明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

Armadillo脫殼知識與方法大全

[摘要]近日對Armadillo殼很感興趣, 緣于它的多種組合的變化, 但仔細(xì)看來, 其保護(hù)的解決方法又有相對固定。 方法無外乎那么幾種脫殼方法(當(dāng)然排除有key和cc), 本人在本論 壇已對標(biāo)準(zhǔn)殼...

近日對Armadillo殼很感興趣, 緣于它的多種組合的變化, 但仔細(xì)看來, 其保護(hù)的解決方法又有相對固定。 方法無外乎那么幾種脫殼方法(當(dāng)然排除有key和cc), 本人在本論

壇已對標(biāo)準(zhǔn)殼的脫殼方法發(fā)貼, 但后來有所更新, 干脆總結(jié)在一塊吧, 以方便大家。 大家可以復(fù)制下來, 放在手邊, 脫殼時按步驟來。 我還是

一小鳥, 同大家一樣在逐漸成長中, 有不對的地方和不成熟的地方, 望大家批評指正, 共同進(jìn)步。

一、基本知識:

該殼有如下保護(hù):

(1)Debug-Blocker(阻止調(diào)試器)--解決方法就是忽略所有異常, 隱藏好OD, 如果加載時, 老出錯, 就多換幾個OD試試。

(2)CopyMem-II(雙進(jìn)程保護(hù))---解決方法是:用手動或者腳本使雙變單。

(3) Enable Import Table Elimination(IAT保護(hù)) –解決方法是用工具ArmaDetach再次載入加殼程序, 記下子進(jìn)程ID, 用另一OD載入, 利用斷

點(diǎn)GetModuleHandleA, 找到Magic Jump, 修改Magic Jump, 得到正確的IAT。

(4)Enable Strategic Code Splicing(遠(yuǎn)地址跳) , 解決方法就是用Arminline工具。

(5) Enable Nanomites Processing(簡稱CC), 就是把一些retn代碼變成CC(INT型), 解決方法:用Arminline工具或Enjoy工具。

(6)Enable Memory-Patching Protections(內(nèi)存保護(hù))

二、脫此類殼常用的斷點(diǎn):

1、WaitForDebugEvent(用于尋找非標(biāo)準(zhǔn)OEP和做補(bǔ)丁用)

2、WriteProcessMemory(用于尋找非標(biāo)準(zhǔn)OEP)

3、DebugActiveProcess(找子程)

4、OpenMutexA(雙進(jìn)程轉(zhuǎn)單進(jìn)程)

5、GetSystemTime(補(bǔ)丁KEY)

6、VirtualProtect(用于5.x)

7、CreateFileMappingA(用于5.x)

8、GetModuleHandleA/LoadLibraryA (用于找Magic Jump)

9、CreateThread(尋找OEP)

三、種類及脫殼方法

說明:對于此殼一般要隱藏OD。 如果按以下方法下斷OD斷不下來, 出錯, 就多換幾個OD試試, 在我脫殼中, 就有個情況, 下斷點(diǎn)后, 老斷不下

來, 多換了幾個OD就成功了。

(一)單線程標(biāo)準(zhǔn)方式

具體方法:2次斷點(diǎn)法加修改Magic Jump。

1、找Magic Jump

方法有二:

方法一、下斷點(diǎn)Bp GetModuleHandleA/he GetModuleHandleA/bp GetModuleHandleA+5/he GetModuleHandleA+5, 按shift+f9運(yùn)行, 當(dāng)經(jīng)過一個

call緩沖有點(diǎn)大時, 一般是在堆棧窗口出現(xiàn)ASCII "kernel32.dll"和ASCII "VirtualFree“后, 再運(yùn)行一次, 出現(xiàn)"kernel32.dll", 就是返回

時機(jī), 取消斷點(diǎn), 按alt+f9執(zhí)行到返回。

方法二、也可以下bp LoadLibraryA斷點(diǎn), 當(dāng)在堆棧窗口出現(xiàn)MSVBVM60.Dll函數(shù)時, 返回時機(jī), 在kernel32.LoadLibraryA下面有一個跳轉(zhuǎn), 一

般情況下, 這個跳轉(zhuǎn)比較大的話, 就改為jmp, 而跳轉(zhuǎn)比較小的話, 就改nop)。 [注:下此斷點(diǎn)的目的是找到Magic Jump, 修改Magic Jump目的

是避開的IAT的加密。 ]

2、找OEP

