简单汇编还原高级代码

汇编还原高级代码在逆向开发中是非常重要的一步,下面通过一小段高级代码生成的汇编代码,根据汇编还原高级代码,步骤及笔记如下:

原高级代码:

1
2
3
4
5
6
7
8
9
10
11
int globala = 12;
int func(int a, int b){
printf("haha");
return a + b + globala;
}
int main(int argc, char * argv[]) {
func(10,20);
return 0;
}

通过 ida 生成的汇编代码如下:

前三句不用看,是函数调用的:
1
2
3
4
5
6
7
8
9
10
11
__text:0000000100006890 _func ; CODE XREF: _main+28↓p
__text:0000000100006890
__text:0000000100006890 var_C = -0xC
__text:0000000100006890 var_8 = -8
__text:0000000100006890 var_4 = -4
__text:0000000100006890 var_s0 = 0
__text:0000000100006890
__text:0000000100006890 SUB SP, SP, #0x20
__text:0000000100006894 STP X29, X30, [SP,#0x10+var_s0]
__text:0000000100006898 ADD X29, SP, #0x10
// 开辟栈空间
下面两句是写东西,把后面的放到栈里面去:
1
2
3
4
__text:000000010000689C STUR W0, [X29,#var_4]
// int var_4 = a; 将 a 放在这个栈位置
__text:00000001000068A0 STR W1, [SP,#0x10+var_8]
// int var_8 = b; 同上
这两句是分不开的,获得一个常量或者全局变量:
1
2
3
4
// 一个常量或者全局变量
// printf("haha");
__text:00000001000068A4 ADRP X0, #aHaha@PAGE ; "haha"
__text:00000001000068A8 ADD X0, X0, #aHaha@PAGEOFF ; "haha"
调用 print 函数:
1
__text:00000001000068AC BL _printf
两句分不开的代码:
1
2
3
4
// 拿到一个全局变量放到 X30
// &globala
__text:00000001000068B0 ADRP X30, #_globala@PAGE
__text:00000001000068B4 ADD X30, X30, #_globala@PAGEOFF
拿出栈里面的东西到 W1:
1
2
// int w1 = var_4;
__text:00000001000068B8 LDUR W1, [X29,#var_4]
拿出另一个东西到 W8:
1
2
// int w8 = var_8;
__text:00000001000068BC LDR W8, [SP,#0x10+var_8]
W1 + W8这是一次运算:
1
2
// w8 = w1 + w8;
__text:00000001000068C0 ADD W8, W1, W8
将数据取到 W1:
1
2
// w1 = globala
__text:00000001000068C4 LDR W1, [X30]
后面的都是运算:
1
2
3
4
5
6
7
8
9
10
11
__text:00000001000068C8 ADD W8, W8, W1
// W8 = W8 + W1;
__text:00000001000068CC STR W0, [SP,#0x10+var_C]
// int var_C = a;
__text:00000001000068D0 MOV X0, X8
// return W8; 下面没有代码,所以这个就是返回值
__text:00000001000068D4 LDP X29, X30, [SP,#0x10+var_s0]
__text:00000001000068D8 ADD SP, SP, #0x20
// 恢复栈空间
__text:00000001000068DC RET
__text:00000001000068DC ; End of function _func

main函数的汇编代码:

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
__text:00000001000068E0 _main
__text:00000001000068E0
__text:00000001000068E0 var_14 = -0x14
__text:00000001000068E0 var_10 = -0x10
__text:00000001000068E0 var_8 = -8
__text:00000001000068E0 var_4 = -4
__text:00000001000068E0 var_s0 = 0
__text:00000001000068E0
__text:00000001000068E0 SUB SP, SP, #0x30
__text:00000001000068E4 STP X29, X30, [SP,#0x20+var_s0]
__text:00000001000068E8 ADD X29, SP, #0x20
__text:00000001000068EC MOV W8, #0xA
__text:00000001000068F0 MOV W9, #0x14
__text:00000001000068F4 STUR WZR, [X29,#var_4]
__text:00000001000068F8 STUR W0, [X29,#var_8]
__text:00000001000068FC STR X1, [SP,#0x20+var_10]
__text:0000000100006900 MOV X0, X8
__text:0000000100006904 MOV X1, X9
__text:0000000100006908 BL _func
__text:000000010000690C MOV W8, #0
__text:0000000100006910 STR W0, [SP,#0x20+var_14]
__text:0000000100006914 MOV X0, X8
__text:0000000100006918 LDP X29, X30, [SP,#0x20+var_s0]
__text:000000010000691C ADD SP, SP, #0x30
__text:0000000100006920 RET
__text:0000000100006920 ; End of function _main

下面开始还原:

已知 main 函数调用了 func 函数,通过前三句代码判断这就是一个 func 方法,从 main 方法中看出 func 方法有两个参数,X1,X0(此时此刻我们不知道参数的变量类型,从 main 函数中,X8,X9为立即数,判断,这两个变量是整型,所以可以写成 int):
1
2
3
4
5
int globala = 0; //没有办法得到全局变量的值
void func(int a, int b) {
printf("haha");
return a + b + globala;
}