反編譯實例1:helloworld

第一階段:從源代碼到可執行程序

第一個helloworld程序:

#include <stdio.h>

int main(int argc, char** argv)
{
printf("hello world\n");
return 0;

}
編譯接生成可執行程序(armcc helloworld -o helloworld.axf):
默認生成的可執行文件爲__image.axf,這裏指定了生成的可執行文件名helloworld.axf,需要注意的是這一步同時生成了一箇中間文件helloworld.o。

注意:直接運行.axf文件顯然是行不通的,這裏需要藉助ads提供的調試工具AXD,當然在使用之前需要進行簡單的配置,設定目標環境optition->Configure Target如圖一:


然後File->Load Image選擇helloworld.axf,如圖二:


點擊Go運行,執行結果如圖三:


當然,在字符下運行程序也是可以的(armsd -ARMUL -EXEC helloworld.axf),運行結果如圖四:


第二階段:從目標文件到源代碼

使用IDA打開helloworld.o,如圖五:


我們可以非常簡單的看到main函數以及printf函數,只不過printf是以_printf的形式出現,不過我們可能首先比較疑惑的一點就是:helloworld字符串在哪裏?從調用_printf前的參數傳遞可以簡單分析得出dword_14應該就是helloworld字符串的地址了,我們調整IDA的數據顯示,把dword_14處的四字節數據改爲單字節數據,顯示結果如圖六:


可以非常清晰的看出"hello world"字符串了。

接下來,我們開始分析彙編文件(在分析彙編之前最好熟悉一下彙編指令,否則逢指令就查還是挺耽誤時間的),通過指令查找分析每一步的作用,註釋如圖七:


從彙編指令內容分析,main函數沒僅僅調用printf輸出了一個"hello world\n"字符串,而且這個字符串沒有進行變量定義的字符串,最後通過給R0賦值0當做main返回值。
因此我們可以可以進行簡單的書寫C源代碼helloworldnew.c如下:
#include <stdio.h>

int main(int argc, char** argv)
{
printf("hello world\n");
return 0;
}

armcc helloworldnew.c -o helloworldnew.axf生成可執行文件,並用IDA打開對應的helloworldnew.o文件,導出.asm文件,與之前IDA打開的helloworld.o導出的helloworld.asm使用beyond compare進行對比,比較結果如圖八:


從圖中可以看出,除了文件名上有所不同,其餘的數據和指令是完全一樣的。當然後續可能會明白,想要完全一致基本是不可能的,只能儘量的語義一致。

執行結果如圖九:

到這裏,整個反編譯過程基本就結束了。

當然,你可以嘗試一下如下的操作:

1、新的C源代碼定義一個字符串並把"hello world\n"賦給該字符串指針,查看編譯生成的.o的彙編代碼;

2、函數的返回只修改一下,查看彙編代碼;

1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章