发布于 

Objection 快速逆向、自动分析和主动调用

前言:为什么需要 Objection

在 Android 逆向分析中,Frida 已经成为最强大的动态插桩工具。但实际使用时你会发现,许多操作是重复性的:查看 Activity 列表、搜索特定类名、hook 某个方法查看参数和返回值——每次都需要手写一段 JavaScript 脚本,然后通过 frida -U -f com.app -l hook.js 加载。这种模式虽然灵活,但在快速逆向的场景下效率并不高。

Objection 正是为了解决这个问题而诞生的。它基于 Frida 构建,将常见的逆向操作封装为一组开箱即用的命令,让你在无需编写 JavaScript 的前提下完成大部分逆向分析工作。简单来说:Frida 是底层引擎,Objection 是高级接口。

本文将从工作流、信息收集、类探索、主动调用和实际案例五个维度,系统讲解 Objection 的使用方法。

Objection 快速逆向工作流

Objection 的核心优势在于"零脚本、开箱即用"。一个典型的快速逆向工作流如下:

安装目标 APK → 启动 Objection 注入 → 信息收集 → 定位关键类 → Hook/调用 → 验证结果

安装目标应用(如果你手上有 APK 文件):

# Objection 可以直接安装并启动应用
objection -g com.target.app explore --startup-command "android hooking list classes"

其中关键参数说明:

  • -g--gadget:指定目标包名
  • explore:进入交互式 REPL 环境
  • --startup-command:启动时自动执行一条命令(可多次使用)

进入 REPL 后,Objection 会显示 com.target.app on (xxx) [usb] # 提示符,表示已成功注入。

信息收集阶段

Android Manifest 组件信息

AndroidManifest.xml 是逆向分析的第一站。它包含了应用的四大组件声明、权限请求、intent-filter 等关键信息。

# 获取完整 AndroidManifest.xml
android manifest show

# 查看应用声明的权限
android manifest show permissions

执行后会输出解析后的 Manifest 内容,包括所有注册的 Activity、Service、BroadcastReceiver 和 ContentProvider。这在寻找攻击面(如导出组件)时非常有用。

查询导出组件

导出组件(exported=true)是应用暴露给外部调用的接口,也是安全审计的重点目标:

# 列出所有导出 activities
android hooking list activities

# 列出所有导出 services
android hooking list services

# 列出所有导出 receivers
android hooking list receivers

# 查看 intent-filter,找到可通过特定 action 启动的组件
android intents query_activities -a android.intent.action.MAIN

通过这些命令,你可以快速建立应用的组件拓扑图,了解哪些功能入口是可以直接触发的。

导出密钥库

android keystore list

该命令会列出设备中与应用相关的密钥库信息,帮助你在分析签名验证、数据加密等逻辑时获取密钥信息。

类和方法探索

搜索关键字相关类和方法

在逆向分析中,我们通常不知道具体的类名,只知道功能关键词。Objection 提供了强大的搜索能力:

# 搜索类名中包含 "login" 的所有类
android hooking search classes login

# 搜索类名中包含 "vip" 的所有类
android hooking search classes vip

# 查看某个类的所有方法
android hooking list class_methods com.example.app.VipManager

# 查看某个类的所有实例方法
android hooking search methods vip com.example.app

例如,对一个付费应用执行 android hooking search classes vip,可能会返回:

com.example.app.model.VipInfo
com.example.app.manager.VipManager
com.example.app.utils.VipChecker

从类名就能初步判断:VipChecker 很可能包含 VIP 验证逻辑,VipManager 管理会员状态,VipInfo 是会员信息的数据模型。

查看类的继承关系

了解类的继承关系有助于理解框架的设计模式:

# 查看类的完整信息,包括父类和实现的接口
android hooking list class_methods com.example.app.VipChecker

Objection 会在输出中标注哪些方法是继承自父类的,哪些是类自身定义的,以及类实现的接口列表。这对快速建立类的层次结构非常有帮助。

