亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Getright 5 手動脫殼和重建IAT--第二部分(圖)

互聯(lián)網(wǎng)   發(fā)布時間:2008-10-08 19:05:33   作者:佚名   我要評論
在本參考教程的第一部分我們學(xué)習(xí)了如何正確地轉(zhuǎn)儲(dump)Getright 5. 現(xiàn)在我們將要去找神奇跳轉(zhuǎn),這樣IAT會被正確地轉(zhuǎn)儲下來,而不用手工修復(fù)了. 要完成這一點(diǎn),我們需要打敗程序中的一些陷阱, 并使它們即使在檢測到被執(zhí)行脫殼時也無所作為. 讓我們開始吧! 第一步:如

在本參考教程的第一部分我們學(xué)習(xí)了如何正確地轉(zhuǎn)儲(dump)Getright 5. 現(xiàn)在我們將要去找神奇跳轉(zhuǎn),這樣IAT會被正確地轉(zhuǎn)儲下來,而不用手工修復(fù)了. 要完成這一點(diǎn),我們需要打敗程序中的一些陷阱, 并使它們即使在檢測到被執(zhí)行脫殼時也無所作為.
讓我們開始吧!
第一步:如何找到IAT的起始點(diǎn)和終點(diǎn)
在我們開始之前,先在安全的地方保存一份我們在先前第一部分教程中得到的轉(zhuǎn)儲文件的副本. 我將它命名為TUTE.exe記住這個名字.
用Ollydbg載入TUTE.exe. 我們將要去尋找IAT.

正如我們在上圖中看到的,如果我們稍加跟蹤,我們很容易發(fā)現(xiàn)一個
CALL [xxxxxx] 或者 JMP [xxxxxx] 間接地帶有它們即將跳往IAT中某處的內(nèi)存地址值.在這張圖中,我們可以看到 CALL [5e9d94]. 那意味著這個call將要前往這個內(nèi)存地址,實(shí)際上就是IAT表的入口值.在它的右邊我們可以看到"kernel32.Getversion" (黃色). 這就意味著這是一個可以在IMPORT RECONTRUCTOR上被找到的正確的入口值.
讓我們看一下轉(zhuǎn)儲(DUMP)窗口.在轉(zhuǎn)儲(DUMP)窗口右擊,選擇"前往 表達(dá) 5E9D94".

這就是看上去很不錯的IAT. 正如你所看到的入口5E9D94指向77E5D142,那個值在我的機(jī)器里是API GetVersion.這個入口是正確的,此入口周圍的其它一些入口也是指向類似7xxxxxxx的值.
注意在其它的機(jī)器上值7xxxxxx可能會有所不同.但是這些值都是相互類似的. 現(xiàn)在我們稍微往上看一看,去找此表的起始點(diǎn).我們到達(dá)這里:

紅線標(biāo)記了此表的起始點(diǎn).在此線的上面沒有其它任何API值了.現(xiàn)在我們知道表從哪兒開始了
TABLE STARTS= 5E99EC
現(xiàn)在到右下角轉(zhuǎn)儲區(qū)去找IAT表的終止點(diǎn).正如我們在圖中看到的有兩個可能的終止點(diǎn). 如果我們吃不準(zhǔn)最好選后面那個.但是我們有更好的方法.

選擇任何一個不確認(rèn)的值,然后將表向上翻頁.停在401000.我們必須去找一個CALL [xxxxx]或者一個JMP [xxxxx].右擊鼠標(biāo)并選擇SEARCH FOR BINARY STRING

我們將要去尋找那些不確認(rèn)的入口中的一個,讓我們試試5EA25C.記住逆序?qū)戇@個值如下圖所示.

到了這里

稍稍往上翻一下

我們看到那兒有一個使用此值的CALL,所以那些不確認(rèn)的值也都是屬于IAT的.
現(xiàn)在我們知道了
END OF TABLE= 5EA2BC
終點(diǎn)值是用來計(jì)算表的長度的.這是很簡單的一步:
LENGTH= END-START
LENGTH=5EA2BC-5E99EC
LENGTH= 8D0
在紙上寫下OEP,表的起始點(diǎn)和長度,在使用import reconstructor時你將用到這些值.
第二步:找出那些不指向任何API的錯值.
當(dāng)GETRIGHT.exe正在進(jìn)行轉(zhuǎn)儲時,這個問題變的很容易.然后選擇VIEW-MEMORY你將看到哪些入口指向了dlls而哪些則指向了錯誤的地方.
無論如何如果我們嘗試用revirgin或import reconstructor則會有很多入口無法解決.這就是我們?yōu)槭裁凑埑龉锊ㄌ貛硪恍┠Х?

