安卓逆向入门-Unicorn入门

入门

安装:

1
pip install unicorn capstone

入门:

1
2
3
4
5
6
7
8
9
10
11
12
13
from unicorn import *
from unicorn.x86_const import * #32-bit x86
X86_CODE32=b"\x41\x4a" #INC ecx;DEC dex;
ADDRESS=0x1000000 #模拟运行时地址
mu=Uc(UC_ARCH_X86,UC_MODE_32) #初始化Unicorn实例 硬件架构、硬件模式
mu.mem_map(ADDRESS,2*1024*1024) #再ADDRESS处映射2MB内存空间 所有CPU操作只能访问该内存 默认权限rwx 首地址和内存长度必须为0x1000整数倍 否则抛出UC_ERR_ARG异常
mu.mem_write(ADDRESS,X86_CODE32) #代码装入分配的内存中
mu.reg_write(UC_X86_REG_ECX,0x1234) #设置寄存器值
mu.reg_write(UC_X86_REG_EDX,0x7890)
mu.emu_start(ADDRESS,ADDRESS+len(X86_CODE32)) #开始模拟 代码地址、模拟停止地址、模拟时间、模拟指令数
r_ecx=mu.reg_read(UC_X86_REG_ECX)
r_edx=mu.reg_read(UC_X86_REG_EDX)
print("ECX=0x%x,EDX=0x%x"%(r_ecx,r_edx))

Hook

Unicorn的Hook API:

1
mu.hook_add(UC_HOOK_CODE,hook_code,begin=ADDRESS,end=ADDRESS) #实现Hook函数hook_code 被Hook代码起始地址begin 被Hook代码终止地址end

在上述程序中添加Hook逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from unicorn import *
from unicorn.x86_const import *
def hook_code(mu,address,size,user_data):
print("Tracing instruction at 0x%x,instruction size=0x%x"%(address,size))
X86_CODE32=b"\x41\x4a"
ADDRESS=0x1000000
mu=Uc(UC_ARCH_X86,UC_MODE_32)
mu.mem_map(ADDRESS,2*1024*1024)
mu.mem_write(ADDRESS,X86_CODE32)
mu.reg_write(UC_X86_REG_ECX,0x1234)
mu.reg_write(UC_X86_REG_EDX,0x7890)
mu.hook_add(UC_HOOK_CODE,hook_code,begin=ADDRESS,end=ADDRESS+len(X86_CODE32))
mu.emu_start(ADDRESS,ADDRESS+len(X86_CODE32))
r_ecx=mu.reg_read(UC_X86_REG_ECX)
r_edx=mu.reg_read(UC_X86_REG_EDX)
print("ECX=0x%x,EDX=0x%x"%(r_ecx,r_edx))

实战入门

样本:https://eternal.red/assets/files/2017/UE/fibonacci。

这程序越跑越慢,用Unicorn对他进行分析优化。反汇编如下,发现调用递归Fibonacci函数,第一个参数为函数值,第二个参数为0或1,求返回值:

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
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char *v3; // rbp
int v4; // ebx
__int64 v5; // r8
char v6; // r9
__int64 v7; // r8
char v8; // cl
_DWORD v10[7]; // [rsp+Ch] [rbp-1Ch] BYREF

v3 = (char *)&unk_4007E1;
v4 = 0;
setbuf(stdout, 0LL);
printf("The flag is: ");
while ( 1 )
{
LODWORD(v5) = 0;
do
{
v10[0] = 0;
sub_400670((unsigned int)(v4 + v5), v10);
v8 = v7;
v5 = v7 + 1;
}
while ( v5 != 8 );
v4 += 8;
if ( (unsigned __int8)(v10[0] << v8) == v6 )
break;
++v3;
_IO_putc(v6 ^ (unsigned __int8)(LOBYTE(v10[0]) << v8), stdout);
}
_IO_putc(10, stdout);
return 0LL;
}
__int64 __fastcall sub_400670(int a1, _DWORD *a2)
{
int v3; // r12d
__int64 result; // rax
unsigned int v5; // esi
unsigned int v6; // esi

if ( a1 )
{
if ( a1 == 1 )
{
result = sub_400670(0LL, a2);
}
else
{
v3 = sub_400670((unsigned int)(a1 - 2), a2);
result = v3 + (unsigned int)sub_400670((unsigned int)(a1 - 1), a2);
}
v5 = (((unsigned int)result - (((unsigned int)result >> 1) & 0x55555555)) >> 2) & 0x33333333;
v6 = v5
+ ((result - (((unsigned int)result >> 1) & 0x55555555)) & 0x33333333)
+ ((v5 + (((_DWORD)result - (((unsigned int)result >> 1) & 0x55555555)) & 0x33333333)) >> 4);
*a2 ^= ((BYTE1(v6) & 0xF) + (v6 & 0xF) + (unsigned __int8)((((v6 >> 8) & 0xF0F0F) + (v6 & 0xF0F0F0F)) >> 16)) & 1;
}
else
{
*a2 ^= 1u;
return 1LL;
}
return result;
}

