準(zhǔn)備
- 首先我們準(zhǔn)備一個(gè)工程
- 添加一些簡(jiǎn)單的函數(shù)調(diào)用狐赡,最基本的運(yùn)算
- Bulid得到一個(gè)app包
- 將app包里面的MachO文件放入到ida中分析匯編(ida去網(wǎng)上找資源)
- 初步的將匯編還原成高級(jí)代碼
操作
1.創(chuàng)建工程名字就叫:還原高級(jí)代碼
2.添加函數(shù)、運(yùn)算
3.Bulid得到得到app包
4.將App包中的MachO文件放入到ida進(jìn)行解析疟丙,生成匯編代碼
匯編颖侄、源代碼
匯編
__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個(gè)變量 將一些偏移量存起來,方便觀看
__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] - 獲取一個(gè)常量或者全局變量
__text:000000010000623C ADRP X0, #aHaha@PAGE ; "haha"
__text:0000000100006240 ADD X0, X0, #aHaha@PAGEOFF ; "haha" - 打印這個(gè)常量或者全局變量
__text:0000000100006244 BL _printf - 獲取一個(gè)常量或者全局變量
__text:0000000100006248 ADRP X30, #_number@PAGE
__text:000000010000624C ADD X30, X30, #_number@PAGEOFF - 一個(gè)變量
__text:0000000100006250 LDUR W1, [X29,#var_4] - 一個(gè)變量
__text:0000000100006254 LDR W8, [SP,#0x10+var_8] - 運(yùn)算 +
__text:0000000100006258 ADD W8, W1, W8 - 一個(gè)變量
__text:000000010000625C LDR W1, [X30] - 運(yùn)算 +
__text:0000000100006260 ADD W8, W8, W1 - 將w0存入到棧
__text:0000000100006264 STR W0, [SP,#0x10+var_C] - x0 = x8
__text:0000000100006268 MOV X0, X8 - 讀取回家的路 棧底fp以及l(fā)r
__text:000000010000626C LDP X29, X30, [SP,#0x10+var_s0] - 將椑雷妫空間收回 用之前需要拉伸、 用完需要恢復(fù)
__text:0000000100006270 ADD SP, SP, #0x20 - 返回main函數(shù)
__text:0000000100006274 RET
進(jìn)一步簡(jiǎn)化
-
因?yàn)橐婚_始就知道func函數(shù)炊琉,并且在main的匯編當(dāng)中我們看到 w8 = #1 w9 = #2 w0 = w8 w1 = w9 所以判定有兩個(gè)參數(shù)
func(int a, int b){
} - STUR W0, [X29,#var_4] STR W1, [SP,#0x10+var_8] 存入棧兩個(gè)參數(shù) 就是兩個(gè)變量 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 因?yàn)橄旅娴? 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;
}
最簡(jiǎn)化
最終
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;
}
結(jié)論
問題
怎么確定func是否有返回值锰悼?
因?yàn)閕nt var_c = a; W0, [SP,#0x10+var_C] 這句話,w0都是返回值团赏,如果沒有retrun 為什么多此一舉吶箕般?為什么有返回值在main函數(shù)中調(diào)用玩func沒有調(diào)用w0這個(gè)返回值吶?
因?yàn)榇蠹以趯懘a的時(shí)候舔清,函數(shù)有返回值丝里,但是我們調(diào)用的時(shí)候沒用,就會(huì)出現(xiàn)這個(gè)問題体谒。Number的值拿不到嗎杯聚?
因?yàn)橄到y(tǒng)知道靜態(tài)變量的值,不需要我們做操作抒痒,就好比幌绍,為什么拉伸棧空間的時(shí)候函數(shù)一開始的棧起始位置是多少?因?yàn)橄到y(tǒng)知道傀广,并且我們知道這個(gè)是一個(gè)值就OK痢虹,當(dāng)成一個(gè)常量,只不過不知道它的值