(题外话: 选择话题里应该多一个灌水、胡扯之类的。。。,搞得我都没得选)
☆ 手工脱Armadillo
Milescan Web Security Auditor Trial 1.1 (auditor_1.1_trial.exe)
http://www.milescan.com
spider_trial.exe(4,313,088 bytes)
auditor_trial.exe(4,313,088 bytes)
Milescan是一款商用WWW扫描器,不是太出名,其主站为http://www.milescan.com。
支持SQL注入扫描。它有一个兄弟产品更出名些,Paros Proxy,这是一款开源软件,
可以当普通代理使用,但更重要的是作为WWW扫描器使用,从名字上可能看不出后一
点来,我实测过其扫描功能,相当不错,其主站为http://www.parosproxy.org/。既
然开源的不错,想必商用的更不错,这是我关注Milescan的最初原因。
Milescan在其主站提供试用版下载,需要免费注册进入下载页面,文件较大(24.7M)。
这个试用版本身包含了完整的功能性代码,但通过其它手段做了如下两个限制:
. 30天试用期
. 只能扫描如下IP:
10.0.0.0 10.255.255.255
172.16.0.0 172.31.255.255
192.168.0.0 192.168.255.255
127.0.0.0 127.255.255.255
第一个限制是通过Armadillo实现的,第二个限制是软件本身的。软件本身是用Java
开发的,最终编译成native code,没有保持在字节码状态。
运气不太好,终于碰上自己关心的程序需要脱壳,之前从未接触过脱壳。PEiD报
Armadillo壳,版本信息不太对,ArmaGUI.rar、mm_dillodie1.6.zip都可以成功脱掉
这个版本的壳。就本例而言,手脱虽然是个无意义的举动,但还是记录备忘一下手脱
过程,艺多不压身。
因为第一次接触手工脱壳,很多观点、操作相当稚嫩,贻笑大方。
用PEiD查origspider_trial.exe,报:
Armadillo 1.xx - 2.xx -> Silicon Realms Toolworks
用Armadillo find protected查origspider_trial.exe,报:
Debug-Blocker
Enable Strategic Code Splicing
Armadillo一般有类似这样的程序逻辑:
--------------------------------------------------------------------------
HANDLE mutex;
mutex = OpenMutex( ..., ..., "%X::DA%08X" );
if ( !mutex )
{
/*
* 父进程流程
*/
CreateProcess();
DebugActiveProcess();
SuspendThread();
while ( 1 )
{
WaitForDebugEvent( lpDebugEvent, ... );
switch ( lpDebugEvent->dwDebugEventCode )
{
/*
* 1
*/
case EXCEPTION_DEBUG_EVENT:
switch ( lpDebugEvent->u.Exception.ExceptionRecord.ExceptionCode )
{
/*
* STATUS_GUARD_PAGE_VIOLATION,0x80000001
*/
case EXCEPTION_GUARD_PAGE:
... ...
WriteProcessMemory();
... ...
break;
/*
* STATUS_ACCESS_VIOLATION,0xC0000005
*/
case EXCEPTION_ACCESS_VIOLATION:
... ...
break;
/*
* STATUS_BREAKPOINT,0x80000003
*/
case EXCEPTION_BREAKPOINT:
... ...
break;
case ...
} /* end of switch */
... ...
break;
/*
* 3
*/
case CREATE_PROCESS_DEBUG_EVENT:
... ...
/*
* 确保子进程不会再走父进程流程,否则无限递归了
*/
CreateMutex( ..., ..., "%X::DA%08X" );
/*
* 与DebugActiveProcess()之后的那个SuspendThread()配对
*/
ResumeThread();
... ...
break;
case ...
} /* end of switch */
ContinueDebugEvent( lpDebugEvent->dwProcessId, lpDebugEvent->dwThreadId, ... );
} /* end of while */
}
else
{
/*
* 子进程流程
*
* 子进程自己负责处理引入表
*/
}
--------------------------------------------------------------------------
单纯的Debug-Blocker只是靠DebugActiveProcess()确保无法用Ring 3调试器attach
子进程,从而无法调试子进程。
更复杂的则是子进程有意识地触发EXCEPTION_GUARD_PAGE、EXCEPTION_BREAKPOINT异
常,父进程捕获异常进行相应处理之后子进程再继续执行。
我碰上的这个是单纯的Debug-Blocker。
Armadillo在反调试器,一定要用HideOD隐藏OD。
就本例而言,只需对付IsDebuggerPresent()即可,下面是一个cdb.exe调试示例:
--------------------------------------------------------------------------
cdb.exe -hd -noinh origspider_trial.exe
g $exentry
ba e 1 IsDebuggerPresent "g poi(esp);r eax=0;g"
--------------------------------------------------------------------------
OD载入origspider_trial.exe,停在如下位置:
--------------------------------------------------------------------------
0092FBFB >/$ 55 push ebp
0092FBFC |. 8BEC mov ebp, esp
0092FBFE |. 6A FF push -1
0092FC00 |. 68 28829500 push origspid.00958228
0092FC05 |. 68 70EF9200 push origspid.0092EF70 ; SE handler installation
0092FC0A |. 64:A1 0000000>mov eax, dword ptr fs:[0]
0092FC10 |. 50 push eax
0092FC11 |. 64:8925 00000>mov dword ptr fs:[0], esp
--------------------------------------------------------------------------
he OpenMutexA
F9
--------------------------------------------------------------------------
7C830607 > 8BFF mov edi, edi // OpenMutexA入口
7C830609 55 push ebp
--------------------------------------------------------------------------
断在OpenMutexA入口时查看stack:
--------------------------------------------------------------------------
0006F798 0091B205 /CALL to OpenMutexA from origspid.0091B1FF
0006F79C 001F0001 |Access = 1F0001
0006F7A0 00000000 |Inheritable = FALSE
0006F7A4 0006FDD8 \MutexName = "520::DAE5F88F3F" // 记下字符串指针0x0006FDD8
--------------------------------------------------------------------------
在IDA中看看相关汇编代码(没有实际意义,仅记录备忘):
--------------------------------------------------------------------------
0091B1CA A1 B8 23 95 00 mov eax, ds:dword_9523B8 ; 0xAF7D5A38
0091B1CF 33 05 D0 23 95 00 xor eax, ds:dword_9523D0 ; 0xAF7D5A38 ^ 0x4A85D507 = 0xE5F88F3F
0091B1D5 50 push eax ; 0xE5F88F3F
0091B1D6 FF 15 B8 21 95 00 call ds:GetCurrentProcessId
0091B1DC 50 push eax ; PID
0091B1DD 68 D4 26 95 00 push offset aXDa08x ; "%X::DA%08X"
0091B1E2 8D 8D D8 FE FF FF lea ecx, [ebp+Name]
0091B1E8 51 push ecx ; Dest
0091B1E9 E8 0C 3C 01 00 call _sprintf
0091B1EE 83 C4 10 add esp, 10h
0091B1F1 8D 95 D8 FE FF FF lea edx, [ebp+Name]
0091B1F7 52 push edx ; lpName
0091B1F8 6A 00 push 0 ; bInheritHandle
0091B1FA 68 01 00 1F 00 push 1F0001h ; dwDesiredAccess
0091B1FF FF 15 A8 20 95 00 call ds:OpenMutexA
0091B205 85 C0 test eax, eax
--------------------------------------------------------------------------
00921400 8B 15 B8 23 95 00 mov edx, ds:dword_9523B8
00921406 33 15 D0 23 95 00 xor edx, ds:dword_9523D0
0092140C 52 push edx
0092140D A1 6C 97 95 00 mov eax, ds:child_pi
00921412 8B 48 08 mov ecx, [eax+8]
00921415 51 push ecx
00921416 68 D4 26 95 00 push offset aXDa08x ; "%X::DA%08X"
0092141B 8D 95 F8 FD FF FF lea edx, [ebp-208h]
00921421 52 push edx
00921422 E8 D3 D9 00 00 call _sprintf
00921427 83 C4 10 add esp, 10h
0092142A 8D 85 F8 FD FF FF lea eax, [ebp-208h]
00921430 50 push eax
00921431 6A 00 push 0
00921433 6A 00 push 0
00921435 FF 15 A4 20 95 00 call ds:CreateMutexA
--------------------------------------------------------------------------
我没有动态拦截CreateMutexA(),只是在IDA中查看"%X::DA%08X"的交叉引用关系定
位0x00921416的。
at 0x00401000
--------------------------------------------------------------------------
00401000 0000 add byte ptr [eax], al
00401002 0000 add byte ptr [eax], al
00401004 0000 add byte ptr [eax], al
00401006 0000 add byte ptr [eax], al
00401008 0000 add byte ptr [eax], al
0040100A 0000 add byte ptr [eax], al
0040100C 0000 add byte ptr [eax], al
0040100E 0000 add byte ptr [eax], al
00401010 0000 add byte ptr [eax], al
00401012 0000 add byte ptr [eax], al
00401014 0000 add byte ptr [eax], al
00401016 0000 add byte ptr [eax], al
--------------------------------------------------------------------------
这是一片空闲的有效内存(可以另找空闲区域),手工输入如下汇编代码:
--------------------------------------------------------------------------
00401000 60 pushad
00401001 9C pushfd
00401002 68 D8FD0600 push 6FDD8 ; ASCII "520::DAE5F88F3F"
00401007 33C0 xor eax, eax
00401009 50 push eax
0040100A 50 push eax
0040100B E8 9783427C call kernel32.CreateMutexA
00401010 9D popfd
00401011 61 popad
00401012 - E9 F0F5427C jmp kernel32.OpenMutexA
--------------------------------------------------------------------------
60 9C 68 D8 FD 06 00 33 C0 50 50 E8 97 83 42 7C 9D 61 E9 F0 F5 42 7C
--------------------------------------------------------------------------
这段代码模拟0x00921435处的CreateMutexA(),以此欺骗0x0091B1FF处的OpenMutexA(),
强制走子进程流程。这次是单纯的Debug-Blocker,可以一开始就强制走子进程流程,
如果父进程需要处理EXCEPTION_GUARD_PAGE、EXCEPTION_BREAKPOINT异常,处理时机
要复杂些。
在理解这个壳的时候重点参考了两份文档:
Armadillo 2.52加壳原理分析和改进的脱壳方法 - leo_cyl
http://blog.csdn.net/compiler/articles/91123.aspx
试玩armadillo3.50a一点心得 - mysqladm [2004-03-06]
http://www.pediy.com/bbshtml/BBS6/pediy6837.htm
这两份文档解释了一些重要原理,适合对Win32本身较熟但对脱壳不熟的程序员参看。
其中mysqladm原创了欺骗OpenMutexA()的方案,致敬。
手工修改EIP指向0x00401000,F9之后再次断在OpenMutexA入口:
--------------------------------------------------------------------------
7C830607 > 8BFF mov edi, edi // OpenMutexA入口
7C830609 55 push ebp
--------------------------------------------------------------------------
先撤消0x00401000附近的所有修改。
hd OpenMutexA
Alt-M
--------------------------------------------------------------------------
00400000 00001000 origspid PE header Imag R RWE
00401000 00163000 origspid .text Imag R RWE // 在.text上设内存访问断点
00564000 00084000 origspid .data Imag R RWE
005E8000 00004000 origspid .bss Imag R RWE
005EC000 002D0000 origspid .rdata Imag R RWE
008BC000 0000D000 origspid .jidata data Imag R RWE
008C9000 00001000 origspid .idata Imag R RWE
008CA000 00010000 origspid .jedata Imag R RWE
008DA000 00017000 origspid .reloc Imag R RWE
008F1000 00001000 origspid .config Imag R RWE
008F2000 00050000 origspid .text1 code Imag R RWE
00942000 00010000 origspid .adata code Imag R RWE
00952000 00010000 origspid .data1 imports Imag R RWE
00962000 00010000 origspid .reloc1 relocations Imag R RWE
00972000 000F0000 origspid .pdata Imag R RWE
00A62000 00003000 origspid .rsrc resources Imag R RWE
--------------------------------------------------------------------------
F9运行,中间如果有异常抛出(注意OD下方状态栏)就用Shift-F9继续,直至内存访问
断点命中:
--------------------------------------------------------------------------
00FDEBA7 0FBE00 movsx eax, byte ptr [eax] // 此时EAX=00401000
--------------------------------------------------------------------------
00401000 6A 00 push 0
00401002 E8 43F91500 call origspid.0056094A
00401007 50 push eax
00401008 6A 01 push 1
0040100A 50 push eax
0040100B E8 24000000 call origspid.00401034
00401010 85C0 test eax, eax
00401012 74 16 je short origspid.0040102A
00401014 68 00000000 push 0
--------------------------------------------------------------------------
TNND,都不知道什么时候0x00401000已被写了新数据(原来全零),OD的内存访问断点
还真是不可靠,太容易被VirtualProtect()系列函数干挠。若想定位向0x00401000写
入新数据的代码,可用硬件断点。
清除.text上的内存访问断点。
he 00401000
F9
断在0x00401000之后清除所有断点。
在.text上设内存访问断点,不知是谁的原创,我看到的文档都在引别人的,却没有
看到源头。其本意是假设OEP位于.text中,在.text上设内存访问断点可快速定位OEP。
0x00401000即本例的OEP。现在来对付"Enable Strategic Code Splicing"。运行
ArmInline v0.96 Final,在Processs里选中origspider_trial.exe,会自动获取如
下信息:
(Slave)Process ID
Start Of Target Code 0x401000
Length Of Target Code 0x163000
Start Of Spliced Code 0x3C60000
Lenght Of Spliced Code 0x1000
用Alt-M查看内存信息加深理解:
--------------------------------------------------------------------------
Memory map
Address Size Owner Section Contains Type Access Initial Mapped as
00400000 00001000 origspid Imag R RWE
00401000 00163000 origspid .text Imag R RWE // Target Code
00564000 00084000 origspid .data Imag R RWE
005E8000 00004000 origspid .bss Imag R RWE
005EC000 002D0000 origspid .rdata Imag R RWE
008BC000 0000D000 origspid .jidata data Imag R RWE
008C9000 00001000 origspid .idata Imag R RWE
008CA000 00010000 origspid .jedata Imag R RWE
008DA000 00017000 origspid .reloc Imag R RWE
008F1000 00001000 origspid .config Imag R RWE
008F2000 00050000 origspid .text1 code Imag R RWE
00942000 00010000 origspid .adata code Imag R RWE
00952000 00010000 origspid .data1 imports Imag R RWE
00962000 00010000 origspid .reloc1 relocations Imag R RWE
00972000 000F0000 origspid .pdata Imag R RWE
00A62000 00003000 origspid .rsrc resources Imag R RWE
00A70000 00103000 Map R R
00B80000 000C8000 Map R E R E
00E80000 00001000 Priv RW RW
00E90000 00001000 Priv RW RW
00EA0000 0000E000 Priv RW RW
00EB0000 00001000 Priv RW RW
00FB0000 00056000 Priv RW RW
01010000 00002000 Map R R
01020000 00002000 Map R R
01030000 00005000 Priv RW RW
0116D000 00001000 Priv RW Guar RW
0116E000 00002000 stack of thr Priv RW Guar RW
01170000 00018000 Priv RW RW
01190000 000A4000 Priv RW RW
01253000 00002000 Priv RW RW
01270000 00007000 Priv RW RW
012B0000 0000C000 Priv RW RW
012C0000 00006000 Priv RW RW
012D0000 00004000 Priv RW RW
012E0000 00001000 Map RW RW
012F0000 00002000 Map R R
01300000 00003000 Priv RW RW
01340000 00001000 Map RW RW
01350000 00022000 Priv RW RW
01391000 00026000 Priv RW RW
01550000 00001000 Priv RW RW
01560000 0003E000 Priv RW RW
01660000 00001000 Priv RW RW
016E0000 00001000 Priv RW RW
0172D000 00001000 Priv RW Guar RW
0172E000 00002000 stack of thr Priv RW Guar RW
03C60000 00011000 Priv R E RWE // Spliced Code
--------------------------------------------------------------------------
在ArmInline里点"Remove Splices",得到如下提示信息:
73 splices repaired.
Splice repairing complete. Patching process...
Patch succesful.
最后那个succesful不是我写错的,是它自己写错的。关于ArmInline参看:
Armadillo客户版Code Splicing+Import Table Elimination的简便修复方法 - fly [2005-09-28]
http://bbs.pediy.com/showthread.php?t=17253
(介绍了一些Armadillo保护机制的术语以及ArmInline的使用方法)
fly这里用的是个低版本的ArmInline,现在的0.96版用起来更省事。
后面的操作回头来看可能有些稚嫩,但我还是忠实地记录原始学习过程,见笑。
运行LordPE选中origspider_trial.exe,dump full,保存成dumped.exe。
运行ImportREC,选中origspider_trial.exe,将OEP改成00001000,注意,一定不要
直接写成00401000,这里减去的00400000即ImageBase。自动查找IAT,现在RVA变成
004C9078。
0x004C9078 + 0x00400000 = 0x008C9078
回到OD,查看相关信息:
--------------------------------------------------------------------------
00401000 6A 00 push 0
00401002 E8 43F91500 call origspid.0056094A
--------------------------------------------------------------------------
00560908 - FF25 A8908C00 jmp near dword ptr [8C90A8] ; ADVAPI32.DeregisterEventSource
0056090E - FF25 A4908C00 jmp near dword ptr [8C90A4] ; ADVAPI32.RegCloseKey
00560914 - FF25 A0908C00 jmp near dword ptr [8C90A0]
0056091A - FF25 9C908C00 jmp near dword ptr [8C909C] ; ADVAPI32.RegSetValueExA
00560920 - FF25 98908C00 jmp near dword ptr [8C9098] ; ADVAPI32.RegisterEventSourceA
00560926 - FF25 94908C00 jmp near dword ptr [8C9094] ; ADVAPI32.ReportEventA
0056092C - FF25 18918C00 jmp near dword ptr [8C9118]
00560932 - FF25 14918C00 jmp near dword ptr [8C9114] ; kernel32.FindClose
00560938 - FF25 10918C00 jmp near dword ptr [8C9110]
0056093E - FF25 0C918C00 jmp near dword ptr [8C910C]
00560944 - FF25 08918C00 jmp near dword ptr [8C9108] ; kernel32.GetModuleFileNameA
0056094A - FF25 04918C00 jmp near dword ptr [8C9104] ; from 0x00401002
00560950 - FF25 00918C00 jmp near dword ptr [8C9100]
00560956 - FF25 FC908C00 jmp near dword ptr [8C90FC]
0056095C - FF25 F8908C00 jmp near dword ptr [8C90F8] ; kernel32.GetStdHandle
00560962 - FF25 F4908C00 jmp near dword ptr [8C90F4] ; ntdll.RtlAllocateHeap
00560968 - FF25 F0908C00 jmp near dword ptr [8C90F0] ; ntdll.RtlFreeHeap
0056096E - FF25 EC908C00 jmp near dword ptr [8C90EC]
00560974 - FF25 E8908C00 jmp near dword ptr [8C90E8]
0056097A - FF25 28918C00 jmp near dword ptr [8C9128] ; USER32.OemToCharA
... ...
0056367A FF25 D4878C00 jmp near dword ptr [8C87D4]
00563680 FF25 00888C00 jmp near dword ptr [8C8800]
00563686 FF25 08888C00 jmp near dword ptr [8C8808]
0056368C FF25 10888C00 jmp near dword ptr [8C8810]
00563692 FF25 18888C00 jmp near dword ptr [8C8818]
00563698 FF25 20888C00 jmp near dword ptr [8C8820]
0056369E FF25 30888C00 jmp near dword ptr [8C8830]
005636A4 FF25 38888C00 jmp near dword ptr [8C8838]
005636AA FF25 40888C00 jmp near dword ptr [8C8840]
005636B0 FF25 48888C00 jmp near dword ptr [8C8848]
--------------------------------------------------------------------------
008C9078 004C9192 origspid.004C9192
008C907C 004C917A origspid.004C917A
008C9080 004C9168 origspid.004C9168
008C9084 004C9156 origspid.004C9156
008C9088 004C9148 origspid.004C9148
008C908C 004C9130 origspid.004C9130
008C9090 00000000
008C9094 77F3F9D8 ADVAPI32.ReportEventA
008C9098 77F3B857 ADVAPI32.RegisterEventSourceA
008C909C 77F3EBD7 ADVAPI32.RegSetValueExA
008C90A0 00FCB725
008C90A4 77F56CCE ADVAPI32.RegCloseKey
008C90A8 77F3F160 ADVAPI32.DeregisterEventSource
008C90AC 00FC7E3F
008C90B0 004C926E origspid.004C926E
008C90B4 004C925E origspid.004C925E
008C90B8 004C9252 origspid.004C9252
008C90BC 004C9246 origspid.004C9246
008C90C0 004C9236 origspid.004C9236
008C90C4 004C9224 origspid.004C9224
008C90C8 004C9212 origspid.004C9212
008C90CC 004C91FE origspid.004C91FE
008C90D0 004C91E8 origspid.004C91E8
008C90D4 004C91CE origspid.004C91CE
008C90D8 004C91BC origspid.004C91BC
008C90DC 004C91B0 origspid.004C91B0
008C90E0 004C91A2 origspid.004C91A2
008C90E4 00000000
008C90E8 00FC9931
008C90EC 00FC7E85
008C90F0 7C959E17 ntdll.RtlFreeHeap
008C90F4 7C959FD6 ntdll.RtlAllocateHeap
008C90F8 7C82B437 kernel32.GetStdHandle
008C90FC 00FCBD32
008C9100 00FC72A7
008C9104 00FCB213
008C9108 7C8245FF kernel32.GetModuleFileNameA
008C910C 00FC86CD
008C9110 00FCACCD
008C9114 7C82BFB3 kernel32.FindClose
008C9118 00FC8BC6
008C911C 00FC7E49
008C9120 004C927A origspid.004C927A
008C9124 00000000
008C9128 77E519CC USER32.OemToCharA
008C912C 00FC7D67
--------------------------------------------------------------------------
获取输入表,显示无效函数,剪切指针,修复转存文件,这将生成一个dumped_.exe。
退出OD,双击执行dumped_.exe,出错信息表明0x00FCB213内存无效。这是Armadillo
的一种反dump机制,针对IAT中部分Entry进行特殊处理,使之指向更难理解、不易
dump的hook code,后者最终调用完成实际功能的Win32 API。前面dump时IAT已被处
理过,IAT中出现了指向hook code的Entry:
008C9104 00FCB213
而0x00FCB213处的代码不在dump范围内,所以执行dumped_.exe时出错。
--------------------------------------------------------------------------
00FCB213 55 push ebp
00FCB214 8BEC mov ebp, esp
00FCB216 51 push ecx
00FCB217 53 push ebx
00FCB218 56 push esi
00FCB219 57 push edi
00FCB21A E8 81270000 call 00FCD9A0
00FCB21F FF75 08 push dword ptr [ebp+8]
00FCB222 E8 61CAFFFF call 00FC7C88
00FCB227 85C0 test eax, eax
00FCB229 59 pop ecx
00FCB22A 8945 FC mov dword ptr [ebp-4], eax
00FCB22D 75 2A jnz short 00FCB259
00FCB22F 60 pushad
00FCB230 8B15 18B7FF00 mov edx, dword ptr [FFB718] ; kernel32.7C82196D
00FCB236 83C2 64 add edx, 64 ; 注意这个加0x64
00FCB239 FFD2 call near edx ; kernel32.GetTickCount
00FCB23B 8B15 B4B6FF00 mov edx, dword ptr [FFB6B4] ; kernel32.7C8246E6
00FCB241 83C2 64 add edx, 64 ; 注意这个加0x64
00FCB244 B9 05000000 mov ecx, 5
00FCB249 803A CC cmp byte ptr [edx], 0CC
00FCB24C 74 07 je short 00FCB255
00FCB24E ^ E2 F9 loopd short 00FCB249
00FCB250 FF75 08 push dword ptr [ebp+8]
00FCB253 FFD2 call near edx ; kernel32.GetModuleHandleA,这是完成实际功能的Win32 API
00FCB255 8945 FC mov dword ptr [ebp-4], eax
00FCB258 61 popad
00FCB259 8B45 FC mov eax, dword ptr [ebp-4]
00FCB25C 5F pop edi
00FCB25D 5E pop esi
00FCB25E 5B pop ebx
00FCB25F C9 leave
00FCB260 C2 0400 retn 4
--------------------------------------------------------------------------
关于针对IAT中部分Entry进行特殊处理,参看:
Armadillo标准壳完全扫盲 - [2007-05-17]
http://hi.baidu.com/%CC%EC%CD%E2%C3%AB%B3%E6/blog/item/91313df5a0483e24bc3109b4.html
(解释了一些原理,适合新手,但有些术语并不正确,自己修正着理解吧)
重新用OD调试origspider_trial.exe,欺骗OpenMutexA()之后清除所有断点。
hw 008C912C
F9
dd 008C9078
--------------------------------------------------------------------------
008C9078 004C9192 origspid.004C9192
008C907C 004C917A origspid.004C917A
008C9080 004C9168 origspid.004C9168
008C9084 004C9156 origspid.004C9156
008C9088 004C9148 origspid.004C9148
008C908C 004C9130 origspid.004C9130
008C9090 00000000
008C9094 004C9192 origspid.004C9192
008C9098 004C917A origspid.004C917A
008C909C 004C9168 origspid.004C9168
008C90A0 004C9156 origspid.004C9156
008C90A4 004C9148 origspid.004C9148
008C90A8 004C9130 origspid.004C9130
008C90AC 00000000
008C90B0 004C926E origspid.004C926E
008C90B4 004C925E origspid.004C925E
008C90B8 004C9252 origspid.004C9252
008C90BC 004C9246 origspid.004C9246
008C90C0 004C9236 origspid.004C9236
008C90C4 004C9224 origspid.004C9224
008C90C8 004C9212 origspid.004C9212
008C90CC 004C91FE origspid.004C91FE
008C90D0 004C91E8 origspid.004C91E8
008C90D4 004C91CE origspid.004C91CE
008C90D8 004C91BC origspid.004C91BC
008C90DC 004C91B0 origspid.004C91B0
008C90E0 004C91A2 origspid.004C91A2
008C90E4 00000000
008C90E8 004C926E origspid.004C926E
008C90EC 004C925E origspid.004C925E
008C90F0 004C9252 origspid.004C9252
008C90F4 004C9246 origspid.004C9246
008C90F8 004C9236 origspid.004C9236
008C90FC 004C9224 origspid.004C9224
008C9100 004C9212 origspid.004C9212
008C9104 004C91FE origspid.004C91FE
008C9108 004C91E8 origspid.004C91E8
008C910C 004C91CE origspid.004C91CE
008C9110 004C91BC origspid.004C91BC
008C9114 004C91B0 origspid.004C91B0
008C9118 004C91A2 origspid.004C91A2
008C911C 00000000
008C9120 004C927A origspid.004C927A
008C9124 00000000
008C9128 004C927A origspid.004C927A
008C912C 00000000
--------------------------------------------------------------------------
清除所有断点。与处理后的IAT比较一下,设置如下数据断点:
hw 008C90A0
--------------------------------------------------------------------------
00FDDB8E 8908 mov dword ptr [eax], ecx ; 数据断点命中
00FDDB90 8B85 10D9FFFF mov eax, dword ptr [ebp-26F0] ; origspid.008C90A0
00FDDB96 83C0 04 add eax, 4
00FDDB99 8985 10D9FFFF mov dword ptr [ebp-26F0], eax
00FDDB9F ^ E9 4DFCFFFF jmp 00FDD7F1
--------------------------------------------------------------------------
单步跟踪这附近的代码执行情况,可以定位如下代码:
--------------------------------------------------------------------------
00FDD9D2 50 push eax ; 比较Win32 API的名字
00FDD9D3 FF15 7873FE00 call near dword ptr [FE7378] ; msvcrt._stricmp
00FDD9D9 59 pop ecx
00FDD9DA 59 pop ecx
00FDD9DB 85C0 test eax, eax
00FDD9DD /75 11 jnz short 00FDD9F0 ; 改成jmp,否则开始针对IAT中部分Entry进行特殊处理
00FDD9DF 8B85 58C2FFFF mov eax, dword ptr [ebp-3DA8]
00FDD9E5 8B40 08 mov eax, dword ptr [eax+8]
00FDD9E8 8985 68CAFFFF mov dword ptr [ebp-3598], eax
00FDD9EE EB 02 jmp short 00FDD9F2
00FDD9F0 ^ EB 9C jmp short 00FDD98E
--------------------------------------------------------------------------
0x00FDD9D3处进行名字比较,检查是否是需要特殊处理的Win32 API。0x00FDD9DD处
不跳转表明找到一个需要特殊处理的Win32 API,最终向IAT中写入hook code入口地
址。若不需要特殊处理则直接在IAT中写入Win32 API入口地址。
重新用OD调试origspider_trial.exe,欺骗OpenMutexA()之后清除所有断点。
hw 008C912C
F9
dd 008C9078
清除所有断点。
hw 008C9094
F9
at 00FDD9DD
将0x00FDD9DD处的jnz改成jmp。
hw 008C912C
F9
dd 008C9078
--------------------------------------------------------------------------
008C9078 004C9192 origspid.004C9192
008C907C 004C917A origspid.004C917A
008C9080 004C9168 origspid.004C9168
008C9084 004C9156 origspid.004C9156
008C9088 004C9148 origspid.004C9148
008C908C 004C9130 origspid.004C9130
008C9090 00000000
008C9094 77F3F9D8 ADVAPI32.ReportEventA
008C9098 77F3B857 ADVAPI32.RegisterEventSourceA
008C909C 77F3EBD7 ADVAPI32.RegSetValueExA
008C90A0 77F46A17 ADVAPI32.RegCreateKeyExA
008C90A4 77F56CCE ADVAPI32.RegCloseKey
008C90A8 77F3F160 ADVAPI32.DeregisterEventSource
008C90AC 00FC7E3F
008C90B0 004C926E origspid.004C926E
008C90B4 004C925E origspid.004C925E
008C90B8 004C9252 origspid.004C9252
008C90BC 004C9246 origspid.004C9246
008C90C0 004C9236 origspid.004C9236
008C90C4 004C9224 origspid.004C9224
008C90C8 004C9212 origspid.004C9212
008C90CC 004C91FE origspid.004C91FE
008C90D0 004C91E8 origspid.004C91E8
008C90D4 004C91CE origspid.004C91CE
008C90D8 004C91BC origspid.004C91BC
008C90DC 004C91B0 origspid.004C91B0
008C90E0 004C91A2 origspid.004C91A2
008C90E4 00000000
008C90E8 7C825529 kernel32.WriteFile
008C90EC 7C801DC6 kernel32.LoadLibraryA
008C90F0 7C959E17 ntdll.RtlFreeHeap
008C90F4 7C959FD6 ntdll.RtlAllocateHeap
008C90F8 7C82B437 kernel32.GetStdHandle
008C90FC 7C823EC7 kernel32.GetProcessHeap
008C9100 7C823D7A kernel32.GetProcAddress
008C9104 7C82474A kernel32.GetModuleHandleA // 对比前述0x00FCB253处的代码
008C9108 7C8245FF kernel32.GetModuleFileNameA
008C910C 7C830BE4 kernel32.GetEnvironmentVariableA
008C9110 7C831FE1 kernel32.FindFirstFileA
008C9114 7C82BFB3 kernel32.FindClose
008C9118 7C8268F1 kernel32.ExitProcess
008C911C 00FC7E49
008C9120 004C927A origspid.004C927A
008C9124 00000000
008C9128 77E519CC USER32.OemToCharA
008C912C 00FC7D67
--------------------------------------------------------------------------
务必撤消0x00FDD9DD处的修改,将jmp改回成jnz,清除所有断点。
he 00401000
F9
断在0x00401000之后清除所有断点。现在我们有未被处理过的IAT。
运行ArmInline v0.96 Final,选中origspider_trial.exe,Remove Splices。
运行LordPE选中origspider_trial.exe,dump full,保存成dumped.exe。
运行ImportREC,选中origspider_trial.exe,将OEP改成00001000,自动查找IAT,
现在RVA变成004C9078。获取输入表,显示无效函数,剪切指针,修复转存文件,这
将生成一个dumped_.exe。
退出OD,双击执行dumped_.exe,搞定。脱壳后30天试用期自动去除。破解IP限制与
脱壳无关,与本文无关。注意origauditor_trial.exe也加了壳,手脱原理同上。
本来还有个脱壳后的优化,照着下文简单折腾了一下:
脱壳后软件减肥大法 - yesky1 [2003-11-20]
http://www.pediy.com/bbshtml/BBS6/pediy6313.htm
但未成功,不打算深究这一步了。前面有几次提到撤消某某处的修改,是为了躲避内
存中的自校验过程。
曾参看过一些手脱Armadillo壳的文章,不过不太适合我入门,主要原因是之前我完
全不了解该壳的一些保护机制,如果照着TA们的步骤做,会有很多细节对不上号,比
如那个所谓的"magic jmp",照葫芦画瓢只会让我更困惑,还好我一开始也没打算照
葫芦画瓢。由于这次的保护机制只用到两个:
Debug-Blocker
Enable Strategic Code Splicing
所以像我这样的脱壳新手还可以承受,再复杂的以后有需求时再学习吧。
没有技术含量的操作备忘录。
我把这次对我产生原理性的直接帮助的几篇文章列在正文中了。后面的参考资源则是
一个良莠不齐的总收集,亦可参看。
☆ 参考资源
[ 2] Armadillo壳相关文档
脱壳入门初级教学
http://bbs.pediy.com/showthread.php?t=20366
Armadillo 2.52加壳原理分析和改进的脱壳方法 - leo_cyl
http://blog.csdn.net/compiler/articles/91123.aspx
(解释了一些重要原理,适合喜欢折腾的Win32程序员)
试玩armadillo3.50a一点心得 - mysqladm [2004-03-06]
http://www.pediy.com/bbshtml/BBS6/pediy6837.htm
(解释了一些重要原理,适合喜欢折腾的Win32程序员)
Armadillo标准壳完全扫盲 - [2007-05-17]
http://hi.baidu.com/%CC%EC%CD%E2%C3%AB%B3%E6/blog/item/91313df5a0483e24bc3109b4.html
(解释了一些原理,适合新手,但有些术语并不正确,自己修正着理解吧)
Armadillo客户版Code Splicing+Import Table Elimination的简便修复方法 - fly [2005-09-28]
http://bbs.pediy.com/showthread.php?t=17253
(介绍了一些Armadillo保护机制的术语以及ArmInline的使用方法)
Armadillo 3.6主程序脱壳 - tDasm [2004-03-13]
http://www.pediy.com/bbshtml/BBS6/pediy6444.htm
(一些原创脱壳技巧)
Armadillo COPYMEMEII之DUMP的一个LOADPE小插件 - jwh51 [2004-03-15]
http://www.pediy.com/bbshtml/BBS6/pediy6443.htm
Armadillo 双进程标准壳快速脱壳 - fly [2004-03-16]
http://www.pediy.com/bbshtml/BBS6/pediy6446.htm
Blaze Media Pro5.05脱壳+基本修复CC(int3)+破解 - pyzpyz [2004-04-22]
http://www.pediy.com/bbshtml/BBS6/pediy6499.htm
(在tDasm文章基础上新增更多原创脱壳技巧)
手动脱Armadillo CopyMem-ll +Debug-Blocker壳全过程 - [2004-05-04]
http://www.cnblogs.com/f4ncy/archive/2005/01/22/95674.html
http://www.pediy.com/bbshtml/BBS6/pediy6732.htm
iRider.exe 2.20BETA主程序脱壳 - wxhing [2004-11-12]
http://wxhing.blogcn.com/diary,204358883.shtml
浅谈Armadillo V.3.75 与 V.3.78的保护 - C-pen [2004-12-06]
http://www.pediy.com/bbshtml/BBS6/pediy6906.htm
(不适合学习阶段的人看,基本是熟手的自我总结小片段,不成体系)
Armadillo V4.0输入表乱序的简便修复方法 - fly [2004-12-31]
http://bbs.pediy.com/showthread.php?t=9193
(介绍了ImportREC)
脱Armadillo 1.xx - 2.xx的壳教程 - [2005-01-20]
http://bbs.pediy.com/showthread.php?t=10131
用Ollydbg手脱Armadillo加壳的DLL - jameshero [2005-05-31]
http://bbs.pediy.com/showthread.php?t=14098
Armadillo几个版本脱壳总结 - wynney [2005-06-26]
http://bbs.pediy.com/showthread.php?t=14753
ArmadilloCopyMem-ll+Debug-Block - wynney [2005-06-27]
http://bbs.pediy.com/showthread.php?t=14778
Armadillo双进程标准壳快速脱壳 - KuNgBiM [2005-08-18]
http://bbs.pediy.com/showthread.php?t=16342
(这个基本照搬前文pediy6446.htm)
Patch 修复 Armadillo 的IAT乱序 - [2005-12-07]
http://bbs.pediy.com/showthread.php?t=19202
(有创意,可参考)
脱带KEY的ARM双进程的壳
http://bbs.pediy.com/showthread.php?t=29177
用OD手脱 Armadillo v4.40 DLL壳 - regkiller
https://forum.eviloctal.com/read-htm-tid-19169.html
Armadillo 1.xx - 2.xx脱壳 - layper
http://www.juntuan.net/pjjs/pjjs/n/2005-07-22/6420.html
老生常谈Armadillo CopyMem-II+Debug-Blocker 保护方式脱壳 - daxia2002
http://www.hacker.com.cn/forum/view_120213.html
脱壳后软件减肥大法 - yesky1 [2003-11-20]
http://www.pediy.com/bbshtml/BBS6/pediy6313.htm
浅谈程序脱壳后的优化 - CCDebuger [2006-07-03]
http://bbs.pediy.com/showthread.php?t=28402
Armadillo壳相关工具
http://www.pediy.com/tools/unpacker.htm
http://www.pediy.com/tools/unpack/Armadillo/armafp/armafp.zip
http://www.pediy.com/tools/unpack/Armadillo/ArmaGUI/ArmaGUI.rar
http://www.pediy.com/tools/unpack/Armadillo/ArmInline/ArmInlinev0.96f.zip
http://www.pediy.com/tools/PE_tools/Lordpe/LPE-DLX.rar
http://www.pediy.com/tools/PE_tools/Rebuilder/Import%20REC/ucfir16f.rar
- 标 题:手工脱Armadillo(Milescan Web Security Auditor Trial 1.1)
- 作 者:scz
- 时 间:2008-02-25 15:29
- 链 接:http://bbs.pediy.com/showthread.php?t=60205