先尝试跑起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from unicorn import *
from unicorn.x86_const import *
import struct
def read(name):
with open(name,"rb") as f:
return f.read()
def u32(data): #4字节小端序字符串转整数
return struct.unpack("I",data)[0]
def p32(num): #整数转4字节小端序字符串
return struct.pack("I",num)
def hook_code(mu,address,size,user_data):
print("Tracing instruction at 0x%x,instruction size=0x%x"%(address,size))
mu=Uc(UC_ARCH_X86,UC_MODE_64) #x86-64
BASE=0x400000
STACK_ADDR=0x0
STACK_SIZE=1024*1024
mu.mem_map(BASE,1024*1024)
mu.mem_map(STACK_ADDR,STACK_SIZE)
mu.mem_write(BASE,read("./fibonacci"))
mu.reg_write(UC_X86_REG_RSP,STACK_ADDR+STACK_SIZE-1)
mu.hook_add(UC_HOOK_CODE,hook_code)
mu.emu_start(0x00000000004004E0,0x0000000000400575)

发现报错,原因是有些调用指令访问不到,没载入虚拟内存。

1
2
3
4
5
6
7
8
9
10
11
12
13
Tracing instruction at 0x4004e0,instruction size=0x1
Tracing instruction at 0x4004e1,instruction size=0x1
Tracing instruction at 0x4004e2,instruction size=0x2
Tracing instruction at 0x4004e4,instruction size=0x5
Tracing instruction at 0x4004e9,instruction size=0x2
Tracing instruction at 0x4004eb,instruction size=0x4
Tracing instruction at 0x4004ef,instruction size=0x7
Traceback (most recent call last):
File "demo.py", line 22, in <module>
mu.emu_start(0x00000000004004E0,0x0000000000400575)
File "D:\Python\lib\site-packages\unicorn\unicorn.py", line 547, in emu_start
raise UcError(status)
unicorn.unicorn.UcError: Invalid memory read (UC_ERR_READ_UNMAPPED)

