程序员的吸星大法-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:akunspy@sina.com
總結
以上是生活随笔為你收集整理的程序员的吸星大法-IDA反汇编工具初探的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用ida对程序的静态链接库进行处理
- 下一篇: 十招教你学会软件破解(转)