【移动安全】frida集成工具-objection

admin 2024年11月14日23:47:58评论22 views字数 11325阅读37分45秒阅读模式

公众号发出来格式有点乱,建议直接下方阅读原文

介绍

Frida 是一款功能强大的动态分析工具,可以使用它的 API 来编写各种自定义的脚本和插件。而 Objection 是基于 Frida API 开发的一个工具,它将常见的 Frida 脚本和插件整合到一起,并提供了一个命令行接口,使用户可以方便地使用这些功能,而无需编写复杂的脚本。

Objection 的目标是使移动应用程序的安全评估更加简单和高效。它提供了许多常见的功能,如反调试、禁用证书绑定、绕过安全检查、修改应用程序的行为等等。这些功能都是通过调用 Frida 的 API 来实现的,但是 Objection 将它们封装成易于使用的命令行接口,从而降低了使用门槛,并提高了效率。

GitHub: https://github.com/sensepost/objection

安装说明

安装

pip3 install objection

参数说明

   objectionUsage: objection [OPTIONS] COMMAND [ARGS]...选项:  -N,--network 使用网络连接而不是USB进行连接。[默认值:False]  -h,--host TEXT 使用的主机地址。[默认值:127.0.0.1]  -p,--port INTEGER 连接使用的端口号。[默认值:27042]  -ah,--api-host TEXT API服务器绑定的主机地址。[默认值:127.0.0.1]  -ap,--api-port INTEGER API服务器绑定的端口号。[默认值:8888]  -g,--gadget TEXT 要连接的Frida Gadget/进程的名称。[默认值:Gadget]  -S,--serial TEXT 要连接的设备序列号。  -d,--debug 启用调试模式并输出详细信息。(包括堆栈跟踪中的代理源映射)  --help 显示此帮助消息并退出。命令:  api 在无头模式下启动Objection API服务器。  device-type 获取附加设备的信息。  explore 启动Objection exploration REPL。  patchapk 使用frida-gadget.so修补APK。  patchipa 使用FridaGadget dylib修补IPA。  run 运行单个Objection命令。  signapk 使用Objection密钥对APK进行zipalign和签名。  version 打印当前版本并退出。

启动 objection

sieve为目标,注入目标中

默认是连接 USB,如果有多个 USB,就需要用-S 指定

Objection 在启动时会自动注入 Frida Agent 到目标应用程序中

objection -S emulator-5554 -g com.mwr.example.sieve explore

启动后,不知道输入什么命令,可以按tab,他会帮你提示,支持 tab 键自动补齐,也可以通过help 命令来查看对应命令的说明,如help android

【移动安全】frida集成工具-objection
image

启动 activity/service

获取 activity 列表

android hooking list activities

启动 activity

android intent launch_activity com.mwr.example.sieve.PWList

获取 service 列表

android hooking list services

启动 service

android intent launch_service com.mwr.example.sieve.CryptoService

内存操作

内存搜索

memory search "abcde" --string

内存查看

# memory dump <base address> <size to dump> <local destination>memory dump from_base 0xf7778765 200 main

搜索类

列出所有加载的类

android hooking list classes

搜索类

# android hooking search classes 关键词android hooking search classes sieve

搜索方法

列出指定类的方法

# android hooking list class_methods 类名android hooking list class_methods com.mwr.example.sieve.MainLoginActivity

搜索方法

# android hooking search methods 关键词android hooking search methods com.mwr.example.sieve.MainLoginActivity

主动执行方法

先尝试找到该类的实例(和Java.choose类似)

android heap search instances com.mwr.example.sieve.MainLoginActivity# resClass instance enumeration complete for com.mwr.example.sieve.MainLoginActivity Hashcode  Class                                    toString()---------  ---------------------------------------  -----------------------------------------------135299310  com.mwr.example.sieve.MainLoginActivity  com.mwr.example.sieve.MainLoginActivity@81080ee

尝试调用这个实例的com.mwr.example.sieve.MainLoginActivity.loginSuccessful()方法

android heap execute 135299310 loginSuccessful# resHandle 135299310 is to class        com.mwr.example.sieve.MainLoginActivityExecuting method: loginSuccessful()

也可以直接 hook 这个实例,去编写 js 脚本;默认实例是clazz

android heap evaluate 135299310# res(The hashcode at `135299310` will be available as the `clazz` variable.)console.log(clazz);console.log(clazz.loginSuccessful());JavaScript capture complete. Evaluating...Handle 135299310 is to class        com.mwr.example.sieve.MainLoginActivitycom.mwr.example.sieve.MainLoginActivity@81080eeundefined

生成 hook 代码

# android hooking generate simple 类名android hooking generate simple com.mwr.example.sieve.MainLoginActivity

生成的框架代码如下,我们只需要根据要 hook 的逻辑进行修改即可,其中arguments就是传入的参数。

Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.sendFailed.implementation = function() {        //        return clazz.sendFailed.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.loginSuccessful.implementation = function() {        //        return clazz.loginSuccessful.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onCreateOptionsMenu.implementation = function() {        //        return clazz.onCreateOptionsMenu.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.loginFailed.implementation = function() {        //        return clazz.loginFailed.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onOptionsItemSelected.implementation = function() {        //        return clazz.onOptionsItemSelected.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.checkKeyResult.implementation = function() {        //        return clazz.checkKeyResult.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.login.implementation = function() {        //        return clazz.login.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.connected.implementation = function() {        //        return clazz.connected.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.firstLaunchResult.implementation = function() {        //        return clazz.firstLaunchResult.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.welcomeUser.implementation = function() {        //        return clazz.welcomeUser.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.setPinResult.implementation = function() {        //        return clazz.setPinResult.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.unbind.implementation = function() {        //        return clazz.unbind.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.openSettings.implementation = function() {        //        return clazz.openSettings.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.initaliseActivity.implementation = function() {        //        return clazz.initaliseActivity.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.setPin.implementation = function() {        //        return clazz.setPin.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onResume.implementation = function() {        //        return clazz.onResume.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onBackPressed.implementation = function() {        //        return clazz.onBackPressed.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onStart.implementation = function() {        //        return clazz.onStart.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onActivityResult.implementation = function() {        //        return clazz.onActivityResult.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onCreate.implementation = function() {        //        return clazz.onCreate.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.onPause.implementation = function() {        //        return clazz.onPause.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.setKeyResult.implementation = function() {        //        return clazz.setKeyResult.apply(this, arguments);    }});Java.perform(function() {    var clazz = Java.use('com.mwr.example.sieve.MainLoginActivity');    clazz.checkPinResult.implementation = function() {        //        return clazz.checkPinResult.apply(this, arguments);    }});

监听类和方法

hook 类中所有的方法

# android hooking watch class 类名android hooking watch class com.mwr.example.sieve.MainLoginActivity# res(agent) Hooking com.mwr.example.sieve.MainLoginActivity.checkKeyResult(boolean)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.checkPinResult(boolean)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.connected()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.firstLaunchResult(int)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.login(android.view.View)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onActivityResult(int, int, android.content.Intent)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onBackPressed()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onCreate(android.os.Bundle)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onCreateOptionsMenu(android.view.Menu)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onOptionsItemSelected(android.view.MenuItem)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onPause()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onResume()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.onStart()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.sendFailed()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.setKeyResult(boolean)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.setPinResult(boolean)(agent) Hooking com.mwr.example.sieve.MainLoginActivity.initaliseActivity()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.loginFailed()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.loginSuccessful()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.openSettings()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.setPin()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.unbind()(agent) Hooking com.mwr.example.sieve.MainLoginActivity.welcomeUser()(agent) Registering job 963225. Type: watch-class for: com.mwr.example.sieve.MainLoginActivity

hook 后,输入jobs list可以查看该类下的方法都被 hook

job list# resJob ID  Hooks  Type------  -----  --------------------------------------------------------963225     23  watch-class for: com.mwr.example.sieve.MainLoginActivity

正常操作 app,当 hook 的方法被调用时,会自动将这些方法输出。

【移动安全】frida集成工具-objection
image

hook 对应方法的参数、返回值和调用栈

# android hooking watch class_method <方法名> --dump-args --dump-return  --dump-backtraceandroid hooking watch class_method com.mwr.example.sieve.MainLoginActivity.login --dump-args --dump-return  --dump-backtrace

当这个方法被调用时,会输出相关的信息

com.mwr.example.sieve on (Xiaomi: 6.0.1) [usb] # (agent) [880894] Called com.mwr.example.sieve.MainLoginActivity.login(android.view.View)(agent) [880894] Backtrace:    com.mwr.example.sieve.MainLoginActivity.login(Native Method)        java.lang.reflect.Method.invoke(Native Method)    android.view.View$DeclaredOnClickListener.onClick(View.java:4453)    android.view.View.performClick(View.java:5204)    android.view.View$PerformClick.run(View.java:21153)    android.os.Handler.handleCallback(Handler.java:739)    android.os.Handler.dispatchMessage(Handler.java:95)    android.os.Looper.loop(Looper.java:148)    android.app.ActivityThread.main(ActivityThread.java:5647)    java.lang.reflect.Method.invoke(Native Method)    com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)    com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)(agent) [880894] Arguments com.mwr.example.sieve.MainLoginActivity.login(android.widget.Button{8efa50c VFED..C.. ...P.... 0,879-1872,1004 #7f080010 app:id/mainlogin_button_login})(agent) [880894] Return Value: (none)

其他技巧

其他命令

查看命令的帮助

objection explore --hel# 如同步执行命令objection -g com.xxx.xxx -S emulator-5554 explore --startup-command 'android hooking search classes sieve'

显示当前应用程序环境的目录信息。

env

导入 js 脚本(需要 结合 frida[1]使用 ,不然会有找不到 pid 的问题,参考issue[2]

import <js脚本路径>

关闭 root 检测

android root disable

绕过 ssl pinning 检测

android sslpinning disable

设置 proxy 代理(不是很好用)

android proxy set 172.20.10.2 8080

获取当前的 activity

android hooking get current_activity

截图并保存到本地

android ui screenshot ./1.png

结合 frida

部分情况,比如存在 root 检测这种,需要在 app 启动时进行 hook,但是直接用objection提供的-s或者-S参数又不能生效,或者有各种问题,因此可以直接结合 frida 来进行,也很方便好用。

# 绕过root检测frida -D emulator-5554 -l root_detection_bypass.js -f owasp.mstg.uncrackable1# 获取pidfrida-ps -D emulator-5554 -a# objection attachobjection -g 4093 -S emulator-5554 explore

参考资料

[1]

结合 frida: #结合frida

[2]

issue: https://github.com/sensepost/objection/issues/335

原文始发于微信公众号(初始安全):【移动安全】frida集成工具-objection

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月14日23:47:58
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【移动安全】frida集成工具-objectionhttps://cn-sec.com/archives/1638415.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息