objection 使用详解

简介

objection是一个基于Frida的动态的移动测试工具包,可以帮助我们来进行应用程序安全评估。

主要由以下三个组件组成

1.Frida-Gadget,以嵌入式模式运行应用,通过objection自己的api方法去调用frda执行我们想要的命令

2.objeciton本身是由python编写的可以通过python实现一个交互式shell进行命令的加载和使用,以此来调用objection

3.objection进行hook时会通过TypeScript独立生成一个agent.js文件,这样可以在使用中可以去直接调用所有的功能

objection.png

首先挂一张图

image-20220715164700277

下载

# 推荐兼容下载也可自行选择
pip3 install frida==5.3.0
pip3 install frida==12.8.0
pip3 install objection==1.8.4
# 下载最新版本
pip3 install --upgrade objection
# 测试环境
Mac OS 12.3
Kali 2022
Nexus 6P
MUMU模拟器

基础命令

查看环境任务

jobs

用于查看和管理当前Hook所执行的任务,可以同时运行多项hook作业。

com.android.settings on (google: 6.0.1) [usb] # jobs list
Job ID Hooks Type
----------- ----- ------------------------------------
5tk3e403t35 4 watch-method for: java.io.File.$init

Frida命令

查看Frida相关信息

常用命令

列出内存中的所有类

android hooking list classes

内存中所有已加载的类中搜索包含关键词的类