这种代码有:

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
.text:00000000004004E0                             ; __int64 __fastcall main(int, char **, char **)
.text:00000000004004E0 main proc near ; DATA XREF: start+1D↓o
.text:00000000004004E0
.text:00000000004004E0 var_1C = dword ptr -1Ch
.text:00000000004004E0
.text:00000000004004E0 ; __unwind {
.text:00000000004004E0 000 55 push rbp
.text:00000000004004E1 008 53 push rbx
.text:00000000004004E2 010 31 F6 xor esi, esi ; buf
.text:00000000004004E4 010 BD E1 07 40 00 mov ebp, offset unk_4007E1
.text:00000000004004E9 010 31 DB xor ebx, ebx ; Logical Exclusive OR
.text:00000000004004EB 010 48 83 EC 18 sub rsp, 18h ; Integer Subtraction
.text:00000000004004EF 028 48 8B 3D 42 0B 20 00 mov rdi, cs:stdout ; stream 这里
.text:00000000004004F6 028 E8 B5 FF FF FF call _setbuf ; Call Procedure 这里
.text:00000000004004FB 028 BF D0 07 40 00 mov edi, offset format ; "The flag is: "
.text:0000000000400500 028 31 C0 xor eax, eax ; Logical Exclusive OR
.text:0000000000400502 028 E8 B9 FF FF FF call _printf ; Call Procedure 这里
.text:0000000000400507 028 41 B9 49 00 00 00 mov r9d, 49h ; 'I'
.text:000000000040050D 028 0F 1F 00 nop dword ptr [rax] ; No Operation
.text:0000000000400510
.text:0000000000400510 loc_400510: ; CODE XREF: main+8A↓j
.text:0000000000400510 028 45 31 C0 xor r8d, r8d ; Logical Exclusive OR
.text:0000000000400513 028 EB 06 jmp short loc_40051B ; Jump
.text:0000000000400513 ; ---------------------------------------------------------------------------
.text:0000000000400515 028 0F 1F 00 align 8
.text:0000000000400518
.text:0000000000400518 loc_400518: ; CODE XREF: main+67↓j
.text:0000000000400518 028 41 89 F9 mov r9d, edi
.text:000000000040051B
.text:000000000040051B loc_40051B: ; CODE XREF: main+33↑j
.text:000000000040051B 028 42 8D 3C 03 lea edi, [rbx+r8] ; Load Effective Address
.text:000000000040051F 028 48 8D 74 24 0C lea rsi, [rsp+28h+var_1C] ; Load Effective Address
.text:0000000000400524 028 C7 44 24 0C 00 00 00 00 mov [rsp+28h+var_1C], 0
.text:000000000040052C 028 E8 3F 01 00 00 call sub_400670 ; Call Procedure
.text:0000000000400531 028 8B 7C 24 0C mov edi, [rsp+28h+var_1C]
.text:0000000000400535 028 44 89 C1 mov ecx, r8d
.text:0000000000400538 028 49 83 C0 01 add r8, 1 ; Add
.text:000000000040053C 028 D3 E7 shl edi, cl ; Shift Logical Left
.text:000000000040053E 028 89 F8 mov eax, edi
.text:0000000000400540 028 44 31 CF xor edi, r9d ; Logical Exclusive OR
.text:0000000000400543 028 49 83 F8 08 cmp r8, 8 ; Compare Two Operands
.text:0000000000400547 028 75 CF jnz short loc_400518 ; Jump if Not Zero (ZF=0)
.text:0000000000400549 028 83 C3 08 add ebx, 8 ; Add
.text:000000000040054C 028 44 38 C8 cmp al, r9b ; Compare Two Operands
.text:000000000040054F 028 48 8B 35 E2 0A 20 00 mov rsi, cs:stdout ; fp 这里
.text:0000000000400556 028 74 18 jz short loc_400570 ; Jump if Zero (ZF=1)
.text:0000000000400558 028 40 0F BE FF movsx edi, dil ; c
.text:000000000040055C 028 48 83 C5 01 add rbp, 1 ; Add
.text:0000000000400560 028 E8 6B FF FF FF call __IO_putc ; Call Procedure
.text:0000000000400565 028 44 0F B6 4D FF movzx r9d, byte ptr [rbp-1] ; Move with Zero-Extend
.text:000000000040056A 028 EB A4 jmp short loc_400510 ; Jump
.text:000000000040056A ; ---------------------------------------------------------------------------
.text:000000000040056C 028 0F 1F 40 00 align 10h
.text:0000000000400570
.text:0000000000400570 loc_400570: ; CODE XREF: main+76↑j
.text:0000000000400570 028 BF 0A 00 00 00 mov edi, 0Ah ; c
.text:0000000000400575 028 E8 56 FF FF FF call __IO_putc ; Call Procedure
.text:000000000040057A 028 48 83 C4 18 add rsp, 18h ; Add
.text:000000000040057E 010 31 C0 xor eax, eax ; Logical Exclusive OR
.text:0000000000400580 010 5B pop rbx
.text:0000000000400581 008 5D pop rbp
.text:0000000000400582 000 C3 retn ; Return Near from Procedure
.text:0000000000400582 ; } // starts at 4004E0
.text:0000000000400582 main endp

