Getright 5 手動(dòng)脫殼和重建IAT--第一部分(圖)
互聯(lián)網(wǎng) 發(fā)布時(shí)間:2008-10-08 19:05:36 作者:佚名
我要評(píng)論

這是一篇Armadillo加殼軟件Getright 5.01的脫殼譯文,我是參照Ricardo Narvaja的“Getright 5 脫殼和重建IAT”的文章以及Bighead[DFCG][YCG]的譯文,一邊實(shí)踐一邊再次翻譯的。感謝Ricardo Narvaja和Bighead[DFCG][YCG]。
Armadillo for Dummies: Getright 5 手動(dòng)脫殼
這是一篇Armadillo加殼軟件Getright 5.01的脫殼譯文,我是參照Ricardo Narvaja的“Getright 5 脫殼和重建IAT”的文章以及Bighead[DFCG][YCG]的譯文,一邊實(shí)踐一邊再次翻譯的。感謝Ricardo Narvaja和Bighead[DFCG][YCG]。
Armadillo for Dummies: Getright 5 手動(dòng)脫殼和重建 IAT (第一部分)
因?yàn)锳rmadillo實(shí)在是太復(fù)雜了,以至于人們已經(jīng)不得不沿用下面這個(gè)手動(dòng)的方法去脫殼armadillo,這不是我的過錯(cuò),只是因?yàn)閍rmadillo實(shí)在是太難脫殼了,然后我將會(huì)在這個(gè)文檔中一步一步地去完成脫殼,同時(shí)配上很多圖片,只是想讓它變得盡量容易理解.我并不想寫一個(gè)10兆大的參考教程,所以我把這個(gè)文檔分成兩部分.第一部分主要講如何轉(zhuǎn)儲(chǔ)(dump)armadillo保護(hù)的程序,然后我會(huì)在第二部分中提及一些以前在其它任何教程中都未曾見過的東西,那就是輸入表(import table)的redirection和rebuilding.
在我們開始之前,我必須聲明這篇參考教程只在Windows XP上測試.請(qǐng)不要在 windows98或者2000中嘗試.原因是只有Windows xp才擁有必要的API,能夠把子進(jìn)程(child)從它的父進(jìn)程father那兒脫鉤下來.
這次練習(xí),我們找到的自愿者是Getright 5 final. Crusader曾經(jīng)寫過關(guān)于這個(gè)軟件的某一個(gè)版本的參考教程,但是這篇參考教程在很多方面都不同于crusader寫的那篇.
crusader寫的那篇參考教程(原版)----附(1)
crusader寫的那篇參考教程(FTBirthday翻譯版本)----附(2)
你可以從以下連接下載GetRight 5.不管怎樣我在我的ftp中保存了一個(gè)副本,所以你可以從那兒下載,就不用去管它在網(wǎng)上被放在哪兒了.
http://www.getright.com/
抓起你的鼠標(biāo),安裝好Getright然后準(zhǔn)備作戰(zhàn).Armadillo將會(huì)變得軟弱無力.
如何脫殼(UNPACK)以及轉(zhuǎn)儲(chǔ)(DUMP)Getright 5
在OLLYBG中載入GETRIGHT.exe然后整裝待發(fā).我將按照以下的步驟,很容易記住的,你可以在其它任何armadillo保護(hù)軟件中按部就班.
第一步:重新設(shè)置檢測ISDEBUGGERPRESENT API的字節(jié)
我將要解釋如何在任何電腦中去尋找這個(gè)字節(jié).
首先從這個(gè)連接下載命令行插件:
http://dd.x-eye.net/file/cmdbar10802.zip
解壓它然后復(fù)制dll到OLLYDBG文件夾.只要你運(yùn)行Ollydbg你將會(huì)在調(diào)試窗口的左下角看到一個(gè)白色的輸入框,在那兒你可以鍵入很多命令.讓我們鍵入:
Bp IsDebuggerPresent
我們將要使用BP而不是BPX,因?yàn)锽P可以直接在API上下斷點(diǎn),那正是我們所需要的.
我們必須準(zhǔn)確地鍵入Bp IsDebuggerPresent.記住我們必須保證大小寫的順序,因?yàn)槿绻覀冩I入了任何不同于以上形式的命令,那么一個(gè)錯(cuò)誤提示(UNKNOWN COMMAND)將在命令行的右邊產(chǎn)生.所以正確地鍵入BP IsDebuggerPresent然后按回車. 如果在按回車后沒有錯(cuò)誤提示出現(xiàn),那就說明這個(gè)BP已經(jīng)生效.
現(xiàn)在按F9運(yùn)行程序,它將會(huì)中斷在API IsDebuggerPresent