android hooking search classes
eg: android hooking search classes display
com.android.settings on (google: 6.0.1) [usb] # android hooking search classes display
[Landroid.icu.text.DisplayContext$Type;
[Landroid.icu.text.DisplayContext;
[Landroid.view.Display$ColorTransform;
[Landroid.view.Display$Mode;
android.hardware.display.DisplayManager
android.hardware.display.DisplayManager$DisplayListener
android.hardware.display.DisplayManagerGlobal
android.hardware.display.DisplayManagerGlobal$DisplayListenerDelegate
android.hardware.display.DisplayManagerGlobal$DisplayManagerCallback
android.hardware.display.IDisplayManager
android.hardware.display.IDisplayManager$Stub
android.hardware.display.IDisplayManager$Stub$Proxy
android.hardware.display.IDisplayManagerCallback
android.hardware.display.IDisplayManagerCallback$Stub
android.icu.impl.CurrencyData$CurrencyDisplayInfo
android.icu.impl.CurrencyData$CurrencyDisplayInfoProvider
android.icu.impl.ICUCurrencyDisplayInfoProvider
android.icu.impl.ICUCurrencyDisplayInfoProvider$ICUCurrencyDisplayInfo
android.icu.text.CurrencyDisplayNames
android.icu.text.DisplayContext
android.icu.text.DisplayContext$Type
android.media.RemoteDisplay
android.opengl.EGLDisplay
android.util.DisplayMetrics
android.view.Choreographer$FrameDisplayEventReceiver
android.view.Display
android.view.Display$ColorTransform
android.view.Display$ColorTransform$1
android.view.Display$Mode
android.view.Display$Mode$1
android.view.DisplayAdjustments
android.view.DisplayEventReceiver
android.view.DisplayInfo
android.view.DisplayInfo$1
android.view.DisplayListCanvas
android.view.SurfaceControl$PhysicalDisplayInfo
com.android.settings.DisplaySettings
com.android.settings.wfd.WifiDisplaySettings
com.google.android.gles_jni.EGLDisplayImpl
javax.microedition.khronos.egl.EGLDisplay

Found 40 classes

内存中搜索所有包含关键词key的方法

android hooking search methods <keys>
eg:android hooking search methods dispaly

列出类的所有方法

android hooking list class_methods
android hooking list class_methods <class>
android hooking list class_methods android.hardware disapaly.DisplayManager

列出进程中所有的activity

android hooking list activities

列出进程中所有的service

android hook list services

列出进程中所有的广播接收器

android hooking list receivers

列出进程中所有的内容提供者

android hooking list providers

对指定的方法进行hook

android hooking watch class_method <method_Name>
android hooking watch class java.io.File
com.android.settings on (google: 6.0.1) [usb] # jobs list
Job ID Hooks Type
----------- ----- -----------------------------
nenk6ks64jg 64 watch-class for: java.io.File
android hooking watch class_method java.io.File.$init --dump-args --dump-backtrace --dump-return
--dump-args //打印函数的参数
--dump-backtrace //调用栈
--dump-return //返回值
com.android.settings on (google: 6.0.1) [usb] # android hooking watch class_method java.io.File.$init --dump-args --dump-backtrace --dump-return
(agent) Attempting to watch class java.io.File and method $init.
(agent) Hooking java.io.File.$init(java.io.File, java.lang.String)
(agent) Hooking java.io.File.$init(java.lang.String)
(agent) Hooking java.io.File.$init(java.lang.String, java.lang.String)
(agent) Hooking java.io.File.$init(java.net.URI)
(agent) Registering job 5tk3e403t35. Type: watch-method for: java.io.File.$init

虽然只确定了Hook构造,但是默认会Hook对应方法的所有重载。同时,在输出的最后一行显示Registering job 5tk3e403t35,表示这个Hook被作为一个任务被添加。

com.android.settings on (google: 6.0.1) [usb] # jobs list
Job ID Hooks Type
----------- ----- ------------------------------------
5tk3e403t35 4 watch-method for: java.io.File.$init

在“设置”应用中的任意位置进行点击时,会发现java.ioFile.File(java.io.lang.String)这一个函数被调用了。在Backtrace之后打印的调用栈中,我们可以清楚的看到这个构造函数的调用来源

(agent) [5tk3e403t35] Called java.io.File.File(java.lang.String)
(agent) [5tk3e403t35] Backtrace:
java.io.File.<init>(Native Method)
android.content.res.XResources.isFirstLoad(XResources.java:115)
de.robv.android.xposed.XposedInit.cloneToXResources(XposedInit.java:396)
de.robv.android.xposed.XposedInit.access$100(XposedInit.java:63)
de.robv.android.xposed.XposedInit$9.afterHookedMethod(XposedInit.java:326)
de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:374)
android.app.ResourcesManager.getTopLevelResources(<Xposed>)
android.app.ActivityThread.getTopLevelResources(ActivityThread.java:1701)
android.app.ApplicationPackageManager.getResourcesForApplication(ApplicationPackageManager.java:1032)
de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:360)
android.app.ApplicationPackageManager.getResourcesForApplication(<Xposed>)
android.app.ApplicationPackageManager.getText(ApplicationPackageManager.java:1286)
android.content.pm.ComponentInfo.loadLabel(ComponentInfo.java:85)
com.android.settings.DreamBackend.getActiveDreamName(DreamBackend.java:136)
com.android.settings.DreamSettings.getSummaryTextWithDreamName(DreamSettings.java:261)
com.android.settings.DisplaySettings.updateScreenSaverSummary(DisplaySettings.java:425)
com.android.settings.DisplaySettings.updateState(DisplaySettings.java:381)
com.android.settings.DisplaySettings.onResume(DisplaySettings.java:362)
android.app.Fragment.performResume(Fragment.java:2263)
android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1008)
android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1130)
android.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:1963)
android.app.FragmentController.dispatchResume(FragmentController.java:174)
android.app.Activity.performResume(Activity.java:6348)
android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092)
android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
android.app.ActivityThread.-wrap11(ActivityThread.java)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:148)
android.app.ActivityThread.main(ActivityThread.java:5417)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
de.robv.android.xposed.XposedBridge.main(XposedBridge.java:107)

(agent) [5tk3e403t35] Arguments java.io.File.File(/data/app/com.google.android.deskclock-1/base.apk)
(agent) [5tk3e403t35] Return Value: (none)

测试结束后,可以根据作业的ID来删除作业,取消对这些函数的Hook,最终执行结果如下

