但開源的程序畢竟是在少數,大多數程序都只會分發可執行文件及相關文件,這時我們要想查看此程序的代碼,就只有把它反匯編,當然這需要壹定的匯編功底,但是壹個好的反匯編工具能為妳閱讀反匯編出來的程序提供非常大的幫助。
了解反匯編的朋友也壹定知道WINDASM這個有名的反匯編工具,比如我們用WINDASM反匯編壹個程序,在其程序入口點反匯編得到如下代碼:
//*********************** Program Entry Point *****************
:00401000 6A00 push 00000000
:00401002 E8FF050000 call 00401606
:00401007 A316304000 mov [00403016], eax
:00401007 E8EF050000 call 00401600
:00401011 A30E304000 mov [0040300E],八臺連線機, eax
:00401016 6A0A push 0000000A
:00401018 FF350E304000 push dword ptr [0040300E]
:0040101E 6A00 push 00000000
:00401020 EF3516304000 push dword ptr [00403016]
:00401026 E806000000 call 00401031
:0040102B 50 push eax
:0040102c E8C9050000 call 004015FA
如果不聯系上下文及知道這是程序入口的話,很難看出來這壹段代碼到底是幹什麽的,但IDA就不壹樣了,它不但會反匯編程序,並會盡量分析程序,並加上相應的註釋(正因為這樣,IDA反匯編壹個大的程序會花非常長的時間),請看下面壹段IDA反匯編出來的代碼,是不是明了多了?
.text:00401000 push 0 ; lpModuleName
.text:00401002 call GetModuleHandleA
.text:00401007 mov hInstance, eax
.text:0040100C call GetCommandLineA
.text:00401011 mov dword_0_40300E,瑪莉機, eax
.text:00401016 push 0Ah
.text:00401018 push dword_0_40300E
.text:0040101E push 0
.text:00401020 push hInstance
.text:00401026 call sub_0_401031
.text:0040102B push eax ; uExitCode
.text:0040102C call ExitProcess
IDA反匯編程序後,會生成壹個 .idb文件,裏面保存了反匯編出來的代碼及註釋及IDA的壹些其它相關數據,我們可以直接在IDA中寫自己的分析結果和註釋並保存,下次直接打開.idb文件就可以了,例如上面
.text:00401000 push 0 ; lpModuleName
.text:00401002 call GetModuleHandleA
.text:00401007 mov hInstance, eax
我們可以看出來實際上就是hInstance = GetModuleHandleA(nil);我們可以在後面直接加上註釋,在.text:00401007這壹行最後面的空白處點右鍵,在彈出的菜單中選擇"註釋",然後在彈出的窗口中填上"取得當前模塊實例句柄",這壹行就會變為
.text:00401007 mov hInstance, eax ; 取得當前模塊實例句柄
這樣就為我們的反匯編出的代碼增加了可讀性.
IDA不但可以在當前代碼中加註釋,還可以更改其默認的符號名,比如
.text:00401011 mov dword_0_40300E, eax
其中的dwrd_0_40300E可以看出來是存放取得的命令行的緩沖區指針(可以雙擊符號名,函數名跳到其定義處),在dword_0_40300E上面點右鍵,選取"重命名",然後在彈出的窗口中填入lpCommandline,點確定,這樣程序中所有使用到了dword_0_40300E這個變量的地方都會將dword_0_40300E替換為lpCommandline.如下所示:
.text:00401011 mov lpCommandline, eax
.text:00401016 push 0Ah
.text:00401018 push lpCommandline
我們再來看.text:00401026 call sub_0_401031這壹行
可以從上面的代碼看出來,這是調用的WinMain函數,在sub_0_401031上面點右鍵,選取"重命名",然這個函數命名為WinMain,這時IDA就將所有sub_0_401031符號變為WinMain, 並且自動加上函數定義,並會在函數調用時入棧的參數後面加上其對應的變量註釋,這時我們反匯編出來的這壹段代碼就成了下面這個樣子的了:
.text:00401000 start proc near
.text:00401000 push 0 ; lpModuleName
.text:00401002 call GetModuleHandleA
.text:00401007 mov hInstance, eax ; 取得當前模塊實例句柄
.text:0040100C call GetCommandLineA
.text:00401011 mov lpCommandline, eax
.text:00401016 push 0Ah ; nShowCmd
.text:00401018 push lpCommandline ; lpCmdLine
.text:0040101E push 0 ; hPrevInstance
.text:00401020 push hInstance ; hInstance
.text:00401026 call WinMain
.text:0040102B push eax ; uExitCode
.text:0040102C call ExitProcess
是不是壹目了解了呢?
當我們通過閱讀源碼,能確定某壹個子函數的作用及傳入的參數類型時,我們可以雙擊這個函數名,跳到函數定義處,在函數定義處點右鍵,使用"設置函數類型"功能來編輯函數定義(C++語法),這樣所有調用到這個函數的地方都會在入棧的參數後面加上其對應的變量註釋. 還可以通過在函數定義處後面空白處點右鍵加上"可重復註釋",這樣所有調用此函數的地方都會在後面加上這個重復的註釋.
如果想查看某個變量或函數被調用的情況,搖擺機生產,可以通過在函數或變量名上點右鍵,點擊"查看操作數交叉索引處"功能,就可以在打開的窗口中查看到所有調用其的代碼,並可通過雙擊跳到這段代碼處.這是壹個很有用的功能,能幫助妳快速的搞清函數及變量的調用關系.
按下F12還可以查看到程序的流程圖,搖擺機廠家,CTRL+12可以查看到函數的調用圖.
IDA還擁有符號調試技術,能識別常見編釋器編釋的程序,例如下面反匯編出的VC6.0的程序代碼段:
.text:00405427 push edx
.text:00405428 call _swscanf
.text:0040542D lea eax, [esp+38h+arg_40]
.text:00405431 push offset unk_0_5DB1A4 ; const wchar_t *
.text:00405436 push eax ; const wchar_t *
.text:00405437 call _wcscmp
.text:0040543C add esp, 1Ch
.text:0040543F test eax, eax
.text:00405441 jz short loc_0_405459
.text:00405443 lea ecx, [esp+24h+arg_40]
.text:00405447 push offset unk_0_5DB18C ; const wchar_t *
.text:0040544C push ecx ; const wchar_t *
.text:0040544D call _wcscmp
就檢查到了其調用了MFC類庫中的函數,並把它們替換成了相應的函數名.
還可以調用IDA導出.MAP文件,來配合其它動態調試工具如SOFT-ICE來進行代碼分析.
IDA是壹個非常強大的反匯編工具,這裏只是討論了壹下它的壹些基本的應用,希望能起到拋磚引玉的作用