首页
社区
课程
招聘
[原创]Albatross 支持hook指令的强大hook和反射库
发表于: 2025-7-27 10:16 8224

[原创]Albatross 支持hook指令的强大hook和反射库

2025-7-27 10:16
8224

Albatross 是一个功能强大的 Android Hook 框架,不仅支持方法级别的 Hook,现在还支持指令级别的 Hook,允许开发者在 Android 7(Nougat)到最新的 Android 16之间,对任意方法中的某条或某段 Dalvik 字节码指令的运行结果进行监控和修改。以下将介绍 Albatross 的指令级 Hook 功能,包括虚拟机模型、寄存器分配机制以及具体 API 的使用方式,并通过一个完整示例进行演示。

在深入 Albatross 的指令 Hook 之前,我们先了解 Android ART 虚拟机使用的 寄存器模型,以及它与传统的 栈模型 的区别。

优点:结构简单,易于实现。
缺点:频繁的栈操作导致性能较差。

优点:减少内存访问,提升性能。
缺点:指令编码更复杂。

在 ART 虚拟机中,每个方法都有一个虚拟寄存器池,数量由 .registers 伪指令指定。这些寄存器用于保存局部变量、参数和中间计算结果。

Albatross 提供了以下核心 API 来进行指令级 Hook:

该类提供了对当前执行上下文中虚拟寄存器的访问能力:

以下是一个完整的指令级 Hook 示例,展示了如何 Hook getCaller(View) 方法的指令,修改运行过程中的值。

对应的 Dalvik 指令:

Dalvik PC = 4 对应 move-result-object 指令执行完。

通过hookgetCaller方法中dexPc=0到dexPc=10的指令范围,在dexPc=4(即move-result-object v0指令执行时)修改v0寄存器的值,将调用者类改为当前类。

Albatross 的指令级 Hook 功能为 Android 开发者提供了前所未有的灵活性和控制力。通过理解 ART 虚拟机的寄存器模型和 Dalvik 指令结构,开发者可以在任意方法的任意指令位置插入自定义逻辑,实现高级调试、行为注入、逻辑绕过等功能。

结合 InstructionCallbackInvocationContext,开发者可以实时读写寄存器内容,甚至修改执行流程,这使得 Albatross 成为 Android 动态分析和逆向工程的利器。

提示:如需获取 Dalvik PC 值,可使用 jadx-guismali 工具查看反编译代码中的 .line 和指令偏移。

public static InstructionListener hookInstruction(Member member, int minDexPc, int maxDexPc, InstructionCallback callback)
public static InstructionListener hookInstruction(Member member, int minDexPc, int maxDexPc, InstructionCallback callback)
参数 类型 说明
member Member 要 Hook 的方法(Method/Constructor)
minDexPc int 起始 Dalvik PC 值(包括)
maxDexPc int 结束 Dalvik PC 值(包括)
callback InstructionCallback 指令执行时的回调
public interface InstructionCallback {
    void onEnter(Member method, Object self, int dexPc, InvocationContext invocationContext);
}
public interface InstructionCallback {
    void onEnter(Member method, Object self, int dexPc, InvocationContext invocationContext);
}
参数 类型 说明
method Member 当前执行的方法
self Object 方法调用者(this,静态方法为null)
dexPc int 当前 Dalvik PC 值 (偏移量)
invocationContext InvocationContext 当前执行上下文,用于读写寄存器
public void getCaller(View view) {
    Class<?> caller = Albatross.getCallerClass();
    textView.setText("caller:" + caller.getName() + ":" + callerCount++);
}
public void getCaller(View view) {
    Class<?> caller = Albatross.getCallerClass();
    textView.setText("caller:" + caller.getName() + ":" + callerCount++);
}
InstructionListener listener = null;
 
public void instruction(View view) throws NoSuchMethodException {
    if (listener == null) {
        Method getCaller = AlbatrossDemoMainActivity.class.getDeclaredMethod("getCaller", View.class);
        listener = Albatross.hookInstruction(getCaller, 0, 10, (method, self, dexPc, invocationContext) -> {
            assert dexPc <= 10;
            assert dexPc >= 0;
            assert method == getCaller;
            assert self == AlbatrossDemoMainActivity.this;
            assert invocationContext.NumberOfVRegs() == 7;
 
            Albatross.log("onEnter:" + dexPc);
 
            Object receiver = invocationContext.GetParamReference(0);
            assert receiver == self;
 
            Object v = invocationContext.GetParamReference(1);
            assert (v instanceof View);
 
            if (dexPc == 4) {
                // Hook Dalvik PC == 4 的指令
                // 原始调用:Albatross.getCallerClass()
                // 修改为返回当前类 AlbatrossDemoMainActivity.class
                invocationContext.SetVRegReference(0, AlbatrossDemoMainActivity.class);
            }
        });
    } else {
        listener.unHook();
        listener = null;
    }
}
InstructionListener listener = null;
 
