• 标 题:用Ollydbg手脱 幻影 V2.33 加壳的DLL
  • 作 者:fly
  • 时 间:004-06-06,20:10
  • 链 接:http://bbs.pediy.com

【目标程序】:幻影 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