.
【作者声明】:只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【调试环境】:WinXP、flyODBG、PEiD、LordPE
―――――――――――――――――――――――――――――――――
【脱壳过程】:
ACProtect是非常优秀的中国强壳。至今没有脱ACProtect加壳DLL的教程,所以我来写个简单的过程。
DLL例子虽然是用现今最新的ACProtect V1.41专业版加壳,但是没有SDK、Stolen Code,也不是Delphi程序,不必生搬硬套。
本教程提供了寻找ACProtect加壳DLL重定位表信息、不用ImportREC来恢复其输入表的方法。
放个PEiD的Sign:
[ACProtect V1.3X-1.4X DLL -> risco]
signature = 80 7C 24 08 01 0F 85
ep_only = true
设置Ollydbg忽略所有的异常选项。老规矩:用IsDebug V1.4插件去掉Ollydbg的调试器标志。
―――――――――――――――――――――――――――――――――
一、EP和OEP
003D7000 807C24 08 01 cmp byte ptr ss:[esp+8],1
//进入Ollydbg后暂停在这
003D7005 0F85 FE700100 jnz EdrLib.003EE109
//DLL退出时会跳转
003D700B 60 pushad
003D700C 4B dec ebx
003D700D 03D1 add edx,ecx
003D700F 40 inc eax
003D7010 85D8 test eax,ebx
003D7012 E8 01000000 call EdrLib.003D7018
DLL退出时会再次中断在EP处,找OEP就非常简单了。
退出时会从003D7005处跳转,而这下面就是跳向OEP的地方!
003EE109 FF25 4BE13E00 jmp dword ptr ds:[3EE14B]; EdrLib.003D11C9
//飞向光明之巅! ^O^
―――――――――――――――――――――――――――――――――
二、寻找重定位表信息
一个有趣的现象,很多保护壳都没有加密重定位表,如ASProtect、Armadillo、ACProtect、幻影等;而一些压缩壳却加密了重定位表,如Neolite、Petite等。
下断:HE GlobalFree Shift+F9运行,中断后取消断点。Alt+F9返回
003E9598 FF95 03FD4000 call dword ptr ss:[ebp+40FD03]; kernel32.GlobalFree
003E959E 5E pop esi
//返回这里
003E959F 83C6 08 add esi,8
003E95A2 EB B1 jmp short EdrLib.003E9555
Ctrl+F 在当前位置下搜索命令:
sub ebx,eax
找到在003EBB58处,下断,F9运行,中断。
003EBB58 2BD8 sub ebx,eax ; LOADDLL.00400000
//这里其实就是检测与映像基址是否相符,和ASProtect的方法一样。不符则重定位处理!★
003EBB5A 899D 055B4100 mov dword ptr ss:[ebp+415B05],ebx
003EBB60 0BDB or ebx,ebx
003EBB62 0F84 BB000000 je EdrLib.003EBC23
//可以在这里改标志位Z=1,使其跳转,这样脱壳后就不需要修改基址了 ★
003EBB68 8BB5 46F84000 mov esi,dword ptr ss:[ebp+40F846]
003EBB6E 03B5 F75A4100 add esi,dword ptr ss:[ebp+415AF7]
//[ebp+415AF7]=[003EBAF7]=00006000 这里保存的是重定位表的RVA ★
003EBB74 8B8D FB5A4100 mov ecx,dword ptr ss:[ebp+415AFB]
//[ebp+415AFB]=[003EBAFB]=000003B0 这里保存的是重定位表的Size ★
下面处理重定位表部分就不看了。在003EBB62处,转存中跟随ebp+415AF7和ebp+415AFB,得到重定位表RVA和Size后修改标志位Z=1,使其跳转,免得脱壳后要修改基址。
―――――――――――――――――――――――――――――――――
三、搞定输入表,不用ImportREC了
ACProtect的输入表加密一直是比较弱的,作者以后肯定会加强这方面保护的。
Go Go Go!呵呵,我们继续下断:HE GetModuleHandleA
Shift+F9运行,中断后取消断点。Alt+F9返回。 注释如下
003EB479 8BB5 07F94000 mov esi,dword ptr ss:[ebp+40F907]
003EB47F 03F2 add esi,edx
003EB481 8B46 0C mov eax,dword ptr ds:[esi+C]
003EB484 0BC0 or eax,eax
003EB486 0F84 25020000 je EdrLib.003EB6B1
003EB48C 8366 0C 00 and dword ptr ds:[esi+C],0
//这里清空ImageImportDescriptor的Name! NOP掉 ① ★
要注意的是,当我们中断后返回003EB4AF时,这里已经运行过一次了,清除了第一个Name指针。
可以根据当时的寄存器情况来恢复这个指针。在003EB4AF时ESI=003D442C,[esi+C]=[003D4438]=00 00,而EBX=003D454C ASCII "KERNEL32.dll" 是第一个处理的DLL名,所以可以确定[003D4438]=4C 45,修改之,否则DLLName会有错误 ★
003EB490 03C2 add eax,edx
003EB492 8BD8 mov ebx,eax
003EB494 56 push esi
003EB495 57 push edi
003EB496 50 push eax
003EB497 8BF3 mov esi,ebx
003EB499 8BFB mov edi,ebx
003EB49B AC lods byte ptr ds:[esi]
003EB49C C0C0 03 rol al,3
//解码出DLL名 ★
003EB49F AA stos byte ptr es:[edi]
003EB4A0 803F 00 cmp byte ptr ds:[edi],0
003EB4A3 75 F6 jnz short EdrLib.003EB49B
003EB4A5 58 pop eax
003EB4A6 5F pop edi
003EB4A7 5E pop esi
003EB4A8 50 push eax
003EB4A9 FF95 20854100 call dword ptr ss:[ebp+418520]; kernel32.GetModuleHandleA
003EB4AF 0BC0 or eax,eax
//返回这里
//此时ESI=003D442C-003D0000=442C 输入表的RVA ★
003EB4B1 75 43 jnz short EdrLib.003EB4F6
003EB4F6 60 pushad
003EB4F7 2BC0 sub eax,eax
003EB4F9 8803 mov byte ptr ds:[ebx],al
//用完之后清空DLL名 NOP掉 ②! ★
003EB4FB 43 inc ebx
003EB4FC 3803 cmp byte ptr ds:[ebx],al
003EB4FE 75 F9 jnz short EdrLib.003EB4F9
003EB500 61 popad
003EB501 8985 3EF84000 mov dword ptr ss:[ebp+40F83E],eax
//保存DLL基址
003EB507 C785 42F84000 000>mov dword ptr ss:[ebp+40F842],0
003EB511 8B95 46F84000 mov edx,dword ptr ss:[ebp+40F846]
003EB517 8B06 mov eax,dword ptr ds:[esi]
003EB519 0BC0 or eax,eax
003EB51B 75 07 jnz short EdrLib.003EB524
003EB51D 90 nop
003EB51E 90 nop
003EB51F 90 nop
003EB520 90 nop
003EB521 8B46 10 mov eax,dword ptr ds:[esi+10]
003EB524 03C2 add eax,edx
003EB526 0385 42F84000 add eax,dword ptr ss:[ebp+40F842]
003EB52C 8B18 mov ebx,dword ptr ds:[eax]
003EB52E 8B7E 10 mov edi,dword ptr ds:[esi+10]
003EB531 03FA add edi,edx
003EB533 03BD 42F84000 add edi,dword ptr ss:[ebp+40F842]
003EB539 85DB test ebx,ebx
003EB53B 0F84 62010000 je EdrLib.003EB6A3
003EB541 F7C3 00000080 test ebx,80000000
003EB547 75 1D jnz short EdrLib.003EB566
003EB549 90 nop
003EB54A 90 nop
003EB54B 90 nop
003EB54C 90 nop
003EB54D 03DA add ebx,edx
003EB54F 83C3 02 add ebx,2
003EB552 56 push esi
003EB553 57 push edi
003EB554 50 push eax
003EB555 8BF3 mov esi,ebx
003EB557 8BFB mov edi,ebx
003EB559 AC lods byte ptr ds:[esi]
003EB55A C0C0 03 rol al,3
//解码出函数名 ★
003EB55D AA stos byte ptr es:[edi]
003EB55E 803F 00 cmp byte ptr ds:[edi],0
003EB561 75 F6 jnz short EdrLib.003EB559
003EB563 58 pop eax
003EB564 5F pop edi
003EB565 5E pop esi
003EB566 3B9D 46F84000 cmp ebx,dword ptr ss:[ebp+40F846]
003EB56C 7C 11 jl short EdrLib.003EB57F
003EB56E 90 nop
003EB56F 90 nop
003EB570 90 nop
003EB571 90 nop
003EB572 83BD 1A204000 00 cmp dword ptr ss:[ebp+40201A],0
003EB579 75 0A jnz short EdrLib.003EB585
003EB57B 90 nop
003EB57C 90 nop
003EB57D 90 nop
003EB57E 90 nop
003EB57F 81E3 FFFFFF0F and ebx,0FFFFFFF
003EB585 53 push ebx
003EB586 FFB5 3EF84000 push dword ptr ss:[ebp+40F83E]
003EB58C FF95 1C854100 call dword ptr ss:[ebp+41851C]; kernel32.GetProcAddress
003EB592 3B9D 46F84000 cmp ebx,dword ptr ss:[ebp+40F846]
003EB598 7C 0F jl short EdrLib.003EB5A9
003EB59A 90 nop
003EB59B 90 nop
003EB59C 90 nop
003EB59D 90 nop
003EB59E 60 pushad
003EB59F 2BC0 sub eax,eax
003EB5A1 8803 mov byte ptr ds:[ebx],al
//用完之后清空函数名 NOP掉 ③! ★
003EB5A3 43 inc ebx
003EB5A4 3803 cmp byte ptr ds:[ebx],al
003EB5A6 75 F9 jnz short EdrLib.003EB5A1
003EB5A8 61 popad
003EB5A9 0BC0 or eax,eax
003EB5AB 0F84 15FFFFFF je EdrLib.003EB4C6
003EB5B1 3B85 2C854100 cmp eax,dword ptr ss:[ebp+41852C]; USER32.MessageBoxA
//是否是MessageBoxA ? EMbedded Protector 专用APT接口
003EB5B7 74 20 je short EdrLib.003EB5D9
003EB5B9 90 nop
003EB5BA 90 nop
003EB5BB 90 nop
003EB5BC 90 nop
003EB5BD 3B85 C4FD4000 cmp eax,dword ptr ss:[ebp+40FDC4]; USER32.RegisterHotKey
//是否是RegisterHotKey ?
003EB5C3 74 09 je short EdrLib.003EB5CE
003EB5C5 90 nop
003EB5C6 90 nop
003EB5C7 90 nop
003EB5C8 90 nop
003EB5C9 EB 14 jmp short EdrLib.003EB5DF
003EB5CB 90 nop
003EB5CC 90 nop
003EB5CD 90 nop
003EB5CE 8D85 31FE4000 lea eax,dword ptr ss:[ebp+40FE31]
003EB5D4 EB 09 jmp short EdrLib.003EB5DF
003EB5D6 90 nop
003EB5D7 90 nop
003EB5D8 90 nop
003EB5D9 8D85 4BFE4000 lea eax,dword ptr ss:[ebp+40FE4B]
003EB5DF 56 push esi
003EB5E0 FFB5 3EF84000 push dword ptr ss:[ebp+40F83E]
003EB5E6 5E pop esi
003EB5E7 39B5 12204000 cmp dword ptr ss:[ebp+402012],esi; kernel32.7C800000
//比较是否是Kernel32.DLL基址
003EB5ED 74 15 je short EdrLib.003EB604
003EB5EF 90 nop
003EB5F0 90 nop
003EB5F1 90 nop
003EB5F2 90 nop
003EB5F3 39B5 16204000 cmp dword ptr ss:[ebp+402016],esi
//比较是否是User32.DLL基址
003EB5F9 74 09 je short EdrLib.003EB604
003EB5FB 90 nop
003EB5FC 90 nop
003EB5FD 90 nop
003EB5FE 90 nop
003EB5FF EB 63 jmp short EdrLib.003EB664
003EB601 90 nop
003EB602 90 nop
003EB603 90 nop
003EB604 80BD 16564100 00 cmp byte ptr ss:[ebp+415616],0
003EB60B 74 57 je short EdrLib.003EB664
//Magic Jump! 如果用ImportREC修复输入表,则可以修改这里为:jmp 003EB664 ★
//这样就可以得到未被加密的函数了。但是我这次不用ImportREC,所以不修改这里 ^O^
003EB60D 90 nop
003EB60E 90 nop
003EB60F 90 nop
003EB610 90 nop
003EB611 EB 07 jmp short EdrLib.003EB61A
//下面就是加密了
003EB613 90 nop
003EB614 90 nop
003EB615 90 nop
003EB616 0100 add dword ptr ds:[eax],eax
003EB618 0000 add byte ptr ds:[eax],al
003EB61A 8BB5 0BF94000 mov esi,dword ptr ss:[ebp+40F90B]
003EB620 83C6 0D add esi,0D
003EB623 81EE 02184000 sub esi,401802
003EB629 2BF5 sub esi,ebp
003EB62B 83FE 00 cmp esi,0
003EB62E 7F 34 jg short EdrLib.003EB664
003EB630 90 nop
003EB631 90 nop
003EB632 90 nop
003EB633 90 nop
003EB634 8BB5 0BF94000 mov esi,dword ptr ss:[ebp+40F90B]
003EB63A 53 push ebx
003EB63B 50 push eax
003EB63C E8 8DB2FFFF call EdrLib.003E68CE
003EB641 8BD8 mov ebx,eax
003EB643 58 pop eax
003EB644 33C3 xor eax,ebx
003EB646 C606 68 mov byte ptr ds:[esi],68
003EB649 8946 01 mov dword ptr ds:[esi+1],eax
003EB64C C746 05 81342400 mov dword ptr ds:[esi+5],243481
003EB653 895E 08 mov dword ptr ds:[esi+8],ebx
003EB656 C646 0C C3 mov byte ptr ds:[esi+C],0C3
003EB65A 5B pop ebx
003EB65B 8BC6 mov eax,esi
003EB65D 8385 0BF94000 0D add dword ptr ss:[ebp+40F90B],0D
003EB664 5E pop esi
003EB665 60 pushad
003EB666 8BD0 mov edx,eax
003EB668 2BBD 46F84000 sub edi,dword ptr ss:[ebp+40F846]
003EB66E 8BC7 mov eax,edi
003EB670 B9 01010000 mov ecx,101
003EB675 8DBD EBEC4000 lea edi,dword ptr ss:[ebp+40ECEB]
003EB67B F2:AF repne scas dword ptr es:[edi]
003EB67D 0BC9 or ecx,ecx
003EB67F 74 13 je short EdrLib.003EB694
003EB681 90 nop
003EB682 90 nop
003EB683 90 nop
003EB684 90 nop
003EB685 81E9 01010000 sub ecx,101
003EB68B F7D1 not ecx
003EB68D 89948D EBE84000 mov dword ptr ss:[ebp+ecx*4+40E8EB],edx
003EB694 61 popad
003EB695 8907 mov dword ptr ds:[edi],eax
//API函数的系统地址(或者加密地址)填充到IAT中 NOP掉 ④!★
003EB697 8385 42F84000 04 add dword ptr ss:[ebp+40F842],4
003EB69E E9 6EFEFFFF jmp EdrLib.003EB511
003EB6A3 83C6 14 add esi,14
003EB6A6 8B95 46F84000 mov edx,dword ptr ss:[ebp+40F846]
003EB6AC E9 D0FDFFFF jmp EdrLib.003EB481
//循环处理
003EB6B1 8DBD EBEC4000 lea edi,dword ptr ss:[ebp+40ECEB]
//修改上面4处后直接F4到这里 输入表处理完毕了
运行LordPE完全Dump出这个dll,保存为UnPacked.dll
―――――――――――――――――――――――――――――――――
四、第2区段内存断点法,飞向光明之巅
Alt+M 打开内存查看窗口:
003D0000 00001000 EdrLib 003D0000 (itself) PE header
003D1000 00003000 EdrLib 003D0000 .text code//第二区段
003D4000 00001000 EdrLib 003D0000 .rdata code,data,exports
003D5000 00001000 EdrLib 003D0000 .data code
003D6000 00001000 EdrLib 003D0000 .reloc code
003D7000 00018000 EdrLib 003D0000 .perplex code,imports
在003D1000第二区段上设置内存访问断点,Shift+F9运行
确定ACProtect的试用版保护标记,Ollydbg中断在OEP!
003D11C9 55 push ebp
//OEP ^O^
003D11CA 8BEC mov ebp,esp
003D11CC 53 push ebx
003D11CD 8B5D 08 mov ebx,dword ptr ss:[ebp+8]
003D11D0 56 push esi
003D11D1 8B75 0C mov esi,dword ptr ss:[ebp+C]
003D11D4 57 push edi
003D11D5 8B7D 10 mov edi,dword ptr ss:[ebp+10]
003D11D8 85F6 test esi,esi
003D11DA 75 09 jnz short EdrLib.003D11E5
―――――――――――――――――――――――――――――――――
五、PE修正
用LordPE修正UnPacked.dll的OEP RVA=000011C9,重定位表RVA=00006000、大小=000003B0,输入表RVA=0000442C。保存之。ACProtect没有对输出表动手脚,因此不需要处理。
用LordPE删除.perplex壳区段,然后重建PE优化一下。
OK,脱壳完成了!
2004年的最后一天,昨夜落了微雪,今天天晴了。
―――――――――――――――――――――――――――――――――
, _/
/| _.-~/ \_ , 青春都一晌
( /~ / \~-._ |\
`\\ _/ \ ~\ ) 忍把浮名
_-~~~-.) )__/;;,. \_ //'
/'_,\ --~ \ ~~~- ,;;\___( (.-~~~-. 换了破解轻狂
`~ _( ,_..--\ ( ,;'' / ~-- /._`\
/~~//' /' `~\ ) /--.._, )_ `~
" `~" " `" /~'`\ `\\~~\
" " "~' ""
UnPacked By : fly
2004-12-31 12:00
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)