动态分析类加载情况

# 列出所有已加载的类
android hooking list classes

# 配合 grep 过滤(在 shell 中使用)
android hooking list classes | grep -i "pay"

如果你在运行时操作了应用(如点击某个按钮触发了懒加载),再次执行该命令就能看到新加载的类。这可以帮助你追踪动态加载的行为。

主动调用方法

Objection 最强大的功能之一是主动调用(Active Invocation),即在运行时直接调用应用中的 Java 方法。

执行方法调用

# 无参方法调用
android hooking invoke com.example.app.VipManager isVip

# 带参方法调用
android hooking invoke com.example.app.VipManager checkVip java.lang.String user007

android hooking invoke 命令的基本语法为:

android hooking invoke <类全名> <方法名> [参数类型1 参数值1] [参数类型2 参数值2] ...

构造参数并调用

参数类型的指定遵循 Java 的全限定类名规范:

# 传入 int 参数
android hooking invoke com.example.app.PayManager pay int 100

# 传入 boolean 参数
android hooking invoke com.example.app.VipManager setVipStatus boolean true

# 传入 String 参数
android hooking invoke com.example.app.UserManager login java.lang.String admin java.lang.String 123456

# 传入多个不同类型参数
android hooking invoke com.example.app.OrderManager createOrder java.lang.String prod001 int 2 boolean false

与 Frida 的联系:在 Frida 原生脚本中,主动调用需要这样写:

Java.perform(function() {
    var VipManager = Java.use("com.example.app.VipManager");
    var result = VipManager.isVip();
    console.log("VIP Status: " + result);
});

Objection 将这段代码封装为单条命令,省去了编写脚本的步骤。本质上,Objection 底层就是在运行时生成并注入类似的 Frida JavaScript 代码。

获取和设置类属性值

除了方法调用,Objection 还支持直接操作类的属性(字段):

# 设置静态字段值
android hooking set static_field com.example.app.VipInfo isVip boolean true

# 获取静态字段值(通过 invoke 访问 getter 方法)
android hooking invoke com.example.app.VipInfo getIsVip

这在绕过状态检查时非常实用——直接修改内存中的标志位,比 hook 方法更简洁。

实际案例:逆向 VIP 验证逻辑

定位 VIP 检查方法

假设我们面对一个付费视频应用,目标是分析其 VIP 验证机制。首先搜索相关类:

android hooking search classes vip

输出:

com.video.app.member.VipChecker
com.video.app.member.MemberManager
com.video.app.model.MemberInfo

查看 VipChecker 的方法:

android hooking list class_methods com.video.app.member.VipChecker

输出中找到关键方法:

private boolean checkVipStatus(String userId)
public boolean isVipUser()
public int getVipLevel()
public long getVipExpireTime()

修改返回值

Hook checkVipStatus 方法,让它始终返回 true

# Hook 方法并修改返回值
android hooking set return_value com.video.app.member.VipChecker checkVipStatus true

执行后,每次应用调用 checkVipStatus 都会得到 true,VIP 验证即被绕过。你也可以通过 --include-overloads 参数处理重载方法。

主动调用付费功能方法

找到会员功能的入口方法后,可以直接调用:

# 解锁会员视频
android hooking invoke com.video.app.member.MemberManager unlockPremiumVideo java.lang.String video_12345

# 查看当前 VIP 等级
android hooking invoke com.video.app.member.VipChecker getVipLevel

# 设置会员到期时间(操作属性)
android hooking set static_field com.video.app.model.MemberInfo expireTime long 1893456000000

通过组合主动调用和属性修改,你可以在不修改 APK 的情况下完整验证付费功能的逻辑。

实际案例:使用 wallbreaker 插件 dump 敏感对象

wallbreaker 是 Objection 的一个强大插件,可以在运行时 dump 内存中的 Java 对象实例。

# 加载 wallbreaker 插件
plugin load wallbreaker

# 列出某个类的所有活动实例
android heap search instances com.video.app.model.MemberInfo

