iawen 发表于 2009-1-31 22:12

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

【文章标题】: Morphine.Shell.V1.5l脱壳的详细分析
【文章作者】: iawen
【作者主页】: www.iawen.com
【软件名称】: CrackMe
【下载地址】: 见附件
【加壳方式】: Morphine
【编写语言】: VC
【使用工具】: 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:,eax
00511A1C      89C7            mov edi,eax
00511A1E      8B75 08         mov esi,dword ptr ss:
00511A21      56            push esi
00511A22      89F1            mov ecx,esi
00511A24      034E 3C         add ecx,dword ptr ds:
00511A27      8B49 54         mov ecx,dword ptr ds:      ; 要复制的大小,0x400,即1024字节
00511A2A      F3:A4         rep movs byte ptr es:,byte ptr >; 复制PE头到上面分配的空间里
00511A2C      5E            pop esi
00511A2D      0376 3C         add esi,dword ptr ds:
00511A30      81C6 F8000000   add esi,0F8
00511A36      8B45 08         mov eax,dword ptr ss:
00511A39      0340 3C         add eax,dword ptr ds:      ; 获取程序的区段数
00511A3C      0FB640 06       movzx eax,byte ptr ds:
00511A40      8D7D C8         lea edi,dword ptr ss:
00511A43      57            push edi
00511A44      6A 0A         push 0A
00511A46      59            pop ecx
00511A47      F3:A5         rep movs dword ptr es:,dword pt>; 将区段名保存到堆栈
00511A49      5F            pop edi
00511A4A      8B57 14         mov edx,dword ptr ds:
00511A4D      85D2            test edx,edx
00511A4F      74 14         je short Morphed.00511A65
00511A51      56            push esi                           ; 将下一个区段名压入堆栈
00511A52      8B75 08         mov esi,dword ptr ss:
00511A55      01D6            add esi,edx
00511A57      8B4F 10         mov ecx,dword ptr ds:      ; 取得将要拷贝的区段大小
00511A5A      8B57 0C         mov edx,dword ptr ds:         ; 取得复制位置的偏移
00511A5D      8B7D F4         mov edi,dword ptr ss:
00511A60      01D7            add edi,edx                        ; 移动位置到要拷贝的目标地址
00511A62      F3:A4         rep movs byte ptr es:,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:         ; 循环结束,数据也全拷贝过去了
由于加载的地址变化,接着开始处理数据的重定位了!
如果我们不想在Dump出来后,修改基址,我们这里就需要跳过,将
je short Morphed.00511ACC===========改成jmp short Morphed.00511ACC就OK了:
00511A68      8B55 F4         mov edx,dword ptr ss:
00511A6B      2B55 FC         sub edx,dword ptr ss:       ; 这里开始比较基址
00511A6E      74 5C         je short Morphed.00511ACC          ; 如果是默认的,则跳过,否则进行数据重定位
00511A70      8B45 F4         mov eax,dword ptr ss:
00511A73      89C3            mov ebx,eax
00511A75      035B 3C         add ebx,dword ptr ds:
00511A78      8B9B A0000000   mov ebx,dword ptr ds:
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:
00511A87      85C0            test eax,eax
00511A89      74 41         je short Morphed.00511ACC
00511A8B      8D48 F8         lea ecx,dword ptr ds:
00511A8E      D1E9            shr ecx,1
00511A90      8D7B 08         lea edi,dword ptr ds:
00511A93      0FB707          movzx eax,word ptr ds:
00511A96      52            push edx
00511A97      89C2            mov edx,eax
00511A99      C1E8 0C         shr eax,0C
00511A9C      8B75 F4         mov esi,dword ptr ss:
00511A9F      66:81E2 FF0F    and dx,0FFF
00511AA4      0333            add esi,dword ptr ds:
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:
00511B3A      85C0            test eax,eax
00511B3C      0F84 92000000   je 00511BD4
00511B42      8B4B 10         mov ecx,dword ptr ds:
00511B45      01F1            add ecx,esi
00511B47      894D C4         mov dword ptr ss:,ecx
00511B4A      8B0B            mov ecx,dword ptr ds:
00511B4C      85C9            test ecx,ecx
00511B4E      75 03         jnz short 00511B53
00511B50      8B4B 10         mov ecx,dword ptr ds:
00511B53      01F1            add ecx,esi
00511B55      894D C0         mov dword ptr ss:,ecx
00511B58      01F0            add eax,esi
00511B5A      50            push eax
00511B5B      E8 72F7FFFF   call 005112D2
00511B60      8986 00040000   mov dword ptr ds:,eax
00511B66      8B45 10         mov eax,dword ptr ss:
00511B69      FF10            call dword ptr ds:
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:
00511B7D      8B11            mov edx,dword ptr ds:
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:,edx
00511BA3      57            push edi
00511BA4      8B45 0C         mov eax,dword ptr ss:
00511BA7      FF10            call dword ptr ds:            ; 取IAT函数的地址
00511BA9      E8 CBF7FFFF   call 00511379                      ; 对IAT函数名进行清0处理
00511BAE      E8 3FF7FFFF   call 005112F2                      ; 对IAT地址进行加密
00511BB3      C786 00040000 0>mov dword ptr ds:,0
00511BBD      8B4D C4         mov ecx,dword ptr ss:
00511BC0      8901            mov dword ptr ds:,eax         ; 将得到虚拟地址保存到IAT地址表
00511BC2      8345 C4 04      add dword ptr ss:,4      ; 移动到下一个IAT指针
00511BC6      8345 C0 04      add dword ptr ss:,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:
0051130A      FF10            call dword ptr ds:
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:       ; 获取VirtualAlloc函数的地址
00511327      FF10            call dword ptr ds:
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:,ebx         ; 然后复制到刚才的位置
00511352      C706 6A0050A1   mov dword ptr ds:,A150006A
00511358      8946 04         mov dword ptr ds:,eax
0051135B      C646 08 05      mov byte ptr ds:,5
0051135F      8956 09         mov dword ptr ds:,edx
00511362      C746 0D 8944240>mov dword ptr ds:,4244489
00511369      66:C746 11 58C3 mov word ptr ds:,0C358
0051136F      C646 13 E8      mov byte ptr ds:,0E8
00511373      897424 1C       mov dword ptr ss:,esi
00511377      61            popad                              ; 上面开始硬编码,让程序能解析出真实IAT地址
00511378      C3            retn
对IAT函数名的处理:
00511379      60            pushad
0051137A      8B9E 00040000   mov ebx,dword ptr ds:
00511380      C603 00         mov byte ptr ds:,0            ; 填充0字节
00511383      43            inc ebx
00511384      803B 00         cmp byte ptr ds:,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:
004E0008    05 029F730A   add eax,0A739F02
004E000D    894424 04       mov dword ptr ss:,eax
004E0011    58            pop eax
004E0012    C3            retn
004E0013    E8 267B0C72   call 725A7B3E
004E0018    0000            add byte ptr ds:,al
为了避开IAT的加密,我们只需要将下面2个CALL给NOP掉就OK了:
00511BA9    call 00511379 ; 对IAT函数名进行清0处理
00511BAE    call 005112F2 ; 对IAT地址进行加密

再做了上面的修改之后,我们F9运行:
005110D3      894C24 04       mov dword ptr ss:,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

zapline 发表于 2009-1-31 22:15

00511BA9    call 00511379 ; 对IAT函数名进行清0处理
00511BAE    call 005112F2 ; 对IAT地址进行加密

现在学到了这里

小生我怕怕 发表于 2009-1-31 22:17

膜拜下,老鸦最近文章真猛,学习啦!

sj3421565 发表于 2009-1-31 22:19

拜膜下!!!!


   

鬼手 发表于 2009-1-31 22:22

好强悍,真的佩服啊。膜拜!{我一个都看不懂!}

:lol :lol

Hmily 发表于 2009-1-31 22:48

00511BA9    call 00511379 ; 对IAT函数名进行清0处理
00511BAE    call 005112F2 ; 对IAT地址进行加密

我是走到这里就过去了 ,然后就飞了.... 然后的然后就给我Delete了...

Hmily 发表于 2009-2-1 00:59

那个朋友写的啥鸟脚本,在我这直接挂了,运行补起来~

pcfans 发表于 2009-2-1 01:57

对重定位那里还是很模糊

estelle 发表于 2009-2-1 11:18

学习下这个壳重定位

小糊涂虫 发表于 2009-2-1 11:40

对于这个壳我很模糊。。。。。。。
页: [1] 2 3
查看完整版本: Morphine.Shell.V1.5l脱壳的详细分析