在這張圖中我們可以看到OllyDBG中斷在API IsDebuggerPresent(紅色), 然后按F7步進(jìn)到第三行(白色)
77E52749 0FB640 02 MOVZX EAX,BYTE PTR DS:[EAX 2]
一旦到達(dá)那兒,看一下disassembly,在那兒我們可以看到如下圖的內(nèi)容:

這兒我們可以看到在我的機(jī)器中偏移是7ffdf002,包含了值01.這個(gè)地址在其它機(jī)器中可能會(huì)不同. 值01意味著調(diào)試器被檢測到了,所以寫下這個(gè)地址,在任何時(shí)候我們?cè)趏llydbg中運(yùn)行程序,都必須把它修改為00,從而避免被packer檢測到.記住在ollydbg中運(yùn)行或重運(yùn)行程序的任何時(shí)候修改此值為00.
我們將以重啟ollydbg (ctrl F2)來結(jié)束第一步,到轉(zhuǎn)儲(chǔ)窗口(DUMP)單擊右鍵選擇"前往 表達(dá)" 7ffdf002或者其它任何先前你記下的地址,然后把它的值從01修改為00.


把它改為00.

第二步:BP WAITFORDEBUGEVENT
這一步并非必要,但卻是一個(gè)好的選擇,當(dāng)它停止時(shí)在轉(zhuǎn)儲(chǔ)(DUMP)區(qū)看到report.讓我們看看該怎樣做.
首先我們需要在命令行輸入BP WaitForDebugEvent,和我們輸入IsDebuggerPresent的方法是相同的.
現(xiàn)在運(yùn)行它,當(dāng)它停下時(shí)我們可以在堆棧窗口(Stack window)看到關(guān)于這個(gè)API的所有參數(shù)信息.

看一下第二行.那兒我們可以看到它將在哪兒顯示report,所以到轉(zhuǎn)儲(chǔ)窗口(dump window), 右鍵選擇 "前往 表達(dá)"= 12EFF8.注意這個(gè)值在一些機(jī)器上可能會(huì)不同,所以前往你的機(jī)器顯示的值.

我們?cè)谏厦娴膱D中看到的是我們將要稱之為"API report"的東西.主程序(讓我們把它稱為Father)通過那里得知secondary program(讓我們把它稱為son)發(fā)生了什么.
現(xiàn)在我們可以很容易地通過在命令行輸入BC WaitForDebugEvent來刪除這個(gè)斷點(diǎn).
所有的操作都是為了在轉(zhuǎn)儲(chǔ)窗口(dump window)看到report,在這個(gè)report中我們可以看到入口點(diǎn)OEP(entry point).
第三步: BP WRITEPROCESSMEMORY

像圖中一樣設(shè)置這個(gè)斷點(diǎn)然后點(diǎn)擊"運(yùn)行".也許你會(huì)在一些例外(exceptions)處停下,但是你可以通過按SHIFT F9很容易地走過.一旦我們停在了WriteProcessMemory API不要做任何事情,看下圖:
正如我們?cè)谙聢D中看到的, father將要復(fù)制給son的第一個(gè)塊(block)的所有信息,都可以在堆棧窗口(STACK window)看到.

FTBirthday:由經(jīng)驗(yàn),我覺得很難走到這一步,但是我知道是在005F949E處call了WriteProcessMemory如圖:

