關於Armadillo 1.8x-2.x的anti-debug&加殼原理初步探討和脫殼方法 (12千字)
目標軟體:Wealth-Lab Developer 2.0
目標檔案:WealthLab.exe
加殼方式:Armadillo 1.8x-2.x
使用工具:WinDbg或trw2000, peditor, WinHex 10.2 SR-2,m$的win32 sdk文件
URL: http://www.silicmdr.com/downloads/WealthLabSetup.exe
本文作者:leo_cyl
論題中關於Armadillo 外殼的討論很少,以前hying曾經寫過一些,但很少人能理解,現在就
以Wealth-Lab Developer 2.0為例子初步探討對付Armadillo 外殼的方法。因為我在xp下沒裝s-ice
,只有WinDbg可用,所以本文兼做WinDbg的簡單教學吧,同時為照顧使用trw2000的朋友,我會列出
等價的trw命令。
Armadillo 外殼反跟蹤和反dump挺強的,(至少用procdump不行)。當我們執行
WealthLab.exe後,在Program Files\Wealth-Lab Developer 2.0目錄下產生WEALTHLAB.TMP0檔案。
這是個不能執行的脫殼檔案,也是Armadillo 外殼的至命弱點。
(一)對anti-debug的分析
首先WealthLab.exe透過CreateFileA 產生ArmXXXX.tmp 檔案(在window的temp目錄)並作為
dll載入,Armadillo的一些重要功能在ArmXXXX.tmp中,它的一個主要引出函式是GetProgramInfo,
作用是un-packing 和 un-encrypting ,還有就是檢查系統中有無偵錯程式。
用WinDbg載入WealthLab.exe,因為Armadillo採用seh技術改變程式的流程,所以使用以下命
令“sxd *”就是告訴WinDbg捕獲異常後不要處理,有原程式處理,對應trw2000的命令是“faults
off”,另外Armadillo 呼叫IsDebuggerPresent來判斷系統中有無偵錯程式,如果用trw2000,當然檢
查不到,但用WinDbg時要下斷點“bp IsDebuggerPresent”,然後f5執行……中斷後來到這裡:
kernel32!IsDebuggerPresent:
77e52e92 64a118000000 mov eax,fs:[00000018]
77e52e98 8b4030 mov eax,[eax+0x30]
77e52e9b 0fb64002 movzx eax,byte ptr [eax+0x2]
77e52e9f c3 ret
《==== eax=1表示系統有偵錯程式,所以將eax改為0
(如果用trw2000,忽略這裡)
然後f5執行……中斷後來到這裡:
04064be 33854cfbffff xor
eax,[ebp-0x4b4]
004064c4 8be8 mov
ebp,eax
004064c6 b804000000 mov eax,0x4
004064cb cc int
3 〈==== seh技術!
004064cc 8b0dbc574100 mov
ecx,[image00400000+0x157bc (004157bc)]
看一下seh鏈“dd fs:0”最後查到地址40a944。下命令“gn
40a944”(trw2000中要用 INT3HERE
OFF命令,並下斷點bpx 40a944)來到這裡:
0040a944
55 push ebp
0040a945 8bec mov ebp,esp
0040a947 83ec08 sub esp,0x8
0040a94a 53 push
ebx
0040a94b 56 push
esi
0040a94c 57 push
edi
0040a94d 55 push
ebp
0040a94e fc cld
……
……
以上程式碼產生ArmXXXX.tmp,並獲得引出函式地址(在此忽略),執行到00406807
時將呼叫
GetProgramInfo
004067f6 mov dword ptr [ebp-0x134],0x4157dc
00406800 lea ecx,[ebp-0x154]
00406806 push
ecx
00406807 call dword ptr [ebp-0x490]{ARM1!GetProgramInfo
(1000b0c0)} 〈=進入
0040680d add esp,0x4
00406810
and eax,0xff
00406815 test eax,eax
00406817
jnz image00400000+0x6823 (00406823)
進入ARM1!GetProgramInfo
(1000b0c0)後來到這……
1000913c 8065d800 and
byte ptr [ebp-0x28],0x0
10009140 8365fc00
and dword ptr [ebp-0x4],0x0
10009144 0f018dbcfdffff sidt
[ebp-0x244] 〈==[ebp-0x244]中防入idt表
1000914b 8b85befdffff
mov eax,[ebp-0x242]
10009151 83c008
add eax,0x8 〈=== int2 handle的地址
10009154 8b18 mov ebx,[eax]
10009156 83c010 add eax,0x10
〈===int3 handle的地址
10009159 8b00
mov eax,[eax]
1000915b 25ffff0000
and eax,0xffff
10009160 81e3ffff0000 and
ebx,0xffff
10009166 2bc3
sub eax,ebx 〈== int2,3 handle的地址相減
10009168
83f81e cmp eax,0x1e
1000916b
7547 jnz ARM1!ReleaseHook+0x3c5b
(100091b4)
1000916d 8b8548fcffff mov eax,[ebp-0x3b8]
10009173 050c010000 add eax,0x10c
這是第二個anti-debug程式碼,判斷int2,3 handle地址的距離,正常的話小於0x1e。如果安裝了
int3 handle(某些偵錯程式會)的話,大於0x1e。奇怪的是WinDbg不能走完這段程式碼,在1000914b
處異常(trw2000就可以)。所以在10009144 處,我把eip改到10009168,並改eax小於0x1e。
f5繼續執行,其間在kernel32!IsDebuggerPresent又會中斷一次,將返回值改為0;來到這裡:
1000b82e push
ebx
1000b82f push 0x3
1000b831 push
ebx
1000b832 push eax
1000b833 call ARM1!GetProgramInfo+0x8c8
(1000b988)
1000b838 pop ecx
1000b839 push
eax
1000b83a call dword ptr [10013048]{kernel32!CreateFileA
(77e5a837)}
1000b840 cmp eax,0xffffffff
1000b843 jz
ARM1!GetProgramInfo+0x78e (1000b84e)
1000b845 push
eax
1000b846 call dword ptr [ARM1!NukeNow+0x6da1 (10013044)]
1000b84c jmp ARM1!GetProgramInfo+0x799 (1000b859)
1000b84e
call dword ptr [10013060]{ntdll!RtlGetLastWin32Error}
1000b854
cmp eax,0x2
1000b857 jz ARM1!GetProgramInfo+0x79d
(1000b85d)
1000b859 mov byte ptr [ebp-0x1],0x1
eax為"\\.\SICE",
"\\.\NTICE", 和 "\\.\SIWDEBUG" ,哈哈,檢測s-ice!如果它們存在或
RtlGetLastWin32Error(win98是GetLastError
)不等於2,將設立DEBUG 標誌。注意這裡重複3次
。
以上是anti-debug的分析,對付它的方法大家都知道了吧!
:)
(二)脫殼
WealthLab.exe執行後,在工作目錄下產生WEALTHLAB.TMP0檔案。這是個不能執行的脫殼檔案
。把改名為WEAL-NUPACK.exe。用peditor檢視,OEP是4086fc。用WinHex 10.2開啟,發現從0x400到
0x40400共256k的內容被添入0x58,即 pop eax的機器碼。只要找回這部分程式碼就是完整的脫殼檔案
了。但不能用procdump,系統會崩潰,幸好WinHex提供了類似功能。先用peditor的FLC計算器計算
0x400和0x40400的虛擬地址,分別是0x401000,0x441000。
WealthLab.exe執行後,在執行WinHex
,按ALT+F9 開始記憶體編輯,選WEALTHLAB.TMP0程式,
來到偏移0x401000初,選0x401000到0x441000(共256k)的一塊記憶體,複製下來,並把它貼上到
WEAL-NUPACK.exe對應的地方(0x400到0x40400共256k)。
到此已經把加殼檔案還原了,但還是不能執行!why?呵呵……因為OEP不對嘛!
(三)找OEP
前面兩步還挺容易,找OEP卻把我難住了,足足花了3個小時才找到。因為外殼和原程式在兩個
不同的程式中,地址空間不一樣,debug起來有困難,幸好我們知道是外殼產生了原程式的程式,所
以斷點CreateProcessA是關鍵!
從新載入WealthLab.exe,躲過anti-debug,繼續從第一步描述的地址開始,下斷點“bp
CreateProcessA”,來到這裡:
:00408908 6820594100
push 00415920
:0040890D 8D45B8
lea eax, dword ptr [ebp-48]
:00408910
50
push eax
:00408911 6A00
push 00000000
:00408913 6A00
push 00000000
:00408915 6A04
push 00000004
:00408917
6A00 push
00000000
:00408919 6A00
push 00000000
:0040891B 6A00
push 00000000
* Reference To: KERNEL32.GetCommandLineA,
Ord:00CAh
|
:0040891D FF15D4004100
Call dword ptr [004100D4]
:00408923 50
push eax
:00408924 8B4D08
mov ecx, dword ptr [ebp+08]
:00408927 51
push ecx
* Reference To: KERNEL32.CreateProcessA,
Ord:0044h
|
:00408928 FF1544004100
Call dword ptr [00410044]
:0040892E 85C0
test eax, eax
:00408930 7527
jne 00408959
:00408932 C705E057410009000000 mov dword ptr [004157E0],
00000009
外殼在這裡產生WEALTHLAB.TMP0程式,在此前已經把環境變數和命令列引數設定好了。f10執行10多
行來到這裡:
* Reference To: KERNEL32.ResumeThread, Ord:022Ch
|
:00406DC1 FF152C004100
Call dword ptr [0041002C]
……
……
……
* Reference To: KERNEL32.GetExitCodeProcess, Ord:010Bh
|
:00406DE2 FF1540004100
Call dword ptr [00410040]
:00406DE8 81BD4CF2FFFF03010000
cmp dword ptr [ebp+FFFFF24C], 00000103
:00406DF2 7423
je 00406E17
:00406DF4
C705E05741000A000000 mov dword ptr [004157E0], 0000000A
……
……
……
* Reference To: KERNEL32.Sleep, Ord:0296h
|
:00406E19 FF1558004100
Call dword ptr [00410058]
:00406E1F 8B1524594100
mov edx, dword ptr [00415924]
:00406E25
52
push edx
* Reference To: KERNEL32.SuspendThread, Ord:0298h
|
:00406E26 FF1554014100
Call dword ptr [00410154]
:00406E2C 83F8FF
cmp eax, FFFFFFFF
:00406E2F
7530 jne
00406E61
……
……
……
* Reference To: KERNEL32.GetThreadContext,
Ord:0167h
|
:00406E6F FF1538004100
Call dword ptr [00410038]
:00406E75 85C0
test eax, eax
:00406E77 7530
jne 00406EA9
:00406E79 C705E05741000A000000 mov dword ptr [004157E0],
0000000A
:00406E83 A124594100
mov eax, dword ptr [00415924]
注意,實際上外殼自身作為偵錯程式來啟動WEALTHLAB.TMP0程式,把WEALTHLAB.TMP0程式掛起後呼叫
GetThreadContext獲得執行緒Context即“執行緒上下文”,如果不懂的話,請看看有關作業系統原理的
書吧。獲得執行緒Context有什麼用呢?等一下有說明……,繼續執行:
* Reference To: KERNEL32.ResumeThread, Ord:022Ch
|
:00406ED2 FF152C004100
Call dword ptr [0041002C]
:00406ED8 E9EAFEFFFF
jmp 00406DC7
……
……
……
* Reference To: KERNEL32.VirtualProtectEx, Ord:02C4h
|
:00406F08 FF1558014100
Call dword ptr [00410158]
:00406F0E 85C0
test eax, eax
:00406F10 7523
jne 00406F35
:00406F12 C705E05741000A000000 mov dword ptr [004157E0], 0000000A
……
……
……
:00406F35 8D8554F2FFFF
lea eax, dword ptr [ebp+FFFFF254]
:00406F3B 50
push eax
:00406F3C 6A02
push 00000002
:00406F3E 6894554100
push 00415594
:00406F43 8B0DCC224100
mov ecx, dword ptr [004122CC]
:00406F49 330DD8224100
xor ecx, dword ptr [004122D8]
:00406F4F
330DE0224100 xor ecx, dword ptr [004122E0]
:00406F55 330DF0224100 xor ecx,
dword ptr [004122F0]
:00406F5B 51
push ecx
:00406F5C 8B1520594100
mov edx, dword ptr [00415920]
:00406F62
52
push edx
* Reference To: KERNEL32.WriteProcessMemory, Ord:02E9h
|
:00406F63 FF1534004100
Call dword ptr [00410034]
:00406F69 85C0
test eax, eax
:00406F6B 7523
jne 00406F90
看看上面程式碼,呵呵…… 原來外殼將WEALTHLAB.TMP0程式的部分段(即內容是0x58的那部分)設為
類似不可讀寫或執行的屬性,來觸發自己解碼。前面說過外殼將作為偵錯程式而WEALTHLAB.TMP0正好
是被偵錯程式!具體可看看hying以前關於Armadillo
外殼的帖子,精華里有。
繼續執行:
:00407035 6A64
push 00000064
* Reference To: KERNEL32.Sleep,
Ord:0296h
|
:00407037 FF1558004100
Call dword ptr [00410058]
:0040703D 8B0DD4224100
mov ecx, dword ptr [004122D4]
:00407043
330DF8224100 xor ecx, dword ptr [004122F8]
:00407049 330DE0224100 xor ecx,
dword ptr [004122E0]
:0040704F 330DF0224100
xor ecx, dword ptr [004122F0]
:00407055 898D18F3FFFF
mov dword ptr [ebp+FFFFF318], ecx
:0040705B 8D9560F2FFFF
lea edx, dword ptr [ebp+FFFFF260]
:00407061
52
push edx
:00407062 A124594100
mov eax, dword ptr [00415924]
:00407067 50
push eax
* Reference To: KERNEL32.SetThreadContext, Ord:0283h
|
:00407068 FF158C004100
Call dword ptr [0041008C] 〈==關鍵啊!!!
:0040706E 85C0
test eax, eax
:00407070
7523 jne
00407095
外殼呼叫SetThreadContext來改變WEALTHLAB.TMP0程式的eip來達到改變EOP的目的!!!
關於SetThreadContext的說明請看MSDN文件。其中edx是Context指標,edx+b8是eip的值;
下命令“dd edx+b8"將看到OEP的地址是006a19c4。(有關Context結構請看附錄),用peditor將
WEAL-NUPACK.exe的OEP改為006a19c4,到此脫殼完成,脫殼檔案完美執行!!
(四)總結
外殼作為偵錯程式來除錯加殼程式,並利用類似頁異常的處理方式來動態解碼,利用除錯函式
SetThreadContext來動態改變加殼程式的OEP,達到隱藏OEP的目的。
其實相對來說,Armadillo 比aspr要容易多了,(如果你對window的除錯原理有了解的話)如
果再加上類似aspr的花指令和反反覆覆的seh,來加強反靜態分析,應該是個保護很強的外殼。
附錄:
Context結構的宣告(來自winnt.h
註釋是我加的)
typedef struct _CONTEXT86 {
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
FLOATING_SAVE_AREA FloatSave; //FLOATING_SAVE_AREA的大小是112byte
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD
Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
// 偏移是0xb8
DWORD
Eip;
DWORD SegCs;
// MUST BE SANITIZED
DWORD EFlags;
// MUST BE SANITIZED
DWORD
Esp;
DWORD SegSs;
} CONTEXT86;
相關文章
- Armadillo 2.52加殼原理分析和改進的脫殼方法
(12千字)2015-11-15
- ASPR1.2x新版本的脫殼初步探討 (5千字)2015-11-15
- 用Armadillo標準加殼的程式的脫殼和引入表修復方案---OLLYDBG (8千字)2015-11-15
- Armadillo3.60
加殼的EXE檔案脫殼全過程2004-09-08
- 關於用ASProtect v1.3加殼軟體的脫殼方法體會 (5千字)2001-11-21
- 加殼技術探討-加殼時處理IAT2015-11-15
- 關於雙程式Armadillo標準殼的脫法2015-11-15
- 壹次脫殼法――Armadillo 雙程式標準殼 快速脫殼2015-11-15
- 殼的工作原理脫殼2013-04-10
- 脫殼----對用pecompact加殼的程式進行手動脫殼
(1千字)2000-07-30
- Armadillo 3.6主程式脫殼2015-11-15
- ASPROtect 1.22加殼的ahaview2.0脫殼 (5千字)2002-03-24View
- 實戰Armadillo V3.60標準加殼方式的脫殼――WinXP的Notepad2015-11-15
- 對PECompact加殼的DLL脫殼的一點分析 (7千字)2000-08-17
- 脫殼----對用Petite2.2加殼的程式進行手動脫殼的一點分析
(5千字)2000-07-27
- Armadillo V3.01標準加殼方式的脫殼(第一篇)--SoundEdit
Pro2015-11-15
- Armadillo V2.xx標準加殼方式的脫殼(第二篇)--Virtual
Personality 4.02015-11-15
- telock脫殼總結 (12千字)2001-09-27
- 手動脫殼的教程(由petite v2.2加殼) (4千字)2001-11-26
- Armadillo V3.6雙程式標準殼 ------神速脫殼大法2015-11-15
- 談談如何使用加殼保護自己的軟體不被常用方法脫殼(2千字)2000-10-10
- iOS逆向學習之五(加殼?脫殼?)2019-10-10iOS
- Asprotect 1.2x 加殼的 Advanced Direct
Remailer 2.17 脫殼 (3千字)2002-06-20REMAI
- 脫ASPack2.12加殼的DLL檔案簡便方法2004-12-18
- 用OD對Aspr加殼程式的手動脫殼及修復 (7千字)2015-11-15
- 關於java加殼和程式碼混淆2014-08-16Java
- 股市風暴4.0的外殼分析與脫殼方法(一) (7千字)2001-06-10
- Armadillo殼時間問題的解決And脫殼――Mr.Captor
V2.82015-11-15APT
- 怎樣脫pklite32, Shrinker 3.4 和 NeoLite加的殼(3千字)2000-07-31
- ASPRTECT1.2X加殼的Delphi
Application Peeper Pro 2.3.1.9 脫殼(簡單) (3千字)2002-04-06APP
- aspr脫殼總結(部分適用於其他殼保護) (3千字)2001-09-14
- ExeStealth 常用脫殼方法 + ExeStealth V2.72主程式脫殼2015-11-15
- FTPrint的脫殼(asprotect) (2千字)2001-02-05FTP
- Thebat!139脫殼詳情及對Asprotect加殼保護的一點小結
(4千字)2000-03-27BAT
- 小甜餅 --- 有關新版Asprotect加殼程式的脫殼的又一種思路
(798字)2000-09-10
- Krypton
0.5加殼程式脫殼及輸入表修復記2004-10-06
- 脫Crunch/PE -> BitArts的殼。 (3千字)2002-05-03
- jdpack的脫殼及破解 (5千字)2002-06-25