近期由于生活所迫阅读了Dobby的源码,正好在此梳理一下,加深印象,也给后面需要的人一点微小的帮助。Dobby一共两个功能,其一是inlinehook,其二是指令插桩,两者原理差不多,主要介绍指令插桩。所谓指令插桩,就是在任意一条指令(函数头或者函数内部都行),进行插桩,执行到这条指令的时候,会去执行我们定义的回调函数,然后再回来执行原来的指令流。使用方法:
所谓听君一席话,胜读十年书;看君一张图,胜过十席话。用图来说明最好不过了,我在阅读的过程中也是一边梳理一边画图。
被插桩指令处被替换为
arm处理器采用指令流水技术,即取指译码执行三阶段同步进行,pc寄存器指向的是正在取指的指令,arm模式中为当前执行的指令地址+8,thhumb模式中为当前位置+4,故而上面的ldr执行的时候,pc寄存器值为ldr指令位置+4,所以ldr,pc,[pc,-0x0]刚好是把下一条内容放入pc中,即跳转了;这种跳转方式支持的范围是一个寄存器的宽度,也就是32位,4g内存,linux进程的虚拟地址空间好像也是4g,这样就可以进程全地址跳转了。那会跳转到哪里呢,跳转到
prologue_dispatch_bridge
0xcea0a0ac。
主要做了两件事,第一,把0xa2305b80放到ip寄存器,第二,跳转到0xcea0a000;注意,这里的是arm模式的指令,pc偏移是8
其中,0xcea0a000就是
closure bridge上半场
这里0xcea0a060处的0x9d2b43e1是高层handler,高层handler会调用我们自定义的handler,就是它
instrument_call_forward_handler
这个handler除了调用我们的handler,还做了一件苟且的事情,后面会说到
梳理一下这个closure bridge,首先保存寄存器环境,然后到地址0xcea0a054时,用bl指令跳到 0xcea0a05c,0xcea0a05c通过ldr方式找到高层handler地址并且调用,注意,bl指令会把下一条指令地址,即0xcea0a058放入lr寄存器,当bl跳到指定函数并且执行之后,函数会返回到lr寄存器保存的地址,即0xcea0a058 b #0xcea0a064,看看0xcea0a064内容
closure bridge下半场
做的事情很平常,就是把之前上半场保存的寄存器出栈,同时恢复栈平衡;只有一点不平常,就是最后一条mov,pc,ip,跳到ip寄存存保存的地址,那么ip寄存起保存的地址是啥呢,还记得上文说的苟且之事吗?instrument_call_forward_handler函数的最后一句
就是把entry->relocated_origin_instructions的内容赋给r12寄存器,这个entry->relocated_origin_instructions就是原始指令的重定位之后的位置,因为原始指令被我们patch成了ldr pc,[pc,-4]以及一条地址,这些被patch的指令会被修复好,放在entry->relocated_origin_instructions(指令修复问题后文继续说),执行完修复好的原始指令之后,会跳回到被patch的原始指令之后的那些指令,继续执行,这个过程大致如下
原指令
因为是patch需要至少8字节,而这里原始指令是thumb,所以patch了四条,修复好的
重定位后的指令
指令修复的逻辑是,pc相关的指令,采用ldr给它跳回正确的位置;pc无关的指令,直接复制过来,这里push指令,add指令以及str.w指令都被直接复制过来,插入的一些nop指令是为了4字节对齐,至于为啥要对齐我就不知道了,印象中thumb指令似乎是两字节对齐就可以了。原指令中,只有cbz是pc相关的,这条指令的语义是,看r0寄存器是否为零,为零则跳转到到给定位置,这个例子中是跳转到当前位置+0x10,即偏移25ED44处;可以看到,Dobby的修复手段是,修改cbz指令,如果r0为0,则通过ldr(0xcea0a0d0 ldr.w pc, [pc, #0x14])指令,给它跳回偏移25ED44处(0x9d639d45);若不为0,则通过ldr(0xcea0a0e0 ldr.w pc, [pc, #-0x0])跳转到被patch指令之后的指令继续去执行,在这里是偏移25ED3C(0x9d639d3d),这两条地址都加了个1,是因为原指令是thumb指令,arm处理器通过末尾地址是否为1来确定采用arm模式还是thumb模式,为1采用thum模式。至此,整个Dobby指令插桩的逻辑就完了。
先遍历一个HookEntry链表,这个链表保存了每一次插桩的信息;每插桩一条指令,都会生成一个HookEntry结构体并且添加到这个链表。遍历这个链表可以判断当前要插桩的指令是否被插过。route->DispatchRouting();为重点方法,这个方法完成几乎所有的插桩工作,route->DispatchRouting()调用了两个方法BuildDynamicBinaryInstrumentRouting()和GenerateRelocatedCode(trampolinebuffer->getSize())
其中,closuretrampoline = ClosureTrampoline::CreateClosureTrampoline(entry, handler);会生成
prologue_dispatch_bridge的那些汇编指令,其中__ EmitAddress((uint32_t)get_closure_bridge())是一个重点,closure_bridge的指令在这里生成,
BuildDynamicBinaryInstrumentRouting()还调用了这个GenerateTrampolineBuffer(entry_->target_address, GetTrampolineTarget()); 这个方法生成了TrampolineBuffer,也就是用于patch原始指令的那些指令,流程图的第二个小方块
其中GenRelocateCodeAndBranch(relocate_buffer, origin, relocated);是重点,它会生成重定位代码,放在relocated指针指向的地址空间中。
感觉有点啰嗦了,重点说一下指令修复那块吧,我们的例子中,要修复的指令是thumb1指令,最终会调到这里;我省略了其他指令的修复,只看cbz的,细节就不说了,大概思路就是,用ldr pc,[pc,xxx]去跳转,但是第一次生成ldr指令的时候,xxx是没用的,等到全部重定位指令都生成之后,这些ldr都会被修正,因为ldr跳转的地址,都是储存在所有指令之后的,从流程图以及上面说的各个块的汇编指令也可以看出,地址都是存在指令末尾。
至此,代码详解也结束了,其实代码修复主要是解析指令,这一块稍微繁琐一点。
最主要的是有了一次完整的源码阅读经验,同时学到了一些工程技巧,比如c++的链表技巧
先定义一个通用链表头,
具体数据节点
这样写的好处是,遍历链表时,直接采用NodHead指针去遍历,然后需要读取数据的时候,把NodHead转为 EntryNod即可,因为结构体指针就是结构体首项地址,这NodHead和EntryNod值都是一样的。这样就可以写出一个通用的链表模板,以后设么链表都可以用这套模板,把EntryNod改改就行
第二个收获是,一些经典宏,比如##可以连接字符串,比如这个宏,可以通过类类型,类成员名称,类成员地址取到类的this指针,参考 container_of宏
同时,Dobby有自己的内存分配模块,他会把每次分配的相同属性的内存记录下来,等到需要申请内存的时候,先查看已经分配的内存是否有可用的,这样就避免了频繁的内存分配。
我总共遇到了三个问题,第一个问题是插桩的时候,正好那条指令正在执行,这样就会出错。修复办法有两个,第一个是在so加载的第一时间就完成插桩;第二个办法是,通过异常使进程中断,自定义信号处理函数,在异常处理过程中完成插桩。我采用的是第一个办法,在so加载的第一时间就完成插桩.android的so加载最终都是通过linker的do_dlopen加载so,而do_dlopen会调用
soinfo* si = find_library(ns, translated_name, flags, extinfo, caller);在这里可以拿到soinfo指针,有了soinfo就有了一切,所以只需要hook这个函数即可。实际上,在aosp10,这个函数是内联的,所以我hook了find_library中的si->increment_ref_count();这个函数拿到的soinfo指针。
第二个问题是,mproterct问题,因为需要patch 的原指令,但是原指令一般内存属性是只读的,需要使用mprotect去把属性改成可写,mprotect是按页整数倍进行修改的,Dobby会把需要插桩的那条指令所在页面权限修改,大多数情况下没有问题,但是偶尔,被插桩的指令位于页面底部,而patch又需要至少8字节,这就导致了会横跨两个页面,而Dobby只是修改了一个页面,需要注意一下
第三个问题,sigll,这个问题主要是指令修复的时候,没有生成正确的汇编,跳错地方了,这个需要针对性的根据源码来修复了,这也是我去看Dobby源码的原因,太南了。。。
目前逆向工具中,ida是静态分析的王者,frida(估计)是动态分析的王者,但是frida是函数级的工作,粒度不够,需要Dobby配合使用,即可达到指令级的动态分析。
调试器虽然也可以达到目的,但是调试器容易引入很多其他的问题,我开始就是使用gdb的,但是遇到了很多问题,比如gdb把进程暂停了,android一些广播超时,就把我的进程杀了,或者不小心摸了一下屏幕,屏幕响应超时,又把我杀了,有时候gdb识别不出thumb指令,还得给它手动设置模式,体验大大滴坏;不过gdb有个内存断点,估计有时候不得不用一下。
int
res_instument
=
DobbyInstrument((void
*
) addr, offset_name_handler);
/
/
handler即我们自定义的回调
/
/
RegisterContext为寄存器上下文,HookEntrtInfo为hook一些必要信息,比如hook地址等
void offset_name_handler(RegisterContext
*
ctx, const HookEntryInfo
*
info)
typedef struct _RegisterContext {
uint32_t dummy_0;
uint32_t dummy_1;
uint32_t dummy_2;
uint32_t sp;
union {
uint32_t r[
13
];
struct {
uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
} regs;
} general;
uint32_t lr;
} RegisterContext
/
/
HookEntryInfo为hook地址及
id
typedef struct _HookEntryInfo {
int
hook_id;
union {
void
*
target_address;
void
*
function_address;
void
*
instruction_address;
};
} HookEntryInfo;
int
res_instument
=
DobbyInstrument((void
*
) addr, offset_name_handler);
/
/
handler即我们自定义的回调
/
/
RegisterContext为寄存器上下文,HookEntrtInfo为hook一些必要信息,比如hook地址等
void offset_name_handler(RegisterContext
*
ctx, const HookEntryInfo
*
info)
typedef struct _RegisterContext {
uint32_t dummy_0;
uint32_t dummy_1;
uint32_t dummy_2;
uint32_t sp;
union {
uint32_t r[
13
];
struct {
uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
} regs;
} general;
uint32_t lr;
} RegisterContext
/
/
HookEntryInfo为hook地址及
id
typedef struct _HookEntryInfo {
int
hook_id;
union {
void
*
target_address;
void
*
function_address;
void
*
instruction_address;
};
} HookEntryInfo;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
process
6089
0x9d639d32
nop
0x9d639d34
ldr.w pc, [pc,
0x9d639d38
/
/
地址
0xcea0a0ac
0x9d639d38
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
ac a0 a0 ce ....
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
process
6089
0x9d639d32
nop
0x9d639d34
ldr.w pc, [pc,
0x9d639d38
/
/
地址
0xcea0a0ac
0x9d639d38
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
ac a0 a0 ce ....
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
0xcea0a0ac
ldr ip, [pc]
0xcea0a0b0
ldr pc, [pc]
0xcea0a0b4
/
/
地址
0xa2305b80
0xcea0a0b8
/
/
地址
0xcea0a000
0xcea0a0b4
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
80
5b
30
a2
00
a0 a0 ce
0xcea0a0ac
ldr ip, [pc]
0xcea0a0b0
ldr pc, [pc]
0xcea0a0b4
/
/
地址
0xa2305b80
0xcea0a0b8
/
/
地址
0xcea0a000
0xcea0a0b4
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
80
5b
30
a2
00
a0 a0 ce
0xcea0a000
sub sp, sp,
0xcea0a004
str
lr, [sp,
0xcea0a008
str
ip, [sp,
0xcea0a00c
str
fp, [sp,
0xcea0a010
str
sl, [sp,
0xcea0a014
str
sb, [sp,
0xcea0a018
str
r8, [sp,
0xcea0a01c
str
r7, [sp,
0xcea0a020
str
r6, [sp,
0xcea0a024
str
r5, [sp,
0xcea0a028
str
r4, [sp,
0xcea0a02c
str
r3, [sp,
0xcea0a030
str
r2, [sp,
0xcea0a034
str
r1, [sp,
0xcea0a038
str
r0, [sp]
0xcea0a03c
add r0, sp,
0xcea0a040
sub sp, sp,
0xcea0a044
str
r0, [sp,
0xcea0a048
sub sp, sp,
0xcea0a04c
mov r0, sp
0xcea0a050
mov r1, ip
0xcea0a054
bl
0xcea0a058
b
0xcea0a05c
ldr pc, [pc,
0xcea0a060
/
/
地址
0x9d2b43e1
0xcea0a060
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
e1
43
2b
9d
0xcea0a000
sub sp, sp,
0xcea0a004
str
lr, [sp,
0xcea0a008
str
ip, [sp,
0xcea0a00c
str
fp, [sp,
0xcea0a010
str
sl, [sp,
0xcea0a014
str
sb, [sp,
0xcea0a018
str
r8, [sp,
0xcea0a01c
str
r7, [sp,
0xcea0a020
str
r6, [sp,
0xcea0a024
str
r5, [sp,
0xcea0a028
str
r4, [sp,
0xcea0a02c
str
r3, [sp,
0xcea0a030
str
r2, [sp,
0xcea0a034
str
r1, [sp,
0xcea0a038
str
r0, [sp]
0xcea0a03c
add r0, sp,
0xcea0a040
sub sp, sp,
0xcea0a044
str
r0, [sp,
0xcea0a048
sub sp, sp,
0xcea0a04c
mov r0, sp
0xcea0a050
mov r1, ip
0xcea0a054
bl
0xcea0a058
b
0xcea0a05c
ldr pc, [pc,
0xcea0a060
/
/
地址
0x9d2b43e1
0xcea0a060
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
e1
43
2b
9d
void instrument_call_forward_handler(RegisterContext
*
ctx, HookEntry
*
entry) {
DynamicBinaryInstrumentRouting
*
route
=
(DynamicBinaryInstrumentRouting
*
)entry
-
>route;
if
(route
-
>handler) {
DBICallTy handler;
HookEntryInfo entry_info;
entry_info.hook_id
=
entry
-
>
id
;
entry_info.instruction_address
=
entry
-
>instruction_address;
handler
=
(DBICallTy)route
-
>handler;
(
*
handler)(ctx, (const HookEntryInfo
*
)&entry_info);
}
/
/
set
prologue bridge
next
hop address with origin instructions that have been relocated(patched)
set_routing_bridge_next_hop(ctx, entry
-
>relocated_origin_instructions);
}
void instrument_call_forward_handler(RegisterContext
*
ctx, HookEntry
*
entry) {
DynamicBinaryInstrumentRouting
*
route
=
(DynamicBinaryInstrumentRouting
*
)entry
-
>route;
if
(route
-
>handler) {
DBICallTy handler;
HookEntryInfo entry_info;
entry_info.hook_id
=
entry
-
>
id
;
entry_info.instruction_address
=
entry
-
>instruction_address;
handler
=
(DBICallTy)route
-
>handler;
(
*
handler)(ctx, (const HookEntryInfo
*
)&entry_info);
}
/
/
set
prologue bridge
next
hop address with origin instructions that have been relocated(patched)
set_routing_bridge_next_hop(ctx, entry
-
>relocated_origin_instructions);
}
0xcea0a064
add sp, sp,
0xcea0a068
add sp, sp,
0xcea0a06c
pop {r0}
0xcea0a070
pop {r1}
0xcea0a074
pop {r2}
0xcea0a078
pop {r3}
0xcea0a07c
pop {r4}
0xcea0a080
pop {r5}
0xcea0a084
pop {r6}
0xcea0a088
pop {r7}
0xcea0a08c
pop {r8}
0xcea0a090
pop {sb}
0xcea0a094
pop {sl}
0xcea0a098
pop {fp}
0xcea0a09c
pop {ip}
0xcea0a0a0
pop {lr}
0xcea0a0a4
mov pc, ip
0xcea0a064
add sp, sp,
0xcea0a068
add sp, sp,
0xcea0a06c
pop {r0}
0xcea0a070
pop {r1}
0xcea0a074
pop {r2}
0xcea0a078
pop {r3}
0xcea0a07c
pop {r4}
0xcea0a080
pop {r5}
0xcea0a084
pop {r6}
0xcea0a088
pop {r7}
0xcea0a08c
pop {r8}
0xcea0a090
pop {sb}
0xcea0a094
pop {sl}
0xcea0a098
pop {fp}
0xcea0a09c
pop {ip}
0xcea0a0a0
pop {lr}
0xcea0a0a4
mov pc, ip
/
/
set
prologue bridge
next
hop address with origin instructions that have been relocated(patched)
set_routing_bridge_next_hop(ctx, entry
-
>relocated_origin_instructions);
void set_routing_bridge_next_hop(RegisterContext
*
ctx, void
*
address) {
*
reinterpret_cast<void
*
*
>(&ctx
-
>general.regs.r12)
=
address;
}
/
/
set
prologue bridge
next
hop address with origin instructions that have been relocated(patched)
set_routing_bridge_next_hop(ctx, entry
-
>relocated_origin_instructions);
void set_routing_bridge_next_hop(RegisterContext
*
ctx, void
*
address) {
*
reinterpret_cast<void
*
*
>(&ctx
-
>general.regs.r12)
=
address;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
process
6089
0xcea0a0c0
nop
0xcea0a0c2
nop
0xcea0a0c4
push {r0, r1, r2, lr}
0xcea0a0c6
nop
0xcea0a0c8
cbz r0,
0xcea0a0ca
nop
0xcea0a0cc
b.w
0xcea0a0d0
ldr.w pc, [pc,
0xcea0a0d4
nop
0xcea0a0d6
nop
0xcea0a0d8
add r2, sp,
0xcea0a0da
nop
0xcea0a0dc
str
r1, [r2,
0xcea0a0e0
ldr.w pc, [pc,
0xcea0a0e4
/
/
地址
0x9d639d3d
0xcea0a0e8
/
/
地址
0x9d639d45
0xcea0a0e4
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
3d
9d
63
9d
45
9d
63
9d
=
.c.E.c.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
process
6089
0xcea0a0c0
nop
0xcea0a0c2
nop
0xcea0a0c4
push {r0, r1, r2, lr}
0xcea0a0c6
nop
0xcea0a0c8
cbz r0,
0xcea0a0ca
nop
0xcea0a0cc
b.w
0xcea0a0d0
ldr.w pc, [pc,
0xcea0a0d4
nop
0xcea0a0d6
nop
0xcea0a0d8
add r2, sp,
0xcea0a0da
nop
0xcea0a0dc
str
r1, [r2,
0xcea0a0e0
ldr.w pc, [pc,
0xcea0a0e4
/
/
地址
0x9d639d3d
0xcea0a0e8
/
/
地址
0x9d639d45
0xcea0a0e4
0
1
2
3
4
5
6
7
8
9
A B C D E F
0123456789ABCDEF
00000000
3d
9d
63
9d
45
9d
63
9d
=
.c.E.c.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
PUBLIC
int
DobbyInstrument(void
*
address, DBICallTy handler) {
if
(!address) {
ERROR_LOG(
"the function address is 0x0.\n"
);
return
RS_FAILED;
}
RAW_LOG(
1
,
"\n\n"
);
DLOG(
0
,
"[DobbyInstrument] Initialize at %p"
, address);
/
/
check
if
we already instruemnt
HookEntry
*
entry
=
Interceptor::SharedInstance()
-
>FindHookEntry(address);
if
(entry) {
DynamicBinaryInstrumentRouting
*
route
=
(DynamicBinaryInstrumentRouting
*
)entry
-
>route;
if
(route
-
>handler
=
=
handler) {
ERROR_LOG(
"instruction %s already been instrumented."
, address);
return
RS_FAILED;
}
}
entry
=
new HookEntry();
entry
-
>
id
=
Interceptor::SharedInstance()
-
>GetHookEntryCount();
entry
-
>
type
=
kDynamicBinaryInstrument;
entry
-
>instruction_address
=
address;
DynamicBinaryInstrumentRouting
*
route
=
new DynamicBinaryInstrumentRouting(entry, (void
*
)handler);
route
-
>Prepare();
/
/
重点方法
route
-
>DispatchRouting();
Interceptor::SharedInstance()
-
>AddHookEntry(entry);
route
-
>Commit();
return
RS_SUCCESS;
}
PUBLIC
int
DobbyInstrument(void
*
address, DBICallTy handler) {
if
(!address) {
ERROR_LOG(
"the function address is 0x0.\n"
);
return
RS_FAILED;
}
RAW_LOG(
1
,
"\n\n"
);
DLOG(
0
,
"[DobbyInstrument] Initialize at %p"
, address);
/
/
check
if
we already instruemnt
HookEntry
*
entry
=
Interceptor::SharedInstance()
-
>FindHookEntry(address);
if
(entry) {
DynamicBinaryInstrumentRouting
*
route
=
(DynamicBinaryInstrumentRouting
*
)entry
-
>route;
if
(route
-
>handler
=
=
handler) {
ERROR_LOG(
"instruction %s already been instrumented."
, address);
return
RS_FAILED;
}
}
entry
=
new HookEntry();
entry
-
>
id
=
Interceptor::SharedInstance()
-
>GetHookEntryCount();
entry
-
>
type
=
kDynamicBinaryInstrument;
entry
-
>instruction_address
=
address;
DynamicBinaryInstrumentRouting
*
route
=
new DynamicBinaryInstrumentRouting(entry, (void
*
)handler);
route
-
>Prepare();
/
/
重点方法
route
-
>DispatchRouting();
Interceptor::SharedInstance()
-
>AddHookEntry(entry);
route
-
>Commit();
return
RS_SUCCESS;
}
void DynamicBinaryInstrumentRouting::DispatchRouting() {
BuildDynamicBinaryInstrumentRouting();
/
/
generate relocated code which size
=
=
trampoline size
GenerateRelocatedCode(trampoline_buffer_
-
>getSize());
}
void DynamicBinaryInstrumentRouting::DispatchRouting() {
BuildDynamicBinaryInstrumentRouting();
/
/
generate relocated code which size
=
=
trampoline size
GenerateRelocatedCode(trampoline_buffer_
-
>getSize());
}
void DynamicBinaryInstrumentRouting::BuildDynamicBinaryInstrumentRouting() {
/
/
create closure trampoline jump to prologue_routing_dispath with the `entry_` data
ClosureTrampolineEntry
*
closure_trampoline;
void
*
handler
=
(void
*
)instrument_routing_dispatch;
handler
=
__builtin_ptrauth_strip(handler, ptrauth_key_asia);
closure_trampoline
=
ClosureTrampoline::CreateClosureTrampoline(entry_, handler);
this
-
>SetTrampolineTarget(closure_trampoline
-
>address);
DLOG(
0
,
"[closure bridge] Carry data %p "
, entry_);
DLOG(
0
,
"[closure bridge] Create prologue_dispatch_bridge %p"
, closure_trampoline
-
>address);
/
/
generate trampoline
buffer
, run before `GenerateRelocatedCode`
GenerateTrampolineBuffer(entry_
-
>target_address, GetTrampolineTarget());
}
void DynamicBinaryInstrumentRouting::BuildDynamicBinaryInstrumentRouting() {
/
/
create closure trampoline jump to prologue_routing_dispath with the `entry_` data
ClosureTrampolineEntry
*
closure_trampoline;
void
*
handler
=
(void
*
)instrument_routing_dispatch;
handler
=
__builtin_ptrauth_strip(handler, ptrauth_key_asia);
closure_trampoline
=
ClosureTrampoline::CreateClosureTrampoline(entry_, handler);
this
-
>SetTrampolineTarget(closure_trampoline
-
>address);
DLOG(
0
,
"[closure bridge] Carry data %p "
, entry_);
DLOG(
0
,
"[closure bridge] Create prologue_dispatch_bridge %p"
, closure_trampoline
-
>address);
/
/
generate trampoline
buffer
, run before `GenerateRelocatedCode`
GenerateTrampolineBuffer(entry_
-
>target_address, GetTrampolineTarget());
}
ClosureTrampolineEntry
*
ClosureTrampoline::CreateClosureTrampoline(void
*
carry_data, void
*
carry_handler) {
ClosureTrampolineEntry
*
entry
=
nullptr;
entry
=
new ClosureTrampolineEntry;
/
/
use closure trampoline template code, find the executable memory
and
patch it.
Code
*
code
=
Code::FinalizeCodeFromAddress(closure_trampoline_template, CLOSURE_TRAMPOLINE_SIZE);
/
/
use assembler
and
codegen modules instead of template_code
TurboAssembler turbo_assembler_(
0
);
PseudoLabel entry_label;
PseudoLabel forward_bridge_label;
_ Ldr(r12, &entry_label);
_ Ldr(pc, &forward_bridge_label);
_ PseudoBind(&entry_label);
_ EmitAddress((uint32_t)entry);
_ PseudoBind(&forward_bridge_label);
_ EmitAddress((uint32_t)get_closure_bridge());
AssemblyCodeChunk
*
code
=
nullptr;
code
=
AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_);
entry
-
>address
=
(void
*
)code
-
>raw_instruction_start();
entry
-
>size
=
code
-
>raw_instruction_size();
entry
-
>carry_data
=
carry_data;
entry
-
>carry_handler
=
carry_handler;
delete code;
return
entry;
}
ClosureTrampolineEntry
*
ClosureTrampoline::CreateClosureTrampoline(void
*
carry_data, void
*
carry_handler) {
ClosureTrampolineEntry
*
entry
=
nullptr;
entry
=
new ClosureTrampolineEntry;
/
/
use closure trampoline template code, find the executable memory
and
patch it.
Code
*
code
=
Code::FinalizeCodeFromAddress(closure_trampoline_template, CLOSURE_TRAMPOLINE_SIZE);
/
/
use assembler
and
codegen modules instead of template_code
TurboAssembler turbo_assembler_(
0
);
PseudoLabel entry_label;
PseudoLabel forward_bridge_label;
_ Ldr(r12, &entry_label);
_ Ldr(pc, &forward_bridge_label);
_ PseudoBind(&entry_label);
_ EmitAddress((uint32_t)entry);
_ PseudoBind(&forward_bridge_label);
_ EmitAddress((uint32_t)get_closure_bridge());
AssemblyCodeChunk
*
code
=
nullptr;
code
=
AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_);
entry
-
>address
=
(void
*
)code
-
>raw_instruction_start();
entry
-
>size
=
code
-
>raw_instruction_size();
entry
-
>carry_data
=
carry_data;
entry
-
>carry_handler
=
carry_handler;
delete code;
return
entry;
}
void
*
get_closure_bridge() {
/
/
if
already initialized, just
return
.
if
(closure_bridge)
return
closure_bridge;
/
/
check
if
enable the inline
-
assembly closure_bridge_template
extern void closure_bridge_tempate();
closure_bridge
=
closure_bridge_template;
/
/
otherwise, use the Assembler build the closure_bridge
TurboAssembler turbo_assembler_(
0
);
_ sub(sp, sp, Operand(
14
*
4
));
_
str
(lr, MemOperand(sp,
13
*
4
));
_
str
(r12, MemOperand(sp,
12
*
4
));
_
str
(r11, MemOperand(sp,
11
*
4
));
_
str
(r10, MemOperand(sp,
10
*
4
));
_
str
(r9, MemOperand(sp,
9
*
4
));
_
str
(r8, MemOperand(sp,
8
*
4
));
_
str
(r7, MemOperand(sp,
7
*
4
));
_
str
(r6, MemOperand(sp,
6
*
4
));
_
str
(r5, MemOperand(sp,
5
*
4
));
_
str
(r4, MemOperand(sp,
4
*
4
));
_
str
(r3, MemOperand(sp,
3
*
4
));
_
str
(r2, MemOperand(sp,
2
*
4
));
_
str
(r1, MemOperand(sp,
1
*
4
));
_
str
(r0, MemOperand(sp,
0
*
4
));
/
/
store sp
_ add(r0, sp, Operand(
14
*
4
));
_ sub(sp, sp, Operand(
8
));
_
str
(r0, MemOperand(sp,
4
));
/
/
stack align
_ sub(sp, sp, Operand(
8
));
_ mov(r0, Operand(sp));
_ mov(r1, Operand(r12));
_ CallFunction(ExternalReference((void
*
)intercept_routing_common_bridge_handler));
/
/
stack align
_ add(sp, sp, Operand(
8
));
/
/
restore sp placeholder stack
_ add(sp, sp, Operand(
8
));
_ ldr(r0, MemOperand(sp,
4
, PostIndex));
_ ldr(r1, MemOperand(sp,
4
, PostIndex));
_ ldr(r2, MemOperand(sp,
4
, PostIndex));
_ ldr(r3, MemOperand(sp,
4
, PostIndex));
_ ldr(r4, MemOperand(sp,
4
, PostIndex));
_ ldr(r5, MemOperand(sp,
4
, PostIndex));
_ ldr(r6, MemOperand(sp,
4
, PostIndex));
_ ldr(r7, MemOperand(sp,
4
, PostIndex));
_ ldr(r8, MemOperand(sp,
4
, PostIndex));
_ ldr(r9, MemOperand(sp,
4
, PostIndex));
_ ldr(r10, MemOperand(sp,
4
, PostIndex));
_ ldr(r11, MemOperand(sp,
4
, PostIndex));
_ ldr(r12, MemOperand(sp,
4
, PostIndex));
_ ldr(lr, MemOperand(sp,
4
, PostIndex));
/
/
auto switch A32 & T32 with `least significant bit`, refer `docs
/
A32_T32_states_switch.md`
_ mov(pc, Operand(r12));
AssemblyCodeChunk
*
code
=
AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_);
closure_bridge
=
(void
*
)code
-
>raw_instruction_start();
DLOG(
0
,
"[closure bridge] Build the closure bridge at %p"
, closure_bridge);
return
(void
*
)closure_bridge;
}
void
*
get_closure_bridge() {
/
/
if
already initialized, just
return
.
if
(closure_bridge)
return
closure_bridge;
/
/
check
if
enable the inline
-
assembly closure_bridge_template
extern void closure_bridge_tempate();
closure_bridge
=
closure_bridge_template;
/
/
otherwise, use the Assembler build the closure_bridge
TurboAssembler turbo_assembler_(
0
);
_ sub(sp, sp, Operand(
14
*
4
));
_
str
(lr, MemOperand(sp,
13
*
4
));
_
str
(r12, MemOperand(sp,
12
*
4
));
_
str
(r11, MemOperand(sp,
11
*
4
));
_
str
(r10, MemOperand(sp,
10
*
4
));
_
str
(r9, MemOperand(sp,
9
*
4
));
_
str
(r8, MemOperand(sp,
8
*
4
));
_
str
(r7, MemOperand(sp,
7
*
4
));
_
str
(r6, MemOperand(sp,
6
*
4
));
_
str
(r5, MemOperand(sp,
5
*
4
));
_
str
(r4, MemOperand(sp,
4
*
4
));
_
str
(r3, MemOperand(sp,
3
*
4
));
_
str
(r2, MemOperand(sp,
2
*
4
));
_
str
(r1, MemOperand(sp,
1
*
4
));
_
str
(r0, MemOperand(sp,
0
*
4
));
/
/
store sp
_ add(r0, sp, Operand(
14
*
4
));
_ sub(sp, sp, Operand(
8
));
_
str
(r0, MemOperand(sp,
4
));
/
/
stack align
_ sub(sp, sp, Operand(
8
));
_ mov(r0, Operand(sp));
_ mov(r1, Operand(r12));
_ CallFunction(ExternalReference((void
*
)intercept_routing_common_bridge_handler));
/
/
stack align
_ add(sp, sp, Operand(
8
));
/
/
restore sp placeholder stack
_ add(sp, sp, Operand(
8
));
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2022-6-29 20:18
被KerryS编辑
,原因: