【文章標題】:?失業的娛樂-IDA逆向工程入門(三)-匯編程序(2)
【文章作者】:?layper
【作者郵箱】:?layper@yahoo.comcn
【作者主頁】:?http://blog.csdn.net/layper/
【下載地址】:?自己搜索下載
【編寫語言】:?asm
【使用工具】:?IDA\reshack\radasm\
【作者聲明】:?只是感興趣,沒有其他目的。失誤之處敬請諸位大俠賜教!
--------------------------------------------------------------------------------
【詳細過程】
??多謝大家的支持,特別是fly還關心我的工作問題,無已回報,只能繼續寫些小文供大家批評了!!!
??
??上一篇我們所逆的是非常簡單的win32匯編,總共才兩個api函數,一個消息框和ExitProcess函數,這篇我們就涉及一個真正的窗口
??程序firstwindows,我學匯編是看了羅云彬的《windows環境下匯編語言程序設計》才入門的,我直接拿里面的例子來講吧,如果作
??者覺得不合適,我會刪去的!!!!!
??
??順便講一下學習逆向工程的方法,這個跟學脫殼方法類似,你先用一種語言寫一個程序(剛開始比較簡單的),編譯后用IDA或者
??其他工具反匯編,觀察源代碼和反匯編代碼有什么異同,想辦法在逆向代碼中逐漸靠近源代碼,最后再把他整理到編譯工具中不
??斷編譯,在編譯器中看那里出錯,逐步修改,直至成功,最后總結經驗,這樣就會逐步提高了.
??
??限于篇幅,我只把完整源碼貼出來,未修改的反匯編在壓縮包內的1.asm,請自行查看
??firstwindows源碼
??
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??;?Sample?code?for?<?Win32ASM?Programming?>
??;?by?羅云彬,?http://asm.yeah.net
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??;?FirstWindow.asm
??;?窗口程序的模板代碼
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??;?使用?nmake?或下列命令進行編譯和鏈接:
??;?ml?/c?/coff?FirstWindow.asm
??;?Link?/subsystem:windows?FirstWindow.obj
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??????.386
??????.model?flat,stdcall
??????option?casemap:none
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??;?Include?文件定義
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??include????windows.inc
??include????gdi32.inc
??includelib??gdi32.lib
??include????user32.inc
??includelib??user32.lib
??include????kernel32.inc
??includelib??kernel32.lib
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??;?數據段
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??????.data?
??
??hInstance??dd?????
??hWinMain??dd?????
??
??????.const
??
??szClassName??db??'MyClass',0
??szCaptionMain??db??'My?first?Window?!',0
??szText????db??'Win32?Assembly,?Simple?and?powerful?!',0
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??;?代碼段
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??????.code
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??;?窗口過程
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??_ProcWinMain??proc??uses?ebx?edi?esi,hWnd,uMsg,wParam,lParam
??????local??@stPs:PAINTSTRUCT
??????local??@stRect:RECT
??????local??@hDc
??
??????mov??eax,uMsg
??;********************************************************************
??????.if??eax?==??WM_PAINT
????????invoke??BeginPaint,hWnd,addr?@stPs
????????mov??@hDc,eax
??
????????invoke??GetClientRect,hWnd,addr?@stRect
????????invoke??DrawText,@hDc,addr?szText,-1,\
??????????addr?@stRect,\
??????????DT_SINGLELINE?or?DT_CENTER?or?DT_VCENTER
??
????????invoke??EndPaint,hWnd,addr?@stPs
??;********************************************************************
??????.elseif??eax?==??WM_CLOSE
????????invoke??DestroyWindow,hWinMain
????????invoke??PostQuitMessage,NULL
??;********************************************************************
??????.else
????????invoke??DefWindowProc,hWnd,uMsg,wParam,lParam
????????ret
??????.endif
??;********************************************************************
??????xor??eax,eax
??????ret
??
??_ProcWinMain??endp
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??_WinMain??proc
??????local??@stWndClass:WNDCLASSEX
??????local??@stMsg:MSG
??
??????invoke??GetModuleHandle,NULL
??????mov??hInstance,eax
??????invoke??RtlZeroMemory,addr?@stWndClass,sizeof?@stWndClass
??;********************************************************************
??;?注冊窗口類
??;********************************************************************
??????invoke??LoadCursor,0,IDC_ARROW
??????mov??@stWndClass.hCursor,eax
??????push??hInstance
??????pop??@stWndClass.hInstance
??????mov??@stWndClass.cbSize,sizeof?WNDCLASSEX
??????mov??@stWndClass.style,CS_HREDRAW?or?CS_VREDRAW
??????mov??@stWndClass.lpfnWndProc,offset?_ProcWinMain
??????mov??@stWndClass.hbrBackground,COLOR_WINDOW?+?1
??????mov??@stWndClass.lpszClassName,offset?szClassName
??????invoke??RegisterClassEx,addr?@stWndClass
??;********************************************************************
??;?建立并顯示窗口
??;********************************************************************
??????invoke??CreateWindowEx,WS_EX_CLIENTEDGE,offset?szClassName,offset?szCaptionMain,\
????????WS_OVERLAPPEDWINDOW,\
????????100,100,600,400,\
????????NULL,NULL,hInstance,NULL
??????mov??hWinMain,eax
??????invoke??ShowWindow,hWinMain,SW_SHOWNORMAL
??????invoke??UpdateWindow,hWinMain
??;********************************************************************
??;?消息循環
??;********************************************************************
??????.while??TRUE
????????invoke??GetMessage,addr?@stMsg,NULL,0,0
????????.break??.if?eax??==?0
????????invoke??TranslateMessage,addr?@stMsg
????????invoke??DispatchMessage,addr?@stMsg
??????.endw
??????ret
??
??_WinMain??endp
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??start:
??????call??_WinMain
??????invoke??ExitProcess,NULL
??;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
??????end??start
??
??在radasm編譯通過.
??
??用IAD反匯編載入完成后,點擊文件-創建文件-創建asm文件就得到未經修改的反匯編后得到的1.asm文件(有點繞口:)),直接用
??radasm打開,在radasm中ctrl+f5構建并運行看看結果怎樣,呵呵,出錯了.
因為一步一步來講比較長,我先把操作過程寫下來,在慢慢解釋,1.asm修改如下:
(一)增加模式定義\options語句\還原include語句
??????.686p
??????.mmx
??????.model?flat,stdcall
??????option?casemap:none
??include?WINDOWS.INC
??include?kernel32.inc
??includelib?kernel32.lib
??include?user32.inc
??includelib?user32.lib
(二)刪除結構MSG\POINT\PAINTSTRUCT\RECT,并把余下的結構移動到??includelib?user32.lib之后,即第一步之后,
然后做如下修改:
tagMSG????struc?;??(sizeof=0x1C,?standard?type)
hwnd????dd????????;?offset
message????dd??
wParam????dd??
lParam????dd??
time????dd??
pt????POINT??????;這里修改為pt????POINT?<>
tagMSG????ends
tagPAINTSTRUCT??struc?;??(sizeof=0x40,?standard?type)
hdc????dd????????;?offset
fErase????dd??
rcPaint????RECT????????;這里修改為rcPaint????RECT?<>
fRestore??dd??
fIncUpdate??dd??
rgbReserved??db?32?dup(?)
tagPAINTSTRUCT??ends
(三)對函數的局部變量進行修改
一共三個函數start\sub_401000和sub_401089,修改如下
sub_401089:
sub_401089??proc?near????;?CODE?XREF:?startp
Msg????=?MSG?ptr?-4Ch
var_30????=?WNDCLASSEXA?ptr?-30h
修改為:
sub_401089??proc?near????;?CODE?XREF:?startp
????LOCAL?Msg:MSG?
????LOCAL?var_30:WNDCLASSEXA?
sub_401000:
sub_401000??proc?near????;?DATA?XREF:?sub_401089+43o
hDC????=?dword??ptr?-54h
Rect????=?tagRECT?ptr?-50h
Paint????=?PAINTSTRUCT?ptr?-40h
hWnd????=?dword??ptr??8
Msg????=?dword??ptr??0Ch
wParam????=?dword??ptr??10h
lParam????=?dword??ptr??14h
修改為:
sub_401000??proc?uses?ebx?edi?esi?,hWnd,Msg,wParam,lParam????;?DATA?XREF:?sub_401089+43o
????LOCAL?hDC
????LOCAL?Rect:tagRECT
????LOCAL?Paint:PAINTSTRUCT
(四)_text段修改
刪除
在_text段前增加.code
_text????segment??para?public?'CODE'?use32
????assume?cs:_text
????;org?401000h
????assume?es:nothing,?ss:nothing,?ds:_data,?fs:nothing,?gs:nothing
和
_text????ends
注意:中間的代碼不要刪除!!!
(五)刪除align?40h
(六)移動修改_data段
在.code前增加.data,并且把_data段移動到這里
把
_data????segment??para?public?'DATA'?use32
????assume?cs:_data
????;org?403000h
和??????????;?sub_401089+A6r
_data????ends
刪除
注意:中間的代碼不要刪除!!!
(七)修改sub_401000的hWnd,只要出現有的都修改為hWnd1.
(八)刪除_idata段
(九)
把函數含有[ebp+變量]的代碼全部修改為變量
sub_401089的代碼
[ebp+var_30]?改為??var_30
[ebp+var_30.hCursor]??改為??var_30.hCursor
[ebp+var_30.hInstance]??改為??var_30.hInstance
[ebp+var_30.cbSize]??改為??var_30.cbSize
[ebp+var_30.style]??改為??var_30.style
[ebp+var_30.lpfnWndProc]??改為??var_30.lpfnWndProc
[ebp+var_30.hbrBackground]??改為??var_30.hbrBackground
[ebp+var_30.lpszClassName]??改為??var_30.lpszClassName
[ebp+Msg]????改為??Msg
sub_401000的代碼
[ebp+hDC]????改為??hDC
[ebp+Rect]????改為??Rect
[ebp+Paint]????改為??Paint
[ebp+hWnd1]????改為??hWnd1
[ebp+Msg]????改為??Msg
[ebp+wParam]????改為??wParam
[ebp+lParam]????改為??lParam
(十)刪掉函數多余的開頭
sub_401089處:
sub_401089??proc?near????;?CODE?XREF:?startp
????LOCAL?Msg:MSG?
????LOCAL?var_30:WNDCLASSEXA?
????push??ebp????;刪掉
????mov??ebp,?esp??刪掉
????add??esp,?0FFFFFFB4h??;刪掉
sub_401000處:
sub_401000??proc?near?uses?ebx?edi?esi?,hWnd1,Msg,wParam,lParam????;?DATA?XREF:?sub_401089+43o
????LOCAL?hDC
????LOCAL?Rect:tagRECT
????LOCAL?Paint:PAINTSTRUCT
????push??ebp??;刪掉
????mov??ebp,?esp??;刪掉
????add??esp,?0FFFFFFACh??;刪掉
????push??ebx????;刪掉
????push??edi????;刪掉
????push??esi????;刪掉
--------------------------------------------------------------------------------
【經驗總結】
?其實只要你把反編譯的代碼按照radasm的提示一步一步修改就可以了.
解釋:
(一)
這一步我在上篇已經解釋的比較明白了.因為我們匯編開頭就是那么幾句代碼.
include語句加回去這個是因為我們編譯的是匯編程序,這樣肯定要用到庫.如果IDA使用生成的_data段
就非常容易出錯.畢竟它只是"識別"而不是源碼!!!!!!!
(二)
?(1)刪除結構體MSG\POINT\PAINTSTRUCT\RECT
我們進行了第一步操作后,用radasm進行構建,就會提示我們
D:\masm32\Include\WINDOWS.INC(7873)?:?error?A2163:??:?POINT
D:\masm32\Include\WINDOWS.INC(7874)?:?error?A2163:??:?POINT
D:\masm32\Include\WINDOWS.INC(8841)?:?error?A2163:??:?MSG
D:\masm32\Include\WINDOWS.INC(8842)?:?error?A2163:??:?MSG
D:\masm32\Include\WINDOWS.INC(8843)?:?error?A2163:??:?MSG
D:\masm32\Include\WINDOWS.INC(8844)?:?error?A2163:??:?MSG
D:\masm32\Include\WINDOWS.INC(8845)?:?error?A2163:??:?MSG
D:\masm32\Include\WINDOWS.INC(8846)?:?error?A2163:??:?MSG
D:\masm32\Include\WINDOWS.INC(8846)?:?fatal?error?A1016:?
構建時發生錯誤.
總共編譯時間?271?毫秒
這個這個意思說我們的庫文件出錯,這個可能嗎?當然也有可能,但我想你首先應該想到是你的反匯編代碼錯.
先查詢一下windows.inc"出錯"的到底是什么
POINT?STRUCT
??x??DWORD????;7873行
??y??DWORD????;7874行
POINT?ENDS
MSG?STRUCT
??hwnd??????DWORD?????????;8841
??message???DWORD?????????;8842
??wParam????DWORD?????????;8843
??lParam????DWORD?????????;8844
??time??????DWORD?????????;8845
??pt????????POINT??????<>??;8846
MSG?ENDS
呵呵,你再看看反匯編代碼開頭
MSG????struc?;??(sizeof=0x1C,?standard?type)
hwnd????dd????????;?offset
message????dd??
wParam????dd??
lParam????dd??
time????dd??
pt????POINT??
MSG????ends
;?---------------------------------------------------------------------------
POINT????struc?;??(sizeof=0x8,?standard?type)
x????dd??
y????dd??
POINT????ends
明白怎么是這樣了吧?我們反匯編代碼重復定義了結構msg,point所以要把他們刪除.同理PAINTSTRUCT\RECT也刪除了.
(2)移動剩余結構到include語句后.
這一步我是為了省事,剩余三個結構
tagMSG????struc?;??(sizeof=0x1C,?standard?type)
hwnd????dd????????;?offset
message????dd??
wParam????dd??
lParam????dd??
time????dd??
pt????POINT??
tagMSG????ends
;?---------------------------------------------------------------------------
WNDCLASSEXA??struc?;??(sizeof=0x30,?standard?type)
cbSize????dd??
style????dd??
lpfnWndProc??dd????????;?offset
cbClsExtra??dd??
cbWndExtra??dd??
hInstance??dd????????;?offset
hIcon????dd????????;?offset
hCursor????dd????????;?offset
hbrBackground??dd????????;?offset
lpszMenuName??dd????????;?offset
lpszClassName??dd????????;?offset
hIconSm????dd????????;?offset
WNDCLASSEXA??ends
;?---------------------------------------------------------------------------
tagRECT????struc?;??(sizeof=0x10,?standard?type)
left????dd??
top????dd??
right????dd??
bottom????dd??
tagRECT????ends
;?---------------------------------------------------------------------------
tagPAINTSTRUCT??struc?;??(sizeof=0x40,?standard?type)
hdc????dd????????;?offset
fErase????dd??
rcPaint????RECT??
fRestore??dd??
fIncUpdate??dd??
rgbReserved??db?32?dup(?)
tagPAINTSTRUCT??ends
其中tagMSG和tagPAINTSTRUCT結構分別用到了POINT結構和RECT結構,剛才我們刪了,只有windows.inc中有
所以直接把他們剪切到這里省去出錯的機會.
(3)修改結構
tagMSG結構和tagPAINTSTRUCT結構修改,我是參照windows.inc結構定義方法.結構中用結構<>?:)
這個不一定完全正確,想研究這方面多閱讀.inc文件
(三)函數修改
在反匯編代碼中只要出現proc的,到現在為止我都看成是函數!!!
IDA反匯編都它的函數都變成這個樣子
sub_401000??proc?near????;?DATA?XREF:?sub_401089+43o
hDC????=?dword??ptr?-54h??;注意這里是減(-)
Rect????=?tagRECT?ptr?-50h
Paint????=?PAINTSTRUCT?ptr?-40h
hWnd????=?dword??ptr??8????;這里其實是加(+)
Msg????=?dword??ptr??0Ch
wParam????=?dword??ptr??10h
lParam????=?dword??ptr??14h
????push??ebp
????mov??ebp,?esp
????add??esp,?0FFFFFFACh
????push??ebx
????push??edi
????push??esi
????mov??eax,?[ebp+Msg]
這里就會出現一個問題.我們先前又刪結構又改結構,而這里又用到結構,不修改編譯也會出錯的.
我們改成比較正規的win32匯編程序格式.
剛才我提示加減的地方,總結一條規律給大家:
函數開頭?xx?=?結構?-?xxh?這個就是函數的局部變量,可用local?xx:結構替換.
函數開頭?xx?=?dword??ptr?xxh?這個是函數的參數,函數可改為
函數名?proc?xx
(四)_text段修改
代碼段
_text????segment??para?public?'CODE'?use32
????assume?cs:_text
????;org?401000h
????assume?es:nothing,?ss:nothing,?ds:_data,?fs:nothing,?gs:nothing
和
_text????ends
IDA這種段寫法有很大的弊端,也是引起我們修改后的代碼編譯不通過的一個很重要原因.(具體我還說不上來,我還很菜)
(五)刪除align?40h
align是反匯編代碼不通過編譯的一種常見錯誤.
(六)移動修改_data段
一般來說_data段是我們的數據段,一般我們放在前面.(呵呵,代碼順序也很重要)
(七)在數據段中
hWnd????dd????????;?DATA?XREF:?sub_401000+54r
??????????;?sub_401089+94w?sub_401089+9Br
??????????;?sub_401089+A6r
提示hWnd是函數sub_401089的,并不是sub_401000,所以要重命名他們.
(八)刪除_idata段
include語句已經有了函數定義,再保留這里就會出錯.
(九)
把函數含有[ebp+變量]的代碼全部修改為變量
[ebp+]這個是編譯器加上去的,我們直接用的話,編譯后會變成[ebp+ebp+變量],容易出錯.
(十)刪掉函數多余的開頭
反匯編代碼中,編譯器為你加上象這樣的代碼
????push??ebp
????mov??ebp,?esp
????add??esp,?0FFFFFFB4h
如果你直接編譯的話代碼就變成了:
????push??ebp
????mov??ebp,?esp
????add??esp,?0FFFFFFB4h
????push??ebp
????mov??ebp,?esp
????add??esp,?0FFFFFFB4h
重新編譯也容易出錯,所以要刪去.
同理,要注意函數結束地方看看是否要刪去.
(十一)
這里說一點跟上一篇不同的是沒有刪除_rdata,因為這里有我們程序要的數據,所以沒刪除.如
果你還想優化自己弄了!!!
呵呵,終于弄完這篇了,把它整理好花了好大工夫.錯誤難免,請多包涵!!!!
--------------------------------------------------------------------------------
【版權聲明】:?本文原創于看雪技術論壇,?轉載請注明作者并保持文章的完整,?謝謝!
???????????????????????????????????????????????????????2007年03月04日?12:21:20