首页
论坛
课程
招聘
[原创]基于LIEF实现InlineHook
2021-3-10 17:31 7587

[原创]基于LIEF实现InlineHook

2021-3-10 17:31
7587
前言

之前用 LIEF 最多也就是添加一个依赖so,偶然细读了一下 LIEF的文档 ,意外发现他还有一些比较好玩的操作,比如合并段,新增导出函数,修改导出函数之类的,结合一下inlinehook,于是就有了这篇文章

简介

使用ndk编译提供代码so,再使用lief合并代码进原始so,最后在对汇编代码稍作修改即可完成最原滋原味的inlinehook

具体操作
lief的简单使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import lief
 
def swap(obj,sym1,sym2):
    s1 = obj.get_symbol(sym1)
    s2 = obj.get_symbol(sym2)
    temp = s2.name
    s2.name = s1.name
    s1.name = temp
 
if __name__ == '__main__':
 
    lib_src = lief.parse("libnative-lib.so")
    lib_code = lief.parse("libcodeProvider.so")
    print(lib_code)
 
    # 互换导出函数地址
    swap(lib_src,"Java_com_lzy_lieftest_MainActivity_Test1","Java_com_lzy_lieftest_MainActivity_Test2")
 
    # libcodeProvider.so 的第二个段(包含.text节)添加进 libnative-lib.so
    segment_added = lib_src.add(lib_code.segments[1])
 
    # 合并进来的两个函数依旧为其添加导出函数(方便我们查找)
    code_test3 = lib_code.get_symbol("test3")
    code_innerCallFunctionRep = lib_code.get_symbol("innerCallFunctionRep")
    lib_src.add_exported_function(segment_added.virtual_address + code_test3.value, "test3Rep")
    lib_src.add_exported_function(segment_added.virtual_address + code_innerCallFunctionRep.value, "innerCallFunctionRep")
 
    lib_src.write("libnative-lib1.so")

 

由上脚本合并so的代码段
下面介绍一下三种inlinehook姿势


使用BL替换BL
 

 

 

nop之间的代码就是我们正式的hook代码(ndk编译的那部分代码),这部分代码如果使用到got表的函数需要手动去修正一下,比如上截图的日志函数
这么操作的话可拓展性就非常的大,多余的参数零时变量什么的,你都可以进入hook函数的时候去申请更大的栈空间用来存放,退出的时候也记得恢复

使用B替换
 

 

 

 

在跳走的empFunction中我们就有空位随意的写入汇编指令
跳走之后被替换部分的汇编跳转记得手动修复一下跳转地址

 

上文中举例的Demo so很小,所以直接就用bl/b跳转,但是这里需要注意Arm的B系列指令跳转范围只有±32MB,Thumb的B系列指令跳转范围只有±256字节,遇到so比较大的情况,考虑使用 add pc 来进行跳转

 

另一种跳转(ldr pc)可以参考inlinehook的这篇文档http://ele7enxxh.com/Android-Arm-Inline-Hook.html

使用 add pc 替换任意位置
 

 

 

 

这里简单的讲解一下0xdf34的值是怎么算的:
代码执行到0xdf30时,pc的值应该是等0xdf38,所以0xdf34位置的值应该是 0x40b3c - 0xdf38

拓展
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
extern "C"
void injectLog(){
 
    void* v_r0;
    void* v_r1;
    void* v_r2;
    void* v_r3;
 
    void* v_r4;
    void* v_r5;
    void* v_r6;
    void* v_r7;
    void* v_r8;
    void* v_r9;
    void* v_r10;
    void* v_r11;
 
    void* v_ip;
    void* v_sp;
    void* v_lr;
    void* v_pc;
 
    asm(
    "mov %0,r0\n"
    "mov %1,r1\n"
    "mov %2,r2\n"
    "mov %3,r3\n"
    "mov %4,r4\n"
    "mov %5,r5\n"
    "mov %6,r6\n"
    "mov %7,r7\n"
    "mov %8,r8\n"
    "mov %9,r9\n"
    "mov %10,r10\n"
    "mov %11,r11\n"
    :"=r"(v_r0),"=r"(v_r1),"=r"(v_r2),"=r"(v_r3)
        ,"=r"(v_r4),"=r"(v_r5),"=r"(v_r6),"=r"(v_r7),"=r"(v_r8),"=r"(v_r9),"=r"(v_r10),"=r"(v_r11)
    );
 
    asm(
    "mov %0,ip\n"
    "mov %1,sp\n"
    "mov %2,lr\n"
    "mov %3,pc\n"
    :"=r"(v_ip),"=r"(v_sp),"=r"(v_lr),"=r"(v_pc)
    );
 
    LOGD("inject register log : \n"
            "%p\t%p\t%p\t%p\n"
            "%p\t%p\t%p\t%p\t%p\t%p\t%p\t%p\n"
//            "%p\t%p\t%p\t%p\n"
            ,v_r0,v_r1,v_r2,v_r3
            ,v_r4,v_r5,v_r6,v_r7,v_r8,v_r9,v_r10,v_r11
//            ,v_ip,v_sp,v_lr,v_pc
            );
}
总结

用到lief做这样的inlinehook,目前还没有发现有什么好的实际用处,但是可以帮我们用实践去更好的理解inlinehook的原理,很多东西看着简单但是一操作起来就踩坑,实践大于理论,有兴趣的伙伴可以试试

 

附件(APK DEMO):
https://pan.baidu.com/s/176tG65p8v7s9Bzc2eiO_nQ
tcui


看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

最后于 2021-3-10 18:14 被唱过阡陌编辑 ,原因:
收藏
点赞5
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回