ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

objection:基于Frida的移动应用运行时安全测试与逆向实战指南

objection:基于Frida的移动应用运行时安全测试与逆向实战指南 1. 为什么移动应用测试绕不开 objection做移动端安全测试和逆向分析的朋友大概率都遇到过这种情况拿到一个目标 App想看看它内部有什么敏感操作、有没有做证书校验、能不能动态调用某个类的方法结果抓包工具被 SSL Pinning 挡住反编译出来的代码又看得头大直接上 Frida 写脚本吧光调试 hook 点就得折腾半天。我第一次接触 objection 就是在这种场景下。当时要快速确认一个支付类 App 是否在运行时做了 root 检测如果用 Frida 写脚本得先定位检测函数、再写 hook 逻辑、还要处理线程问题前前后后一晚上没了。而 objection 提供了一条现成的命令敲下去直接返回检测结果还能一键绕过。那一刻我就意识到这类给 Frida 套一层现成工具箱的中间层工具才是实际干活时效率最高的方式。objection 不是新的 hook 引擎它本质上是一套基于 Frida 的运行时探测与动态调试工具包。你不需要写一行业务代码只需要通过命令行就能完成大量常见的移动应用测试动作枚举已加载的类、定位具体类的方法、内存搜索、SSL Pinning 绕过、模拟运行环境绕过 root 检测、动态调用目标方法、dump 敏感字符串等。它适用于 Android 和 iOS 两大平台底层对接 Frida 的注入机制但把我要写脚本实现变成了我敲一条命令实现。这篇文章我会把 objection 的使用逻辑拆开讲清楚包括环境搭建、核心命令背后的原理、实战中常见的坑以及它与 Frida 原生脚本的协作关系。目标是让还没用过的人能直接上手让用过但只停留在会敲几条命令阶段的人能理解它每个功能模块的底层机制从而在真实测试中选对工具、少走弯路。2. 部署与启动先把 objection 和 Frida 的关系理顺2.1 版本匹配是第一个容易踩的坑很多人装 objection 的第一步就栽了原因不是安装命令出错而是没有搞懂 objection、Frida 工具端、frida-server 三者的版本关系。objection 通过 Python 包管理工具安装它依赖 Frida 的 Python 绑定而手机端需要运行一个 frida-server 程序才能让 PC 端的指令真正注入到应用进程里。我当时在一个测试机上装的 Frida 是 15.x 版本frida-server 也用的 15.x直接跑 objection 完全没问题。后来另一台测试机刷了一个老系统镜像手头只有 frida-server 12.8 的包结果 objection 怎么都连不上。排查半天才意识到Frida Python 包、frida-server、objection 三方之间必须保持一个大版本兼容否则会出现连接成功但命令超时报错 device not foundRPC 调用失败等一系列诡异现象。安装顺序建议如下先安装指定版本的 Frida再安装 objection最后在测试设备端 push 对应版本的 frida-server。命令大致是这样# 指定版本安装 Frida避免装到最新版造成和 frida-server 不匹配 pip install frida15.1.17 pip install objection安装完成后用objection version查看当前工具版本。接着把对应版本的 frida-server 传到设备的/data/local/tmp/目录加执行权限后手动启动adb push frida-server /data/local/tmp/ adb shell chmod 755 /data/local/tmp/frida-server adb shell /data/local/tmp/frida-server 2.2 启动方式和普通 Frida 脚本的差异objection 连接应用有两种常见方式一种是直接启动一个新的应用进程另一种是附加到已经运行的进程上。从命令上区分非常直观# 启动应用并立即注入适合冷启动分析 objection -g com.example.target explore # 附加到正在运行的进程适合动态调试场景 objection -p 12345 explore这里的explore是进入交互式命令界面的关键字进去之后你就面对一个类似终端的环境后续所有操作都在这套命令体系里完成。如果是 iOS 设备通常还需要加-N参数指定设备地址或者通过--host和--port指定远程连接参数。我建议新手在熟悉阶段先不要急着连接真机而是在模拟器上演练。模拟器环境下 frida-server 的启动相对简单而且不用担心设备变砖等命令都跑熟了再换到真机上做完整测试。注意-g参数后跟的是包名不是应用名称。很多人第一次运行时把 App 的名字敲进去了结果 tool 报错找不到目标进程。3. 核心命令模块从内存搜索到方法钩子进入 explore 交互环境之后objection 能做的事情就非常多了。我按实际使用频率把最核心的功能分成几个模块逐一说明。3.1 内存搜索与字符串扫描拿到一个应用我最先做的事永远是字符串扫描。应用里的敏感信息往往直接以字符串形式存在内存中比如加密密钥、API Token、硬编码的密码等。memory search api_key这条命令会在整个进程的堆内存中搜索包含api_key的字符串。objection 返回的结果会带上地址和对应的内存区域类型。搜索到目标字符串之后可以用memory read来读取对应地址附近的内容看看到底存了什么。内存搜索模块有一个细节经常被忽略——默认搜索的是当前进程的堆区也就是 Java 层和 Native 层动态分配的内存。理论上你可以通过memory list modules先看进程加载了哪些 so 库再用memory search在特定模块的内存范围内搜索但这样的操作对工具使用者来说要求比较高需要先搞清楚目标数据可能存在于哪个区域。以我个人的实践来看先全局搜一遍字符串再用结果反推位置比一开始就精确锁定模块更高效。3.2 类与方法的运行时探测这是 objection 最常被使用的功能模块也是它相对于手写 Frida 脚本最大的优势。android hooking list classes这条命令会列出当前进程中所有已加载的类。如果你对包名有预期可以直接用搜索过滤android hooking list classes -s target.package.name拿到类名之后再列出该类下的所有方法android hooking list class_methods target.package.name.MainActivity这两条命令的底层机制其实依赖于 Frida 对 Java 虚拟机运行时ART的枚举能力。objection 把 Frida 的枚举 API 封装成了一条条命令你不需要写 JavaScript 代码去遍历只需要学会命令参数即可。这里有个比较关键的点list classes列出的类是当前时刻已经加载的类不是应用 DEX 文件里的所有类。如果一个类还没被创建实例或被反射调用它可能不在列表里。所以当你发现某个目标类搜不到时别急着怀疑命令写错了先在应用里多点击几个功能让更多代码路径被执行然后再重新枚举。3.3 动态调用与 hook 方法类和方法找出来之后下一步通常是 hook 它、观察它的调用时机或者干脆直接调用它。android hooking watch class_method target.package.name.Utils.getKey --dump-args --dump-return这条命令会 hook 指定方法的进入和返回打印参数和返回值。当你觉得某个方法会在特定操作中被调用时这个方法非常直观执行一下目标操作控制台直接打印出入参、返回值和调用栈。还有android hooking set method系列命令用于替换方法实现。它的原理本质上就是 Frida 的Java.perform配合overload和implementation属性只是换成了命令行交互。android hooking set return_value true target.package.name.Utils.isRooted这条命令我几乎每次都会用到尤其是有 root 检测逻辑的应用。它直接把方法的返回值改成 true 或者 false不需要写任何 hook 代码。提示如果要 hook 的方法存在多个重载版本objection 会提示你指定参数类型。你可以先用list class_methods查看方法签名再按--class-loader参数配好重载类型。3.4 SSL Pinning 绕过移动应用测试中被提到最多的需求应该就是 SSL Pinning 绕过了。很多应用使用了证书校验导致抓包工具看到的全是加密流量。objection 提供了一条相当经典的命令android sslpinning disable这条命令会尝试绕过应用中常见的证书锁定逻辑。它的实现原理是动态替换系统网络栈中的验证逻辑比如把 OkHttp 的CertificatePinner、TrustManager 的验证方法等替换为不做校验的实现版本。但这里有两点必须提醒第一sslpinning disable不是万能的。它主要覆盖常见的开源网络库和系统默认的网络栈如果应用内部实现了自定义的证书校验协议比如私有协议加密后做签名校验这条命令就失效了还是得回到 Frida 脚本针对具体函数下手。第二如果应用使用了 native 层的证书校验比如通过 JNI 调用 C/C 代码做证书绑定Java 层的 hook 方式可能完全不起作用。遇到这种情况需要配合android hooking list activities等命令先定位到具体的网络模块再分析它的 native 校验逻辑。3.5 活动与服务组件操作在处理一些需要深链路跳转的测试场景时直接调用 Activity 比手动操作 UI 高效得多。android activity start -c target.package.name.DeepLinkActivity这条命令可以启动任意 Activity前提是它没有被系统限制比如需要特殊权限才能启动的组件。还有android activity hooking系列命令用于监控 Activity 的生命周期回调。类似的还有android service系列和android broadcast系列可以枚举和操作服务与广播接收器。这些能力从底层看都是利用 Frida 对 Java 层组件的反射调用objection 只不过把常用的启动、枚举、监控封装成了命令行指令帮你省去了大量重复脚本编写的时间。4. 运行环境伪装与安全检测对抗4.1 root 检测与模拟器检测的绕过很多应用会在启动阶段检测运行环境是否被 root 或者是否运行在模拟器上一旦检测到就直接退出或限制功能。做动态测试时这种检测会极大阻碍分析进度。objection 提供了环境伪装相关的功能模块核心命令是android root simulation这条命令的逻辑是对常见的 root 检测点返回假数据让应用认为当前设备没有 root。类似地android emulator detection相关命令用于模拟器检测的绕过。但说实话这些统一条命令的实际效果取决于应用时是怎么写的检测逻辑。如果只是检查Build.TAGS字段或尝试su文件的路径这些模拟手段通常有效但如果应用在 native 层自己做了文件枚举或使用了一些比较偏门的检测 API单纯靠默认的模拟命令是不够的。我的建议是把 objection 自带的伪装命令当成第一层防线跑完检测看应用反应如果仍然被检测到再用android hooking watch class_method去定位具体的检测函数观察调用时机然后针对性地做返回值替换。4.2 文件操作与二进制导出运行时测试经常会遇到需要从应用私有目录中提取文件的情况。objection 提供了文件操作模块file cd /data/data/target.package.name file cat shared_prefs/target.xml file download /data/data/target.package.name/files/test.db /tmp/test.db这三条命令分别对应切换目录、查看文件内容、导出文件到本地。对测试最有用的是file download它能直接把应用私有目录下的数据库、配置文件、缓存文件拉回 PC方便离线分析。这里有一个安全边界的理解问题objection 之所以能读取应用私有目录是因为 Frida 注入的进程拥有应用本身的 UID 权限。所以你能读到的范围和 App 自身拥有的权限一致不能越权访问其他应用的数据。这个概念想清楚就不会对着file cat /data/data/other.package/...的报错一头雾水了。4.3 敏感信息快速筛查排查 Logcat 日志和剪贴板数据是快速发现敏感泄露的手段之一。android heap search strings android keystore listheap search strings会遍历 Java 堆上的字符串对象输出所有可读的字符串常量敏感信息很容易混在里面。比如某个应用在内存里拼接 Token 或银行卡号这条命令往往能直接捞到。android keystore list则是查看应用在 Android Keystore 里存储的密钥条目。它不能直接导出私钥Android Keystore 在硬件级别保护私钥但至少能确认应用使用了哪些别名和密钥类型对于分析密钥管理流程很有参考价值。5. 多包联动与 Frida 脚本的协作模式5.1 在 objection 中加载自定义脚本objection 满足不了 100% 的需求尤其是面对混淆严重的代码或者私有协议时还是离不开自定义 Frida 脚本。好消息是 objection 支持加载额外的自定义脚本frida script load /tmp/my_custom_hook.js你可以在交互环境中动态加载一个写好的 Frida 脚本它会在目标进程里立刻执行后续输出会与 objection 的命令行输出混在一起方便你在同一会话里同时使用两种工具。以我的经验推荐的协作模式是先用 objection 的自动化命令做快速侦察明确目标方法和调用逻辑再用 Frida 脚本做精细化 hook处理混淆函数、native 层逻辑等 objection 覆盖不到的场景。两者的关系是互补的不是替代的。5.2 多应用同时调试日常工作中偶尔会遇到需要同时分析多个协作进程的情况。objection 支持-p参数附加多个进程但实际操作时要注意每个 objection 会话占用一个终端窗口否则输出会互相干扰。多开时建议给每个会话打标签区分objection -p 10001 explore objection -p 10002 explore两条命令分别开两个终端即可。从底层来看每个会话都是独立的 Frida RPC 通道互相之间没有数据共享但如果你能理解应用之间通过 Binder 或 Socket 的交互逻辑多开会话交叉观察就能拼出完整的调用链条。6. 一个典型的实操排查过程从定位方法到绕过检测为了把这些命令串起来我拿一个模拟的真实场景走一遍流程帮大家建立完整的操作手感。假设目标应用包名是com.example.demo它在启动时检测 root检测到就退出。第一步附加或启动进程进入 explore 环境objection -g com.example.demo explore第二步观察应用行为确认它在启动时直接退出了。此时我们不确定它用的是哪个检测函数先枚举一下与 root 相关的类android hooking list classes -s root返回结果里有几个可疑的类包括一个名为com.example.demo.security.SecurityChecker的类。紧接着列出这个类的方法android hooking list class_methods com.example.demo.security.SecurityChecker可以看到它有一个isRooted()方法很好那就不用做粗粒度的全盘 hook 了直接针对这个方法的返回值下手android hooking set return_value false com.example.demo.security.SecurityChecker.isRooted重新触发应用的检测逻辑观察是否还能正常进入主界面。如果仍然被拦截说明还有其他检测点继续用list classes -s root扩大搜索范围或者用android hooking watch class_method监控整个包的类加载动向看它在启动阶段到底执行了哪些方法。第三步解决完 root 检测后用同样的思路检查它有没有做 SSL Pinningandroid sslpinning disable然后开 Charles 或 Burp 抓包验证 HTTPS 流量是否可以正常解密查看。这个流程不算复杂但它是真实测试中最常见的一条主线。掌握这条思路之后很多问题都能用类似方法逐步分解掉而不是一头扎进源码里从零开始逆向。7. 实战中容易栽的六个具体问题7.1 注入后应用崩溃多半是进程启动方式不对使用-g参数冷启动注入时如果应用自身具有反调试或 anti-Frida 机制注入过程可能被检测到导致启动即崩溃。优先尝试附加方式-p也就是先手动打开应用再附加到进程。另外检查应用是否有越狱检测、Frida 检测相关的代码路径如有需要先用环境伪装命令处理再注入。7.2 命令执行超时未必是命令错了超时最常见的原因是进程内大量类和对象导致枚举缓慢尤其是在复杂的商业 App 中list classes可能要好几分钟。这不算 bug耐心等即可。如果长时间无响应还可以用android hooking list activities观察是否只是某个功能模块在阻塞主线程。7.3 抓包失败确定是 Pinning 还是在 native 层加密sslpinning disable之后抓包还是乱码先确认流量是否走了 SO 层的自定义加密。最直接的验证方式是抓取明文特征比如搜索 HTTP 头、JSON key 等关键字如果这些关键字也存在且加密说明应用做了自定义加密封装和 Pinning 就没有关系了。7.4 文件传输失败检查写权限file download导出文件时目标路径必须拥有当前用户写权限。如果 PC 端路径选了一个没有权限创建的目录命令会直接失败。更常见的失败原因是应用目标文件本身被占用或权限受限比如某些数据库文件只能由应用自身读写这时候先在应用内触发一次关闭数据库连接再导出。7.5 自动化命令覆盖不了的高混淆代码有些应用做了字符串混淆和类名混淆list class_methods看到的方法名可能完全没有意义。这种情况下objection 的自动化命令只是辅助定位的作用真正要突破的是通过 Frida 脚本精确指定内存地址来 hook 函数或通过android hooking watch class_method观察调用时附带的参数特征反推逻辑。7.6 模拟器和真机的行为差异模拟器上的测试结果不能代表真机这个坑我反复踩过。很多应用对模拟器的检测比对 root 的检测更严格特别是在系统属性、硬件信息、传感器数据等维度。如果你想在模拟器上跑 objection遇到环境检测严格的应用时优先排查模拟器指纹其次才是 root 状态。8. 进阶使用思路objection 在自动化巡检里的位置objection 除了在单次测试中发挥作用也可以嵌入到自动化的安全巡检流程里。比如在 CI 环境里准备一个测试机每次构建出新包后自动安装、自动进入 explore、自动执行一组固定的检查命令枚举敏感字符串、列出允许导出的组件、检测风险方法等从而形成轻量级的基线巡检。这个思路的核心不是让它替代专业扫描器而是给测试团队提供一个可以快速执行的运行时检查通道。巡检结果输出为文本日志再配合解析脚本可以自动把风险项汇总到工单里。我实际落地过一套这样的流程检查项大约 20 条执行时间约三分钟对于发布前的快速反馈来说性价比很高。如果后续有兴趣我还可以写一篇专门讲 objection 配合 CI 做自动化巡检的文章把命令封装、结果解析、风险阈值判定这些细节都展开讲清楚。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表