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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
| from capstone import *
from keystone import *
class BinaryPatcher:
"""二进制 Patch 工具"""
def __init__(self, arch='arm64'):
if arch == 'arm64':
self.md = Cs(CS_ARCH_ARM64, CS_MODE_ARM)
self.ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN)
elif arch == 'arm':
self.md = Cs(CS_ARCH_ARM, CS_MODE_ARM)
self.ks = Ks(KS_ARCH_ARM, KS_MODE_ARM)
self.md.detail = True
self.patches = []
def find_pattern(self, code, base_addr, pattern):
"""查找指令模式"""
results = []
for insn in self.md.disasm(code, base_addr):
if pattern in f"{insn.mnemonic} {insn.op_str}":
results.append({
'address': insn.address,
'offset': insn.address - base_addr,
'size': insn.size,
'instruction': f"{insn.mnemonic} {insn.op_str}",
'bytes': insn.bytes.hex()
})
return results
def create_nop_patch(self, size, arch='arm64'):
"""创建 NOP 填充"""
if arch == 'arm64':
nop = bytes([0x1f, 0x20, 0x03, 0xd5]) # nop
else:
nop = bytes([0x00, 0xf0, 0x20, 0xe3]) # nop (ARM)
return nop * (size // 4)
def patch_function_call(self, code, base_addr, target_func, return_value):
"""Patch 函数调用,直接返回指定值"""
# 生成: mov x0, #return_value; ret
patch_asm = f"mov x0, #{return_value}; ret"
patch_bytes, _ = self.ks.asm(patch_asm)
# 查找目标函数
matches = self.find_pattern(code, base_addr, target_func)
return matches, bytes(patch_bytes)
def apply_patches(self, code, patches):
"""应用所有 Patch"""
patched = bytearray(code)
for p in patches:
offset = p['offset']
new_bytes = p['bytes']
for i, b in enumerate(new_bytes):
if offset + i < len(patched):
patched[offset + i] = b
return bytes(patched)
# 使用示例
patcher = BinaryPatcher('arm64')
# 模拟一段检测 Root 的代码
sample_code = bytes([
0xfd, 0x7b, 0xbf, 0xa9, # stp x29, x30, [sp, #-16]!
0xfd, 0x03, 0x00, 0x91, # mov x29, sp
0x00, 0x00, 0x00, 0x94, # bl check_root (占位)
0x1f, 0x00, 0x00, 0xf1, # cmp x0, #0
0x40, 0x00, 0x00, 0x54, # b.eq not_rooted
0x20, 0x00, 0x80, 0xd2, # mov x0, #1 (rooted)
0x00, 0x00, 0x00, 0x14, # b exit
0x00, 0x00, 0x80, 0xd2, # mov x0, #0 (not rooted)
0xfd, 0x7b, 0xc1, 0xa8, # ldp x29, x30, [sp], #16
0xc0, 0x03, 0x5f, 0xd6, # ret
])
# 查找 bl 指令
calls = patcher.find_pattern(sample_code, 0x1000, 'bl')
print("找到的函数调用:")
for c in calls:
print(f" 0x{c['address']:x}: {c['instruction']}")
|