-
-
[原创]基于LIEF实现InlineHook
-
发表于: 2021-3-10 17:31 10400
-
之前用 LIEF 最多也就是添加一个依赖so,偶然细读了一下 LIEF的文档 ,意外发现他还有一些比较好玩的操作,比如合并段,新增导出函数,修改导出函数之类的,结合一下inlinehook,于是就有了这篇文章
使用ndk编译提供代码so,再使用lief合并代码进原始so,最后在对汇编代码稍作修改即可完成最原滋原味的inlinehook
由上脚本合并so的代码段
下面介绍一下三种inlinehook姿势
nop之间的代码就是我们正式的hook代码(ndk编译的那部分代码),这部分代码如果使用到got表的函数需要手动去修正一下,比如上截图的日志函数
这么操作的话可拓展性就非常的大,多余的参数零时变量什么的,你都可以进入hook函数的时候去申请更大的栈空间用来存放,退出的时候也记得恢复
在跳走的empFunction中我们就有空位随意的写入汇编指令
跳走之后被替换部分的汇编跳转记得手动修复一下跳转地址
上文中举例的Demo so很小,所以直接就用bl/b跳转,但是这里需要注意Arm的B系列指令跳转范围只有±32MB,Thumb的B系列指令跳转范围只有±256字节,遇到so比较大的情况,考虑使用 add pc 来进行跳转
另一种跳转(ldr pc)可以参考inlinehook的这篇文档d7bK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3g2D9k6e0N6W2L8Y4S2^5K9q4)9J5k6h3y4G2L8g2)9J5c8V1q4F1k6s2u0G2K9h3c8Q4x3X3c8m8M7X3#2Q4x3X3c8u0L8X3I4A6L8X3g2Q4x3X3c8t1L8$3!0C8i4K6u0W2K9s2c8E0L8l9`.`.
这里简单的讲解一下0xdf34的值是怎么算的:
代码执行到0xdf30时,pc的值应该是等0xdf38,所以0xdf34位置的值应该是 0x40b3c - 0xdf38
用到lief做这样的inlinehook,目前还没有发现有什么好的实际用处,但是可以帮我们用实践去更好的理解inlinehook的原理,很多东西看着简单但是一操作起来就踩坑,实践大于理论,有兴趣的伙伴可以试试
附件(APK DEMO):
d64K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3j5h3&6Q4x3X3g2T1j5h3W2V1N6g2)9J5k6h3y4G2L8g2)9J5c8Y4y4Q4x3V1j5I4y4K6k6@1c8K6j5#2M7o6S2$3y4%4x3&6b7Y4A6U0x3X3g2A6e0#2)9#2k6X3&6c8
tcui
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"
)
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"
)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [原创]逆向角度看C++部分特性 22451
- [原创]__builtin_return_address()引发的思考 7433
- [原创]静态InlineHook的脚本实现 30893
- [原创]记录一下YAHFA相关 10120
- [原创]基于LIEF实现InlineHook 10401