.text:0000000000400670 ; __int64 __fastcall sub_400670(int, _DWORD *)
.text:0000000000400670 sub_400670 proc near ; CODE XREF: main+4C↑p
.text:0000000000400670 ; sub_400670+19↓p ...
.text:0000000000400670 ; __unwind {
.text:0000000000400670 000 85 FF test edi, edi ; Logical Compare
.text:0000000000400672 000 41 54 push r12
.text:0000000000400674 008 55 push rbp
.text:0000000000400675 010 48 89 F5 mov rbp, rsi
.text:0000000000400678 010 53 push rbx
.text:0000000000400679 018 74 7D jz short loc_4006F8 ; Jump if Zero (ZF=1)
.text:000000000040067B 018 83 FF 01 cmp edi, 1 ; Compare Two Operands
.text:000000000040067E 018 89 FB mov ebx, edi
.text:0000000000400680 018 0F 84 8A 00 00 00 jz loc_400710 ; Jump if Zero (ZF=1)
.text:0000000000400686 018 8D 7F FE lea edi, [rdi-2] ; Load Effective Address
.text:0000000000400689 018 E8 E2 FF FF FF call sub_400670 ; Call Procedure
.text:000000000040068E 018 8D 7B FF lea edi, [rbx-1] ; Load Effective Address
.text:0000000000400691 018 41 89 C4 mov r12d, eax
.text:0000000000400694 018 48 89 EE mov rsi, rbp
.text:0000000000400697 018 E8 D4 FF FF FF call sub_400670 ; Call Procedure
.text:000000000040069C 018 44 01 E0 add eax, r12d ; Add
.text:000000000040069F 018 89 C2 mov edx, eax
.text:00000000004006A1 018 89 C3 mov ebx, eax
.text:00000000004006A3 018 D1 EA shr edx, 1 ; Shift Logical Right
.text:00000000004006A5 018 81 E2 55 55 55 55 and edx, 55555555h ; Logical AND
.text:00000000004006AB 018 29 D3 sub ebx, edx ; Integer Subtraction
.text:00000000004006AD 018 89 D9 mov ecx, ebx
.text:00000000004006AF 018 89 DA mov edx, ebx
.text:00000000004006B1 018 C1 E9 02 shr ecx, 2 ; Shift Logical Right
.text:00000000004006B4 018 81 E1 33 33 33 33 and ecx, 33333333h ; Logical AND
.text:00000000004006BA 018 89 CE mov esi, ecx
.text:00000000004006BC
.text:00000000004006BC loc_4006BC: ; CODE XREF: sub_400670+C2↓j
.text:00000000004006BC 018 81 E2 33 33 33 33 and edx, 33333333h ; Logical AND
.text:00000000004006C2 018 8D 0C 16 lea ecx, [rsi+rdx] ; Load Effective Address
.text:00000000004006C5 018 89 CA mov edx, ecx
.text:00000000004006C7 018 C1 EA 04 shr edx, 4 ; Shift Logical Right
.text:00000000004006CA 018 01 CA add edx, ecx ; Add
.text:00000000004006CC 018 89 D6 mov esi, edx
.text:00000000004006CE 018 81 E2 0F 0F 0F 0F and edx, 0F0F0F0Fh ; Logical AND
.text:00000000004006D4 018 C1 EE 08 shr esi, 8 ; Shift Logical Right
.text:00000000004006D7 018 81 E6 0F 0F 0F 00 and esi, 0F0F0Fh ; Logical AND
.text:00000000004006DD 018 8D 0C 16 lea ecx, [rsi+rdx] ; Load Effective Address
.text:00000000004006E0 018 89 CA mov edx, ecx
.text:00000000004006E2 018 C1 EA 10 shr edx, 10h ; Shift Logical Right
.text:00000000004006E5 018 01 CA add edx, ecx ; Add
.text:00000000004006E7 018 83 E2 01 and edx, 1 ; Logical AND
.text:00000000004006EA 018 31 55 00 xor [rbp+0], edx ; Logical Exclusive OR
.text:00000000004006ED 018 5B pop rbx
.text:00000000004006EE 010 5D pop rbp
.text:00000000004006EF 008 41 5C pop r12
.text:00000000004006F1 000 C3 retn ; Return Near from Procedure
.text:00000000004006F1 ; ---------------------------------------------------------------------------
.text:00000000004006F2 000 66 0F 1F 44 00 00 align 8
.text:00000000004006F8
.text:00000000004006F8 loc_4006F8: ; CODE XREF: sub_400670+9↑j
.text:00000000004006F8 018 BA 01 00 00 00 mov edx, 1
.text:00000000004006FD 018 31 55 00 xor [rbp+0], edx ; Logical Exclusive OR
.text:0000000000400700 018 B8 01 00 00 00 mov eax, 1
.text:0000000000400705 018 5B pop rbx
.text:0000000000400706 010 5D pop rbp
.text:0000000000400707 008 41 5C pop r12
.text:0000000000400709 000 C3 retn ; Return Near from Procedure
.text:0000000000400709 ; ---------------------------------------------------------------------------
.text:000000000040070A 000 66 0F 1F 44 00 00 align 10h
.text:0000000000400710
.text:0000000000400710 loc_400710: ; CODE XREF: sub_400670+10↑j
.text:0000000000400710 018 31 FF xor edi, edi ; Logical Exclusive OR
.text:0000000000400712 018 E8 59 FF FF FF call sub_400670 ; Call Procedure
.text:0000000000400717 018 89 C2 mov edx, eax
.text:0000000000400719 018 89 C7 mov edi, eax
.text:000000000040071B 018 D1 EA shr edx, 1 ; Shift Logical Right
.text:000000000040071D 018 81 E2 55 55 55 55 and edx, 55555555h ; Logical AND
.text:0000000000400723 018 29 D7 sub edi, edx ; Integer Subtraction
.text:0000000000400725 018 89 FE mov esi, edi
.text:0000000000400727 018 89 FA mov edx, edi
.text:0000000000400729 018 C1 EE 02 shr esi, 2 ; Shift Logical Right
.text:000000000040072C 018 81 E6 33 33 33 33 and esi, 33333333h ; Logical AND
.text:0000000000400732 018 EB 88 jmp short loc_4006BC ; Jump
.text:0000000000400732 ; } // starts at 400670
.text:0000000000400732 sub_400670 endp