public void instruction(View view) throws NoSuchMethodException {
    if (listener == null) {
        Method getCaller = AlbatrossDemoMainActivity.class.getDeclaredMethod("getCaller", View.class);
        listener = Albatross.hookInstruction(getCaller, 0, 10, (method, self, dexPc, invocationContext) -> {
            assert dexPc <= 10;
            assert dexPc >= 0;
            assert method == getCaller;
            assert self == AlbatrossDemoMainActivity.this;
            assert invocationContext.NumberOfVRegs() == 7;
 
            Albatross.log("onEnter:" + dexPc);
 
            Object receiver = invocationContext.GetParamReference(0);
            assert receiver == self;
 
            Object v = invocationContext.GetParamReference(1);
            assert (v instanceof View);
 
            if (dexPc == 4) {
                // Hook Dalvik PC == 4 的指令
                // 原始调用:Albatross.getCallerClass()
                // 修改为返回当前类 AlbatrossDemoMainActivity.class
                invocationContext.SetVRegReference(0, AlbatrossDemoMainActivity.class);
            }
        });
    } else {
        listener.unHook();
        listener = null;
    }
}
caller:qing.albatross.demo.AlbatrossDemoMainActivity:0
caller:qing.albatross.demo.AlbatrossDemoMainActivity:0
.method public getCaller(Landroid/view/View;)V
    .registers 7
    .param p1, "view" # Landroid/view/View;

    .line 180
    invoke-static {}, Lqing/albatross/core/Albatross;->getCallerClass()Ljava/lang/Class;
    move-result-object v0
// 寄存器数量:7个(v0-v6,p0-p1)
.registers 7
// 调用Albatross.getCallerClass()并将结果存入v0

invoke-static {}, Lqing/albatross/core/Albatross;->getCallerClass()Ljava/lang/Class;
move-result-object v0
// 后续逻辑:使用v0的值构建字符串并更新textView

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2025-7-27 10:19 被WanQing编辑 ,原因: 添加项目地址
收藏
免费 157
支持
分享
最新回复 (132)
雪    币: 1766
活跃值: (2575)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
路过看看
2025-7-27 10:34
0
雪    币: 105
活跃值: (2272)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
66666
2025-7-27 11:06
0
雪    币: 6469
活跃值: (4681)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4

学习了~

最后于 2025-7-27 11:14 被anenn编辑 ,原因:
2025-7-27 11:14
0
雪    币: 255
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
6
2025-7-27 11:31
0
雪    币: 3032
活跃值: (3884)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习一下
2025-7-27 11:47
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
感谢分享
2025-7-27 13:36
1
雪    币: 200
活跃值: (58)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢分享的内容!
2025-7-27 16:27
0
雪    币: 16571
活跃值: (1681)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2025-7-28 01:16
0
雪    币: 5
活跃值: (1935)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
看下。好像so层没开源是吧
2025-7-28 02:26
0
雪    币: 2790
活跃值: (5491)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
学习一下
2025-7-28 08:45
0
雪    币: 1265
活跃值: (2227)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习学些
2025-7-28 09:12
0
雪    币: 46
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
恋一世的爱 看下。好像so层没开源是吧
是的,等一段时间
2025-7-28 09:20
0
雪    币: 82
活跃值: (1598)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
学习一下
2025-7-28 10:18
0
雪    币: 54
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
666
2025-7-28 10:49
0
雪    币: 204
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
学习一下
2025-7-28 11:37
0
雪    币: 1762
活跃值: (1255)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
17
学习一下
2025-7-28 14:49
0
雪    币: 343
活跃值: (1756)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
6666
2025-7-28 15:09
0
雪    币: 4
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
66666
2025-7-28 15:58
0
雪    币: 175
活跃值: (361)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
66666666666666
2025-7-28 16:12
0
雪    币: 178
活跃值: (3061)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
21
666
2025-7-28 17:20
0
雪    币: 86
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
学习一下
2025-7-28 21:55
0
雪    币: 0
活跃值: (2439)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
学习一下
2025-7-29 09:32
0
雪    币: 104
活跃值: (7159)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
tql
2025-7-29 09:33
0
雪    币: 19
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
25
mark
2025-7-29 10:23
0
游客
登录 | 注册 方可回帖
返回