Use lief, keystone and capstone to manually inline hook elf(libil2cpp.so) file
前文说到使用基于LIEF的InlineHook实现 ,在这里我们再借助 keystone 和 capstone 来完善一下这个想法,解决一些比较枯燥且容易出错的事,比如 地址偏移的计算,指令备份还原 ...
小提示
记录下用到的五个起始位置
原来的样子
这里在+-32MB范围内建议直接用bl会比较简洁一些
脚本中提供了三种方式的 hook:ldr(3)/b(1)/bl(1)
hook之后使用三条指令跳转到 trampolines
进入到trampolines
做一次中转,保存上下文同时跳转到hook代码
进入到textCodes
真实的hook代码位置,使用的每一个小功能代码连续且独立成块,用一条b跳过相对寻址占用的位置
GLOBAL_TABLE
STR_TABLE
(目前有一个已知的问题是对CallStaticVoidMethod参数的构建,具体JValueArray的内存实现大概是猜对了,基本数据类型是没啥问题,主要是引用数据类型不能正确读取)
具体实现如下:
继承关系
AsmPatch -> AndroidPatch -> UnityPatch
然后就得到了这种 arm32 hook
https://github.com/axhlzy/PyAsmPatch
[手动狗头].png
def
fixGot(
self
, log):
self
.mprotect(mPtr
=
functionsMap.get(
"GOT_TABLE"
), size
=
1024
*
8
, log
=
log)
self
.loadBaseToReg(reg
=
"R9"
, log
=
True
)
self
.relocationGot(reg
=
"R9"
)
self
.endHook()
def
fixGot(
self
, log):
self
.mprotect(mPtr
=
functionsMap.get(
"GOT_TABLE"
), size
=
1024
*
8
, log
=
log)
self
.loadBaseToReg(reg
=
"R9"
, log
=
True
)
self
.relocationGot(reg
=
"R9"
)
self
.endHook()
def
mprotect(
self
, mPtr
=
None
, size
=
4096
, prot
=
7
, log
=
False
):
if
mPtr
is
None
:
self
.patchASM(
"MOV R2,PC"
)
else
:
self
.loadToReg(
self
.addPtr(mPtr), reg
=
"R2"
)
self
.prepareStack(
3
)
self
.patchASM(
"MOV R1,R2,LSR#12"
)
self
.patchASM(
"MOV R0,R1,LSL#12"
)
self
.saveRegToStack(reg
=
"R0"
, index
=
0
)
self
.patchASM(
"MOV R1,#{}"
.
format
(size))
self
.saveRegToStack(reg
=
"R1"
, index
=
1
)
self
.patchASM(
"MOV R2,#{}"
.
format
(prot))
self
.saveRegToStack(reg
=
"R2"
, index
=
2
)
self
.jumpTo(
self
.getRelocation(
"mprotect"
), jmpType
=
"REL"
, reg
=
"R3"
, resetPC
=
False
)
self
.patchASM(
"MOV R3,R0"
)
if
log:
self
.android_log_print_reg(formart
=
"mprotect ret = %d args : %p %p %p"
)
self
.restoreStack(
3
)
def
loadBaseToReg(
self
, reg
=
"R4"
, log
=
False
):
self
.loadToReg(
self
.addPtr(
self
.currentPC
+
7
*
self
._pSize), reg
=
"R1"
, fix
=
1
)
self
.patchASM(
"LDR R2,[R1]"
)
self
.patchASM(
"SUB R0,PC,R2"
)
self
.patchASM(
"MOV {},R0"
.
format
(reg))
if
log:
self
.patchASM(
"MOV R3,R0"
)
self
.android_log_print_reg(formart
=
"soAddr -> %p"
)
def
relocationGot(
self
, reg
=
"R9"
):
self
.prepareStack(
2
)
self
.loadToReg(functionsMap.get(
"GOT_TABLE"
), reg
=
"R5"
, fix
=
1
)
self
.patchASM(
"MOV R7,#0"
)
self
.patchASM(
"MOV R10,#0"
)
self
.patchASM(
"ADD R8,R5,R7"
)
self
.patchASM(
"LDR R6,[R8]"
)
self
.patchASM(
"CMP R6,#0"
)
self
.jumpTo(
self
.currentPC
+
self
._pSize
*
24
, jmpType
=
"BEQ"
, resetPC
=
False
)
self
.patchASM(
"MOV R3,R8"
)
self
.patchASM(
"ADD R10,#1"
)
self
.saveRegToStack(reg
=
"R6"
, index
=
0
)
self
.patchASM(
"ADD R6,R6,{}"
.
format
(reg))
self
.saveRegToStack(reg
=
"R6"
, index
=
1
)
self
.android_log_print_reg(formart
=
"GOT relocation %p ---> %p ---> %p"
)
self
.patchASM(
"STR R6,[R8]"
)
self
.patchASM(
"ADD R7,R7,#4"
)
self
.jumpTo(
self
.currentPC
-
self
._pSize
*
26
, jmpType
=
"B"
, resetPC
=
False
)
self
.patchASM(
"MOV R3,R10"
)
self
.android_log_print_reg(formart
=
"Finished GOT relocation all:%d"
)
self
.restoreStack(
2
)
def
mprotect(
self
, mPtr
=
None
, size
=
4096
, prot
=
7
, log
=
False
):
if
mPtr
is
None
:
self
.patchASM(
"MOV R2,PC"
)
else
:
self
.loadToReg(
self
.addPtr(mPtr), reg
=
"R2"
)
self
.prepareStack(
3
)
self
.patchASM(
"MOV R1,R2,LSR#12"
)
self
.patchASM(
"MOV R0,R1,LSL#12"
)
self
.saveRegToStack(reg
=
"R0"
, index
=
0
)
self
.patchASM(
"MOV R1,#{}"
.
format
(size))
self
.saveRegToStack(reg
=
"R1"
, index
=
1
)
self
.patchASM(
"MOV R2,#{}"
.
format
(prot))
self
.saveRegToStack(reg
=
"R2"
, index
=
2
)
self
.jumpTo(
self
.getRelocation(
"mprotect"
), jmpType
=
"REL"
, reg
=
"R3"
, resetPC
=
False
)
self
.patchASM(
"MOV R3,R0"
)
if
log:
self
.android_log_print_reg(formart
=
"mprotect ret = %d args : %p %p %p"
)
self
.restoreStack(
3
)
def
loadBaseToReg(
self
, reg
=
"R4"
, log
=
False
):
self
.loadToReg(
self
.addPtr(
self
.currentPC
+
7
*
self
._pSize), reg
=
"R1"
, fix
=
1
)
self
.patchASM(
"LDR R2,[R1]"
)
self
.patchASM(
"SUB R0,PC,R2"
)
self
.patchASM(
"MOV {},R0"
.
format
(reg))
if
log:
self
.patchASM(
"MOV R3,R0"
)
self
.android_log_print_reg(formart
=
"soAddr -> %p"
)
def
relocationGot(
self
, reg
=
"R9"
):
self
.prepareStack(
2
)
self
.loadToReg(functionsMap.get(
"GOT_TABLE"
), reg
=
"R5"
, fix
=
1
)
self
.patchASM(
"MOV R7,#0"
)
self
.patchASM(
"MOV R10,#0"
)
self
.patchASM(
"ADD R8,R5,R7"
)
self
.patchASM(
"LDR R6,[R8]"
)
self
.patchASM(
"CMP R6,#0"
)
self
.jumpTo(
self
.currentPC
+
self
._pSize
*
24
, jmpType
=
"BEQ"
, resetPC
=
False
)
self
.patchASM(
"MOV R3,R8"
)
self
.patchASM(
"ADD R10,#1"
)
self
.saveRegToStack(reg
=
"R6"
, index
=
0
)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-10-27 14:33
被唱过阡陌编辑
,原因: