准备
- 首先我们准备一个工程
- 添加一些简单的函数调用,最基本的运算
- Bulid得到一个app包
- 将app包里面的MachO文件放入到ida中分析汇编(ida去网上找资源)
- 初步的将汇编还原成高级代码
操作
1.创建工程名字就叫:还原高级代码
2.添加函数、运算
3.Bulid得到得到app包
4.将App包中的MachO文件放入到ida进行解析,生成汇编代码
汇编、源代码
汇编
__text:0000000100006228 _func ; CODE XREF: _main+28↓p
__text:0000000100006228
__text:0000000100006228 var_C = -0xC
__text:0000000100006228 var_8 = -8
__text:0000000100006228 var_4 = -4
__text:0000000100006228 var_s0 = 0
__text:0000000100006228
__text:0000000100006228 SUB SP, SP, #0x20
__text:000000010000622C STP X29, X30, [SP,#0x10+var_s0]
__text:0000000100006230 ADD X29, SP, #0x10
__text:0000000100006234 STUR W0, [X29,#var_4]
__text:0000000100006238 STR W1, [SP,#0x10+var_8]
__text:000000010000623C ADRP X0, #aHaha@PAGE ; "haha"
__text:0000000100006240 ADD X0, X0, #aHaha@PAGEOFF ; "haha"
__text:0000000100006244 BL _printf
__text:0000000100006248 ADRP X30, #_number@PAGE
__text:000000010000624C ADD X30, X30, #_number@PAGEOFF
__text:0000000100006250 LDUR W1, [X29,#var_4]
__text:0000000100006254 LDR W8, [SP,#0x10+var_8]
__text:0000000100006258 ADD W8, W1, W8
__text:000000010000625C LDR W1, [X30]
__text:0000000100006260 ADD W8, W8, W1
__text:0000000100006264 STR W0, [SP,#0x10+var_C]
__text:0000000100006268 MOV X0, X8
__text:000000010000626C LDP X29, X30, [SP,#0x10+var_s0]
__text:0000000100006270 ADD SP, SP, #0x20
__text:0000000100006274 RET
__text:0000000100006274 ; End of function _func
源代码
int number = 30;
int func(int a, int b){
printf("haha");
return a + b + number;
}
int main(int argc, char * argv[]) {
printf("%d",func(1, 2));
return 0;
}
汇编分析
- 定义的4个变量 将一些偏移量存起来,方便观看
__text:0000000100006228 var_C = -0xC
__text:0000000100006228 var_8 = -8
__text:0000000100006228 var_4 = -4
__text:0000000100006228 var_s0 = 0 - 下面三句拉伸栈空间
__text:0000000100006278 SUB SP, SP, #0x30
__text:000000010000627C STP X29, X30, [SP,#0x20+var_s0]
__text:0000000100006280 ADD X29, SP, #0x20 - 将w0 w1 放入栈
__text:0000000100006234 STUR W0, [X29,#var_4]
__text:0000000100006238 STR W1, [SP,#0x10+var_8] - 获取一个常量或者全局变量
__text:000000010000623C ADRP X0, #aHaha@PAGE ; "haha"
__text:0000000100006240 ADD X0, X0, #aHaha@PAGEOFF ; "haha" - 打印这个常量或者全局变量
__text:0000000100006244 BL _printf - 获取一个常量或者全局变量
__text:0000000100006248 ADRP X30, #_number@PAGE
__text:000000010000624C ADD X30, X30, #_number@PAGEOFF - 一个变量
__text:0000000100006250 LDUR W1, [X29,#var_4] - 一个变量
__text:0000000100006254 LDR W8, [SP,#0x10+var_8] - 运算 +
__text:0000000100006258 ADD W8, W1, W8 - 一个变量
__text:000000010000625C LDR W1, [X30] - 运算 +
__text:0000000100006260 ADD W8, W8, W1 - 将w0存入到栈
__text:0000000100006264 STR W0, [SP,#0x10+var_C] - x0 = x8
__text:0000000100006268 MOV X0, X8 - 读取回家的路 栈底fp以及lr
__text:000000010000626C LDP X29, X30, [SP,#0x10+var_s0] - 将栈空间收回 用之前需要拉伸、 用完需要恢复
__text:0000000100006270 ADD SP, SP, #0x20 - 返回main函数
__text:0000000100006274 RET
进一步简化
-
因为一开始就知道func函数,并且在main的汇编当中我们看到 w8 = #1 w9 = #2 w0 = w8 w1 = w9 所以判定有两个参数
func(int a, int b){
} - STUR W0, [X29,#var_4] STR W1, [SP,#0x10+var_8] 存入栈两个参数 就是两个变量 main 中w8 = #1 w9 = #2 w0 = w8 w1 = w9
int var_4 = a;
int var_8 = b; - ADRP X0, #aHaha@PAGE ; "haha" ADD X0, X0, #aHaha@PAGEOFF ; "haha" BL _printf
printf("haha"); - ADRP X30, #_number@PAGE ADD X30, X30, #_number@PAGEOFF 拿到的是&number 因为下面的 LDR W1, [X30],ADD W8, W8, W1 w8 == var_8 var_8 == b b 是int 所以 _number 是int类型
_number 是全局变量
int number; &number - LDUR W1, [X29,#var_4]
int w1 = var_4 - LDR W8, [SP,#0x10+var_8]
int w8 = var_8 - ADD W8, W1, W8
w8 = w1 + w8 - LDR W1, [X30]
w1 = number - ADD W8, W8, W1
w8 = W8 + W1 - W0, [SP,#0x10+var_C]
int var_c = a; - MOV X0, X8 保存返回值
return x8;
初步还原的代码
int number;
func(int a, int b){
int var_4 = a;
int var_8 = b;
printf("haha");
int w1 = var_4;
int w8 = var_8;
w8 = w1 + w8;
w1 = number;
w8 = W8 + W1;
int var_c = a;
return x8;
}
最简化
最终
int number;
func(int a, int b){
printf("haha");
return a + b + number;
}
原码
>int number = 30;
int func(int a, int b){
printf("haha");
return a + b + number;
}
int main(int argc, char * argv[]) {
printf("%d",func(1, 2));
return 0;
}
结论
问题
-
怎么确定func是否有返回值?
因为int var_c = a; W0, [SP,#0x10+var_C] 这句话,w0都是返回值,如果没有retrun 为什么多此一举呐? -
为什么有返回值在main函数中调用玩func没有调用w0这个返回值呐?
因为大家在写代码的时候,函数有返回值,但是我们调用的时候没用,就会出现这个问题。 -
Number的值拿不到吗?
因为系统知道静态变量的值,不需要我们做操作,就好比,为什么拉伸栈空间的时候函数一开始的栈起始位置是多少?因为系统知道,并且我们知道这个是一个值就OK,当成一个常量,只不过不知道它的值
网友评论