目标软件: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
1 2 下一页 |