今天逆向並找出循環的特徵。包括常見的 for、while、do-while、break、continue。今天換一套逆向工具,使用 Hopper Disassembler 來逆向程式。
透過 cmp, jl 與 add 這三個指令達成 for 迴圈的效果(下圖綠色、藍色交互箭頭即為判斷是否滿足 for 迴圈條件)。
解答公布:
#include<stdio.h>
int main(void){
int num1 = 16;
int num2 = 32;
for(num1; num1 < num2; num1++){
printf("Hello, world!\n");
}
return 0;
}
跟 for 迴圈架構很相似。但只有 cmp 與 jle 而並沒有 add。符合條件則 call 0x1050 (就是printf()),反之則跳出迴圈。
解答公布:
#include<stdio.h>
int main(void){
int num1 = 16;
while(num1 < 32){
printf("Hello, world\n");
}
return 0;
}
先執行一次 call,接下來比較 rbp+var_4 與 0x1f 的大小。若小於成立,則呼叫 loc_115c,直到條件不成立則跳出迴圈。
解答公布:
#include<stdio.h>
int main(void){
int num = 16;
do{
printf("Hello, world!\n");
} while (num < 32);
return 0;
}
雖然程式碼是寫 i==5 ,不過其實會先判斷 i 是否 <= 5。若成立,再區分是否等於5。若等於5,則跳到 nop,程式不執行,最後跳出迴圈。
解答公布:
#include<stdio.h>
int main(void){
for(int i=0; i<= 10; i++){
if(i == 5){
break;
}
printf("The number is %d\n", i);
}
return 0;
}
continue 是忽略該次(i == 5)迴圈以下的動作,並繼續執行下一次迴圈。透過程式不難發現,continue 與 break 都是透過跳到 nop 告訴程式不要執行接下來的指令。差異在 break nop 完後就是接 return ,相對的,continue nop 完後接的是 add,繼續跑迴圈。
解答公布:
#include<stdio.h>
int main(void){
for(int i=0; i <= 10; i++){
if(i == 5){
continue;
}
printf("The number is %d\n", i);
}
return 0;
}
今天介紹循環的特徵,很好認,只要看到反組譯後箭頭往回跑(圖型有環產生)就知道該程式有用到循環式。明日接著介紹呼叫函式時會有什麼特徵!