IDA反彙編工具初探

看過<<笑傲江湖>>的朋友一定知道吸星大法吧,這是一種可以吸取他人內功來使自己功力增長的神功,(段譽的北冥神功也是這樣, 扯遠了...).對於程序員來說,增長自己編程功力的一個好方法是閱讀其它人開發的程序的源碼,從而把別人的技術來消化成爲自己知識,這是不是很象吸星大法?
但開源的程序畢竟是在少數,大多數程序都只會分發可執行文件及相關文件,這時我們要想查看此程序的代碼,就只有把它反彙編,當然這需要一定的彙編功底,但是一個好的反彙編工具能爲你閱讀反彙編出來的程序提供非常大的幫助.
瞭解反彙編的朋友也一定知道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是一個非常強大的反彙編工具,這裏只是討論了一下它的一些基本的應用,希望能起到拋磚引玉的作用,如果對IDA應用有興趣的朋友可以來信討論,或參考段鋼先生的<<加密與解密>>一書,裏面對IDA的應用有較祥細的講解.
我的Mail:[email protected]

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