com.android.settings on (google: 6.0.1) [usb] # jobs list
Job ID Hooks Type
----------- ----- ------------------------------------
5tk3e403t35 4 watch-method for: java.io.File.$init
com.android.settings on (google: 6.0.1) [usb] # jobs kill 5tk3e403t35
com.android.settings on (google: 6.0.1) [usb] # jobs list
Job ID Hooks Type
------ ----- ----

主动调用

android heap search instances <classname>
android heap search instances java.io.File
Class instance enumeration complete for java.io.File
Handle Class toString()
-------- ------------ ---------------------------------------------------------------------------------------
0x200d26 java.io.File /data/app/com.google.android.gms-1/base.apk
0x200d2a java.io.File /data/user/0/com.android.settings/shared_prefs
0x200d2e java.io.File /data/user/0/com.android.settings/shared_prefs/com.android.settings_preferences.xml
0x200d32 java.io.File /data/user/0/com.android.settings/shared_prefs/com.android.settings_preferences.xml.bak
0x100d36 java.io.File /data/app/com.google.android.deskclock-1/base.apk
0x100d3a java.io.File /data/misc/keychain/cacerts-added
0x100d3e java.io.File /data/misc/keychain/cacerts-removed
0x100d42 java.io.File /system/etc/security/cacerts
0x100d46 java.io.File /data
0x100d4a java.io.File /data
0x100d4e java.io.File /system
0x100d52 java.io.File /storage
0x100d56 java.io.File /oem
0x100d5a java.io.File /vendor
0x100d5e java.io.File /cache
0x100d62 java.io.File /data/secure
0x100d66 java.io.File /vendor/lib64
0x100d6a java.io.File /system/lib64
0x100d6e java.io.File
0x100d72 java.io.File /data/app/mobi.acpm.inspeckage-1/base.apk
0x100d76 java.io.File /vendor/lib64
0x100d7a java.io.File /system/lib64
0x100d7e java.io.File
0x100d82 java.io.File
0x100d86 java.io.File /data/data/mobi.acpm.sslunpinning/shared_prefs/UnpinningPrefs.xml
0x100d8a java.io.File /vendor/lib64
0x100d8e java.io.File /system/lib64
0x100d92 java.io.File
0x100d96 java.io.File /data/app/mobi.acpm.sslunpinning-1/base.apk
0x100d9a java.io.File /data/data/mobi.acpm.inspeckage/shared_prefs/InspeckagePrefs.xml
0x100d9e java.io.File /vendor/lib64
0x100da2 java.io.File /system/lib64
0x100da6 java.io.File
0x100daa java.io.File /data/app/just.trust.me-1/base.apk
0x100dae java.io.File /data/dalvik-cache
0x100db2 java.io.File /vendor/lib64
0x100db6 java.io.File /system/lib64
0x100dba java.io.File
0x100dbe java.io.File /system/framework/XposedBridge.jar
0x100dc2 java.io.File /data/misc/user/0
0x100dc6 java.io.File /data/misc/user/0/cacerts-added
0x100dca java.io.File /data/misc/user/0/cacerts-removed
0x100dce java.io.File /data/user/0/com.android.settings/shared_prefs/home_prefs.xml.bak
0x100dd2 java.io.File /data/user/0/com.android.settings/shared_prefs/home_prefs.xml
0x100dd6 java.io.File /data/user/0/com.android.settings/shared_prefs/development.xml.bak
0x100dda java.io.File /data/user/0/com.android.settings/shared_prefs/development.xml
0x100dde java.io.File /data/user/0/com.android.settings/files
0x100de2 java.io.File /data/user/0/com.android.settings/shared_prefs
0x100de6 java.io.File /data/user/0/com.android.settings/cache
0x100dea java.io.File /data/user/0/com.android.settings/databases
0x100dee java.io.File /data/user/0/com.android.settings
0x100df2 java.io.File /
0x100df6 java.io.File /data/data/com.android.settings/cache
0x100dfa java.io.File /vendor/lib64
0x100dfe java.io.File /system/lib64
0x100e02 java.io.File lib/arm64-v8a
0x100e06 java.io.File /system/priv-app/Settings/Settings.apk
0x100e0a java.io.File /system/priv-app/Settings/lib/arm64
0x100e0e java.io.File /system/priv-app/Settings/Settings.apk!/lib/arm64-v8a
0x100e12 java.io.File
0x100e16 java.io.File /system/priv-app/Settings/Settings.apk