对这些指令Hook以下,直接修改RIP,执行后面的指令。而且打印字符时调用的glibc库也没加载入虚拟内存,也需要Hook:

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
from unicorn import *
from unicorn.x86_const import *
import struct
def read(name):
with open(name,"rb") as f:
return f.read()
def u32(data): #4字节小端序字符串转整数
return struct.unpack("I",data)[0]
def p32(num): #整数转4字节小端序字符串
return struct.pack("I",num)
instructions_skip_list=[0x00000000004004EF,0x00000000004004F6,0x0000000000400502,0x000000000040054F]
FIBONACCI_ENTRY=0x0000000000400670
FIBONACCI_END=[0x00000000004006F1,0x0000000000400709]
stack=[]
d={}
def hook_code(mu,address,size,user_data):
print("Tracing instruction at 0x%x,instruction size=0x%x"%(address,size))
if address in instructions_skip_list:
mu.reg_write(UC_X86_REG_RIP,address+size)
elif address==0x0000000000400560:
c=mu.reg_read(UC_X86_REG_RDI)
print(chr(c))
mu.reg_write(UC_X86_REG_RIP,address+size)
elif address==FIBONACCI_ENTRY:
arg0=mu.reg_read(UC_X86_REG_RDI)
r_rsi=m.reg_read(UC_X86_REG_RSI)
arg1=u32(mu.mem_read(r_rsi,4))
if (arg0,arg1) in d:
(ret_rax,ret_ref)=d[(arg0,arg1)]
mu.reg_write(UC_X86_REG_RAX,ret_rax)
mu.mem_write(r_rsi,p32(ret_ref))
mu.reg_write(UC_X86_REG_RIP,0x0000000000400582)
else:
stack.append((arg0,arg1,r_rsi))
elif address in FIBONACCI_END:
(arg0,arg1,r_rsi)=stack.pop()
ret_rax=mu.reg_read(UC_X86_REG_RAX)
ret_ref=u32(mu.mem_read(r_rsi,4))
d[(arg0,arg1)]=(ret_rax,ret_ref)
mu=Uc(UC_ARCH_X86,UC_MODE_64) #x86-64
BASE=0x400000
STACK_ADDR=0x0
STACK_SIZE=1024*1024
mu.mem_map(BASE,1024*1024)
mu.mem_map(STACK_ADDR,STACK_SIZE)
mu.mem_write(BASE,read("./fibonacci"))
mu.reg_write(UC_X86_REG_RSP,STACK_ADDR+STACK_SIZE-1)
mu.hook_add(UC_HOOK_CODE,hook_code)
mu.emu_start(0x00000000004004E0,0x0000000000400575)