正如在表中看到的,還存在一些(黃色標(biāo)記)沒有解決的入口.通常對付這種情況的方法是從我開始轉(zhuǎn)儲起就跟蹤,然后追蹤每一個調(diào)用API的call,寫下名字最后用Import Reconstructor.
如果自由很少幾處沒有解決的入口這樣做將非常簡便,但是如果有很多的話,這項(xiàng)工作將令人難以忍受,所以讓我們看看另一種方法.
第三步:如何去找出MAGIC JUMP
這里說明一點(diǎn):我們已經(jīng)知道程序的父進(jìn)程和他的子進(jìn)程是相同文件,但要用不同的句柄裝入兩次,所以他們變成兩個不同的進(jìn)程。一方面父進(jìn)程的OEP是5F90B9,父進(jìn)程從這里開始運(yùn)行.

另一方面我們知道當(dāng)子進(jìn)程被轉(zhuǎn)儲時其OEP是534E90,但我也要告訴你,子進(jìn)程也是以相同的父進(jìn)程的入口點(diǎn)5F80B9開始運(yùn)行.子進(jìn)程運(yùn)行并且解出自己的IAT然后跳到子進(jìn)程引起錯誤的OEP,我希望你記住這一點(diǎn),我在第一部分曾經(jīng)講過.
如果你相信以上所說,我告訴你,跟蹤父進(jìn)程直到父進(jìn)程開始轉(zhuǎn)變?yōu)閮蓚€進(jìn)程,父進(jìn)程和子進(jìn)程,找到那個地方,那非常有用.我已經(jīng)找到了那個地方,那是個條件跳轉(zhuǎn),至于如何找到的,我以后再告訴你.
順便一提它不是從父進(jìn)程那復(fù)制 IAT 到它的子進(jìn)程,卻是從子進(jìn)程那解出自己的 IAT。這應(yīng)該是一大麻煩,因?yàn)槲覀儾荒茉谒麖母高M(jìn)程脫離前用 OllyDbg 進(jìn)入子進(jìn)程。
這是個煩惱,因?yàn)槲也恢廊绾芜M(jìn)入子進(jìn)程去觀察它如何解出自己的IAT.
首先我嘗試著從轉(zhuǎn)儲程序TUTE.exe中找一個錯誤的entry.

我選擇了5E9C34但是你可以選擇其它任何錯誤的entry.正如你所看到的,它的值為DF5070.
按老規(guī)矩記住要將 IsDebuggerPresent 的值設(shè)為零,清除所有以前的 BPX、BP WaitForDebugEvent 然后單擊運(yùn)行.
我們將停在此斷點(diǎn)或者某個例外上.那時,打開PUPE選擇進(jìn)程中2個進(jìn)程中的上面一個(因?yàn)樗亲舆M(jìn)程,是我們需要的).右擊進(jìn)入parcheando窗口選擇4字節(jié),如圖在地址里填入錯誤的entry offset 5E9C34.然后點(diǎn)擊BUSCAR. 你將會看到?jīng)]什么變化,因?yàn)樗兄刀际橇?

然后不斷的在OD中點(diǎn)擊運(yùn)行、在PUPE中點(diǎn)擊BUSCAR,并檢查字節(jié)窗口中的值.
第一次變化可能會很久才發(fā)生, 但是記住不斷的在OllyDbg運(yùn)行、在PUPE中點(diǎn)擊BUSCAR,并檢查字節(jié)窗口中的值,直到字節(jié)窗口中的值從零開始變化.

如圖所示,那個值變化了. 現(xiàn)在再重復(fù)幾次,你將會看到:


子進(jìn)程已經(jīng)完全解出并賦值IAT. 我們必須在那個值第一次變化之后子進(jìn)程賦值之前進(jìn)入子進(jìn)程. 這是個問題,但我耍了一個把戲解決了.
我們將要重復(fù)上述過程.關(guān)閉Parcheando--PUPE的窗口,因?yàn)楫?dāng)重啟后進(jìn)程的句柄會變.
重復(fù)上述過程直到你在PUPE的窗口中觀察到那個值的第一次變化.你應(yīng)該看到類似這樣的東西:


很難找到一種好方法, 所以我決定在某個API上制造一個死循環(huán).就選GetProcAddress吧.所以現(xiàn)在我們要去父進(jìn)程中找到它.選擇VIEW-EJECUTABLE MODULE 查找KERNEL32.dll 這是GetProcAddress所屬的dll.

右擊VIEW-NAMES查找api GetProcAddress


寫下這個地址(紅箭頭).現(xiàn)在在PUPE中選擇子進(jìn)程,讓它去找search (BUSCAR)這個地址值. 不同的機(jī)器這個值會不同. 我的是77E5B332.在字節(jié)窗口你會看到前兩個字節(jié)是55 8B,所以在紙上寫下,并在PUPE中將其改為EB FE然后按下PARCHEAR

在那兒現(xiàn)在子進(jìn)程將會處于死循環(huán)中,我們可以說它已經(jīng)睡著了. 我們現(xiàn)在必須把它從它的父進(jìn)程那兒unhook下來.
在父進(jìn)程窗口任意處點(diǎn)擊鼠標(biāo)右鍵,選擇"新建起源"然后寫下下面的代碼
PUSH (son’shandle)
Call DebugActiveProcessStop
Nop (在這兒BPX并檢查是否EAX=1)

在0042F00A 下中斷,然后運(yùn)行一下停在0042F00A 處??纯醇拇嫫鞔翱诘腅AX值,如果這個值=01就表示子進(jìn)程和父進(jìn)程分離了。如果=00那么可能是子進(jìn)程的句柄填錯了, 你可以在下面重新寫入代碼再次運(yùn)行,直到EAX=01時就可以關(guān)閉OllyDbg了(殺掉父進(jìn)程?。┤缓缶涂梢赃M(jìn)入子進(jìn)程了。
重新運(yùn)行Ollydbg(不要加載程序)附加上子進(jìn)程.
再次在PUPE中恢復(fù)原來的代碼 55 8B并按 "Parchear" 再看看程序中的代碼又還原成了77E5B332.

程序?qū)袛?就像你在下圖中看到的.

讓我們看一下那個錯誤的entry,右擊轉(zhuǎn)儲dump窗口選擇GOTO EXPRESSION 5E9C34.

Bp GetProcAddress 然后按RUN. 你可以看到當(dāng)中斷時錯誤的entry已經(jīng)被重寫了,但是表并不完整. 重新打開一個ollydbg載入tute.exe.如果在5e9c8c下面還有一個錯誤的entry就看那兒.

以5E9c98處的錯值為例,因?yàn)槟莾簩粚懭隓F513C.

回到Getright.exe (第一個ollydbg)看一下堆棧. 那兒的API被Df4cB2處的called調(diào)用并將會返回到DF4cB8.
在主窗口中選擇GOTO EXPRESSION 0Df4cb8.



下圖是我的機(jī)器中這個call了API的call的地址. 在API返回處BPX(這個call的下一行).

點(diǎn)擊RUN
現(xiàn)在在錯誤entry 5E9c98上下HARDWARE BPX ON WRITE然后點(diǎn)擊RUN.當(dāng)在那兒寫入時將被斷下.

你可以看到在前面一行保存著錯誤值.后面指出這個錯值從[ebp-394]處來.所以在轉(zhuǎn)儲窗口中選擇GOTO EXPRESSION EBP-394. 那兒你將會看到這個值.下BREKPOINT HARDWARE ON ACCESS.

如果我按下運(yùn)行鍵,我將看到無論值是好是壞都在這一行被保存.看附近有一個call BPX它.

