【目标程序】:幻影 V2.33加壳的EdrLib.dll。附件中含有输入表和UnPacked以供参考。
【作者声明】:只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【调试环境】:WinXP、Ollydbg1.10修改版、IdtTool、LordPE、ImportREC
【实例下载】:点击此处下载(或鼠标右键另存为)
—————————————————————————————————
【脱壳过程】:
关于用 幻影 加壳DLL的脱壳,直至如今还没有公开一篇教程。于是我琢磨着写了这点东西,聊以充数吧。
先运行 飞叶流枫 兄的IdtTool保存中断地址,调试出错后恢复IDT,免得重启。
老规矩:用IsDebug 1.4插件去掉flyODBG的调试器标志。设置flyODBG忽略所有的异常选项。
其实幻影加壳DLL的脱壳难点就在于重定位表的处理,因为没有资料可以参考,所以只好自己分析了。
你可以先跟到OEP,然后在DLL需要重定位的地址下内存写入断点,从而得到幻影对DLL重定位数据的处理代码段。下面提供的简便方法是在这个基础上归纳、总结出来的,或许不适用于幻影的所有版本。
常听见有朋友说公开的教程大部分只是过程记录而已,没有破解思路,进而怀疑写教程的兄弟害怕观者学习。
不知上面的一段话可否算为 简单的思路?其实很多时候作者的思路皆蕴涵在其过程之中!关键是看你自己怎么去看罢了。
至于“害怕观者学习”等等说法更是无稽之谈了。整理出笔记是件比较辛苦的事,能够发布笔记的兄弟都是忙里偷闲劳神费力无私分享出自己的成果,如果存在防他人学习的意思又何苦写这些东西呀?
另外:幻影 的威力依然不看小觑,刚开始学习脱壳的朋友暂时别碰了,不小心则爱机重启没商量。
卖油翁曰:“唯手熟而”,世上事大多如此,熟练之后方能产生技巧,方能得到属于你自己的感觉。
—————————————————————————————————
一、得到 重定位表 信息
首先我们可以跟到OEP,具体可以参看我以前发的《1分钟寻找 幻影 V2.33 壳的OEP》。
随便找一处DLL需重定位的代码,如:
003B11DC 833D 60533B00 00 cmp dword ptr ds:[3B5360],0
003B11E0处的3B肯定是被重定位之后的,记住这个地址。
用Ollydbg重新载入DLL,再次开始我们的DLL脱壳之旅…… …… GO GO GO! ^O^
代码:
003B7000 EB 20 jmp short EdrLib.003B7022//进入OD后停在这 003B7022 9C pushfd 003B7023 55 push ebp 003B7024 57 push edi 003B7025 56 push esi 003B7026 52 push edx 003B7027 51 push ecx 003B7028 53 push ebx 003B7029 9C pushfd 003B702A E8 00000000 call EdrLib.003B702F
下断:HE VirtualAlloc Shift+F9 运行,注意看堆栈:
代码:
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ HE VirtualAlloc 时的堆栈: 0006F8B4 003B7100 /CALL 到 VirtualAlloc 来自 EdrLib.003B70FA 0006F8B8 00000000 |Address = NULL 0006F8BC 0002DA70 |Size = 2DA70 (186992.) 0006F8C0 00001000 |AllocationType = MEM_COMMIT 0006F8C4 00000004 \Protect = PAGE_READWRITE 0006F8B8 003D4215 /CALL 到 VirtualAlloc 来自 EdrLib.003D420F 0006F8BC 00000000 |Address = NULL 0006F8C0 00030629 |Size = 30629 (198185.) 0006F8C4 00102000 |AllocationType = MEM_RESERVE|MEM_TOP_DOWN 0006F8C8 00000040 \Protect = PAGE_EXECUTE_READWRITE 0006F8BC 003D4234 /CALL 到 VirtualAlloc 来自 EdrLib.003D422E 0006F8C0 7FF60000 |Address = 7FF60000 0006F8C4 00030629 |Size = 30629 (198185.) 0006F8C8 00101000 |AllocationType = MEM_COMMIT|MEM_TOP_DOWN 0006F8CC 00000040 \Protect = PAGE_EXECUTE_READWRITE ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
当中断3次后,0006F8C0=7FF60000,这时ESP=0006F8BC,下断:HR ESP,Shift+F9 运行,2次来到7FFXXXXX地段。
代码:
003D4234 72 03 jb short EdrLib.003D4239//第1次 7FF7D504 83C4 04 add esp,4//第2次 7FF7D507 EB 02 jmp short 7FF7D50B
HD ESP 可以取消0006F8BC处的硬件访问断点了。
运行 hoto 大侠的 花指令去除器,大范围去除幻影花指令,看着清爽多了 ^O^
现在我们在需重定位的003B11E0处下 内存写入 断点:MW 003B11E0
Shift+F9运行,程序会再次在VirtualAlloc处中断2次,此时003B11E0处变为40,即:已经解压,还没有重定位。
可以HD VirtualAlloc、MD 003B11E0取消断点了。如果你还下了其他断点,记得现在全部清除。
然后Ctrl+S 在“整个段块”搜索命令序列:
代码:
mov di,word ptr ds:[esi] cmp di,word ptr ds:[esi+2]
找到在 7FF80FCC 处。我们直接F4到达其上的7FF80FBB处!
代码:
7FF80FB9 33C0 xor eax,eax 7FF80FBB 8BB5 FBCC4200 mov esi,dword ptr ss:[ebp+42CCFB]//直接F4到这里! //[ebp+42CCFB]=[7FF864E2]=00006000 ★ 这个00006000就是重定位表的RVA! 7FF80FC1 83FE 00 cmp esi,0 7FF80FC4 74 60 je short 7FF81026 //可以使这里跳转,避开重定位!★ 7FF80FC6 03B5 CBCA4200 add esi,dword ptr ss:[ebp+42CACB] 7FF80FCC 66:8B3E mov di,word ptr ds:[esi]//找到这里 7FF80FCF 66:3B7E 02 cmp di,word ptr ds:[esi+2] 7FF80FD3 74 51 je short 7FF81026 //重定位处理完毕后则跳转 7FF80FD5 8B3E mov edi,dword ptr ds:[esi] 7FF80FD7 83FF 00 cmp edi,0 7FF80FDA 74 4A je short 7FF81026 7FF80FDC 03BD CBCA4200 add edi,dword ptr ss:[ebp+42CACB] 7FF80FE2 8B4E 04 mov ecx,dword ptr ds:[esi+4] 7FF80FE5 83E9 08 sub ecx,8 7FF80FE8 83F9 00 cmp ecx,0 7FF80FEB 74 39 je short 7FF81026 7FF80FED D1E9 shr ecx,1 7FF80FEF 83C6 08 add esi,8 7FF80FF2 66:8B06 mov ax,word ptr ds:[esi] 7FF80FF5 66:25 00F0 and ax,0F000 7FF80FF9 66:3D 0030 cmp ax,3000 7FF80FFD 75 1C jnz short 7FF8101B 7FF80FFF 66:33C0 xor ax,ax 7FF81002 66:8706 xchg word ptr ds:[esi],ax //注意:这里把重定位表清0!如果没在7FF80FC4处跳转的话则需要先把重定位表DUMP出来,脱壳后再粘贴回去!★ 7FF81005 66:25 FF0F and ax,0FFF 7FF81009 8B9D 0FCD4200 mov ebx,dword ptr ss:[ebp+42CD0F] 7FF8100F 291C07 sub dword ptr ds:[edi+eax],ebx 7FF81012 8B9D CBCA4200 mov ebx,dword ptr ss:[ebp+42CACB] 7FF81018 011C07 add dword ptr ds:[edi+eax],ebx 7FF8101B 83C6 02 add esi,2 7FF8101E 49 dec ecx 7FF8101F 83F9 00 cmp ecx,0 7FF81022 75 CE jnz short 7FF80FF2 7FF81024 EB A6 jmp short 7FF80FCC//循环处理 7FF81026 61 popad //这里下硬件断点,或者直接F4到这里。ESI=003B63B0 7FF81027 C3 retn
当我们到达003B7257处时,重定位处理完毕。此时ESI=003B63B0,就是重定位表的结束地址啦。
目的达到,呵呵,得到重定位表信息:
RVA=00006000,大小=003B63B0-003B6000=000003B0
—————————————————————————————————
二、避开重定位、避开IAT加密、Dump
再次载入DLL,现在已经得到重定位表信息,接下来就按照脱EXE幻影壳的方法来操作就行了。
HE VirtualAlloc、HR ESP,按照上面第一部分开始的方法来到7FFXXXXX地段。
直接修改了,具体解释可以看forgot这个狂人写的《幻影之旅》 ^O^
代码:
7FF7D504 83C4 04 add esp,4//来到7FFXXXXX地段 7FF7D507 EB 02 jmp short 7FF7D50B
当然用去花指令插件大面积去花,呵呵。
————————————————————————
1、避开重定位
Ctrl+G :7FF80FC4 见第一部分“得到 重定位表 信息”的分析
代码:
7FF80FC4 74 60 je short 7FF81026 //修改为:jmp short 7FF81026
————————————————————————
2、避开调用表、跳转表加密
在这里绕了个弯子,直接避开重定位表数据处理后,IAT部分的调用表处理有些变化,调试了几次才找到原因。
去花之后,Ctrl+S 在“整个段块”搜索命令序列:
代码:
mov dword ptr ds:[edi],esi nop//去花后的效果 nop nop nop nop add esi,4
找到7FF7F5DC处:
代码:
7FF7F510 F2:66:AF repne scas word ptr es:[edi]//寻找“目标” 7FF7F518 8B1F mov ebx,dword ptr ds:[edi] 7FF7F51F 81E3 00000080 and ebx,80000000 7FF7F52A 81FB 00000080 cmp ebx,80000000 7FF7F530 0F85 BF000000 jnz 7FF7F5F5 7FF7F53B 8B1F mov ebx,dword ptr ds:[edi] 7FF7F542 81E3 FFFFFF7F and ebx,7FFFFFFF 7FF7F548 90 nop 7FF7F549 90 nop 7FF7F54A 90 nop 7FF7F54B 90 nop 7FF7F54C 90 nop //借这几个NOP用用,呵呵 改为:mov dword ptr ds:[edi],ebx ★ 7FF7F548 891F mov dword ptr ds:[edi],ebx 7FF7F54D 3B9D 22CD4200 cmp ebx,dword ptr ss:[ebp+42CD22] 7FF7F553 0F82 97000000 jb 7FF7F5F0 7FF7F586 3B9D 1ECD4200 cmp ebx,dword ptr ss:[ebp+42CD1E] 7FF7F58C 77 5D ja short 7FF7F5EB 7FF7F593 833E FF cmp dword ptr ds:[esi],-1 7FF7F59B 0F84 51030000 je 7FF7F8F2 7FF7F5A6 8B1B mov ebx,dword ptr ds:[ebx] 7FF7F5D5 891E mov dword ptr ds:[esi],ebx 7FF7F5DC 8937 mov dword ptr ds:[edi],esi //写入重定位后的地址!NOP掉 ★ 7FF7F5DE 90 nop 7FF7F5DF 90 nop 7FF7F5E0 90 nop 7FF7F5E1 90 nop 7FF7F5E2 90 nop 7FF7F5E3 83C6 04 add esi,4
上面是调用表的处理,这个DLL没有跳转表的处理。其实下面的跳转表修改方法是相似。
————————————————————————
3、Magic Jump:避开IAT加密
Ctrl+S 在当前位置下搜索命令序列:
代码:
mov dword ptr ds:[edi],ecx nop nop nop nop nop add esi,4
找到在7FF80E83处。把其上的7FF80A43处修改为JMP
代码:
7FF8094B 50 push eax 7FF8094C FFB5 44C24200 push dword ptr ss:[ebp+42C244] 7FF80952 FF95 BA6D4300 call dword ptr ss:[ebp+436DBA] 7FF809B7 3985 900E4300 cmp dword ptr ss:[ebp+430E90],eax 7FF809BD 75 4B jnz short 7FF80A0A 7FF809EC C685 9F774200 01 mov byte ptr ss:[ebp+42779F],1 7FF80A3C 80BD 9F774200 01 cmp byte ptr ss:[ebp+42779F],1 7FF80A43 0F85 59030000 jnz 7FF80DA2 //Magic Jump 当然改为 jmp 7FF80DA2 ★ …… …… 7FF80D8A 61 popad 7FF80D90 8B8D 97774200 mov ecx,dword ptr ss:[ebp+427797] 7FF80DA0 EB 0C jmp short 7FF80DAE 7FF80DA7 8BC8 mov ecx,eax 7FF80DF7 39BD 22CD4200 cmp dword ptr ss:[ebp+42CD22],edi 7FF80DFD 76 10 jbe short 7FF80E0F 7FF80E04 89BD 22CD4200 mov dword ptr ss:[ebp+42CD22],edi 7FF80E26 39BD 1ECD4200 cmp dword ptr ss:[ebp+42CD1E],edi 7FF80E2C 73 34 jnb short 7FF80E62 7FF80E45 89BD 1ECD4200 mov dword ptr ss:[ebp+42CD1E],edi 7FF80E83 890F mov dword ptr ds:[edi],ecx//呵呵,正确的函数写入正确的地址 :-) 7FF80E85 90 nop 7FF80E86 90 nop 7FF80E87 90 nop 7FF80E88 90 nop 7FF80E89 90 nop 7FF80E8A 83C6 04 add esi,4 7FF80E92 83C7 04 add edi,4 7FF80EAC E9 71F9FFFF jmp 7FF80822//循环
————————————————————————
4、OEP 啦
Ctrl+S 在当前位置下搜索命令序列:
代码:
popad pop eax cmp eax,-1
找到在7FF8A96C处。
我们现在已经完成了上面所说的修改,直接在7FF8A96C处下 内存访问 断点,Shift+F9就离成功很近了。
代码:
7FF8A96C 61 popad 7FF8A96D 58 pop eax 7FF8A96E 83F8 FF cmp eax,-1 7FF8A971 75 05 jnz short 7FF8A978 7FF8A973 33C0 xor eax,eax 7FF8A975 C2 0C00 retn 0C 7FF8A978 FFE0 jmp eax; EdrLib.003B11C9//飞向光明之巅! ^O^
代码:
003B11C9 55 push ebp//OEP ★ 003B11CA 8BEC mov ebp,esp 003B11CC 53 push ebx 003B11CD 8B5D 08 mov ebx,dword ptr ss:[ebp+8] 003B11D0 56 push esi 003B11D1 8B75 0C mov esi,dword ptr ss:[ebp+C] 003B11D4 57 push edi 003B11D5 8B7D 10 mov edi,dword ptr ss:[ebp+10] 003B11D8 85F6 test esi,esi 003B11DA 75 09 jnz short EdrLib.003B11E5
用LordPE选中Ollydbg的loaddll.exe的进程,在下面的列表里选择EdrLib.dll,然后完整脱壳,得到dumped.dll。
—————————————————————————————————
三、修复输入表、PE修正、完成脱壳
随便从程序找一个API调用,如:
003B10FD FF15 20403B00 call dword ptr ds:[3B4020]; kernel32.GetVersion
避开重定位后是call dword ptr ds:[404020],你可以改为[3B4020]就能看到函数调用了。
在转存中跟随3B4020,上下看到许多函数地址,很明显的可以找到IAT开始和结束的地址:
开始地址=003B4000
结束地址=003B40C9
运行ImportREC,注意:去掉“使用来自磁盘的PE部首”的选项!
选中Ollydbg的loaddll.exe的进程,然后点“选取DLL”,选择EdrLib.dll,填入RVA=00004000、大小=000000C8 ,点“Get Import”,得到输入表。改OEP=000011C9,FixDump!
用LordPE修正dumped_.dll的重定位表RVA=00006000、大小=000003B0,保存之。
因为在7FF80FC4处跳过了重定位,所以不需要修正基址。OK,脱壳完成啦。
可以用LordPE删除最后一个区段,去掉“脱壳修复”和“清除重定位表”的选项简单优化一下脱壳后的DLL。
—————————————————————————————————
代码:
, _/ /| _.-~/ \_ , 青春都一晌 ( /~ / \~-._ |\ `\\ _/ \ ~\  忍把浮名 _-~~~-.)  __/;;,. \_ //' /'_,\ --~ \ ~~~- ,;;\___( (.-~~~-. 换了破解轻狂 `~ _( ,_..--\ ( ,;'' / ~-- /._`\ /~~//' /' `~\   /--.._, _ `~ " `~" " `" /~'`\ `\\~~\ " " "~' ""
Cracked By 巢水工作坊——fly [OCN][FCG][NUKE][DCM]
2004-06-06 19:00