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

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

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

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


把它改為00.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

選擇上面那個getright.exe然后右擊選擇"parchear".

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

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

它停下時

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

正如我們看到的如果我們運行這個API我們應該去5F751D,所以讓我們通過"前往 表達" 5F751D到主窗口.

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

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

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

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

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

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

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

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

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

這兒我們可以看到完整的補丁代碼
我們可以跟蹤第一個循環(huán),來檢測report中的each entry是否每次都增加1000.
第八步: UNPACK
按F9運行程序然后等待它停在我們先前在補丁中設下nop的bpx處.如果沒有錯誤發(fā)生,當我們停止時,看view-LOG我們將要看到所有的unpacked blocks.
這是假設的所有unpacked blocks的LOG.我沒有完整的給出因為地方不夠但是你可以在你的日志窗口中查看.
所以現(xiàn)在從401000到589000(包括588fff)的所有blocks都被unpacked了,然后dump已經(jīng)就緒.
第九步:把CHILD從FATHER那兒脫鉤
一旦我們停在NOP,讓我們寫下下面幾行.
PUSH (child的handle )
Call DebugActiveProcessStop
如果handle由字母開始,你需要在它前面鍵入一個0,因為不這樣做的話olly不會認出. 想知道son的handle只需看一下pupe, 記住child的handle是在兩個進程中的上面的那個.你一樣可以通過opening file attach來獲得son的handle.那兒你可以看到兩個名稱相同的進程. 紅的是father,黑的是son.在此情況下我得到的是B78 所以我將要寫下0B78.記住handle在每次運行程序時都會改變.

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


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

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

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