你可以看到這是關(guān)鍵call.因?yàn)楫?dāng)它結(jié)束時eax帶著稍后將寫入的值. 我測試了這個call里的每一個跳轉(zhuǎn)(只有5到6個,通常都是這樣):
00DF4B68 /75 03 JNZ SHORT 00DF4B6D
00DF4B79 /75 07 JNZ SHORT 00DF4B82
00DF4B8D /74 0C JE SHORT 00DF4B9B
00DF4B92 /74 1B JE SHORT 00DF4BAF
00DF4B99 ^75 F4 JNZ SHORT 00DF4B8F
勝利者是DF4B8D處的跳轉(zhuǎn). 正如我先前所說的在所有的armadillos里都是一樣的,所以當(dāng)我們在脫其它armadillo時,通過跟蹤這些代碼我們可以很容易發(fā)現(xiàn)這個好跳轉(zhuǎn).
00DF4B8D /74 0C JE SHORT 00DF4B9B
它必須永遠(yuǎn)跳轉(zhuǎn),所以我們做如圖修改:

清除BPX點(diǎn)擊run. (記住清除hardware bpx). 當(dāng)程序走到我們修改為死循環(huán)的指令那兒時輸入表已經(jīng)修復(fù)了,再也沒有壞值了. 然后它在子進(jìn)程的OEP處停下.在紙上寫下magic jump的值(EB 0C),記住.
我們將要重復(fù)那些步驟.當(dāng)我們走到上次我們unhook 子進(jìn)程那一步時,我們將要在magic jump處設(shè)置一個 infinite loop代替在API上設(shè)置.

在那兒從父進(jìn)程處unhook子進(jìn)程,然后它將在magic jump處死循環(huán).
附加子進(jìn)程,按 RUN, 然后停止(F12). 它將停在magic jump.

現(xiàn)在還沒有任何改變,因?yàn)閙agic jump還沒起作用.把它改回先前的值(EB 0C).

如果我們運(yùn)行程序,它將停在OEP,而且輸入表也很完美和完整.現(xiàn)在我們可以利用這個進(jìn)程用Import Reconstructor去修復(fù)在第一部分中轉(zhuǎn)儲的程序了.

所有的值都是好的.最后那幾個是指向dll的.

那些值指向Exxxxx,如果我們看看VIEW-MEMORY我們可以得知那是dll.

現(xiàn)在我們要用一下Import Reconstructor.
打開Import Reconstructor在"Attach to an Active Process"對話框選擇這個進(jìn)程.

裝載這些dll需要很長一段時間.當(dāng)完成后寫下OEP的值,表的起始地址值和表的長度,不要按IAT AutoSearch.

如圖在IMPORT RECONSTRUCTOR中那些值是這樣計(jì)算的:你在紙上寫下的值-Image Base. 比如: OEP=534E90, Image Base=400000, 534E90- 400000= 134E90. RVA也一樣 (表的起始地址值).
現(xiàn)在按GET IMPORTS. 所有的entries都修復(fù)了.



現(xiàn)在按FIX DUMP 載入轉(zhuǎn)儲文件.我把它叫做TUTE.exe

它將被保存為TUTE_.exe.原先的文件保持原樣.
到此armadillo保護(hù)已經(jīng)被擊敗了.
第四步:如何擊敗BOSS
如果我們嘗試運(yùn)行TUTE_.exe它會無故終止.上面我剛說已經(jīng)擊敗了armadillo,但是脫殼文件不能正常運(yùn)行.見鬼了?
程序員(bad guys)不想讓getright 5在我們的機(jī)器中自由運(yùn)行、解壓,然后他們做了手腳.
在OLLYDBG中載入tute_.exe.
運(yùn)行,你會發(fā)現(xiàn)它突然終止.
BPX GetEnvironmentVariableA 當(dāng)它中斷時我們需要改變條件跳轉(zhuǎn),當(dāng)從API返回程序時.
T看下圖.

這是中斷點(diǎn)BPX.現(xiàn)在返回程序用EXECUTE TILL RETURN 然后按一下F7.

這一流程將會重復(fù)多次,所以要熟練掌握.
修改跳轉(zhuǎn).

依次類推.

把JNZ改為JMP 你可以找到所有calls API然后修改臨近的跳轉(zhuǎn).我把那些跳轉(zhuǎn)羅列出來.

把JNZ改為JMP 你可以找到所有calls API然后修改臨近的跳轉(zhuǎn).我把那些跳轉(zhuǎn)羅列出來.

我想這個armadillo已經(jīng)被搞定了. Ricardo Narvaja 英文翻譯Tenshin. 中文翻譯:FTBirthday 完成了

相關(guān)文章

最新評論