diy pe教學3 (28千字)
diy 你的pe 完結篇
上兩篇我教給大家如何diy pe,由於種種原因,都是沒有太實際的例子。今天我就講述一個實際的例子。
我想看雪論壇的人沒有不用w32asm的吧,這個實用的工具大家都愛它。但是w32asm也有些不完善的地方。
首先它不支援滾輪滑鼠的滾動(當然是在你沒有用輔助滑鼠軟體的情況下),然後是不支援檔案的拖放
你開啟w32asm後拖個檔案進去,滑鼠是個禁止拖放的圖示。想實現這些功能麼,那就帶上你的老虎鉗(trw)
,扳手(hiew)我們出發修理機床(w32asm,我修理的w32asm是killer
修改過的w32asm10,原檔案用pecompack壓縮過,
自己脫殼修改),(宣告:我的系統是98,2000下我沒有測試。看完我這篇文章的有興趣的人,可以在2000下試試)
好,我們先做第一個功能吧加入滑鼠滾輪功能(這時候我的想法是假如我有w32asm的源程式的話多好啊,沒有?那只有從反編譯的pe檔案幹活了,
感覺像在修裡煤氣管道漏氣)
第一步:分析問題(每個diy者都應該養成這個習慣,不要上來就bpx 斷點亂下一通)
不支援滾輪是什麼原因造成的?
windows是個訊息系統,w32asm不支援滾輪是因為它接受到滾輪的訊息但是根本不處理它,
我們的目標就是找到w32asm處理windows訊息的地方,然後加入處理滾輪訊息,如果你問我怎麼處理滾輪訊息,很簡單,
我們把滾輪的訊息轉化成按鍵的訊息,w32asm不是可以按上下鍵來滾動麼,我們把滾輪的上下滾動的訊息轉化為上下按鍵
的訊息,然後其他的事情交給w32asm自己去處理就ok,好了修理思路定好了,開始動工
第二步:找到win32asm處理訊息的地方
怎麼找處理訊息,我在上一篇文章已經講過了,這裡我就不在重複了。
找到處理訊息的地方如下
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045E471(U)
|
:0045261E 8B4604
mov eax, dword ptr [esi+04]===》【這裡是函式引數的傳遞,esi+04就是msg 的unit】
:00452621 3D21010000 cmp
eax, 00000121======>這裡eax就是windows訊息的程式碼
:00452626 7F41
jg 00452669
:00452628 0F84A30D0000
je 004533D1
:0045262E 3D11010000
cmp eax, 00000111===>看過我上篇文章的人就熟悉這個吧,就是wm_command
:00452633 7F1B
jg 00452650 *處理訊息的地方很長,因為w32asm有很多訊息要處理*
:00452635 7463
je 0045269A *限於篇幅,我只貼關鍵地方,有興趣的朋友可以自己*
:00452637 2DA0000000 sub
eax, 000000A0 *反彙編原檔案觀察
*
:0045263C 0F84530D0000
je 00453395
*
*
:00452642 83E860
sub eax, 00000060
:00452645 0F8493000000
je 004526DE
:0045264B E92F120000
jmp 0045387F
好我們下斷點bpx 45261e
這時候你會發現不斷的中斷停在這個地方,這很正常,這裡是w32asm處理訊息的核心部分,每一個給w32asm的訊息都經過這裡過濾。
頻繁的windows訊息當然就會頻繁的中斷了:)。這個沒有關係,每次中斷我們就f5,然後在按f5的時候的間隔就滾動滑鼠的滾輪,看看
滾輪的訊息是多少(注:這個在windows程式設計手冊裡可以查到wm_mousewhell訊息的程式碼是20A,我這樣來的目的是因為我不知道其waram的
子引數,也就是如何判斷滾輪向上滾動和向下滾動的子引數是如何定義的,而且手頭上沒有類似的滾輪程式,我只有自己測試了,這個方法
是比較笨了一點,但是我們想人家郭靖都是大智若愚,安慰一下自己),當看到esi+04的值為20a的時候我們d
esi+08(一般子參量都是這個
位置,windows 訊息本身就是這麼定義的),比較向上滾動和向下滾動esi+08地址有什麼不同,我這裡看到的是當向上滾動的時候esi+0a是7800
當向下滾動的時候esi+0a是88ff,我就初步確定向上滾動和向下滾動的判斷了。知道了滾輪的滾動,我們還要測試一下按鍵的子引數,按鍵的訊息
是wm_keydown 100,wm_keyup 101,wm_char 102這裡w32asm只處理wm_keydown的訊息(看w32asm訊息處理的地方,我沒有貼出來,有興趣可以自己反
編譯自己往45264B下面看),好既然只處理wm_keydown的訊息,我們還是老辦法,f5加上在間隔的時候按下向上,向下的按鍵,然後觀察esi+08的地址
的子參量,我這裡當按向上鍵esi+08是26,向下鍵esi+08是28,好現在我們知道了所有要知道的東西了,開始用扳手去修理機床吧
首先找到在程式裡空出來的地方
把原來的
:00452621 3D21010000
cmp eax, 00000121
改為
00452621: E90ACD0500
jmp .0004AF330 ==》跳到我們自己的訊息處理補丁上
|
自己的訊息處理補丁:
004AF330: 3D0A020000
cmp eax,00000020A ;"
==》比較訊息是否是滾輪
"
004AF335: 7415
je .0004AF34C
----- (1)==是的話轉到滾輪處理
004AF337: 3D33020000
cmp eax,000000233 ;"
3"==》比較訊息是否是拖放檔案(這個是補丁第二個功能用的,在下面有闡述)
004AF33C: 7400
je
.0004AF33E ----- (2)==》是的話就轉到(拖放檔案的處理)
004AF33E: 90
nop=====》空出這麼多nop是因為我怕等一下補丁 je .0004AF33E以後會變成長跳轉所以預留這些位元組
004AF33F: 90
nop
004AF340: 90
nop
004AF341: 90
nop
004AF342: 3D21010000
cmp eax,000000121 ;" !"==》恢復原程式動作
004AF347: E9DA32FAFF
jmp .000452626 ----- (3)==》跳回原程式地方
004AF34C: 668B460A
mov ax,[esi][0A]==》取出滾輪的子引數
004AF350: 663DFF00
cmp
ax,000FF ;" "==》比較是向上滾還是向下滾
004AF354: 720A
jb
.0004AF360 ----- (4)
004AF356: B828000000
mov
eax,000000028 ;" ("==》向下滾動,改動訊息子引數為按鍵下
004AF35B: 894608
mov
[esi][08],eax
004AF35E: EB08
jmps .0004AF368
----- (5)
004AF360: B826000000
mov eax,000000026 ;" &"==》向上滾動,改動訊息子引數為按鍵上
004AF365: 894608
mov [esi][08],eax
004AF368: B800010000
mov
eax,000000100 ;" "==》改動訊息為按鍵訊息
004AF36D: 894604
mov
[esi][04],eax
004AF370: EBD0
jmps .0004AF342
----- (6)==》跳回原程式
好到現在為止,我們測試看看,哈哈,果然滾動了,成功!什麼?你說滾動的太慢!)◎)◎※¥)※)(◎,如果嫌慢的話,自己把按鍵訊息子引數改成pgdn。和pgup一次滾動一頁,快了吧。什麼?你說能不能不要這麼快,一次滾動3行,或者5行,最好加個定義視窗想滾動幾行就幾行?我要暈倒了,
大哥,我是改動pe檔案,不是改源程式。如果你想這樣的話,我告訴你思路,你自己做.首先自己在w32asm的menu裡面加個定義滾輪滾動的子選項,我的第二篇
文章有說怎麼做的,然後加入點選這個子選項的訊息處理,讓點選這個子選項的時候彈出一個dialog,可以用CreateDialog的api函式,當然你的先做好這個dialog的資源,然後加入這個dialog的的訊息函式,在dialog裡面做個edit的控制元件和一個button控制元件當點選button的時候就把edit裡面的數值儲存到一個地址
,然後你的滾輪判斷的地方讀入這個地址的值,根據這個值判斷用sendmessage函式向w32asm傳送多少個按鍵訊息,1就發1個,50就發50個,這樣你樂意滾動多少行就多少行,還可以自定義:)。我是很累,不做了,那個大哥不滿意我做的就自己就做一個想滾動幾行就幾行的吧,記得做好了發一個給我用用就行了!好了
到現在為止我們的滾輪版已經做好了。休息一下眼睛,我們要開始大動干戈,開始做拖放版了(如果是初學者就不要往下看了,講述的專業比較多)
現在繼續我們的diy之旅
開啟w32asm試試拖放一個檔案,呵呵,滑鼠是禁止拖放的圖示,證明是w32asm是根本不支援拖放,說白了也就是不處理拖放的訊息。
好,既然我們要是這個w32asm支援拖放,首先我們先了解一下拖放的知識,windows是個圖形介面系統,各種各樣的程式都是基於圖形介面的,
這個介面是我們也可以稱為視窗,視窗很多屬性,比如大家都瞭解的enablewindow就是設定視窗的屬性的,不過這個函式是設定視窗是否可用的
屬性。現在我們需要的是視窗是否接受拖放的屬性,我告訴大家,這個函式就是DragAcceptFiles,它是shell32.dll的函式,與拖放有關的函式還有DragFinish和DragQueryFile,我們要補丁也就要用到這個三個函式,
首先我們看看DragAcceptFiles這個函式是設定視窗是否能接受拖放的訊息,也就是windows是否傳送WM_DROPFILES訊息給這個視窗。使用的方法是api手冊上查到為:
VOID DragAcceptFiles(
HWND hWnd, //
handle to the registering window 註冊視窗的hwnd
BOOL fAccept
// acceptance option 是否接受拖放的訊息
);
知道了DragAcceptFiles的用法後.我的思路是把w32asm的所有的視窗都加上一個
invoke DragAcceptFiles,hwnd,TRUE
當然這個是在彙編裡實現,但是在已經連線好的pe檔案裡如何實現
invoke DragAcceptFiles,hDlg,TRUE呢?
要達到這個目的
第一:首先我們需要pe檔案的import表(注:如果不懂import表的可以自己先學習一下pe檔案的格式,不難,只是有點煩而已)有DragAcceptFiles這個引入函式
第二:然後就是我們需要在pe檔案中的到視窗的hwnd
達到以上條件以後
只要在pe空白空間用以下程式碼就可實現
push
1
push hwnd
call DragAcceptFiles
我們現在先來達到第一個條件
拿出我脫殼的w32asm(注:我自己脫殼的有兩個版本,第一個是在入口點dump完全的pe,然後手動修復import,這個版本很遺憾,只能在98下執行,不能在2000下執行,原因是需要修補的import太多可能有遺漏,或者我也不知道,第二個版本,是情狼大哥在入口點用trw2000的pedump命令dump出來版本,這個版本能跨平臺,但是也遺憾,用pe編輯器看不到任何的import表)
為了能跨平臺,我決定用第二個版本開始改造,由於沒有任何的import表,我們根本不知道是否包含有DragAcceptFiles這個函式,用stud_pe開啟自己做的第一個版本(也就是修復了import表的那個版本),點選function按鈕,觀察import的函式資訊發現其函式有kernell32、gdi32.dll
等,沒有包含shell32.dll,也就是說,不可能有DragAcceptFiles這個我們需要的函式了,沒有函式,我們又想用,那就只有自己手動構造了,三個相關的函式構造起來,還是比較容易的,不過我還是教大家怎麼使用lordpe構造吧(用stud_pe和peeditor都差不多,手動也行,如果來個二三十個函式的話,我看手動的可就吃虧了)
建構函式篇:
用lordpe開啟第二個脫殼版本,點選directories按鈕,然後點選importtabl按鈕,只能看到一個kernell32.dll,在上面點選右鍵,選擇
add import,彈出視窗,在dll填入SHELL32.dll,api填入DragAcceptFiles點選那個加號的按鈕看到DragAcceptFiles已經新增進去了然後用這個方法新增DragFinish和DragQueryFile函式新增完成後點選ok,看到import表多了一個shell32的dll了吧,裡面有我們新增的三個函式,記下這個三個函式的thunkrva值(以後要用到),我這裡如下:
ThunkRva ThunkOffset ThunkValue
Hint ApiName
0015803B 0015803B
0015800C 0000 DragAcceptFiles
0015803F 0015803F 0015801E 0000
DragQueryFile
00158043 00158043 0015802E
0000 DragFinish
其實你也可以自己用winhex構造這個三個函式,不難,看看相關的pe格式文件就能做到,自己構造的有個好處就是結構比較分明,看起來比較舒服,軟體構造的是重新定位過import所以有點混亂,不過你想偷懶就用軟體構造吧,這個方便
構造完了函式,我們的給它一個firshthunk,否則在程式裡面怎麼call那裡呢?這裡就用到了thunkrva的值了,現在工具換成了hiew,用hiew開啟脫殼後的w32asm我們來到004AF29C
如下:
004AF29C: FF25244B4D00
jmp d,[004D4B24]
004AF2A2: FF252C4B4D00
jmp
d,[004D4B2C]
004AF2A8: FF25304B4D00
jmp d,[004D4B30]
004AF2AE: FF25344B4D00
jmp
d,[004D4B34]==>這些jmp都是定位api函式的,每個jmp代表程式要用到api函式地址
004AF2B4: 0000
add
[eax],al *************************************************************
004AF2B6: 0000
add [eax],al *你問,怎麼找到這個地方的,很簡單,隨便下個程式要用到的api函*
004AF2B8: 0000
add [eax],al *數,看看其call的是那個地址,就能找到這個地方
*
004AF2BA: 0000
add
[eax],al *************************************************************
我們現在就要加入DragAcceptFiles、DragQueryFile、DragFinish三個函式的jmp,
jmp到那裡,其實就是jmp那個ThunkRva+imagebase的值,imagebase值是4000000
所以我們要在004AF2B4處填入:
004AF2B4:jmp d,[0055803B] *55803b=15803B(ThunkRva)+4000000(imagebase)以下一樣計算
jmp d,[0055803f]
jmp d,[00558043]
添完後如下:
004AF29C: FF25244B4D00
jmp d,[004D4B24]
004AF2A2:
FF252C4B4D00 jmp
d,[004D4B2C]
004AF2A8: FF25304B4D00
jmp d,[004D4B30]
004AF2AE: FF25344B4D00
jmp d,[004D4B34]
004AF2B4: FF253B805500
jmp
DragAcceptFiles ;SHELL32.dl==>看到我們構造的函式了麼,真是happy啊
004AF2BA: FF253F805500
jmp
DragQueryFile ;SHELL32.dll
004AF2C0: FF2543805500
jmp DragFinish ;SHELL32.dll
004AF2C6: 0000
add [eax],al
004AF2C8: 0000
add
[eax],al
現在記下004AF2B4、004AF2BA、004AF2C0這三個值.以後call 004AF2B4就是call
DragAcceptFiles了,呼叫DragQueryFile 也就是call 004AF2BA了,以此類推
函式構造完成第一個條件也就滿足了,開始我們第二個條件hwnd的尋找吧
尋找hwnd打補丁篇:
如何找到hwnd值呢,對windows程式設計熟悉的人(你不熟悉就慢慢學,總有一天會熟悉的)知道GetWindowRect函式也需要一個hwnd值,我們截獲
getwindowsrect函式,儲存這個hwnd,再使用這個hwnd來DragAcceptFiles 不就ok,好確定思路,開啟trw然後bpx
getwindowsrect
啟動w32asm發現其在這裡呼叫getwindowsrect:
0167:00492941 52
PUSH EDX=========>這個是一個rect的struct的point,也就是一個矩陣結構的指標
0167:00492942 FF700C PUSH
DWORD [EAX+0C]===>這裡就是我們需要的hwnd
0167:00492945 E810C90100
CALL `USER32!GetWindowRect===>呼叫這個函式了也就是call
.0004AF25A
0167:0049294A EB1B JMP
SHORT 00492967
0167:0049294C
8B582C MOV EBX,[EAX+2C]
程式啟動呼叫了很多次GetWindowRect函式,每次hwnd都不同,這是因為w32asm視窗分為好幾個,edit視窗,menu視窗,toolbar,狀態列等等
我們不管它,把每個視窗的DragAcceptFiles 值都設定為ture就行了,管它有多少個呢,有多少個,就ture多少個,個個都能接受拖放,想往
那裡拖就往那裡拖
把這句:
0167:00492945 E810C90100 CALL
`USER32!GetWindowRect
改為:
00492945: E996C90100
jmp .0004AF2E0
-----這裡是我們自己的補丁程式了
自己補丁的地方:
004AF2E0: 58
pop
eax----》取出壓入堆疊的hwnd
004AF2E1: A3C6F24A00
mov [004AF2C6],eax---》儲存到一個地址,我選擇的是004AF2C6
004AF2E6: 50
push eax---》壓hwnd入堆疊
004AF2E7: E86EFFFFFF
call .0004AF25A -----》 CALL `USER32!GetWindowRect
004AF2EC: 6A01
push 001===傳遞ture
004AF2EE:
FF35C6F24A00 push
d,[004AF2C6]==》傳遞hwnd
004AF2F4: E8BBFFFFFF
call
DragAcceptFiles ;SHELL32.dll===》也就是call 004AF2B4我們在上面構造的地方
004AF2F9: E96936FEFF
jmp
.000492967 -----》回到程式原來的地方
現在開啟補丁完的程式,拖個檔案試試,是不是圖示已經變了,你說,變是變了,怎麼沒有反應啊,還沒有加入事件怎麼會有反應?真是的,路要
一步一步的走。不要太急
現在開始我們加入事件的過程了,首先找到接受訊息的地方,加入判斷拖放訊息的程式碼,上面已經說過了在
:0045261E 8B4604
mov eax, dword ptr [esi+04]===》【這裡是函式引數的傳遞,esi+04就是msg 的unit】
:00452621 3D21010000
cmp eax, 00000121======>這裡eax就是windows訊息的程式碼
而且
:00452621 3D21010000
cmp eax, 00000121
已經改為:
00452621: E90ACD0500
jmp .0004AF330
也就是訊息處理已經在我們自己的補丁地方了
004AF330: 3D0A020000
cmp eax,00000020A
;" ==》比較訊息是否是滾輪
"
004AF335: 7415
je
.0004AF34C ----- (1)==是的話轉到滾輪處理
004AF337: 3D33020000
cmp
eax,000000233 ;" 3"==》比較訊息是否是拖放檔案
004AF33C: 7400
je
.0004AF33E ----- (2)==》是的話就轉到(拖放檔案的處理)
好現在我們可以把004AF33C:
7400
je .0004AF33E轉到我們自己拖放處理的地方了
現在程式也能判斷拖放訊息,我們就需要根據這個訊息做相關的動作了,也就是需要做開啟這個拖放檔案並且反彙編它。
學習到這裡,大家是不是已經比較有思路了,首先我們必須得到拖放檔案的檔名,這就需要DragQueryFile 函式了
The DragQueryFile
function retrieves the filenames of dropped files.
UINT DragQueryFile(
HDROP hDrop, // handle to structure
for dropped files===》拖放的hdrop
UINT iFile, //
index of file to query==》為0就可以了
LPTSTR lpszFile, //
buffer for returned filename==》放檔名的地址
UINT cch //
size of buffer for filename==》buffer的尺寸
);
我們看看這個函式需要什麼引數,現在需要找的就是hdrop這個類似於windows視窗的hwnd用來唯一標識拖放的,這個也就是msg的子引數
:0045261E 8B4604
mov eax, dword ptr [esi+04]===》【這裡是函式引數的傳遞,esi+04就是msg 的unit】
esi+04是訊息unit,那麼這個子引數就在esi+08處
好了相關的引數都搞定了,下一步就是看看w32asm怎麼開啟一個根據檔名開啟檔案的動作的;從那裡下手呢?從disassembler的open file下手?這個會彈出一個框子出來,不好,那就從recent
files下手,rencent files可以開啟你最近開啟的檔案,好我們看看它是怎麼開啟的
(跟蹤這個動作很複雜,我要詳細的說,可能打一天的字也打不完,我打字到現在已經很累了,大家就將就一下,我僅僅講跟蹤的關鍵地方)
在訊息判斷(訊息是111 wm_command)的地方下斷點,然後點選recent files的按鈕,發現其子參量為bd02然後又呼叫自己,這時候的子參量變成
0c5f,當你點選open file時候發現子參量也是0c5f,看來是在點選recent files檔案的時候會post一個0c5f訊息回來,那麼rencent裡面的最近開啟的檔案是存在那個地方呢?經過跟蹤可以發現是存在c:\windows\w32dasm8.ini檔案裡面,
windows用來開啟ini檔案的api是GetPrivateProfileString,下bpx GetPrivateProfileString這個斷點,然後點選recent
裡面的最近開啟的檔案程式中斷在這裡:(我們就來分析這裡是什麼意思)
|:100411F0
|
:1004310C
55
push ebp
:1004310D 8BEC
mov ebp, esp===》這是vc程式設計傳遞引數的形式,用vc都是這樣,和編譯器有關係
:1004310F 53
push ebx==》這裡傳遞的引數是視窗的hwnd
:10043110 56
push esi
:10043111 8B450C
mov eax, dword ptr [ebp+0C]==》這裡是訊息的子引數,這裡是最近五個檔案的id
:10043114 2DBD020000 sub
eax, 000002BD
:10043119 D1E0
shl eax, 1
* Possible StringData Ref from Data
Obj ->"12345"
|
:1004311B BB3B5A0410
mov ebx, 10045A3B
:10043120 03D8
add ebx, eax===》把eax做轉換變成了table表,就知道是點選了那個檔案,[ebx]會變成1-5之間
* Possible StringData Ref from Data Obj ->"W32dasm8.ini"
|
:10043122 684A5A0410
push 10045A4A==>引數,檔名
:10043127 6880000000
push 00000080==>buffer size
:1004312C
68575A0410 push 10045A57==>讀入內容地址指標
* Possible StringData Ref from Data Obj ->"NULL"
|
:10043131 68455A0410
push 10045A45==》預設字串的指標
:10043136 53
push ebx==>key name
* Possible StringData Ref from Data Obj ->"RECENT"
|
:10043137 68345A0410
push 10045A34===>段名
* Reference To: KERNEL32.GetPrivateProfileStringA,
Ord:0125h
|
:1004313C E8AB0B0000
Call 10043CEC==>得到key name下的內容
:10043141 A3305A0410 mov dword
ptr [10045A30], eax==>返回的到位元組
:10043146 68575A0410
push 10045A57
* Possible StringData Ref from Data
Obj ->"NULL"
|
:1004314B 68455A0410
push 10045A45
* Reference
To: KERNEL32.lstrcmpiA, Ord:02D9h
|
:10043150 E8F70B0000 Call
10043D4C==>比較上面兩個字串(這個比較的作用是看是不是要調整最近開啟的檔案的順序)
:10043155 0BC0
or eax, eax
:10043157
745E je 100431B7
:10043159 BF575A0410 mov
edi, 10045A57
:1004315E 8B0D305A0410
mov ecx, dword ptr [10045A30]
:10043164 8BF7
mov esi, edi
:10043166 03F9
add edi, ecx
:10043168
FD
std
:10043169 B05C
mov al, 5C
:1004316B F2
repnz
:1004316C AE
scasb
:1004316D 85C9
test ecx, ecx
:1004316F 741C
je 1004318D
:10043171 83C702
add edi, 00000002
:10043174 C647FF00
mov [edi-01], 00
:10043178 3BFE
cmp edi, esi
:1004317A
7411 je 1004318D===》這一段的作用是把d:\1\hiew.exe變成d:\1的形式,為SetCurrentDirectoryA做準備
:1004317C 56
push esi==>esi的地址就是X:\XXX\的形式了
* Reference To: KERNEL32.SetCurrentDirectoryA,
Ord:023Eh==》設定現在的路徑為X:\XXX\
|
:1004317D
E8A60B0000 Call 10043D28
:10043182 57
push edi
:10043183 68575A0410
push 10045A57
* Reference To: KERNEL32.lstrcpyA, Ord:02DCh
|
:10043188 E8C50B0000
Call 10043D52
* Referenced by a (U)nconditional
or (C)onditional Jump at Addresses:
|:1004316F(C), :1004317A(C)
|
:1004318D 68575A0410 push 10045A57
:10043192 68515E0410 push
10045E51
* Reference To: KERNEL32.lstrcpyA, Ord:02DCh
|
:10043197 E8B60B0000
Call 10043D52===》上面一段的作用是調整最近檔案開啟的順序
:1004319C C605505E041002
mov byte ptr [10045E50], 02==》這個可是標誌位哦,如果為零的話,那就會彈出那個開啟檔案的視窗
:100431A3 6A00
push 00000000
* Possible Ref to Menu: MenuID_00CB, Item: "Open
File to Disassemble.."
|
:100431A5
680C5F0000 push 00005F0C
:100431AA 6811010000 push 00000111
:100431AF FF7508
push [ebp+08]==>視窗的hwnd
* Reference To: USER32.PostMessageA, Ord:01DBh
|
:100431B2 E8E70A0000
Call 10043C9E==》我果然沒有猜錯,就是post一個點選open file訊息給自己
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10043157(C)
|
:100431B7 5E
pop esi
:100431B8 5B
pop ebx
:100431B9
C9
leave
:100431BA C20800
ret 0008
這段程式碼我已經分析完畢,現在我們要做的事情就是在的到DragQueryFile 的訊息後,做一樣的處理動作,然後post一個open
file訊息給自己
,就達到目的了,關鍵的地方是如何得到PostMessageA的hwnd呢?這個hwnd是w32asm mune的id,windows程式設計師都知道setmenu的函式吧,我們下斷點bpx
setmenu,看到原程式是在這裡setmenu
:0049CD86 8BF7
mov esi, edi
:0049CD88 56
push esi===》舊hwnd
:0049CD89 8B0B
mov ecx, dword ptr [ebx]
:0049CD8B FF710C
push [ecx+0C]==》新hwnd
* Reference
To: user32.SetMenu, Ord:0221h
|
:0049CD8E
E865230100 Call 004AF0F8
:0049CD93 85C0
test eax, eax
我們要做的事情就是儲存這個新的hwnd,以變PostMessageA的時候用到
:0049CD8E
E865230100 Call 004AF0F8
改為:
0049CD8E: E97D250100
jmp .0004AF310 -----到我們自己儲存hwnd的程式碼
自己儲存hwnd的程式碼:
004AF310: 58
pop
eax==》取出hwnd
004AF311: A3CAF24A00
mov [004AF2CA],eax==》儲存在[004AF2CA],以便用到的時候在這裡取回
004AF316: 50
push eax
004AF317:
E8DCFDFFFF call
.0004AF0F8 -----call setmenu
004AF31C: E972DAFEFF
jmp
.00049CD93 -----回到程式原來地方
004AF321: 0000
add
[eax],al
004AF323: 0000
add [eax],al
004AF325: 0000
add [eax],al
現在hwnd也有了,而且DragQueryFile會返回開啟檔案的位元組,完全和GetPrivateProfileStringA返回的一樣,也就是在原來GetPrivateProfileStringA處改為DragQueryFile就ok,那麼其他的PostMessageA、lstrcpyA、SetCurrentDirectoryA、lstrcmpiA的call到那裡去找呢,如果能看到import表就直接從import表找,但是這個脫殼版的無import表真是麻煩,沒有辦法,下斷點一個一個看,先來bpx
postmessagea
原程式中斷在
:00453402 E85DBD0500
Call 004AF164==》這個就是call postmessagea
其他幾個函式如下:
postmessagea :00453402 E85DBD0500
Call 004AF164
lstrcpyA
:00451C49 E80CD00500
Call 004AEC5A
SetCurrentDirectoryA :0043E679 E8B8050700
Call 004AEC36
lstrcmpiA
:0043E468 E815070700
Call 004AEB82
好了現在需要的函式地址也有了,我們開始補丁
004AF330: 3D0A020000
cmp
eax,00000020A ;" ==》比較訊息是否是滾輪
"
004AF335: 7415
je
.0004AF34C ----- (1)==是的話轉到滾輪處理
004AF337: 3D33020000
cmp
eax,000000233 ;" 3"==》比較訊息是否是拖放檔案
004AF33C: 7400
je
.0004AF33E ----- (2)==》是的話就轉到(拖放檔案的處理)
先把
004AF33C: 7400
je .0004AF33E ----- (2)==》是的話就轉到(拖放檔案的處理)
改成:
004AF33C: 7442
je .0004AF380 -----調到處理拖放的子程式中
處理拖放的子程式:
*這段程式就是參照原來處理程式寫的
004AF380: FF7608
push
d,[esi][08]
004AF383: 8F05CEF24A00
pop d,[004AF2CE]==>儲存拖放的hDrop到[004AF2CE]
004AF389: 6800010000
push 000000100 ;" "==>緩衝區為100所以不要拖動路徑長度大於256的檔案哦,可能要出錯
004AF38E: 68575A0410
push 010045A57 ;"ZW"==》儲存檔名稱的地址
004AF393:
6A00
push 000==》UINT iFile
004AF395: FF35CEF24A00
push
d,[004AF2CE]==》push hDrop
004AF39B: E81AFFFFFF
call DragQueryFile
;SHELL32.dll==》得到拖動的檔名
004AF3A0: A3305A0410
mov [10045A30],eax==》返回的位元組數儲存,以下都是模仿原來程式的動作,上面已經有分析,我就不詳細的說明了
004AF3A5: 68575A0410
push 010045A57 ;"ZW"
004AF3AA: 68455A0410
push
010045A45 ;"ZE"
004AF3AF: E8CEF7FFFF
call .0004AEB82 -----
(2)==》call lstrcmpiA
004AF3B4: 0BC0
or
eax,eax
004AF3B6: 0F846A32FAFF
je .000452626 ----- (3)==》如果為零就直接退出,原動作是直接ret,我們就直接返回
004AF3BC: 6660
pusha==》儲存所有的暫存器,因為下面要用到esi等,所以現在先儲存之
004AF3BE: BF575A0410
mov
edi,010045A57 ;"ZW"
004AF3C3: 8B0D305A0410
mov ecx,[10045A30]
004AF3C9: 8BF7
mov esi,edi
004AF3CB: 03F9
add
edi,ecx
004AF3CD: FD
std
004AF3CE: B05C
mov
al,05C ;"\"
004AF3D0: F2AE
repne
scasb
004AF3D2: 85C9
test ecx,ecx
004AF3D4:
741D
je .0004AF3F3 -----
(4)
004AF3D6: 83C702
add edi,002 ;""
004AF3D9:
C647FF00
mov b,[edi][-01],000 ;" "
004AF3DD: 3BFE
cmp
edi,esi
004AF3DF: 7412
je
.0004AF3F3 ----- (1)
004AF3E1: 56
push
esi
004AF3E2: E84FF8FFFF
call .0004AEC36 ----- (2)就是call
SetCurrentDirectoryA
004AF3E7: 57
push
edi
004AF3E8: 68575A0410
push 010045A57 ;"ZW"
004AF3ED: 90
nop
004AF3EE: E867F8FFFF
call .0004AEC5A
----- (3)就是 call lstrcpyA
004AF3F3: 68575A0410
push 010045A57 ;"ZW"
004AF3F8: 68515E0410
push 010045E51 ;"^Q"
004AF3FD: E858F8FFFF
call
.0004AEC5A ----- (4)就是 call lstrcpyA
004AF402: C605505E041002
mov b,[10045E50],002
;""
004AF409: 6A00
push 000
004AF40B:
680C5F0000 push
000005F0C ;" _
004AF410: 6811010000
push
000000111 ;" "
004AF415: A1CAF24A00
mov eax,[004AF2CA]==》這個就是我們在setmenu儲存的hwnd
004AF41A: 50
push eax
004AF41B:
E844FDFFFF call
.0004AF164 ----- (5)就是 call postmessagea
004AF420: FF35CEF24A00
push
d,[004AF2CE]==》這個是儲存的 hDrop,
004AF426: E895FEFFFF
call DragFinish
;SHELL32.dll==》拖放處理完後要釋放hDrop,呼叫DragFinish
004AF42B: 6661
popa 恢復堆疊
004AF42D: E9F431FAFF
jmp .000452626 ----- (7)跳回原處理地方
好了到現在為止我們diy加強版的w32asm已經出來了,大家享受一下勞動成果吧,如果有興趣的話,還可給w32asm做很多改造,使之更加適合與
我們自己的工作習慣。我已經把方法和原理都教給大家了,有誰做出更加power的版本,記得給我一份哦,
此程式在98下測試成功,2000下我想應該不會成功,因為2000下的拖放函式不同,有興趣的人可以在裡面加上getversion函式判斷是98還是2000
如果是2000下用另外一套函式實現。我自己很少在2000下使用w32asm所以我就不做了:(,就當留給大家的作業吧
後記:寫到這裡已經是兩手發酸,希望這片文章成為diy pe的經典教程,如果看雪出一本diy pe的書是不是考慮選上我這篇文章:)
你的朋友:pll621
2002.8.24
相關文章
- diy pe教學2 (11千字)2002-08-09
- diy pe的教學文章1 (6千字)2002-08-08
- 脫Crunch/PE -> BitArts的殼。 (3千字)2002-05-03
- TRW短篇教學 (6千字)2001-09-29
- 菜鳥教學--密碼學概述 (10千字)2015-11-15密碼學
- SQLite3 使用教學2015-01-12SQLite
- 貼個教學,初學者請進! (11千字)2001-04-20
- 如何完美破解PE EXPLORER 1.2 (5千字)2001-06-13
- 教資 - 高等教育心理學(3)2024-10-08
- PE檔案結構解析32022-05-30
- GICV3 PE是什麼?2024-10-19
- 好久沒發貼,貼個tip:PE 頭部校驗和(checksum)的計算
(3千字)2015-11-15
- 請教關於DremEdit2.28如何算註冊碼? (3千字)2000-07-13REM
- 菜鳥的ollydbg1.08b教學篇 (10千字)2003-01-27
- 我的PE程式加密核心程式碼(MASM 6.0) (9千字)2015-11-15加密ASM
- PE學習筆記(一) (轉)2008-01-25筆記
- PHP DIY 系列------框架篇:3. 路由解析2020-02-20PHP框架路由
- PHP DIY 系列------基礎篇:3. 反射2020-02-18PHP反射
- PE教程3: File Header (檔案頭)2015-11-15Header
- PE-explorer 1.4 的簡要破解過程(1千字)2001-08-08
- 老男孩在創業及培訓中28條教導學生感悟語錄分享!2012-04-06創業
- 教學研究2024-06-21
- 教學影片2024-06-21
- 浮點運算:程式碼管理器 (28千字)2015-11-15
- 每日總結3月28日2024-06-16
- 基於合作教學的幾種教學方法2018-11-16
- Diy React2018-10-21React
- diy tls2024-08-10TLS
- C++順序結構(3)、資料型別_____教學2024-10-18C++資料型別
- 如何完美破解PE EXPLORER 1.3(加入BCG的第二篇) (9千字)2001-06-29
- 2024年3月28日2024-03-28
- 學習請教2007-11-15
- 教學大綱2024-06-21
- 教學隊伍2024-06-21
- 蛙泳教學12024-03-31
- 關於StyleXP反跟蹤程式碼的分析以及WinDbg簡單教學
(7千字)2015-11-15
- 菜鳥學破解(七)之 PowerZip V5.2 (3千字)2000-07-21
- 《Django 3 Web應用開發從零開始學(影片教學版)》簡介2022-08-23DjangoWeb