一定要在Linux下尝试运行,Windows下在修改RIP后会出错。

ARM

下载交叉编译器:https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads。

编译HelloWorld:

1
2
3
4
5
#include <stdio.h>
int main(void){
printf("Hello world");
return 0;
};

编译:

1
2
arm-none-linux-gnueabihf-gcc ./helloworld.c -fPIC -marm -shared -o ./libhello.so
readelf -h ./libhello.so

生成为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.text:000003C0                             ; int __fastcall main(int argc, const char **argv, const char **envp)
.text:000003C0 EXPORT main
.text:000003C0 main ; DATA XREF: LOAD:000001AC↑o
.text:000003C0 000 00 48 2D E9 PUSH {R11,LR} ; Push registers
.text:000003C4 008 04 B0 8D E2 ADD R11, SP, #4 ; Rd = Op1 + Op2
.text:000003C8 008 14 30 9F E5 LDR R3, =(aHelloWorld - 0x3D4) ; Load from Memory
.text:000003CC 008 03 30 8F E0 ADD R3, PC, R3 ; Rd = Op1 + Op2
.text:000003D0 008 03 00 A0 E1 MOV R0, R3 ; format
.text:000003D4 008 C1 FF FF EB BL printf ; Branch with Link
.text:000003D8 008 00 30 A0 E3 MOV R3, #0 ; Rd = Op2
.text:000003DC 008 03 00 A0 E1 MOV R0, R3 ; Rd = Op2
.text:000003E0 008 00 88 BD E8 POP {R11,PC} ; Pop registers
.text:000003E0 ; End of function main
.text:000003E0
.text:000003E0 ; ---------------------------------------------------------------------------
.text:000003E4 AC 00 00 00 off_3E4 DCD aHelloWorld - 0x3D4 ; DATA XREF: main+8↑r
.text:000003E4 ; .text ends ; "Hello world"

用Unicorn调试.so文件:

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
from unicorn import *
from unicorn.arm_const import *
from capstone import *
from capstone.arm import *
def hook_code(mu,address,size,user_data):
inst_code=mu.mem_read(address,size)
for inst in cs.disasm(inst_code,size):
print("0x%x:\t%s\t%s"%(address,inst.mnemonic,inst.op_str))
if address==0x000003D4:
result=mu.mem_read(mu.reg_read(UC_ARM_REG_R3),16)
print("result:",result.decode(encoding="utf-8"))
mu.reg_write(UC_ARM_REG_PC,0x000003E0)
uc=Uc(UC_ARCH_ARM,UC_MODE_ARM) #此处ARM32 还有UC_ARCH_ARM64 ARM32有UC_MODE_ARM和UC_MODE_THUMB两种模式
base=0x00000000
code_size=8*0x1000*0x1000
uc.mem_map(base,code_size)
stack_addr=base+code_size
stack_size=0x1000
stack_top=stack_addr+stack_size-0x8
uc.mem_map(stack_addr,stack_size)
fd=open("./libhello2.so","rb")
SO_DATA=fd.read()
uc.mem_write(base,SO_DATA)
start_base=base+0x000003C0
end_addr=base+0x000003E0
uc.reg_write(UC_ARM_REG_SP,stack_top)
cs=Cs(CS_ARCH_ARM,CS_MODE_ARM)
uc.hook_add(UC_HOOK_CODE,hook_code,begin=start_base,end=end_addr)
uc.emu_start(start_base,end_addr)

OLLVM脱壳

先搁着,官方OLLVM基于LLVM4,早就过时了。Github上有基于LLVM17的移植版,自己手动该代码移植还怪麻烦的,而且也没有预编译版。