我通過一遍遍試驗(yàn),得出了最好的方法:等到前兩次在別處call了WriteProcessMemory后,左手一直按住shift, 右手連續(xù)按F9大約31次,就可以順利到達(dá).
這些信息被保存在父進(jìn)程的一個(gè)緩沖區(qū)從3B8FB0開始,然后它會(huì)復(fù)制給子進(jìn)程一個(gè)從538000開始的 1000 bytes (BYTES TO WRITE)的塊(block),所以如果我們到了這一步,我們可以很容易理解child的第一個(gè)section是完全空的,所以當(dāng)它試圖執(zhí)行到OEP時(shí),它報(bào)告一個(gè)error因?yàn)槟莾簺]有任何東西,所以 father得到了通知正如我們可以在father的report中看到的,所以它停止了運(yùn)行,復(fù)制必要的數(shù)據(jù)塊,然后繼續(xù)運(yùn)行直到下一個(gè)error.被復(fù)制的數(shù)據(jù)塊的大小是1000 bytes,所以當(dāng)程序試圖執(zhí)行任何超過這個(gè)大小的block外的指令時(shí), 另一個(gè)error將會(huì)發(fā)生,然后這個(gè)error會(huì)被通知給father, father會(huì)復(fù)制另外1000 bytes的塊block然后繼續(xù).
順便說一下,我們可以假設(shè)第一個(gè)error發(fā)生是因?yàn)閟on (壞小子)call了它的入口點(diǎn)OEP,它的值應(yīng)該就在 report上.顯然OEP的值必定在第一個(gè)block,father復(fù)制過去來解決son報(bào)告的error.
這個(gè)塊從538000開始知道538fff.OEP值必定在這些值中. 讓我們看一下REPORT.看轉(zhuǎn)儲(chǔ)窗口(DUMP window) 我們先前已經(jīng)知道了指向report的指針12EFF8.

太好了!在那兒我們至少看到了三次這個(gè)值: 538540.數(shù)學(xué)課告訴我538540比538000大,比538fff小 (那些是father試圖拷貝給son的那個(gè)塊的起止值)所以我可以確信538540就是child的OEP.
讓我們從API WriteProcessMemory來改變斷點(diǎn)的性質(zhì).知道哪個(gè)塊被拷貝不是很好嗎.可以通過下面的方法做到.首先選擇bpx所在的行,按F2移除bpx.
右擊選擇"斷點(diǎn)/條件記錄".現(xiàn)在在對(duì)話框中準(zhǔn)確地填入如圖所示的值.這樣做的目的是使我們?cè)谟涗洿翱谥锌吹剿斜籪ather decrypts并拷貝給son的blocks.

第四步: NOP THE CRIPTER CALL
在先前的參考教程s中我們知道,這兒我們是在decripter call.Father為son decrypts了一個(gè)block.但是還有一個(gè)cripter call用來encrypts或者destroys已使用的blocks來避免被轉(zhuǎn)儲(chǔ)dump.現(xiàn)在的任務(wù)是如何找到這個(gè)call并把它nop掉.
我現(xiàn)在在WriteProcessMemory API,所以我打開"呼叫堆棧窗口"(Alt K)在那兒我可以看到:

在這個(gè)"呼叫堆棧窗口"越靠上面的是越最新被執(zhí)行的.從CALLED FROM 我們可以看到5F949E是father calls API的地方. 如果我們向下看,我們可以看到另一個(gè)call.所以我們獲得了decripter call的offset.
DECRIPTER CALL= 5F88D1
通過"前往 表達(dá)" 5F88D1跳到那兒 ,或者左鍵雙擊它.

這是好的CALL,它用來decrypts.現(xiàn)在去找壞的那個(gè),稍稍向下翻屏或者右擊選擇"查找參考/呼叫目標(biāo)" 選擇出現(xiàn)的兩個(gè)參考中的另一個(gè).

它在這兒呢!
重新加密的call--ENCRIPTER CALL = 5F8A24

現(xiàn)在我們把它nop掉.我們選擇這個(gè)call按空格寫入nop.

第五步: 運(yùn)行API并在OEP處設(shè)一個(gè)無限循環(huán)
現(xiàn)在到了執(zhí)行WriteProcessMemory一次了. 我們有兩條路可走,可以選擇執(zhí)行到返回它將會(huì)執(zhí)行直到RET,然后按一次F7. 第二個(gè)選擇是去stack第一行在那兒設(shè)一個(gè)BPX最后運(yùn)行它.
在stack第一行提示程序會(huì)返回到5F94A4, 我們到那兒BPX (F2)然后運(yùn)行它(F9).