# dump 实例的完整字段信息
android heap print_instances com.video.app.model.MemberInfo

执行后会输出该类在内存中所有实例的详细信息,包括每个字段的当前值:

Handle 0x1234:
  className: com.video.app.model.MemberInfo
  fields:
    userId = "user_007"
    vipLevel = 0
    isVip = false
    expireTime = 0
    token = "eyJhbGciOiJIUzI1NiJ9..."

这在分析运行时状态、提取敏感数据(如 token、密钥、用户信息)时极为有用。相比 hook 日志输出,wallbreaker 能直接获取对象的完整快照。

Objection 脚本化操作

交互式 REPL 适合探索性分析,但在需要重复执行的场景下,脚本化是更好的选择。

将命令写入文本文件 objection-script.txt

android hooking search classes vip
android hooking list class_methods com.video.app.member.VipChecker
android hooking set return_value com.video.app.member.VipChecker checkVipStatus true
android hooking invoke com.video.app.member.MemberManager unlockPremiumVideo java.lang.String video_12345

执行脚本:

objection -g com.video.app explore -s objection-script.txt

-s 参数会按顺序执行脚本中的每条命令。这在 CI/CD 自动化测试、批量分析多个应用时非常方便。

你也可以使用 --startup-command 在启动时执行单条命令,结合多个 --startup-command 实现简单的工作流自动化。

Objection 与自定义 Frida 脚本的结合使用

Objection 虽然强大,但终究是封装好的高级命令。当遇到复杂场景(如 trace 函数调用链、修改算法逻辑、处理 native 函数)时,仍然需要自定义 Frida 脚本。

Objection 提供了在 REPL 中加载 Frida 脚本的能力:

# 在 Objection REPL 中加载自定义脚本
import /path/to/custom_hook.js

这等价于在 Frida 中 frida -U -f com.app -l custom_hook.js,但好处是你可以在 Objection 的信息收集结果基础上,有针对性地编写脚本。

典型的结合使用模式:

  1. 先用 Objection 探索android hooking search classeslist class_methods 快速定位目标类和方法
  2. 再用 Frida 精确 hook:根据探索结果编写自定义脚本,实现更复杂的逻辑(如 trace、参数篡改、调用栈打印)
  3. 用 Objection 验证:通过 invokeset return_value 快速验证 hook 效果

例如,先用 Objection 找到 VipChecker.checkVipStatus 方法,然后编写 Frida 脚本打印其完整的调用栈:

Java.perform(function() {
    var VipChecker = Java.use("com.video.app.member.VipChecker");
    VipChecker.checkVipStatus.implementation = function(userId) {
        console.log("[*] checkVipStatus called with: " + userId);
        console.log("[*] Call stack: " + Java.use("android.util.Log")
            .getStackTraceString(Java.use("java.lang.Exception").$new()));
        return this.checkVipStatus(userId);
    };
});

这种"Objection 探索 + Frida 深度分析"的工作模式,是目前 Android 逆向工程师最高效的实践方式。

总结

Objection 将 Frida 的动态插桩能力封装为简洁的命令行接口,大幅降低了逆向分析的使用门槛。核心要点回顾:

功能 命令 用途
信息收集 android manifest show 查看组件和权限
类搜索 android hooking search classes 按关键字定位类
方法查看 android hooking list class_methods 列出类的所有方法
修改返回值 android hooking set return_value 绕过检查逻辑
主动调用 android hooking invoke 直接执行方法
对象 dump android heap print_instances 查看运行时对象状态
脚本执行 objection -g pkg explore -s file 批量自动化操作

掌握 Objection,意味着你可以在几分钟内完成"安装 → 探索 → 定位 → 验证"的完整逆向流程。它不是 Frida 的替代品,而是 Frida 生态中不可或缺的效率工具。在下一篇文章中,我们将深入 Frida 的综合情景案例,展示如何在真实场景中应对更复杂的逆向挑战。