修复结束之后跟踪指令,0x3434处的代码跳到了0x345A,0x345A处的代码主要逻辑是在0x34C6跳到0x34EC通过0x34EC动态计算地址跳到了0x3520,0x3524处的代码跳到了0x365C,0x366E处的代码跳到了0x35A8,0x35A8是JNI_OnLoad的主要逻辑。
如上图所示,0x35A8基本就干了两件事:FindClass(com/meituan/android/common/mtguard/NBridge)和RegisterNatives(com/meituan/android/common/mtguard/NBridge, main, 1)。
sub_3680里面调用sub_36B4通过异或解密了一些字符串,上图我已经把解密之后的结果patch进去了。
当然用unidbg是可以直接跑JNI_OnLoad的:
不过这个系列文章主要是想讨论一下so混淆和反混淆,有精力的话还可以对这个so进行完整分析,混淆应该没有啥新的了。
import
keystone
from
capstone
import
*
import
idc
import
ida_bytes
import
subprocess
arch
=
keystone.KS_ARCH_ARM
mode
=
keystone.KS_MODE_THUMB
ks
=
keystone.Ks(arch, mode)
md
=
Cs(CS_ARCH_ARM, CS_MODE_THUMB)
def
is_BLX_sub407C(ea):
ldr_addr
=
ea
ldr_flags
=
idc.get_full_flags(ldr_addr)
if
not
idc.is_code(ldr_flags):
return
False
if
idc.print_insn_mnem(ldr_addr) !
=
'BLX'
:
return
False
if
idc.print_operand(ldr_addr,
0
) !
=
'sub_407C'
:
return
False
return
True
def
is_BLX_sub4094(ea):
ldr_addr
=
ea
ldr_flags
=
idc.get_full_flags(ldr_addr)
if
not
idc.is_code(ldr_flags):
return
False
if
idc.print_insn_mnem(ldr_addr) !
=
'BLX'
:
return
False
if
idc.print_operand(ldr_addr,
0
) !
=
'sub_4094'
:
return
False
if
idc.print_insn_mnem(ldr_addr
-
2
) !
=
'PUSH'
:
return
False
if
idc.print_insn_mnem(ldr_addr
+
8
) !
=
'POP'
:
return
False
return
True
def
func_patch():
ins_addr
=
idc.next_head(
0
)
while
ins_addr !
=
idc.BADADDR:
if
is_BLX_sub407C(ins_addr):
for
i
in
CodeRefsTo(ins_addr,
False
):
if
idc.get_wide_word(i
+
4
)
=
=
18112
:
index
=
idc.get_wide_word(i
+
6
)
patch_qword(i
+
6
,
0x46C046C0
)
idc.create_insn(i
+
6
)
else
:
index
=
idc.get_wide_word(i
+
4
)
patch_qword(i
+
4
,
0x46C046C0
)
idc.create_insn(i
+
4
)
print
(
"i:"
+
hex
(i))
index
=
index
*
4
+
ins_addr
+
4
offset
=
ida_bytes.get_dword(index)
target
=
ins_addr
+
0x4
+
offset
command
=
"BL "
+
hex
(target)
print
(
"command:"
+
command)
pi
=
subprocess.Popen([
'D:\\keystone-0.9.2-win64\\kstool.exe'
,
'thumb'
, command, \
hex
(i)], shell
=
True
, stdout
=
subprocess.PIPE)
output
=
pi.stdout.read()
ins
=
str
(output[
-
15
:
-
4
])[
2
:
-
1
]
ins
=
ins.split(
" "
)
ins
=
"0x"
+
ins[
3
]
+
ins[
2
]
+
ins[
1
]
+
ins[
0
]
print
(
"ins:"
+
ins)
patch_dword(i,
int
(ins,
16
))
if
is_BLX_sub4094(ins_addr):
patch_dword(ins_addr
-
2
,
0xbf00
)
patch_dword(ins_addr,
0xbf00
)
patch_dword(ins_addr
+
2
,
0xbf00
)
patch_dword(ins_addr
+
4
,
0xbf00
)
patch_dword(ins_addr
+
6
,
0xbf00
)
patch_dword(ins_addr
+
8
,
0xbf00
)
ins_addr
=
idc.next_head(ins_addr)
func_patch()