現(xiàn)在該用PUPE了. PUPE是一個(gè)西班牙工具.你可以在www.google.com搜索一下. 通過下面幾行代碼我們將要在son的OEP設(shè)置一個(gè)無限循環(huán).這會(huì)使son休眠直到我們叫醒它.
這是一張PUPE的圖片.我們可以看到有兩個(gè)進(jìn)程, the son and the father.上面那個(gè)是son. 在右邊我們可以看到進(jìn)程句柄.

選擇上面那個(gè)getright.exe然后右擊選擇"parchear".

寫下出現(xiàn)在對(duì)話框中的original bytes然后用無限循環(huán)代碼EB FE代替,如下面的對(duì)話框中所示.
最后一步就是"PARCHEAR"然后INFINITE LOOP就準(zhǔn)備好了.

第六步: BP WAITFORDEBUGEVENT 和 NOP THE API
不要清除先前斷點(diǎn)WriteProcessMemory,是時(shí)候?qū)懭胄聰帱c(diǎn)了.鍵入BP WaitForDebugEvent回車, 然后按F9運(yùn)行

它停下時(shí)

你必須記住NEVER EVER RUN THIS API.在轉(zhuǎn)儲(chǔ)窗口"DUMP window"看一下report, 然后去堆棧窗口(STACK window).

正如我們看到的如果我們運(yùn)行這個(gè)API我們應(yīng)該去5F751D,所以讓我們通過"前往 表達(dá)" 5F751D到主窗口.

再一次提醒不要RUN THIS API.所以右擊5F751D選擇"新建起源".這是跳過這個(gè)API的方法.

現(xiàn)在我們必須nop the call to the api以及有關(guān)的push.

所以在這些行上按空格鍵然后寫入nop.當(dāng)你完成這項(xiàng)工作時(shí),將會(huì)如下圖所示. 這一步結(jié)束了.

第七步:如何打入補(bǔ)丁
當(dāng)做這一步時(shí)請(qǐng)注意.很多人不知道究竟該如何打補(bǔ)丁,所以努力試著理解我這里所作的, 然后學(xué)會(huì)在其它情況下運(yùn)用.
第一步是改變跳轉(zhuǎn),

我們將要改變這個(gè)跳轉(zhuǎn)為JMP 401000那是我們將要打補(bǔ)丁的地方, 父進(jìn)程offset 401000 .

跳轉(zhuǎn)設(shè)好了,現(xiàn)在去401000 (ctrl G)我們要開始寫補(bǔ)丁了. 在report中我們可以看到三次entry point value.也許OEP在其它情況下會(huì)出現(xiàn)更多次.但是我們只需改變這三個(gè).

father unpacks了在report中顯示的block.所以我們將要欺騙father則他會(huì)相信從第一個(gè)section開始的所有blocks都存在錯(cuò)誤, 一個(gè)接一個(gè)所有的blocks都會(huì)被unpacked.因?yàn)檫@一點(diǎn)我們需要知道第一個(gè) section的起止點(diǎn).點(diǎn)擊"查看/內(nèi)存"

這兒我們可以看到getright的sections.忽略Header section看text section,它從401000開始,結(jié)束在589000-1=588fff.
401000-588fff (第一個(gè)section的范圍)
我們將要在report中用400000代替OEP的值.

正如你在圖中看到的我寫入了40000,然后patch會(huì)在每一個(gè)loop前加1000,所以第一個(gè)被unpack的block將在401000.
現(xiàn)在我們將要在401000處寫下如下補(bǔ)丁.
00401000 8105 10F01200 0>picture1/add DWORD PTR DS:[12F010],1000
0040100A 8105 1CF01200 0>picture1/add DWORD PTR DS:[12F01C],1000
00401014 8105 20F01200 0>picture1/add DWORD PTR DS:[12F020],1000
這些行將我們先前在轉(zhuǎn)儲(chǔ)窗口(dump window)寫的值增加1000.那些藍(lán)色的值在不同的機(jī)器上可能會(huì)不同,所以修改為你在轉(zhuǎn)儲(chǔ)窗口(dump window)看到的實(shí)際值. 再次提醒,證實(shí)在轉(zhuǎn)儲(chǔ)窗口(dump window)寫入了00 00 40 .最容易犯的錯(cuò)誤就是在補(bǔ)丁(藍(lán)色的)中的offset和轉(zhuǎn)儲(chǔ)窗口(dump window)的offset不匹配.
下一行該這樣寫:
0040101E 813D 20F01200 0>CMP DWORD PTR DS:[12F020],getright.00589000
比較是為了讓我們知道何時(shí)所有的塊都被unpacked了.
然后我們必須寫下:
00401028 - 0F85 F6341F00 JNZ getright.005F7524
如果比較為假,則返回called loop的地方.然后我們需要在最后寫下NOP,在那兒我們將要設(shè)下一個(gè)BP. 當(dāng)它完成轉(zhuǎn)儲(chǔ)時(shí),它將會(huì)停在那兒.

這兒我們可以看到完整的補(bǔ)丁代碼
我們可以跟蹤第一個(gè)循環(huán),來檢測report中的each entry是否每次都增加1000.
第八步: UNPACK
按F9運(yùn)行程序然后等待它停在我們先前在補(bǔ)丁中設(shè)下nop的bpx處.如果沒有錯(cuò)誤發(fā)生,當(dāng)我們停止時(shí),看view-LOG我們將要看到所有的unpacked blocks.
這是假設(shè)的所有unpacked blocks的LOG.我沒有完整的給出因?yàn)榈胤讲粔虻悄憧梢栽谀愕娜罩敬翱谥胁榭?
所以現(xiàn)在從401000到589000(包括588fff)的所有blocks都被unpacked了,然后dump已經(jīng)就緒.
第九步:把CHILD從FATHER那兒脫鉤
一旦我們停在NOP,讓我們寫下下面幾行.
PUSH (child的handle )
Call DebugActiveProcessStop
如果handle由字母開始,你需要在它前面鍵入一個(gè)0,因?yàn)椴贿@樣做的話olly不會(huì)認(rèn)出. 想知道son的handle只需看一下pupe, 記住child的handle是在兩個(gè)進(jìn)程中的上面的那個(gè).你一樣可以通過opening file attach來獲得son的handle.那兒你可以看到兩個(gè)名稱相同的進(jìn)程. 紅的是father,黑的是son.在此情況下我得到的是B78 所以我將要寫下0B78.記住handle在每次運(yùn)行程序時(shí)都會(huì)改變.

在圖示的nop處下斷點(diǎn),然后運(yùn)行程序.看registers window,如果當(dāng)程序停止時(shí),EAX=1那意味著son已經(jīng)從father處脫鉤了,我們可以關(guān)閉OLLY.如果EAX=0 那么你要檢查那幾行代碼,因?yàn)槟憧赡芊噶藢戝e(cuò)誤(也許是寫錯(cuò)了handle).
現(xiàn)在關(guān)閉OLLYDBG,然后再次打開他.不要載入任何東西.前往"文件/附加"然后找son,附加它(我們搞定它的father了:X).
一旦附加成功,程序?qū)⒃贗NFINITE LOOP中 RUNNING ,需要按F12 to pause the去暫停程序,但是等一下,在做這個(gè)之前,我們先得把 EB FE改回原始值(那些我叫你記下的值,你有記下嗎?) 55 8B,然后我們將停在OEP,已經(jīng)準(zhǔn)備好dump了.


我們已經(jīng)準(zhǔn)備好dump了,所以打開LORD PE然后找Getright.exe

選擇Getright.exe進(jìn)程然后選擇INTELLIDUMP然后點(diǎn)擊DUMP FULL, 保存后啟動(dòng)PEEDITOR (從www.google.com上搜索它)然后寫入正確的ENTRY POINT值.
在這兒不要填寫538540,而寫入文件偏移,就像這樣: 538540-400000 = 138540.