调用实例方法

android heap execute <Handle> <methodname>
com.android.settings on (google: 6.0.1) [usb] # android heap execute 0x200d2e getPath
Handle 0x200d2e is to class java.io.File
Executing method: getPath()
/data/user/0/com.android.settings/shared_prefs/com.android.settings_preferences.xml

使用execute执行带参数时会报错

com.android.settings on (google: 6.0.1) [usb] # android heap execute 0x200d2e setExecutable True
Handle 0x200d2e is to class java.io.File
Executing method: setExecutable()
A Frida agent exception has occurred.
Error: setExecutable(): argument count of 0 does not match any of:
.overload('boolean')
.overload('boolean', 'boolean')
at throwOverloadError (frida/node_modules/frida-java-bridge/lib/class-factory.js:1020)
at n (frida/node_modules/frida-java-bridge/lib/class-factory.js:667)
at /script1.js:9147
at /script1.js:9435
at frida/node_modules/frida-java-bridge/lib/vm.js:11
at frida/node_modules/frida-java-bridge/index.js:279
at /script1.js:9439
at /script1.js:3011
at /script1.js:9440

执行带参数函数

android heap evaluate <Handle>

执行之后会进入一个迷你的编辑器环境,之后输入我们想要执行的脚本内容,编辑完成后按回车键,即会开始执行这行脚本并输出结果。我们来使用File类的canWrite()函数和setWrite()函数进行测试,具体内容如下

console.log('File is canWrite? =>' ,clazz.canWrite())
clazz.setWritable(false)
console.log('File is canWrite? =>' , clazz.canWrite())
com.android.settings on (google: 6.0.1) [usb] # android heap evaluate 0x200d2e
(The handle at `0x200d2e` will be available as the `clazz` variable.)
console.log('File is canWrite? =>' ,clazz.canWrite())
clazz.setWritable(false)
console.log('File is canWrite? =>' , clazz.canWrite())
JavaScript capture complete. Evaluating...
Handle 0x200d2e is to class java.io.File
File is canWrite? => true
File is canWrite? => false

查看内存中的so库

memory list modules

查看so库的导出(export)函数

memory list exports libssl.so

将结果保存到json文件中

memory list exports libart.so --json /root/libart.json

关闭SSLPINNING

android sslpinning disable

objection远程连接

frida 启动

./fs -l 0.0.0.0:8888

objection远程链接

objection -N -h 192.168.31.52 -p 8888 -g com.xxx.xxx explore

Obejction Wallbreaker插件

下载

git clone https://github.com/hluwa/Wallbreaker ~/.objection/plugins/Wallbreaker

使用

objection: objection -g com.app.name explore -P ~/.objection/plugins

搜索类

plugin wallbreaker classsearch <pattern>
//根据给的 pattern 对所有类名进行匹配,列出匹配到的所有类名。

搜索对象

plugin wallbreaker objectsearch <classname>
//根据类名搜索内存中已经被创建的实例,列出 handle 和 toString() 的结果。

Classdump

plugin wallbreaker classdump <classname> [--fullname]
输出类的结构, 若加了 --fullname 参数,打印的数据中类名会带着完整的包名。

ObjectDump

plugin wallbreaker objectdump <handle> [--fullname]
在 ClassDump 的基础上,输出指定对象中的每个字段的数据。
Author

ol4three

Posted on

2022-03-11

Updated on

2023-01-29

Licensed under


Comments