【软件名称】Armadillo V4.40
【应用平台】WinXP SP2
【作者邮箱】chubing6143@sina.com
【使用工具】OllyDbg1.10,FLY大侠的Get.eXe.PE.Information.osc、DebugActiveProcess.osc、Armadillo.fiXed.IT.osc,ArmInline v0.96
【参考】FLY大侠的破文:http://bbs.pediy.com/showthread.php?threadid=18215
【脱壳过程】FLY大侠在原文中提到“主要利用脚本来完成脱壳,步骤繁琐,不适合新手练习”,我等菜鸟也学习之,我写该帖子的目的不是为了骗取什么了,仅仅是给有可能与我一样菜鸟的人搞清楚如何学习FLY大侠的文章。其中CC的处理,我直接利用ArmInline v0.96搞定了,方便菜鸟学习,而有些步骤是原帖中大侠们认为不介绍,菜鸟也能懂得了,但实际上菜鸟并不一定都懂了。太过啰嗦,言归正传。
利用armadillo.findprotected发现该软件保护方式为
<------- 12-04-2010 08:31:07 ------->
D:\Armadillo\Armadillo.exe
!- Protected Armadillo
Protection system (Professional)
!- <Protection Options>
Debug-Blocker
CopyMem-II
Enable Import Table Elimination
Enable Nanomites Processing
Enable Memory-Patching Protections
!- <Backup Key Options>
Main Key Only, No Backup Keys
!- <Compression Options>
Best/Slowest Compression
!- <Other Options>
一、DebugActiveProcess
设置OllyDBD忽略所有异常选项。
载入Armadillo.exe,用IsDebug插件去掉OllyDBD的调试器标志。
004D8000 Ar> 60 pushad
004D8001 E8 00000000 call Armadill.004D8006
004D8006 5D pop ebp
004D8007 50 push eax
004D8008 51 push ecx
004D8009 0FCA bswap edx
004D800B F7D2 not edx
004D800D 9C pushfd
004D800E F7D2 not edx
004D8010 0FCA bswap edx
每次运行脚本前必须清除以前的所有断点! ★
现在运行DebugActiveProcess.osc
子进程ID=000000D14,开始4个字节EP Code=00000E860
“确定”后,此脚本完成任务,保留此OllyDBG不动。
二、Armadillo.fiXed.IT
新运行一个OllyDBG,Attach上ID=000000D14的子进程Armadillo.exe
7C921231 C3 retn
此时,什么都不要做,请直接运行Armadillo.fiXed.IT.osc,脚本提示:
确定”后F12,OllyDBG暂停在EP死循环处
004D8000 Ar>- EB FE jmp short Armadill.<ModuleEntryPoint>
还原EP Code的EBFE为60E8,还原后为:
004D8000 Ar> 60 pushad
004D8001 E8 00000000 call Armadill.004D8006
Resume脚本,操作如下:
等待一段时间后,出现提示对话框:
00FAD49F FF15 1861FB00 call dword ptr ds:[FB6118] ; kernel32.VirtualProtect
00FAD4A5 A0 BC00FC00 mov al,byte ptr ds:[FC00BC] ; 脚本运行完毕暂停在这里
在目标程序Armadillo.exe目录下脚本自动dump出一个文件:SaveIat000379428.bin
此文件保存的就是所有乱序前的正确函数地址!
00FAD4AA 8885 14A9FFFF mov byte ptr ss:[ebp+FFFFA914],al
00FAD4B0 0FB685 14A9FFFF movzx eax,byte ptr ss:[ebp+FFFFA914]
00FAD4B7 85C0 test eax,eax
00FAD4B9 74 1D je short 00FAD4D8
00FAD4BB 6A 00 push 0
00FAD4BD FFB5 CCB0FFFF push dword ptr ss:[ebp+FFFFB0CC]
00FAD4C3 8B85 0CD8FFFF mov eax,dword ptr ss:[ebp-27F4]
00FAD4C9 0385 BCB0FFFF add eax,dword ptr ss:[ebp+FFFFB0BC]
00FAD4CF 50 push eax
00FAD4D0 E8 8A110000 call 00FAE65F ; 单步运行到此处,解密CALL,修改堆栈值,此时察看堆栈为:
――――――――――――――――――――――――――
00129500 00401000 Armadill.00401000
00129504 0004E001 修改为4E000
――――――――――――――――――――――――――
其实就是解密PE header下面区段的代码
但是此区段的Size为4E000,ALT+M察看内存参见:
这里多了1,将导致其下区段被加密,所以我们要修改这里为4E000
在数据窗口里定位00401000,F8步过上面CALL时会发现00401000段的代码已经全部解密出来了!
00FAD4D5 83C4 0C add esp,0C
00FAD4D8 8B85 FCD7FFFF mov eax,dword ptr ss:[ebp-2804]
00FAD4DE 8BB5 0CD8FFFF mov esi,dword ptr ss:[ebp-27F4]
00FAD4E4 2B70 34 sub esi,dword ptr ds:[eax+34]
00FAD4E7 E8 5C2E0000 call 00FB0348
00FAD4EC F7D8 neg eax
00FAD4EE 1BC0 sbb eax,eax
00FAD4F0 25 00100000 and eax,1000
00FAD4F5 03F0 add esi,eax
00FAD4F7 89B5 C4B0FFFF mov dword ptr ss:[ebp+FFFFB0C4],esi
00FAD4FD 83A5 C8B0FFFF 00 and dword ptr ss:[ebp+FFFFB0C8],0
00FAD504 EB 0D jmp short 00FAD513
00FAD506 8B85 C8B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0C8]
00FAD50C 40 inc eax
00FAD50D 8985 C8B0FFFF mov dword ptr ss:[ebp+FFFFB0C8],eax
00FAD513 8B85 C8B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0C8]
00FAD519 8B8D 24D9FFFF mov ecx,dword ptr ss:[ebp-26DC]
00FAD51F 833C81 00 cmp dword ptr ds:[ecx+eax*4],0
00FAD523 0F84 90000000 je 00FAD5B9
00FAD529 8B85 C8B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0C8]
00FAD52F 8B8D 24D9FFFF mov ecx,dword ptr ss:[ebp-26DC]
00FAD535 8B95 0CD8FFFF mov edx,dword ptr ss:[ebp-27F4]
00FAD53B 031481 add edx,dword ptr ds:[ecx+eax*4]
00FAD53E 8995 B8B0FFFF mov dword ptr ss:[ebp+FFFFB0B8],edx
00FAD544 8B85 B8B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0B8]
00FAD54A 8B00 mov eax,dword ptr ds:[eax]
00FAD54C 8985 B4B0FFFF mov dword ptr ss:[ebp+FFFFB0B4],eax
00FAD552 81BD B4B0FFFF 9090909>cmp dword ptr ss:[ebp+FFFFB0B4],90909>
00FAD55C 74 56 je short 00FAD5B4
00FAD55E 8B85 B4B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0B4]
00FAD564 2B85 C4B0FFFF sub eax,dword ptr ss:[ebp+FFFFB0C4]
00FAD56A 8985 B4B0FFFF mov dword ptr ss:[ebp+FFFFB0B4],eax
00FAD570 FFB5 B4B0FFFF push dword ptr ss:[ebp+FFFFB0B4]
00FAD576 8B85 C8B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0C8]
00FAD57C 33D2 xor edx,edx
00FAD57E 6A 1E push 1E
00FAD580 59 pop ecx
00FAD581 F7F1 div ecx
00FAD583 FF1495 9867FB00 call dword ptr ds:[edx*4+FB6798]
00FAD58A 59 pop ecx
00FAD58B 8985 B4B0FFFF mov dword ptr ss:[ebp+FFFFB0B4],eax
00FAD591 8B85 B4B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0B4]
00FAD597 8B8D E4D7FFFF mov ecx,dword ptr ss:[ebp-281C]
00FAD59D 8D0481 lea eax,dword ptr ds:[ecx+eax*4]
00FAD5A0 8985 B4B0FFFF mov dword ptr ss:[ebp+FFFFB0B4],eax
00FAD5A6 8B85 B8B0FFFF mov eax,dword ptr ss:[ebp+FFFFB0B8]
00FAD5AC 8B8D B4B0FFFF mov ecx,dword ptr ss:[ebp+FFFFB0B4]
00FAD5B2 8908 mov dword ptr ds:[eax],ecx
00FAD5B4 ^ E9 4DFFFFFF jmp 00FAD506
00FAD5B9 A0 BC00FC00 mov al,byte ptr ds:[FC00BC] ; 这里处理结束,下断,Shift+F9中断下来。
设置0044F000(401000+4E000,即解密CALL运行时堆栈中察看到的值)为完整权限,
把SaveIat000379428.bin里面的有序地址全部粘贴到0044F000处。
注意,我们要先去掉非函数地址的数据。利用WinHEX察看SaveIat000379428.bin文件可以看到
自0X374后明显不是正确的地址,就可以全部删除了。
在WINHEX中选中BLOCK 00000000-00000370,然后Copy Block-〉Hex Values
然后回到OD中,CTRL+G,输入44F000,然后选中要粘贴的区域,然后进行二进制粘贴
接着我们来修复这些乱序的输入表函数,Patch代码如下。在00FAD5B9处开始输入以下代码:
00FAD5B9 60 pushad
00FAD5BA 8BB5 E4D7FFFF mov esi,dword ptr ss:[ebp-281C]
00FAD5C0 8BBD 24D9FFFF mov edi,dword ptr ss:[ebp-26DC]
00FAD5C6 833F 00 cmp dword ptr ds:[edi],0
00FAD5C9 74 2E je short 00FAD5F9
00FAD5CB 8B07 mov eax,dword ptr ds:[edi]
00FAD5CD 05 00004000 add eax,400000
00FAD5D2 8B10 mov edx,dword ptr ds:[eax]
00FAD5D4 BB 00F04400 mov ebx,44F000 ; IAT开始的地址
00FAD5D9 81FA 90909090 cmp edx,90909090
00FAD5DF 74 13 je short 00FAD5F4
00FAD5E1 8B12 mov edx,dword ptr ds:[edx]
00FAD5E3 3B13 cmp edx,dword ptr ds:[ebx]
00FAD5E5 74 0B je short 00FAD5F2
00FAD5E7 83C3 04 add ebx,4
00FAD5EA 81FB 78F34400 cmp ebx,44F378 ; IAT开始的地址+IAT的长度
00FAD5F0 ^ 7C F1 jl short 00FAD5E3
00FAD5F2 8918 mov dword ptr ds:[eax],ebx
00FAD5F4 83C7 04 add edi,4
00FAD5F7 ^ EB CD jmp short 00FAD5C6
00FAD5F9 61 popad
00FAD5FA 90 nop
或利用OllyDBG二进制代码复制,然后进行修改。
60 8B B5 E4 D7 FF FF 8B BD 24 D9 FF FF 83 3F 00 74 2E 8B 07 05 00 00 40 00 8B 10 BB 00 F0 44 00
81 FA 90 90 90 90 74 13 8B 12 3B 13 74 0B 83 C3 04 81 FB 78 F3 44 00 7C F1 89 18 83 C7 04 EB CD
61 90
在00FAD5FA处下断点,然后F9在00FAD5FA中断后乱序输入表修复完毕。
因为下面Armadillo还要再对代码段加密,所以此时运行LordPE完全dump出此进程!注意PID选择要正确。
然后运行ImportREC,RVA=0004F000,Size=00000374,获取输入表,Cut掉几个填充在DLL间的垃圾数据,保存树文件。
此时,运行ArmInLine,选中PID对应的Armadillo,
然后依次点击“Rebase IAT”,“Locate”等待完毕后不要关闭ArmInLine。
三、OEP
撤销上面patch的代码,把EIP重新定位在00FAD5B9处,我们来找OEP
BP CreateThread+5,shift+F9运行,中断在下面,
7C81063C FF75 1C push dword ptr ss:[ebp+1C]
7C81063F FF75 18 push dword ptr ss:[ebp+18]
7C810642 FF75 14 push dword ptr ss:[ebp+14]
7C810645 FF75 10 push dword ptr ss:[ebp+10]
7C810648 FF75 0C push dword ptr ss:[ebp+C]
7C81064B FF75 08 push dword ptr ss:[ebp+8]
7C81064E 6A FF push -1
7C810650 E8 D7FDFFFF call kernel32.CreateRemoteThread
7C810655 5D pop ebp
F2取消断点,ALT+F9返回到此处,
00F9C5F3 50 push eax
00F9C5F4 FF15 4C62FB00 call dword ptr ds:[FB624C] ; kernel32.CloseHandle
00F9C5FA 5F pop edi
00F9C5FB 5E pop esi
00F9C5FC C9 leave
00F9C5FD C3 retn
一路F8运行到:
00FAFA18 59 pop ecx
00FAFA19 BE 98FAFB00 mov esi,0FBFA98
00FAFA1E 8BCE mov ecx,esi
00FAFA20 E8 9892FDFF call 00F88CBD
00FAFA25 84C0 test al,al
00FAFA27 75 09 jnz short 00FAFA32
00FAFA29 6A 01 push 1
00FAFA2B 8BCE mov ecx,esi
00FAFA2D E8 6CE2FDFF call 00F8DC9E
00FAFA32 C705 E0C0FB00 D8CFFB0>mov dword ptr ds:[FBC0E0],0FBCFD8
00FAFA3C B9 00ECFB00 mov ecx,0FBEC00
00FAFA41 E8 1BF2FFFF call 00FAEC61
00FAFA46 53 push ebx
00FAFA47 E8 15F2FFFF call 00FAEC61
00FAFA4C 59 pop ecx
00FAFA4D 33D2 xor edx,edx
00FAFA4F 8955 DC mov dword ptr ss:[ebp-24],edx
00FAFA52 895D FC mov dword ptr ss:[ebp-4],ebx
00FAFA55 A0 BC00FC00 mov al,byte ptr ds:[FC00BC]
00FAFA5A 8845 C8 mov byte ptr ss:[ebp-38],al
00FAFA5D 84C0 test al,al
00FAFA5F 75 4A jnz short 00FAFAAB
00FAFA61 A1 E400FC00 mov eax,dword ptr ds:[FC00E4]
00FAFA66 8B48 0C mov ecx,dword ptr ds:[eax+C]
00FAFA69 894D C4 mov dword ptr ss:[ebp-3C],ecx
00FAFA6C 894D D0 mov dword ptr ss:[ebp-30],ecx
00FAFA6F 8B0D FC00FC00 mov ecx,dword ptr ds:[FC00FC] ; Armadill.00400000
00FAFA75 894D C0 mov dword ptr ss:[ebp-40],ecx
00FAFA78 8B70 78 mov esi,dword ptr ds:[eax+78]
00FAFA7B 3370 54 xor esi,dword ptr ds:[eax+54]
00FAFA7E 3370 08 xor esi,dword ptr ds:[eax+8]
00FAFA81 03F1 add esi,ecx
00FAFA83 8975 D4 mov dword ptr ss:[ebp-2C],esi
00FAFA86 8B98 88000000 mov ebx,dword ptr ds:[eax+88]
00FAFA8C 3358 30 xor ebx,dword ptr ds:[eax+30]
00FAFA8F 3358 14 xor ebx,dword ptr ds:[eax+14]
00FAFA92 895D A8 mov dword ptr ss:[ebp-58],ebx
00FAFA95 8D4D D0 lea ecx,dword ptr ss:[ebp-30]
00FAFA98 E8 6315FDFF call 00F81000
00FAFA9D 33D2 xor edx,edx
00FAFA9F F7F3 div ebx
00FAFAA1 03D6 add edx,esi
00FAFAA3 8955 CC mov dword ptr ss:[ebp-34],edx
00FAFAA6 8B12 mov edx,dword ptr ds:[edx]
00FAFAA8 8955 DC mov dword ptr ss:[ebp-24],edx
00FAFAAB 834D FC FF or dword ptr ss:[ebp-4],FFFFFFFF
00FAFAAF EB 11 jmp short 00FAFAC2
00FAFAB1 6A 01 push 1
00FAFAB3 58 pop eax
00FAFAB4 C3 retn
00FAFAB5 8B65 E8 mov esp,dword ptr ss:[ebp-18]
00FAFAB8 834D FC FF or dword ptr ss:[ebp-4],FFFFFFFF
00FAFABC 8B7D 08 mov edi,dword ptr ss:[ebp+8]
00FAFABF 8B55 DC mov edx,dword ptr ss:[ebp-24]
00FAFAC2 A1 E400FC00 mov eax,dword ptr ds:[FC00E4]
00FAFAC7 3150 0C xor dword ptr ds:[eax+C],edx
00FAFACA A1 E400FC00 mov eax,dword ptr ds:[FC00E4]
00FAFACF 3150 0C xor dword ptr ds:[eax+C],edx
00FAFAD2 A1 E400FC00 mov eax,dword ptr ds:[FC00E4]
00FAFAD7 8B88 88000000 mov ecx,dword ptr ds:[eax+88]
00FAFADD 3388 84000000 xor ecx,dword ptr ds:[eax+84]
00FAFAE3 3348 2C xor ecx,dword ptr ds:[eax+2C]
00FAFAE6 030D FC00FC00 add ecx,dword ptr ds:[FC00FC] ; Armadill.00400000
00FAFAEC 8B17 mov edx,dword ptr ds:[edi]
00FAFAEE 85D2 test edx,edx
00FAFAF0 75 1A jnz short 00FAFB0C
00FAFAF2 FF77 18 push dword ptr ds:[edi+18]
00FAFAF5 FF77 14 push dword ptr ds:[edi+14]
00FAFAF8 FF77 10 push dword ptr ds:[edi+10]
00FAFAFB 8B90 88000000 mov edx,dword ptr ds:[eax+88]
00FAFB01 3350 7C xor edx,dword ptr ds:[eax+7C]
00FAFB04 3310 xor edx,dword ptr ds:[eax]
00FAFB06 2BCA sub ecx,edx
00FAFB08 FFD1 call ecx
00FAFB0A EB 1F jmp short 00FAFB2B
00FAFB0C 83FA 01 cmp edx,1
00FAFB0F 75 1D jnz short 00FAFB2E
00FAFB11 FF77 04 push dword ptr ds:[edi+4]
00FAFB14 FF77 08 push dword ptr ds:[edi+8]
00FAFB17 6A 00 push 0
00FAFB19 FF77 0C push dword ptr ds:[edi+C]
00FAFB1C 8B90 88000000 mov edx,dword ptr ds:[eax+88]
00FAFB22 3350 7C xor edx,dword ptr ds:[eax+7C]
00FAFB25 3310 xor edx,dword ptr ds:[eax]
00FAFB27 2BCA sub ecx,edx
00FAFB29 FFD1 call ecx
00FAFB2B 8945 E4 mov dword ptr ss:[ebp-1C],eax
00FAFB2E 8B45 E4 mov eax,dword ptr ss:[ebp-1C]
00FAFB31 8B4D F0 mov ecx,dword ptr ss:[ebp-10]
00FAFB34 64:890D 00000000 mov dword ptr fs:[0],ecx
00FAFB3B 5F pop edi
00FAFB3C 5E pop esi
00FAFB3D 5B pop ebx
00FAFB3E C9 leave
00FAFB3F C3 retn
00FAFB29 FFD1 call ecx ; 此处F7 进去,就是OEP了
此时代码段已经被Armadillo再次加密,不必管了,上面我们已经抓取了他的解密代码。
在ImportREC里面填入OEP=00048BB0,然后从文件载入前面DUMP时保存的IAT文件, Fix Dump。
最后点击ArmInline中的RePair按钮搞定CC。
其实最好的方法是,记住OEP后,从新再来一遍, 然后在启动ArmInline的地方,先FIX DUMP,然后就RePair。
OK,脱壳完毕。其实都是学习别人的成果了,但是学习的过程记录的比较详细罢了,希望对菜鸟们有点帮助。
将详细图示附上。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)