那就是full dump.在本參考教程的第二部分我們會(huì)學(xué)習(xí)怎樣去找magic jump從而完成import table, 修復(fù)IAT,使程序運(yùn)行,因?yàn)樗O(shè)下了一些陷阱來避免被unpack.
現(xiàn)在我們保存轉(zhuǎn)儲(chǔ)(dump)文件(我把它命名為tute.exe),和原始的一樣,只是IAT不同.
第二部分再見.
Ricardo Narvaja
翻譯(西班牙語翻譯為英語)DEGETE和Tenshin,(英語翻譯為中文)FTBirthday.自由傳播,但是請(qǐng)保留作者的姓名.
相關(guān)文章
- “CMOS密碼”就是通常所說的“開機(jī)密碼”,主要是為了防止別人使用自已的計(jì)算機(jī),設(shè)置的一個(gè)屏障2023-08-01
QQScreenShot之逆向并提取QQ截圖--OCR和其他功能
上一篇文章逆向并提取QQ截圖沒有提取OCR功能, 再次逆向我發(fā)現(xiàn)是可以本地調(diào)用QQ的OCR的,但翻譯按鈕確實(shí)沒啥用, 于是Patch了翻譯按鈕事件, 改為了將截圖用百度以圖搜圖搜索.2023-02-04- QQ截圖是我用過的最好用的截圖工具, 由于基本不在電腦上登QQ了, 于是就想將其提取出獨(dú)立版目前除了屏幕錄制功能其他都逆出來了, 在此分享一下2023-02-04
非系統(tǒng)分區(qū)使用BitLocker加密導(dǎo)致軟件無法安裝的解決方法
很多電腦用戶在考慮自己電腦磁盤分區(qū)安全時(shí)會(huì)采用 Windows 自帶的 BitLocker 加密工具對(duì)電腦磁盤分區(qū)進(jìn)行加密。但有些人加密后就會(huì)忘記自己設(shè)置的密碼從而導(dǎo)致在安裝其它軟2020-11-25防止離職員工帶走客戶、防止內(nèi)部員工泄密、避免華為員工泄密事件的發(fā)生
這篇文章為大家詳細(xì)介紹了如何才能防止離職員工帶走客戶、防止內(nèi)部員工泄密、避免華為員工泄密事件的發(fā)生,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-27徹底防止計(jì)算機(jī)泄密、重要涉密人員離職泄密、涉密人員離崗離職前防范舉
近些年企業(yè)商業(yè)機(jī)密泄漏的事件屢有發(fā)生,這篇文章主要教大家如何徹底防止計(jì)算機(jī)泄密、重要涉密人員離職泄密、告訴大家涉密人員離崗離職前的防范舉措,具有一定的參考價(jià)值,2017-06-27量子計(jì)算機(jī)輕松破解加密算法 如何破解加密算法?
最近有電腦用戶反應(yīng)量子計(jì)算機(jī)可以破解下載的所有的加密算法嗎?其實(shí)也不是不可以,下面虛擬就為大家講解買臺(tái)量子計(jì)算機(jī),如何分分鐘破解加密算法2016-09-26怎么破解Webshell密碼 Burpsuite破解Webshell密碼圖文教程
webshell是以asp、php、jsp或者cgi等網(wǎng)頁文件形式存在的一種命令執(zhí)行環(huán)境,一種網(wǎng)頁后門。黑客通常會(huì)通過它控制別人網(wǎng)絡(luò)服務(wù)器,那么怎么破解webshell密碼呢?一起來看看吧2016-09-19針對(duì)Linux系統(tǒng)全盤加密的啟動(dòng)攻擊
本文討論了針對(duì)Linux系統(tǒng)全盤加密的冷啟動(dòng)攻擊,大家都認(rèn)為這種攻擊是可行的,但執(zhí)行這么一次攻擊有多難?攻擊的可行性有多少呢?需要的朋友可以參考下2015-12-28防止泄露公司機(jī)密、企業(yè)數(shù)據(jù)防泄密軟件排名、電腦文件加密軟件排行
面對(duì)日漸嚴(yán)重的內(nèi)部泄密事件,我們?nèi)绾问刈o(hù)企業(yè)的核心信息,如何防止內(nèi)部泄密也就成了擺在各個(gè)企業(yè)領(lǐng)導(dǎo)面前的一大問題。其實(shí),針對(duì)內(nèi)網(wǎng)安全,防止內(nèi)部信息泄漏早已有了比較2015-12-17