下斷點(diǎn)bp GetCurrentThreadId/bp CreateThread, shift+f9運(yùn)行, 中斷后, 取消斷點(diǎn), Alt+F9返回, 單步執(zhí)行, 看到一個call edi之類的。 F7

進(jìn)入, 即到oep。 OD不要關(guān)!打開import--選擇進(jìn)程--OEP輸入va--自動搜索IAT--獲取輸入表--顯示無效函數(shù)--CUT!

(二) 雙線程的標(biāo)準(zhǔn)殼

總體步驟:1、要雙變單;2、處理IAT, 修改Magic Jump;3、尋找OEP;4、修復(fù)

1、雙變單, 方法有三。

方法一:PATCH代碼法

下斷bp OpenMutexA, 斷下后, ctrl+g到00401000, 將空數(shù)據(jù)改為如下代碼:

0040100060 pushad

004010019C pushfd

00401002 68 A0FD1200 push xxxx(注:此處的xxxx為斷下后mutex name前的數(shù)值。 )

0040100733C0 xor eax,eax

0040100950 push eax

0040100A50 push eax

0040100BE8 E694A677call KERNEL32.CreateMutexA

004010109D popfd

0040101161 popad

00401012- E9 8F9FA777jmp KERNEL32.OpenMutexA

點(diǎn)右鍵選擇重建eip,f9運(yùn)行, 斷下后,取消斷點(diǎn),  ctrl+g到00401000, 恢復(fù)修改。

方法二, 下斷點(diǎn):bp OpenMutexA, SHIFT+F9, 斷下后,  ALT+F9返回, 返回后, 將返回代碼下面的第一個跳轉(zhuǎn)改為相反跳轉(zhuǎn), 再次SHIFT+F9,

斷下后, ALT+F9返回, 再次將返回代碼下面的第一個跳轉(zhuǎn)改為相反跳轉(zhuǎn)。 然后再一次SHIFT+F9,取消斷點(diǎn), 至此,同樣,雙進(jìn)程轉(zhuǎn)單進(jìn)程完畢!

方法三、除了用雙變單的腳本外, 還可以用一個工具ARMADETACH, 將帶殼的程序拖入, 記下子進(jìn)程的ID。

2、處理IAT, 修改Magic Jump。

用OD附加該子進(jìn)程, 加載后, ALT+F9返回, 修改前兩個字節(jié)為加殼程序載入時的前兩個字節(jié)。

下斷點(diǎn)bpGetModuleHandleA,  Shift+F9運(yùn)行, 一般是在堆棧窗口出現(xiàn)ASCII "kernel32.dll"和ASCII "VirtualFree“后, 再運(yùn)行一次, 出現(xiàn)

"kernel32.dll", 就是返回時機(jī), 中斷后alt+f9返回,在KERNEL32.LoadLibraryA下面找到Magic Jump!修改為jmp。 再下斷點(diǎn)bp 

GetCurrentThreadId/bp CreateThread(或往下拉找到兩個salc, 在其上面的jmp上下斷, Shift+F9, 斷下!如果文件有校驗(yàn), 則要撤消Magic 

Jump處的修改!打開內(nèi)存鏡像, 在00401000段下斷。 運(yùn)行, 中斷后, 刪除斷點(diǎn), alt+f9返回), F8單步走, 到第一個CALL ECX之類的東西時,

F7進(jìn)入。 到oep。

