【文章標題】: 失業的娛樂-IDA逆向工程入門(四)-匯編程序實戰
【文章作者】: layper
【作者郵箱】:
layper@yahoo.com.cn【作者主頁】:
http://blog.csdn.net/layper/【軟件名稱】: biatch
【下載地址】: 自己搜索下載
【使用工具】: IDA,Radasm,Resource Hacker
【作者聲明】: 只是感興趣,沒有其他目的。失誤之處敬請諸位大俠賜教!
--------------------------------------------------------------------------------
【詳細過程】
這段時間忙著學習網頁制作,剛剛初學,N多問題要學習,搞得我頭暈腦漲.現在放松一下,繼續逆向玩玩.:)
匯編程序在逆向工程中是比較簡單的一種語言,反匯編得到的代碼基本上與源碼差不多,只是稍微作點修改就可以了.前面的
幾篇都是有源碼對照的例子,這篇我們進行實戰,沒有源碼.:)
這是老外的一個工具biatch,今天拿他開刀.
IDA載入完成后,文件-創建文件-創建asm文件保存為1.asm。接著用Resource Hacker載入biatch,保存對話框資源為1.rc。
用RadASM載入1.asm,好了初步工作完成了,接下來先按照上次我寫的第三篇步驟來修改.
(一)增加模式定義\options語句\還原include\lib語句
在IDA中Shift+F7打開區段窗口接著雙擊.idata來到.idata段,
.idata:00403000 ;
.idata:00403000 ; Imports from comdlg32.dll注意這里,使用comdig32.dll
.idata:00403000 ;
.idata:00403000 ; 屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯?
.idata:00403000
.idata:00403000 ; Segment type: Externs
.idata:00403000 ; _idata
.idata:00403000 ; BOOL __stdcall GetOpenFileNameA(LPOPENFILENAMEA)
.idata:00403000 extrn __imp_GetOpenFileNameA:dword
.idata:00403000 ; DATA XREF: GetOpenFileNameAr
.idata:00403000 ; Create an Open common dialog box
.idata:00403004
.idata:00403008 ;
.idata:00403008 ; Imports from gdi32.dll注意這里,使用gdi32.dll
.idata:00403008 ;
.idata:00403008 ; HFONT __stdcall CreateFontIndirectA(const LOGFONTA *)
.idata:00403008 extrn __imp_CreateFontIndirectA:dword
.idata:00403008 ; DATA XREF: CreateFontIndirectAr
.idata:0040300C ; BOOL __stdcall DeleteObject(HGDIOBJ)
.idata:0040300C extrn __imp_DeleteObject:dword ; DATA XREF: DeleteObjectr
.idata:00403010
.idata:00403014 ;
.idata:00403014 ; Imports from kernel32.dll注意這里,使用kernel32.dll
.idata:00403014 ;
.idata:00403014 ; LPTOP_LEVEL_EXCEPTION_FILTER __stdcall SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
.idata:00403014 extrn __imp_SetUnhandledExceptionFilter:dword
.idata:00403014 ; DATA XREF: SetUnhandledExceptionFilterr
.idata:00403018 ; HANDLE GetProcessHeap(void)
.idata:00403018 extrn __imp_GetProcessHeap:dword
.idata:00403018 ; DATA XREF: GetProcessHeapr
.idata:0040301C ; BOOL __stdcall CloseHandle(HANDLE hObject)
.idata:0040301C extrn __imp_CloseHandle:dword ; DATA XREF: CloseHandler
.idata:00403020 ; HANDLE __stdcall CreateFileA(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
.idata:00403020 extrn __imp_CreateFileA:dword ; DATA XREF: CreateFileAr
.......................
........................
.idata:00403040 ; HMODULE __stdcall GetModuleHandleA(LPCSTR lpModuleName)
.idata:00403040 extrn __imp_GetModuleHandleA:dword
.idata:00403040 ; DATA XREF: GetModuleHandleAr
.idata:00403044 ; void __stdcall ExitProcess(UINT uExitCode)
.idata:00403044 extrn __imp_ExitProcess:dword ; DATA XREF: ExitProcessr
.idata:00403048 ; LPVOID __stdcall HeapAlloc(HANDLE hHeap,DWORD dwFlags,DWORD dwBytes)
.idata:00403048 extrn __imp_HeapAlloc:dword ; DATA XREF: HeapAllocr
.idata:0040304C
.idata:00403050 ;
.idata:00403050 ; Imports from user32.dll注意這里,使用user32.dll
.idata:00403050 ;
.idata:00403050 ; LONG __stdcall SetWindowLongA(HWND hWnd,int nIndex,LONG dwNewLong)
.idata:00403050 extrn __imp_SetWindowLongA:dword
.idata:00403050 ; DATA XREF: SetWindowLongAr
.................................
.idata:00403098 extrn __imp_CheckDlgButton:dword
.idata:00403098 ; DATA XREF: CheckDlgButtonr
.idata:00403098 ; Change the check state of a button control
.idata:0040309C ; LRESULT __stdcall CallWindowProcA(WNDPROC lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
.idata:0040309C extrn __imp_CallWindowProcA:dword
.idata:0040309C ; DATA XREF: CallWindowProcAr
.idata:004030A0 ; BOOL __stdcall ShowWindow(HWND hWnd,int nCmdShow)
.idata:004030A0 extrn __imp_ShowWindow:dword ; DATA XREF: ShowWindowr
.idata:004030A4 ; int wsprintfA(LPSTR,LPCSTR,...)
.idata:004030A4 extrn __imp_wsprintfA:dword ; DATA XREF: wsprintfAr
.idata:004030A8
從這里知道了用到四個dll,即comdlg32.dll、gdi32.dll、kernel32.dll、user32.dll,所以我們還原的include和includelib就要包含
這幾個dll。
所以把
.686p
.mmx
.model flat
還原成:
.686p
.mmx
.model flat,stdcall
option casemap:none
include WINDOWS.INC
include comdlg32.inc
includelib comdlg32.lib
include gdi32.inc
includelib gdi32.lib
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
刪除前面的.idata段.
(二)刪除結構
在RadASM中Ctrl+F5試著構建并運行,有錯誤提示.
D:\masm32\Include\WINDOWS.INC(9666) : error A2163: : LOGFONTA
D:\masm32\Include\WINDOWS.INC(9667) : error A2163: : LOGFONTA
D:\masm32\Include\WINDOWS.INC(9668) : error A2163: : LOGFONTA
D:\masm32\Include\WINDOWS.INC(9669) : error A2163: : LOGFONTA
D:\masm32\Include\WINDOWS.INC(9670) : error A2163: : LOGFONTA
從這里可以判斷1.asm的LOGFONTA導致出錯,刪除LOGFONTA結構(在開頭處).把tagOFNA結構移動到includelib user32.lib后面.
(三)修改移動_data段
在_text段前增加
.data
把_data全部移到.data之后
刪除_data段開頭的
_data segment para public 'DATA' use32
assume cs:_data
和_data末尾的
_data ends
注意:中間的代碼不要刪除!!!
(四)修改_text段
加上.code
_text segment para public 'CODE' use32 ;在這之前加上.code
刪除_text開頭的
_text segment para public 'CODE' use32
assume cs:_text
;org 401000h
assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
和_text末尾的
_text ends
注意:中間的代碼不要刪除!!!
(五)修改hWnd錯誤
在RadASM中Ctrl+F5試著構建并運行,有錯誤提示.
D:\crack\國外工具\tf10\1.asm(834) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(1286) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(1499) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(1640) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(2609) : error A2189: : 128
D:\crack\國外工具\tf10\1.asm(821) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(1277) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(1489) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(1629) : error A2005: : hWnd
在.data段尋找hWnd
; HWND hWnd
hWnd dd 0 ; DATA XREF: DialogFunc+241r
; DialogFunc+264w DialogFunc+26Dr
; DialogFunc+28Br DialogFunc+29Dr
; sub_401500+9r ...
這個提示兩個函數DialogFunc和sub_401500用到這個全局變量hWnd,其他函數的hWnd錯誤的地方。我們
逐條尋找出錯位置
1.asm(834) : error A2005: : hWnd
這條錯誤在
sub_401500 proc near ; CODE XREF: DialogFunc+21Fp
var_18 = dword ptr -18h
var_14 = dword ptr -14h
var_10 = dword ptr -10h
var_C = dword ptr -0Ch
hWnd = dword ptr -8 ;這里出錯,這里的局部變量hWnd與全局變量hWnd沖突,修改為hWnd1
lpMem = dword ptr -4
hDlg = dword ptr 8
在IDA中打開Functions窗口,找到sub_401500,
sub_401500 .text 00401500 00000291 R . . . B T .
雙擊來到sub_401500處
.text:00401500 sub_401500 proc near ; CODE XREF: DialogFunc+21Fp
.text:00401500
.text:00401500 var_18 = dword ptr -18h
.text:00401500 var_14 = dword ptr -14h
.text:00401500 var_10 = dword ptr -10h
.text:00401500 var_C = dword ptr -0Ch
.text:00401500 hWnd = dword ptr -8 ;修改這里為hWnd1
.text:00401500 lpMem = dword ptr -4
.text:00401500 hDlg = dword ptr 8
在hWnd上右鍵-重命名把hWnd為hWnd1.
注意:推薦在IDA里面重命名hWnd,經過修改后IDA自動識別全局變量hWnd和hWnd1比手動快,而且正確率高.
繼續查找
1.asm(1286) : error A2005: : hWnd
錯誤在
sub_401810 proc near ; CODE XREF: sub_401380+130p
hWnd = dword ptr -8 ;在IDA中修改為hWnd1
lpMem = dword ptr -4
hDlg = dword ptr 8
1.asm(1499) : error A2005: : hWnd
找到
sub_401A10 proc near ; CODE XREF: DialogFunc+233p
var_8 = dword ptr -8
hWnd = dword ptr -4 ;在IDA中修改為hWnd1
hDlg = dword ptr 8
1.asm(1640) : error A2005: : hWnd
找到
sub_401B6C proc near ; DATA XREF: DialogFunc+9Eo
; DialogFunc+CBo sub_401380+57o
hWnd = dword ptr 8 ;這個不是局部變量了
Msg = dword ptr 0Ch
wParam = dword ptr 10h
lParam = dword ptr 14h
因為這里不是局部變量了,我們先修改前面三個函數(或者子程序),sub_401500,sub_401810,sub_401A10.
保存修改后的代碼為2.asm,接著把1.asm里的sub_401500,sub_401810,sub_401A10這三個函數全部用2.asm
里的sub_401500,sub_401810,sub_401A10替換掉.
接著在RadASM中Ctrl+F5構建并運行,
D:\crack\國外工具\tf10\1.asm(1640) : error A2005: : hWnd
D:\crack\國外工具\tf10\1.asm(2609) : error A2189: : 128
D:\crack\國外工具\tf10\1.asm(1629) : error A2005: : hWnd
看來sub_401B6C的hWnd也要改掉,在IDA中修改后覆蓋到1.asm里,
D:\crack\國外工具\tf10\1.asm(2609) : error A2189: : 128
hWnd沒有出現錯誤了.
(五)刪除align
1.asm(2609) : error A2189: : 128 ;這里就是align,直接刪除了
(六)修改fs[0]
前面幾篇都沒有涉及到這個內容,這里就出現關于fs[0]的出錯代碼的修改.
D:\crack\國外工具\tf10\1.asm(1950) : error A2206:
D:\crack\國外工具\tf10\1.asm(1951) : error A2206:
D:\crack\國外工具\tf10\1.asm(1971) : error A2206:
這幾行在1.asm對應的代碼是sub_401D80中
push large dword ptr fs:0
mov large fs:0, esp
pop large dword ptr fs:0
這幾行代碼都在
D:\crack\國外工具\tf10\1.asm(2010) : error A2206:
D:\crack\國外工具\tf10\1.asm(2011) : error A2206:
D:\crack\國外工具\tf10\1.asm(2054) : error A2206:
這幾行在1.asm對應的代碼是sub_401DE0中
push large dword ptr fs:0
mov large fs:0, esp
pop large dword ptr fs:0
D:\crack\國外工具\tf10\1.asm(2422) : error A2206:
D:\crack\國外工具\tf10\1.asm(2423) : error A2206:
D:\crack\國外工具\tf10\1.asm(2478) : error A2206:
這幾行在1.asm對應的代碼是sub_402050中
push large dword ptr fs:0
mov large fs:0, esp
pop large dword ptr fs:0
D:\crack\國外工具\tf10\1.asm(2536) : error A2206:
D:\crack\國外工具\tf10\1.asm(2537) : error A2206:
D:\crack\國外工具\tf10\1.asm(2581) : error A2206:
這幾行在1.asm對應的代碼是sub_4020F0中
push large dword ptr fs:0
mov large fs:0, esp
pop large dword ptr fs:0
這幾句代碼的寫法不正確,我們把他們改為
push fs:[0]
mov fs:[0], esp
pop fs:[0]
試構建運行看看
D:\crack\國外工具\tf10\1.asm(1950) : error A2108:
D:\crack\國外工具\tf10\1.asm(1951) : error A2108:
D:\crack\國外工具\tf10\1.asm(1971) : error A2108:
D:\crack\國外工具\tf10\1.asm(2010) : error A2108:
D:\crack\國外工具\tf10\1.asm(2011) : error A2108:
D:\crack\國外工具\tf10\1.asm(2054) : error A2108:
D:\crack\國外工具\tf10\1.asm(2422) : error A2108:
D:\crack\國外工具\tf10\1.asm(2423) : error A2108:
D:\crack\國外工具\tf10\1.asm(2478) : error A2108:
D:\crack\國外工具\tf10\1.asm(2536) : error A2108:
D:\crack\國外工具\tf10\1.asm(2537) : error A2108:
D:\crack\國外工具\tf10\1.asm(2581) : error A2108:
還是提示出錯,經過認真觀察,參考了其他代碼,我在函數sub_401D80,sub_401DE0,sub_4020F0,sub_4020F0開頭處加上一句
代碼:
assume fs:nothing
查一下資料,因為MASM編譯器默認是把FS定義為error,所以在程序中要使用FS寄存器就要用
assume fs:nothing 來聲明,否則就會報錯。
構建運行
D:\masm32\BIN\ML.EXE /c /coff /Cp /nologo /I"D:\masm32\Include" "D:\crack\國外工具\tf10\1.asm"
Assembling: D:\crack\國外工具\tf10\1.asm
D:\masm32\BIN\LINK.EXE /SUBSYSTEM:WINDOWS /RELEASE /VERSION:4.0 /LIBPATH:"D:\masm32\LIB" "D:\crack\國外工具\tf10\1.obj"
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
執行:
"D:\crack\國外工具\tf10\1.exe"
構建完成.
總共編譯時間 781 毫秒
無錯誤提示,呵呵,我們逆向的代碼初步成功了.
(七)加入資源
我們試運行1.exe發現沒有出現界面,這個就是沒有把資源加回去才出現這種錯誤的.
利用Resource Hacker生成的1.rc修改后用makefile文件把資源文件編譯進去.
1.rc所做的修改如下:
增加
#include <resource.h>
刪除掉
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
makefile文件:
NAME = 1
OBJS = $(NAME).obj
RES = $(NAME).res
LINK_FLAG = /subsystem:windows
ML_FLAG = /c /coff
$(NAME).exe: $(OBJS) $(RES)
Link $(LINK_FLAG) $(OBJS) $(RES)
.asm.obj:
ml $(ML_FLAG) $<
.rc.res:
rc $<
clean:
del *.obj
del *.res
注意:這里編譯我直接用命令行形式編譯,不用RadASM.
呵呵,現在你已經擁有一份不太完善的biatch的源碼了.
匯編程序的逆向工程就告一段落了.我這里演示的只是一部分還原方法或注意事項,在實際應用當中
并不是僅僅這幾步內容(比如優化就是非常重要),這個就要多多進行練習來提高水平了。
--------------------------------------------------------------------------------
【版權聲明】: 轉載請注明作者并保持文章的完整, 謝謝!
2007年03月30日 0:46:41