Morphine.Shell.V1.5l脱壳的详细分析

【文章标题】: Morphine.Shell.V1.5l脱壳的详细分析
【作者主页】: www.iawen.com
【软件名称】: CrackMe
【下载地址】: 见附件
【加壳方式】: Morphine
【使用工具】: OD,PETools,ImportREC
【操作平台】: XP SP3
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
——————————————————————————–
【详细过程】
  这个壳是今天从UnPackCn站点上Download下来,自己加了一个试试,呵呵!
  有一个很好脱壳脚本,是朋友写的(偶不会,^&^),不过,我还是想自己动手玩一下,于是就有了这篇文章,希望大家不要见笑!
  
  1、OD载入目标程序:
  


  00511E2B Mo>  50                  push eax         //OD停在这里,壳的入口
  00511E2C      81FA 5378EC30       cmp edx,30EC7853
  00511E32      58                  pop eax
  00511E33      52                  push edx
  00511E34      7D 05               jge short Morphed.00511E3B
  00511E36      78 03               js short Morphed.00511E3B
  00511E38      C1F3 40             sal ebx,40
  00511E3B      5A                  pop edx
  00511E3C      52                  push edx
  00511E3D      53                  push ebx
  00511E3E      78 01               js short Morphed.00511E41
  

  
  2、单步一下,留意ESP的值的更改,然后下hr 0013FFC0断点,使用ESP定律
  3、先下断点bp VirtualAlloc,再F9运行程序,留意堆栈,直到出现下面的值:
  [code
  0013FD74   00511A01  /CALL 到 VirtualAlloc 来自 Morphed.005119FF
  0013FD78   00400000  |Address = 00400000
  0013FD7C   00010000  |Size = 10000 (65536.)
  0013FD80   00003000  |AllocationType = MEM_COMMIT|MEM_RESERVE
  0013FD84   00000040  \Protect = PAGE_EXECUTE_READWRITE
  
  
  4、取消断点,返回:
  


  00511A01      59              pop ecx                              ;  返回到这里
  00511A02      85C0            test eax,eax
  00511A04      75 13           jnz short Morphed.00511A19
  00511A06      6A 40           push 40
  00511A08      68 00100000     push 1000
  00511A0D      51              push ecx
  00511A0E      50              push eax
  00511A0F      FFD3            call ebx                             ; 为将还原的程序分配空间
  00511A11      85C0            test eax,eax                         ; 返回的地址,也即程序将要加载的基址
  00511A13      0F84 87020000   je Morphed.00511CA0
  00511A19      8945 F4         mov dword ptr ss:[ebp-C],eax
  00511A1C      89C7            mov edi,eax
  00511A1E      8B75 08         mov esi,dword ptr ss:[ebp+8]
  00511A21      56              push esi
  00511A22      89F1            mov ecx,esi
  00511A24      034E 3C         add ecx,dword ptr ds:[esi+3C]
  00511A27      8B49 54         mov ecx,dword ptr ds:[ecx+54]        ; 要复制的大小,0x400,即1024字节
  00511A2A      F3:A4           rep movs byte ptr es:[edi],byte ptr >; 复制PE头到上面分配的空间里
  00511A2C      5E              pop esi
  00511A2D      0376 3C         add esi,dword ptr ds:[esi+3C]
  00511A30      81C6 F8000000   add esi,0F8
  00511A36      8B45 08         mov eax,dword ptr ss:[ebp+8]
  00511A39      0340 3C         add eax,dword ptr ds:[eax+3C]        ; 获取程序的区段数
  00511A3C      0FB640 06       movzx eax,byte ptr ds:[eax+6]
  00511A40      8D7D C8         lea edi,dword ptr ss:[ebp-38]
  00511A43      57              push edi
  00511A44      6A 0A           push 0A
  00511A46      59              pop ecx
  00511A47      F3:A5           rep movs dword ptr es:[edi],dword pt>; 将区段名保存到堆栈
  00511A49      5F              pop edi
  00511A4A      8B57 14         mov edx,dword ptr ds:[edi+14]
  00511A4D      85D2            test edx,edx
  00511A4F      74 14           je short Morphed.00511A65
  00511A51      56              push esi                             ; 将下一个区段名压入堆栈
  00511A52      8B75 08         mov esi,dword ptr ss:[ebp+8]
  00511A55      01D6            add esi,edx
  00511A57      8B4F 10         mov ecx,dword ptr ds:[edi+10]        ; 取得将要拷贝的区段大小
  00511A5A      8B57 0C         mov edx,dword ptr ds:[edi+C]         ; 取得复制位置的偏移
  00511A5D      8B7D F4         mov edi,dword ptr ss:[ebp-C]
  00511A60      01D7            add edi,edx                          ; 移动位置到要拷贝的目标地址
  00511A62      F3:A4           rep movs byte ptr es:[edi],byte ptr >; 开始复制
  00511A64      5E              pop esi
  00511A65      48              dec eax                              ; 区段数减1
  00511A66    ^ 75 D8           jnz short Morphed.00511A40           ; 还有区段未复制完,则继续
  00511A68      8B55 F4         mov edx,dword ptr ss:[ebp-C]         ; 循环结束,数据也全拷贝过去了
  

  
  由于加载的地址变化,接着开始处理数据的重定位了!
  如果我们不想在Dump出来后,修改基址,我们这里就需要跳过,将
  je short Morphed.00511ACC===========改成jmp short Morphed.00511ACC就OK了:
  


  00511A68      8B55 F4         mov edx,dword ptr ss:[ebp-C]
  00511A6B      2B55 FC         sub edx,dword ptr ss:[ebp-4]       ; 这里开始比较基址
  00511A6E      74 5C           je short Morphed.00511ACC          ; 如果是默认的,则跳过,否则进行数据重定位
  00511A70      8B45 F4         mov eax,dword ptr ss:[ebp-C]
  00511A73      89C3            mov ebx,eax
  00511A75      035B 3C         add ebx,dword ptr ds:[ebx+3C]
  00511A78      8B9B A0000000   mov ebx,dword ptr ds:[ebx+A0]
  00511A7E      85DB            test ebx,ebx
  00511A80      74 4A           je short Morphed.00511ACC
  00511A82      01C3            add ebx,eax
  00511A84      8B43 04         mov eax,dword ptr ds:[ebx+4]
  00511A87      85C0            test eax,eax
  00511A89      74 41           je short Morphed.00511ACC
  00511A8B      8D48 F8         lea ecx,dword ptr ds:[eax-8]
  00511A8E      D1E9            shr ecx,1
  00511A90      8D7B 08         lea edi,dword ptr ds:[ebx+8]
  00511A93      0FB707          movzx eax,word ptr ds:[edi]
  00511A96      52              push edx
  00511A97      89C2            mov edx,eax
  00511A99      C1E8 0C         shr eax,0C
  00511A9C      8B75 F4         mov esi,dword ptr ss:[ebp-C]
  00511A9F      66:81E2 FF0F    and dx,0FFF
  00511AA4      0333            add esi,dword ptr ds:[ebx]
  00511AA6      01D6            add esi,edx
  00511AA8      5A              pop edx
  00511AA9      48              dec eax
  00511AAA      75 07           jnz short Morphed.00511AB3
  00511AAC      89D0            mov eax,edx
  

  
  接着开始处理IAT信息了:
  


  00511B37      8B43 0C         mov eax,dword ptr ds:[ebx+C]
  00511B3A      85C0            test eax,eax
  00511B3C      0F84 92000000   je 00511BD4
  00511B42      8B4B 10         mov ecx,dword ptr ds:[ebx+10]
  00511B45      01F1            add ecx,esi
  00511B47      894D C4         mov dword ptr ss:[ebp-3C],ecx
  00511B4A      8B0B            mov ecx,dword ptr ds:[ebx]
  00511B4C      85C9            test ecx,ecx
  00511B4E      75 03           jnz short 00511B53
  00511B50      8B4B 10         mov ecx,dword ptr ds:[ebx+10]
  00511B53      01F1            add ecx,esi
  00511B55      894D C0         mov dword ptr ss:[ebp-40],ecx
  00511B58      01F0            add eax,esi
  00511B5A      50              push eax
  00511B5B      E8 72F7FFFF     call 005112D2
  00511B60      8986 00040000   mov dword ptr ds:[esi+400],eax
  00511B66      8B45 10         mov eax,dword ptr ss:[ebp+10]
  00511B69      FF10            call dword ptr ds:[eax]
  00511B6B      E8 09F8FFFF     call 00511379
  00511B70      85C0            test eax,eax
  00511B72      0F84 28010000   je 00511CA0
  00511B78      89C7            mov edi,eax
  00511B7A      8B4D C0         mov ecx,dword ptr ss:[ebp-40]
  00511B7D      8B11            mov edx,dword ptr ds:[ecx]
  00511B7F      85D2            test edx,edx
  00511B81      74 49           je short 00511BCC
  00511B83      F7C2 00000080   test edx,80000000
  00511B89      74 08           je short 00511B93
  00511B8B      81E2 FFFFFF7F   and edx,7FFFFFFF
  00511B91      EB 04           jmp short 00511B97
  00511B93      01F2            add edx,esi                        ; Morphe_1.004D0000
  00511B95      42              inc edx
  00511B96      42              inc edx
  00511B97      52              push edx
  00511B98      E8 3DF7FFFF     call 005112DA
  00511B9D      8996 00040000   mov dword ptr ds:[esi+400],edx
  00511BA3      57              push edi
  00511BA4      8B45 0C         mov eax,dword ptr ss:[ebp+C]
  00511BA7      FF10            call dword ptr ds:[eax]            ; 取IAT函数的地址
  00511BA9      E8 CBF7FFFF     call 00511379                      ; 对IAT函数名进行清0处理
  00511BAE      E8 3FF7FFFF     call 005112F2                      ; 对IAT地址进行加密
  00511BB3      C786 00040000 0>mov dword ptr ds:[esi+400],0
  00511BBD      8B4D C4         mov ecx,dword ptr ss:[ebp-3C]
  00511BC0      8901            mov dword ptr ds:[ecx],eax         ; 将得到虚拟地址保存到IAT地址表
  00511BC2      8345 C4 04      add dword ptr ss:[ebp-3C],4        ; 移动到下一个IAT指针
  00511BC6      8345 C0 04      add dword ptr ss:[ebp-40],4
  00511BCA    ^ EB AE           jmp short 00511B7A                 ; 一个DLL模块完毕
  00511BCC      83C3 14         add ebx,14                         ; 移动指针,进行下一个模块
  00511BCF    ^ E9 63FFFFFF     jmp 00511B37
  

  
  
  下面的代码是对IAT地址的加密:
  


  005112F2      60              pushad
  005112F3      89C3            mov ebx,eax
  005112F5      6A 00           push 0
  005112F7      68 2E646C6C     push 6C6C642E
  005112FC      68 656C3332     push 32336C65
  00511301      68 6B65726E     push 6E72656B
         ===============这个PUSH其实是将LoadLibraryA函数名入栈
  00511306      54              push esp
  00511307      8B45 10         mov eax,dword ptr ss:[ebp+10]
  0051130A      FF10            call dword ptr ds:[eax]
  0051130C      83C4 10         add esp,10                         ; 获取DLL的基址
  0051130F      89C7            mov edi,eax
  00511311      6A 00           push 0
  00511313      68 6C6C6F63     push 636F6C6C
  00511318      68 75616C41     push 416C6175
  0051131D      68 56697274     push 74726956
         ===============这个PUSH其实是将VirtualAlloc函数名入栈
  00511322      54              push esp
  00511323      57              push edi
  00511324      8B45 0C         mov eax,dword ptr ss:[ebp+C]       ; 获取VirtualAlloc函数的地址
  00511327      FF10            call dword ptr ds:[eax]
  00511329      83C4 10         add esp,10
  0051132C      89C1            mov ecx,eax
  0051132E      85C0            test eax,eax
  00511330      0F84 6A090000   je Morphed.00511CA0
  00511336      6A 04           push 4                             ; 调用VirtualAlloc分配空间
  00511338      68 00300000     push 3000                          ; 大小是0x18,即24个字节
  0051133D      6A 18           push 18
  0051133F      6A 00           push 0
  00511341      FFD1            call ecx
  00511343      89C6            mov esi,eax                        ; 将分配的空间保存到ESI
  00511345      83C0 14         add eax,14                         ; 在分配的地址上,先空出0x14字节
  00511348      50              push eax
  00511349      0F31            rdtsc==============获取当前的time stamp值
  0051134B      89C2            mov edx,eax========只取其低32位
  0051134D      58              pop eax
  0051134E      29D3            sub ebx,edx                        ; 将真实地址减去上面得到的值
  00511350      8918            mov dword ptr ds:[eax],ebx         ; 然后复制到刚才的位置
  00511352      C706 6A0050A1   mov dword ptr ds:[esi],A150006A
  00511358      8946 04         mov dword ptr ds:[esi+4],eax
  0051135B      C646 08 05      mov byte ptr ds:[esi+8],5
  0051135F      8956 09         mov dword ptr ds:[esi+9],edx
  00511362      C746 0D 8944240>mov dword ptr ds:[esi+D],4244489
  00511369      66:C746 11 58C3 mov word ptr ds:[esi+11],0C358
  0051136F      C646 13 E8      mov byte ptr ds:[esi+13],0E8
  00511373      897424 1C       mov dword ptr ss:[esp+1C],esi
  00511377      61              popad                              ; 上面开始硬编码,让程序能解析出真实IAT地址
  00511378      C3              retn
  

  
  对IAT函数名的处理:
  


  00511379      60              pushad
  0051137A      8B9E 00040000   mov ebx,dword ptr ds:[esi+400]
  00511380      C603 00         mov byte ptr ds:[ebx],0            ; 填充0字节
  00511383      43              inc ebx
  00511384      803B 00         cmp byte ptr ds:[ebx],0
  00511387    ^ 75 F7           jnz short 00511380
  00511389      61              popad
  0051138A      C3              retn
  

  
  经过加密后的IAT地址为VirtualAlloc申请到的地址,此后程序调用都需要通过上面硬编码的一段代码来获取到真实地址,并
  跳转过去。硬编码的代码格式如下:
  


  004E0000    6A 00           push 0
  004E0002    50              push eax
  004E0003    A1 14004E00     mov eax,dword ptr ds:[4E0014]
  004E0008    05 029F730A     add eax,0A739F02
  004E000D    894424 04       mov dword ptr ss:[esp+4],eax
  004E0011    58              pop eax
  004E0012    C3              retn
  004E0013    E8 267B0C72     call 725A7B3E
  004E0018    0000            add byte ptr ds:[eax],al
  

  
  为了避开IAT的加密,我们只需要将下面2个CALL给NOP掉就OK了:
  00511BA9    call 00511379 ; 对IAT函数名进行清0处理
  00511BAE    call 005112F2 ; 对IAT地址进行加密
  
  再做了上面的修改之后,我们F9运行:
  


  005110D3      894C24 04       mov dword ptr ss:[esp+4],ecx
  005110D7      50              push eax
  005110D8      C3              retn        //中断在这里了,ESP断点
  

  
  F8单步一下,OK,这里就是我们的OEP了,哈!
  


  004D29D4      E8 03170000     call 004D40DC
  004D29D9    ^ E9 78FEFFFF     jmp 004D2856
  004D29DE      8BFF            mov edi,edi
  004D29E0      55              push ebp
  004D29E1      8BEC            mov ebp,esp
  

  
  然后DUMP,再修复,一切OK!
  
  
——————————————————————————–
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年01月31日 22:07:58

Morphine.Shell.V1.5.rar

发表评论