注:(對于有些OD有一個字符串溢出漏洞, 盡量用一些修正些錯誤的OD, 有些程序需要處理Anti, 方法如下:下斷點(diǎn)he OutputDebugStringA

斷下后, 選中%s%之類的字符, 在數(shù)據(jù)窗口跟隨, 點(diǎn)右鍵->二進(jìn)制->使用00填充, 中斷2次!都如上修改, 刪除此斷點(diǎn)。

3、修復(fù)。

(三)CopyMem-ll +Debug-Blocke保護(hù)方式

1、先找OEP, 兩個斷點(diǎn)。 (1)斷點(diǎn)bp WaitForDebugEvent,運(yùn)行, 中斷后看堆棧, 在一行有“pDebugEvent”字樣的那一行右鍵點(diǎn)擊“數(shù)據(jù)窗口

跟隨”, 取消斷點(diǎn)。 (2)bp WriteProcessMemory,運(yùn)行, 中斷后, 在數(shù)據(jù)窗口(要地址顯示)發(fā)現(xiàn)oep。

2、patch代碼, 解碼。 方法:重新載入, bp WaitForDebugEvent,運(yùn)行, 中斷, 取消斷點(diǎn), alt+f9返回, CTRL+F搜索命令:or eax, 0FFFFFFF8

, 找到后, 先往上看, 可以看到兩個CMP, 一個是“cmp dword ptr ss:[XXXX],0”在這里下硬件執(zhí)行斷點(diǎn), Shift+F9運(yùn)行, 中斷后取消斷點(diǎn)。

這時看信息窗口:SS[XXXXX]=00000000, 如果這個值不為0的話, 需要將其清0, 如果為0就不用了。 第二個CMP, cmp ecx,dword ptr ds:[XXXX]

, 下面開始解碼。 在這里要記下幾個地址:(1)cmp dword ptr ss:[XXXX],0前的地址和[]內(nèi)的值。 (2)第二個CMP中[]中的值。 接著or eax

, 0FFFFFFF8處往下, 可以找到一處為and eax, 0FF的代碼, 從這里開始Patch, 代碼如下:

inc dword ptr ds:[] //第一個CMP內(nèi)的值

mov dword ptr ds:[XXXX+4],1//XXXX為第二個CMP[]內(nèi)的值

jmp XXXX//第一個CMP前的地址

修改好后, 去掉所有斷點(diǎn), 向下找到第一個CMP下面的跳轉(zhuǎn)所跳到的地址, 來到這個地址, 下硬件執(zhí)行斷點(diǎn), Shift+F9運(yùn)行, 此時代碼解壓完畢

, 可以脫殼。

3、脫殼。 運(yùn)行LordPE,將子進(jìn)程dump出來, 這里的子進(jìn)程就是LordPE第2個進(jìn)程(有2個同名進(jìn)程)。 Dump后用LordPE修改入口點(diǎn)為在第一步中查

到的OEP。

4、修復(fù)輸入表、IAT的尋找

脫殼后不要急著去修復(fù)輸入表, 得先把RVA數(shù)據(jù)獲取, 用OD載入Dump出來的程序, 右鍵搜索二進(jìn)制字符串, 輸入FF25, 找到一個函數(shù), 在數(shù)據(jù)窗

口跟隨, 在數(shù)據(jù)窗口向上找到全是0的地方, 記下地址, 再向下找到全是0的地方, 記下地址。

5、加載子程序。

(1)找子程序pid的方法有二:

方法一:用OD載入原程序(脫殼前的程序), 下斷點(diǎn):bp DebugActiveProcess, 中斷后看堆棧, 記下Processid后面的值(這個值不是每次都

相同的)。 OD不要關(guān)。

第二種方法就是用工具ArmaDetach, 將加殼程序拖入。 記下子程序的pid和前兩個字節(jié)。

(2)另開一個OD, 附加Processid后面的值進(jìn)程或用工具ArmaDetach所記下的進(jìn)程id, 附加后, ALT+F9返回程序, 將前兩個字節(jié)改為原程序載

入時的前兩個字節(jié)。

6、下面的做法就和標(biāo)準(zhǔn)殼的一樣了, 在附加的OD中:

雙變單:方法有二。 其一:patch法。 其二修改跳轉(zhuǎn)法。

方法一:下斷點(diǎn)BP OpenMutexA(雙變單), F9運(yùn)行, 斷下后, ctrl+g到00401000, 將空數(shù)據(jù)改為如下代碼:

0040100060 pushad

004010019C pushfd

00401002 68 A0FD1200 push xxxx(注:此處的xxxx為斷下后name前的數(shù)值。 )

0040100733C0 xor eax,eax

0040100950 push eax

0040100A50 push eax

0040100BE8 E694A677call KERNEL32.CreateMutexA

004010109D popfd

0040101161 popad

00401012- E9 8F9FA777jmp KERNEL32.OpenMutexA

點(diǎn)右鍵選擇重建eip,f9運(yùn)行, 斷下后,取消斷點(diǎn),  ctrl+g到00401000, 恢復(fù)修改。

方法二:下斷點(diǎn)BP OpenMutexA, SHIFT+F9運(yùn)行, 斷下后, ALT+F9返回, 返回后, 將返回代碼下面的第一個跳轉(zhuǎn)改為相反跳轉(zhuǎn), 再次SHIFT+F9

, 斷下后, ALT+F9返回, 再次將返回代碼下面的第一個跳轉(zhuǎn)改為相反跳轉(zhuǎn)。 然后再一次SHIFT+F9,取消斷點(diǎn), 至此,同樣,雙進(jìn)程轉(zhuǎn)單進(jìn)程完畢!

此法相對簡單, 另外適用于00401000空數(shù)據(jù)不能修改的程序。

(2)修改Magic Jump 。

下斷BP GetModuleHandleA+5, 運(yùn)行, 一般是在堆棧窗口出現(xiàn)ASCII "kernel32.dll"和ASCII "VirtualFree后, 再運(yùn)行一次, 就是返回時機(jī), 中

斷后alt+f9返回,在KERNEL32.LoadLibraryA下面找到Magic Jump!修改為jmp。 清除所有斷點(diǎn), 再直接按F9運(yùn)行, 出現(xiàn)暫停。 這時大功告成。

(3)用Imprec1.6f選擇進(jìn)程附加的那個進(jìn)程, 填入OEP地址, 填第4步所記下的RAV, SIZE=1000, 不要按自動搜索IAT, 直接按獲取輸入表, 再

按顯示無效地址, 剪掉修復(fù)抓取文件就OK了。

(四)全保護(hù)脫殼脫殼方法

1、雙變單可以用以下方法, 也可以用腳本, 目的是雙變單。 記下程序加載時的前兩個字節(jié)。 運(yùn)行腳本后, 記下OEP的前兩個字節(jié), OEP地址和子

進(jìn)程ID。

2、用OD附加子進(jìn)程, 加載后, ALT+F9返回, 修改前兩個字節(jié)為腳本記載的OEP的前兩個字節(jié)。

3、處理IATL輸入表

方法:(1)用工具ARMADETACH, 將帶殼的程序拖入, 記下子進(jìn)程的ID。 (2)另開一OD, 附加該子進(jìn)程, 加載后, ALT+F9返回, 修改前兩個字

節(jié)為加殼程序載入時的前兩個字節(jié)。 (3)修改Magic Jump , CTRL+G, 輸入GetModuleHandleA, 在其下面的第一個跳轉(zhuǎn)下硬件執(zhí)行斷點(diǎn),

Shift+F9運(yùn)行, 一般是在堆棧窗口出現(xiàn)ASCII "kernel32.dll"和ASCII "VirtualFree后, 再運(yùn)行一次, 就是返回時機(jī), 中斷后alt+f9返回,在

KERNEL32.LoadLibraryA下面找到Magic Jump!修改為jmp。 往下拉找到兩個salc, 在其上面的jmp上下斷, Shift+F9, 斷下!撤消Magic Jump處

的修改!CTRL+G, 輸入GetCurrentThreadId/ CreateThread, 下斷, 運(yùn)行, 中斷后, 刪除斷點(diǎn), alt+f9返回, F8單步走, 到第一個CALL ECX之

類的東西時, F7進(jìn)入。 (此時的OEP是偽OEP, 但此時的IAT是正確的。 先開的OEP是對的, 但I(xiàn)AT是錯誤的)。 (4)打開先前的OD, CTRL+B, 搜

索FF25, 在數(shù)據(jù)窗口跟隨, 找到函數(shù)的起始位置, 選定1-3個, 二進(jìn)制復(fù)制, 打開后面所開的OD, 打開內(nèi)存鏡像, 在此界面中點(diǎn)一下, 二進(jìn)制搜

索, 將剛才復(fù)制的粘貼, 找到后, 在轉(zhuǎn)存窗口, 找到函數(shù)的起始地址, 選定到末尾, 將選定的函數(shù)復(fù)制到先前開的OD的數(shù)據(jù)窗口, 要對整齊(

起點(diǎn)要一樣), 這時, 后開的OD的任務(wù)完成(目的就是將未加密的IAT找到)。

4、用AMINLINE工具修復(fù), 選擇第一個OD所用的子進(jìn)程, 在Code Splicing中開始Code的地址自動給填好了, 但長度需要設(shè)置一下, 大一些,

20000左右就可以了, 修復(fù)。 在IAT的長度要根據(jù)實(shí)際情況, 一般選1000即可, 依次進(jìn)行修復(fù), 修復(fù)后, 在OD中修復(fù)的地方都變成紅色。

5、用Imprec修復(fù), 無效指針CUT。

6、如果有類似自校驗(yàn)的, 則用AMINLINE工具中的nanomites選項(xiàng)修復(fù)。


上面是電腦上網(wǎng)安全的一些基礎(chǔ)常識,學(xué)習(xí)了安全知識,幾乎可以讓你免費(fèi)電腦中毒的煩擾。