【转载】攻破ZProtect IAT保护最后的堡垒---Anti Hook

Eddy 发布于2010-1-20 16:59:41 分类: 加密解密 已浏览loading 网友评论0条 我要评论

作者:hyperchem

目标程序是一个ZProtect 1.4 企业版加壳的程序。

1.到OEP去
对于这个版本来说,单纯的是ESP定律不再适用,什么意思呢?如果仅仅下硬件断点是断不下来的,我们需要一种辅助断点方式、
先单步走,仍然是走到pushad 以后下hr esp。然后Ctrl+G 输入GetModuleHandleA
到这里来

  1. 7C80B731 >  8BFF            mov edi,edi
     
  2. 7C80B733    55              push ebp
     
  3. 7C80B734    8BEC            mov ebp,esp
     
  4. 7C80B736    837D 08 00      cmp dword ptr ss:[ebp+8],0
     
  5. 7C80B73A    74 18           je short kernel32.7C80B754<--- 在这里下F2断点.
     
  6. 7C80B73C    FF75 08         push dword ptr ss:[ebp+8]
     
  7. 7C80B73F    E8 C0290000     call kernel32.7C80E104
     
  8. 7C80B744    85C0            test eax,eax
     
  9. 7C80B746    74 08           je short kernel32.7C80B750
     
  10. 7C80B748    FF70 04         push dword ptr ds:[eax+4]
     
  11. 7C80B74B    E8 7D2D0000     call kernel32.GetModuleHandleW
     
  12. 7C80B750    5D              pop ebp

解释一下为什么要这么下.GetModuleHandleA这个函数在壳的运行中是至关重要的,调用的次数非常的频繁,而且即便是过了OEP以后,主程序初始化的时候也会调用这个函数,也就是说,我们即便不能到达OEP,也可能到达OEP附近。所以用这个断点来辅助我们找OEP。

断点下好以后,F9运行,注意看反汇编窗口EIP的位置。数次之后,就会断在下面的代码上:

  1. 00A70447  ^\E9 5929FFFF     jmp 00A62DA5

这就是ESP定律应该执行到的位置。

然后取消GetModuleHandleA 里面的Int3断点。这点很重要!!!!!!!否则后面在Patch代码修复IAT的时候就会壳的多线程校验检测到。

再走两步就到了这里,这就是OEP,标准的Delphi入口

  1. 00453D0C    55              push ebp
     
  2. 00453D0D    8BEC            mov ebp,esp
     
  3. 00453D0F    83C4 F0         add esp,-10
     
  4. 00453D12    B8 2C3B4500     mov eax,zp_1_4.00453B2C
     
  5. 00453D17    E8 441FFBFF     call zp_1_4.00405C60
     
  6. 00453D1C    A1 58504500     mov eax,dword ptr ds:[455058]
     
  7. 00453D21    8B00            mov eax,dword ptr ds:[eax]
     
  8. 00453D23    E8 74E3FFFF     call zp_1_4.0045209C
     
  9. 00453D28    8B0D 38514500   mov ecx,dword ptr ds:[455138]            ; zp_1_4.00456BFC
     
  10. 00453D2E    A1 58504500     mov eax,dword ptr ds:[455058]
     
  11. 00453D33    8B00            mov eax,dword ptr ds:[eax]
     
  12. 00453D35    8B15 3C364500   mov edx,dword ptr ds:[45363C]            ; zp_1_4.00453688
     
  13. 00453D3B    E8 74E3FFFF     call zp_1_4.004520B4
     
  14. 00453D40    A1 58504500     mov eax,dword ptr ds:[455058]
     
  15. 00453D45    8B00            mov eax,dword ptr ds:[eax]
     
  16. 00453D47    E8 E8E3FFFF     call zp_1_4.00452134
     
  17. 00453D4C    E8 0B00FBFF     call zp_1_4.00403D5C

上面是比较中规中矩的方法,下面介绍一种比较取巧的方法。

直接在OD中运行程序。然后到00401000去,分析一下代码。

  1. 00401000     /04104000      dd zp_1_4.00401004
     
  2. 00401004     \03            db 03
     
  3. 00401005   .  07            db 07
     
  4. 00401006   .  42 6F 6F 6C 6>ascii "Boolean"
     
  5. 0040100D      01            db 01
     
  6. 0040100E      00            db 00
     
  7. 0040100F      00            db 00
     
  8. 00401010      00            db 00
     
  9. 00401011      00            db 00
     
  10. 00401012      01            db 01
     
  11. 00401013      00            db 00
     
  12. 00401014      00            db 00
     
  13. 00401015      00            db 00
     
  14. 00401016      00104000      dd zp_1_4.00401000
     
  15. 0040101A   .  05            db 05
     
  16. 0040101B   .  46 61 6C 73 6>ascii "False"
     
  17. 00401020   .  04            db 04
     
  18. 00401021   .  54 72 75 65   ascii "True"

看到这些,凭经验很容易判断这是个Delphi的程序,一般来说,Delphi程序的入口点都在代码段的最下面。但是ZProtect合并了所有的数据段,所以找到的时候,我们可以找一串连续的,较长的00 00 就可以了,因为这是原来数据段的分割。这样也很容易就找到了OEP。

2,记录一些数据,方便修复。

OEP=00453d0c

查找E9 ?? ?? ?? ?? 90--这是ZProtect对IAT调用的修改方式。如果是这种形式表示以前的调用方式是FF 25型的
或者E8 ?? ?? ?? ?? 90---如果是这种方式,则代表原来的调用方式是FF 15型的。  
确定被修改的IAT调用方式是FF 25

IAT调用的特征码是
E9 ?? ?? 09 00 90
E9 ?? ?? 07 00 90
E9 ?? ?? 08 00 90

便于后面修复IAT

查找一下FF 25---这是为了确定GetModuleHandleA这个函数的调用位置。因为ZProtect不会处理GetModuleHandleA的调用方式,而只会模拟这个函数。
确定有效的GetModuleHandleA调用有两处。

  1. 00405B9C   $- FF25 E4714500 jmp dword ptr ds:[4571E4] ds:[0045716C]=00A425D0
     
  2. 00401264   $- FF25 6C714500 jmp dword ptr ds:[45716C] ds:[004571E4]=00A425D0

可见两处调用是同一个伪IAT。

IAT调用开始位置:004011F4
IAT调用结束位置:004239A3
这样可以减少查找时间。

3,接下来找IAT的解密call
F7单步走,一直走,直到走进一处IAT调用的代码后,记录下面的代码。
根据我第一篇的分析,下面就是解密call了

  1. 00A643E5    FF15 346FA500   call dword ptr ds:[A56F34] 这个就是解密call了~
     
  2. 00A6D63D    8B0D 8076A500   mov ecx,dword ptr ds:[A57680]--这里装的是伪IAT的地址
     
  3. 00A64674    85C9            test ecx,ecx
     
  4. 00A59940    8BF0            mov esi,eax
     
  5. 00A5AF4D   /0F84 55910000   je 00A640A8
     
  6. 00A5B842    A1 8476A500     mov eax,dword ptr ds:[A57684]
     
  7. 00A673CA    2BC1            sub eax,ecx
     
  8. 00A6C6F8    C1F8 02         sar eax,2
     
  9. 00A5C550    3BF0            cmp esi,eax
     
  10. 00A63FFF  ^\0F82 5981FFFF   jb 00A5C15E
     
  11. 00A5C15E    8B0CB1          mov ecx,dword ptr ds:[ecx+esi*4]--这里就是获得函数地址了
     
  12. 00A5C901    894C24 2C       mov dword ptr ss:[esp+2C],ecx
     
  13. 00A68A0B    5E              pop esi
     
  14. 00A58F96    C2 0400         retn 4
     
  15. 00A620FF    61              popad
     
  16. 00A653E4    C3              retn----------这里返回到API执行 但是代码被复制到内存,无法知道真正的内存地址了。
     
  17. 找到解密call了 我们就可以修复IAT调用了~

到伪IAT一看 发现IAT被Hook了~
伪IAT的开始地址是00A85D48
结束地址是00A86314
这个地址 对于同一台机器和同一个OD,是不变的~

之前说过,ZP会把IAT(包括伪IAT)复制几份放在内存中,但只有
00A6D63D    8B0D 8076A500   mov ecx,dword ptr ds:[A57680]
这里给出的IAT基地址才是真正完整的IAT地址。

4,修复Anti-Hook

下面就是伪IAT了(部分,全本见附件)

  1. 00A85D48  00BE9719
     
  2. 00A85D4C  00BE8F1F
     
  3. 00A85D50  00DBB1DE
     
  4. 00A85D54  00BEB19C
     
  5. 00A85D58  00EAFE01
     
  6. 00A85D5C  00BE42ED
     
  7. 00A85D60  00DBB5EA
     
  8. 00A85D64  00AB2446
     
  9. 00A85D68  00BF0277
     
  10. 00A85D6C  00BE9ED9
     
  11. 00A85D70  00BED226
     
  12. 00A85D74  00AB9F81
     
  13. 00A85D78  00AE60DB

不过首先要先修复被Hook的API地址。

向上翻看下。发现这里有
这里有一连串的DLL基址
简单分析一下就会知道:
数据的结构是这样的:

Dword CopyMemorySize
Dword CopyDllBase
Dword CopyMemoryBase

需要说明的是,这里面的CopyMemorySize正好等于相应dll的镜像大小。
为什么会这样呢?继续看下就知道了~

  1. 00A84CF0  0011E000
     
  2. 00A84CF4  7C800000  kernel32.7C800000
     
  3. 00A84CF8  00AB0000
     

  4.  
  5. 00A84CFC  00090000
     
  6. 00A84D00  77D10000  user32.77D10000
     
  7. 00A84D04  00BD0000
     

  8.  
  9. 00A84D08  000A9000
     
  10. 00A84D0C  77DA0000  advapi32.77DA0000
     
  11. 00A84D10  00C60000
     

  12.  
  13. 00A84D14  0008B000
     
  14. 00A84D18  770F0000  oleaut32.770F0000
     
  15. 00A84D1C  00D10000
     

  16.  
  17. 00A84D20  00008000
     
  18. 00A84D24  77BD0000  version.77BD0000
     
  19. 00A84D28  00DA0000
     

  20.  
  21. 00A84D2C  00049000
     
  22. 00A84D30  77EF0000  gdi32.77EF0000
     
  23. 00A84D34  00DB0000
     

  24.  
  25. 00A84D38  0009A000
     
  26. 00A84D3C  5D170000  comctl32.5D170000
     
  27. 00A84D40  00E00000
     

  28.  
  29. 00A84D44  00093000
     
  30. 00A84D48  7C920000  ntdll.7C920000
     
  31. 00A84D4C  00EA0000
     

  32.  
  33. 00A84D50  007F4000
     
  34. 00A84D54  7D590000  shell32.7D590000
     
  35. 00A84D58  00F40000

我们现在知道了00AB0000 这里内存里面放的是Kernel32.dll的函数。那么我们就进去看看代码

在这里找一段代码,二进制复制,然后在内存中查找这段二进制

  1. 00AB24D6    68 C09A837C     push 7C839AC0
     
  2. 00AB24DB    64:A1 00000000  mov eax,dword ptr fs:[0]
     
  3. 00AB24E1    50              push eax
     
  4. 00AB24E2    8B4424 10       mov eax,dword ptr ss:[esp+10]
     
  5. 00AB24E6    896C24 10       mov dword ptr ss:[esp+10],ebp
     
  6. 00AB24EA    8D6C24 10       lea ebp,dword ptr ss:[esp+10]
     
  7. 00AB24EE    2BE0            sub esp,eax
     
  8. 00AB24F0    53              push ebx
     
  9. 00AB24F1    56              push esi
     
  10. 00AB24F2    57              push edi
     
  11. 00AB24F3    8B45 F8         mov eax,dword ptr ss:[ebp-8]
     
  12. 00AB24F6    8965 E8         mov dword ptr ss:[ebp-18],esp
     
  13. 00AB24F9    50              push eax
     
  14. 00AB24FA    8B45 FC         mov eax,dword ptr ss:[ebp-4]
     
  15. 00AB24FD    C745 FC FFFFFFF>mov dword ptr ss:[ebp-4],-1
     
  16. 00AB2504    8945 F8         mov dword ptr ss:[ebp-8],eax
     
  17. 00AB2507    8D45 F0         lea eax,dword ptr ss:[ebp-10]
     
  18. 00AB250A    64:A3 00000000  mov dword ptr fs:[0],eax
     
  19. 00AB2510    C3              retn
     

  20.  

  21.  
  22. 7C8024D6    68 C09A837C     push kernel32.7C839AC0
     
  23. 7C8024DB    64:A1 00000000  mov eax,dword ptr fs:[0]
     
  24. 7C8024E1    50              push eax
     
  25. 7C8024E2    8B4424 10       mov eax,dword ptr ss:[esp+10]
     
  26. 7C8024E6    896C24 10       mov dword ptr ss:[esp+10],ebp
     
  27. 7C8024EA    8D6C24 10       lea ebp,dword ptr ss:[esp+10]
     
  28. 7C8024EE    2BE0            sub esp,eax
     
  29. 7C8024F0    53              push ebx
     
  30. 7C8024F1    56              push esi
     
  31. 7C8024F2    57              push edi
     
  32. 7C8024F3    8B45 F8         mov eax,dword ptr ss:[ebp-8]
     
  33. 7C8024F6    8965 E8         mov dword ptr ss:[ebp-18],esp
     
  34. 7C8024F9    50              push eax
     
  35. 7C8024FA    8B45 FC         mov eax,dword ptr ss:[ebp-4]
     
  36. 7C8024FD    C745 FC FFFFFFF>mov dword ptr ss:[ebp-4],-1
     
  37. 7C802504    8945 F8         mov dword ptr ss:[ebp-8],eax
     
  38. 7C802507    8D45 F0         lea eax,dword ptr ss:[ebp-10]
     
  39. 7C80250A    64:A3 00000000  mov dword ptr fs:[0],eax
     
  40. 7C802510    C3              retn

找到了,原来在这里。
比较一下就能看出来:代码地址相对于内存基地址的偏移是固定。这也就是为什么内存大小跟相应的dll的镜像大小相等:壳是为了保证能让所有的API都能复制到一个内存段中,所以只能申请一个跟dll的镜像一样大的内存段。

了解了这些,修复的方法就呼之欲出了。
伪IAT中的API地址其实都是真的,只是基地址不对,只要减去当前的基地址,再加上原来的基地址就一些OK了!!

  1. 00453D6C    BE 485DA800     mov esi,0A85D48                          ; 伪IAT的开始地址
     
  2. 00453D71    81FE 1863A800   cmp esi,0A86318                          ; 伪IAT的结束位置
     
  3. 00453D77    68 0000AB00     push 0AB0000
     
  4. 00453D7C    68 0000BD00     push 0BD0000
     
  5. 00453D81    68 0000C600     push 0C60000
     
  6. 00453D86    68 0000D100     push 0D10000
     
  7. 00453D8B    68 0000DA00     push 0DA0000
     
  8. 00453D90    68 0000DB00     push 0DB0000
     
  9. 00453D95    68 0000E000     push 0E00000
     
  10. 00453D9A    68 0000EA00     push 0EA0000
     
  11. 00453D9F    68 0000F400     push 0F40000                             ; 这些是每个dll的代码所在的内存段,具体参见笔记
     
  12. ===========================================================================================
     
  13. 00453DA4    72 05           jb short zp_1_4.00453DAB
     
  14. 00453DA6    E9 07010000     jmp zp_1_4.00453EB2                      ; 出口,在这里下好断点~
     
  15. 00453DAB    8B06            mov eax,dword ptr ds:[esi]
     
  16. 00453DAD    3E:3B4424 20    cmp eax,dword ptr ds:[esp+20]
     
  17. 00453DB2    72 4E           jb short zp_1_4.00453E02                 ; 出错口
     
  18. 00453DB4    3E:3B4424 1C    cmp eax,dword ptr ds:[esp+1C]
     
  19. 00453DB9    72 52           jb short zp_1_4.00453E0D
     
  20. 00453DBB    3E:3B4424 18    cmp eax,dword ptr ds:[esp+18]
     
  21. 00453DC0    72 57           jb short zp_1_4.00453E19
     
  22. 00453DC2    3E:3B4424 14    cmp eax,dword ptr ds:[esp+14]
     
  23. 00453DC7    72 5C           jb short zp_1_4.00453E25
     
  24. 00453DC9    3E:3B4424 10    cmp eax,dword ptr ds:[esp+10]
     
  25. 00453DCE    72 61           jb short zp_1_4.00453E31
     
  26. 00453DD0    3E:3B4424 0C    cmp eax,dword ptr ds:[esp+C]
     
  27. 00453DD5    72 66           jb short zp_1_4.00453E3D
     
  28. 00453DD7    3E:3B4424 08    cmp eax,dword ptr ds:[esp+8]
     
  29. 00453DDC    72 6B           jb short zp_1_4.00453E49
     
  30. 00453DDE    3E:3B4424 04    cmp eax,dword ptr ds:[esp+4]
     
  31. 00453DE3    72 70           jb short zp_1_4.00453E55
     
  32. 00453DE5    3E:3B0424       cmp eax,dword ptr ds:[esp]
     
  33. 00453DE9    72 76           jb short zp_1_4.00453E61
     
  34. 00453DEB    BB A8000000     mov ebx,0A8
     
  35. 00453DF0    8BEC            mov ebp,esp
     
  36. 00453DF2    3E:8B4D 00      mov ecx,dword ptr ds:[ebp]
     
  37. 00453DF6    290E            sub dword ptr ds:[esi],ecx
     
  38. 00453DF8    E8 00000000     call zp_1_4.00453DFD
     
  39. 00453DFD    5A              pop edx
     
  40. 00453DFE    03D3            add edx,ebx
     
  41. 00453E00    FFD2            call edx
     
  42. 00453E02    83C6 04         add esi,4
     
  43. 00453E05    81FE 1863A800   cmp esi,0A86318
     
  44. 00453E0B  ^ EB 97           jmp short zp_1_4.00453DA4
     
  45. =====================================================================================
     
  46. 00453E0D    3E:8D6C24 20    lea ebp,dword ptr ds:[esp+20]
     
  47. 00453E12    BB 70000000     mov ebx,70                               ; ebx中的值是函数的偏移,主要是为了代码的可移植性
     
  48. 00453E17  ^ EB D9           jmp short zp_1_4.00453DF2
     
  49. 00453E19    3E:8D6C24 1C    lea ebp,dword ptr ds:[esp+1C]
     
  50. 00453E1E    BB 77000000     mov ebx,77
     
  51. 00453E23  ^ EB CD           jmp short zp_1_4.00453DF2
     
  52. 00453E25    3E:8D6C24 18    lea ebp,dword ptr ds:[esp+18]
     
  53. 00453E2A    BB 7E000000     mov ebx,7E
     
  54. 00453E2F  ^ EB C1           jmp short zp_1_4.00453DF2
     
  55. 00453E31    3E:8D6C24 14    lea ebp,dword ptr ds:[esp+14]
     
  56. 00453E36    BB 85000000     mov ebx,85
     
  57. 00453E3B  ^ EB B5           jmp short zp_1_4.00453DF2
     
  58. 00453E3D    3E:8D6C24 10    lea ebp,dword ptr ds:[esp+10]
     
  59. 00453E42    BB 8C000000     mov ebx,8C
     
  60. 00453E47  ^ EB A9           jmp short zp_1_4.00453DF2
     
  61. 00453E49    3E:8D6C24 0C    lea ebp,dword ptr ds:[esp+C]
     
  62. 00453E4E    BB 93000000     mov ebx,93
     
  63. 00453E53  ^ EB 9D           jmp short zp_1_4.00453DF2
     
  64. 00453E55    3E:8D6C24 08    lea ebp,dword ptr ds:[esp+8]
     
  65. 00453E5A    BB 9A000000     mov ebx,9A
     
  66. 00453E5F  ^ EB 91           jmp short zp_1_4.00453DF2
     
  67. 00453E61    3E:8D6C24 04    lea ebp,dword ptr ds:[esp+4]
     
  68. 00453E66    BB A1000000     mov ebx,0A1
     
  69. 00453E6B  ^ EB 85           jmp short zp_1_4.00453DF2
     
  70. ================================================================================================
     
  71. 00453E6D    8106 0000807C   add dword ptr ds:[esi],7C800000          ; 下面是每个dll的真实基址
     
  72. 00453E73    C3              retn
     
  73. 00453E74    8106 0000D177   add dword ptr ds:[esi],77D10000
     
  74. 00453E7A    C3              retn
     
  75. 00453E7B    8106 0000DA77   add dword ptr ds:[esi],77DA0000
     
  76. 00453E81    C3              retn
     
  77. 00453E82    8106 00000F77   add dword ptr ds:[esi],770F0000
     
  78. 00453E88    C3              retn
     
  79. 00453E89    8106 0000BD77   add dword ptr ds:[esi],77BD0000
     
  80. 00453E8F    C3              retn
     
  81. 00453E90    8106 0000EF77   add dword ptr ds:[esi],77EF0000
     
  82. 00453E96    C3              retn
     
  83. 00453E97    8106 0000175D   add dword ptr ds:[esi],5D170000
     
  84. 00453E9D    C3              retn
     
  85. 00453E9E    8106 0000927C   add dword ptr ds:[esi],7C920000
     
  86. 00453EA4    C3              retn
     
  87. 00453EA5    8106 0000597D   add dword ptr ds:[esi],7D590000
     
  88. 00453EAB    C3              retn
  1. 二进制
     
  2. BE 48 5D A8 00 81 FE 18 63 A8 00 68 00 00 AB 00 68 00 00 BD 00 68 00 00 C6 00 68 00 00 D1 00 68
     
  3. 00 00 DA 00 68 00 00 DB 00 68 00 00 E0 00 68 00 00 EA 00 68 00 00 F4 00 72 05 E9 07 01 00 00 8B
     
  4. 06 3E 3B 44 24 20 72 4E 3E 3B 44 24 1C 72 52 3E 3B 44 24 18 72 57 3E 3B 44 24 14 72 5C 3E 3B 44
     
  5. 24 10 72 61 3E 3B 44 24 0C 72 66 3E 3B 44 24 08 72 6B 3E 3B 44 24 04 72 70 3E 3B 04 24 72 76 BB
     
  6. A8 00 00 00 8B EC 3E 8B 4D 00 29 0E E8 00 00 00 00 5A 03 D3 FF D2 83 C6 04 81 FE 18 63 A8 00 EB
     
  7. 97 3E 8D 6C 24 20 BB 70 00 00 00 EB D9 3E 8D 6C 24 1C BB 77 00 00 00 EB CD 3E 8D 6C 24 18 BB 7E
     
  8. 00 00 00 EB C1 3E 8D 6C 24 14 BB 85 00 00 00 EB B5 3E 8D 6C 24 10 BB 8C 00 00 00 EB A9 3E 8D 6C
     
  9. 24 0C BB 93 00 00 00 EB 9D 3E 8D 6C 24 08 BB 9A 00 00 00 EB 91 3E 8D 6C 24 04 BB A1 00 00 00 EB
     
  10. 85 81 06 00 00 80 7C C3 81 06 00 00 D1 77 C3 81 06 00 00 DA 77 C3 81 06 00 00 0F 77 C3 81 06 00
     
  11. 00 BD 77 C3 81 06 00 00 EF 77 C3 81 06 00 00 17 5D C3 81 06 00 00 92 7C C3 81 06 00 00 59 7D C3

执行完这段代码后就得到了修复好的IAT了。

  1. 00A85D48  77D29719  user32.PtInRect
     
  2. 00A85D4C  77D28F1F  user32.IntersectRect
     
  3. 00A85D50  77EFB1DE  gdi32.GetDIBColorTable
     
  4. 00A85D54  77D2B19C  user32.DestroyWindow
     
  5. 00A85D58  7C92FE01  ntdll.RtlGetLastWin32Error
     
  6. 00A85D5C  77D242ED  user32.SetForegroundWindow
     
  7. 00A85D60  77EFB5EA  gdi32.CreatePalette
     
  8. 00A85D64  7C802446  kernel32.Sleep
     
  9. 00A85D68  77D30277  user32.OpenClipboard
     
  10. 00A85D6C  77D29ED9  user32.GetKeyState
     
  11. 00A85D70  77D2D226  user32.GetKeyboardState
     
  12. 00A85D74  7C809F81  kernel32.InitializeCriticalSection
     
  13. 00A85D78  7C8360DB  kernel32.GlobalFindAtomA
     
  14. 00A85D7C  77EF700A  gdi32.CreateCompatibleBitmap
     
  15. 00A85D80  77D30D96  user32.EmptyClipboard
     
  16. 00A85D84  77D297FF  user32.IsIconic
     
  17. 00A85D88  5D1B2C59  comctl32.ImageList_BeginDrag
  1. IAT的二进制
     
  2. 19 97 D2 77 1F 8F D2 77 DE B1 EF 77 9C B1 D2 77 01 FE 92 7C ED 42 D2 77 EA B5 EF 77 46 24 80 7C
     
  3. 77 02 D3 77 D9 9E D2 77 26 D2 D2 77 81 9F 80 7C DB 60 83 7C 0A 70 EF 77 96 0D D3 77 FF 97 D2 77
     
  4. 59 2C 1B 5D FD 4C 0F 77 A9 E4 D2 77 7E C1 D2 77 00 10 92 7C 81 9E D2 77 CE EC EF 77 9D 86 D1 77
     
  5. 1C EF EF 77 65 02 D3 77 6B 21 D3 77 5A 51 0F 77 1B 82 EF 77 1B A9 D2 77 B2 DE D2 77 2F 9C D2 77
     
  6. C7 06 81 7C D0 B6 EF 77 5A 13 93 7C 26 ED D3 77 28 8E D1 77 9B F9 D2 77 55 96 D2 77 F6 9B D2 77
     
  7. E1 9A 80 7C 5E 20 83 7C FE A9 F2 77 AB 7A DA 77 46 24 80 7C 1A B6 EF 77 BB 6B 0F 77 84 CB D2 77
     
  8. BF 99 80 7C 8A BA EF 77 B1 C7 F1 77 F3 99 D2 77 30 25 80 7C F3 D5 D2 77 1E 0C 81 7C A5 99 80 7C
     
  9. 7A 97 D2 77 10 AB 0F 77 AB 0B 83 7C 10 F7 D4 77 1C EF D2 77 E8 C2 D2 77 F2 D2 80 7C B4 F6 D4 77
     
  10. C7 03 D3 77 8A 9C D2 77 DB 11 D3 77 08 C9 D2 77 08 C9 D2 77 E6 61 D5 77 78 D5 17 5D 60 9B D2 77
     
  11. AA 18 BD 77 EF D9 EF 77 5D EE D3 77 C1 A0 EF 77 3E D3 D2 77 29 5E EF 77 53 1D 80 7C 1B 9C D2 77
     
  12. A1 01 81 7C 37 D8 EF 77 44 99 D2 77 02 C7 D3 77 AB AE D2 77 AD F0 D2 77 9E 0F D3 77 6D 40 1B 5D
     
  13. D5 8F D2 77 97 D9 EF 77 FF DC EF 77 A0 97 D2 77 82 2B 1B 5D 96 D8 D2 77 8E 90 D2 77 23 98 D2 77
     
  14. 5B F2 D2 77 B0 C8 D2 77 12 B1 D2 77 D0 97 80 7C F6 8B D1 77 5A CA D2 77 16 F7 D1 77 07 95 D2 77
     
  15. 7A C3 D2 77 5F 6E EF 77 A6 8F D2 77 1E DA EF 77 1F 6D F0 77 BA 0D D3 77 FA 2C 1B 5D EE 8B EF 77
     
  16. 5F F4 D2 77 30 99 D2 77 0A 98 80 7C 9E BA EF 77 19 9E EF 77 3C 47 D2 77 21 90 D1 77 AB 7A DA 77
     
  17. C8 F1 D4 77 97 85 EF 77 7F 9A F1 77 7C 79 F0 77 0F 91 D2 77 5A 13 93 7C 55 9C 80 7C E2 DF D2 77
     
  18. C7 86 D1 77 9D D3 D2 77 17 87 D2 77 12 FF 80 7C EA 07 D5 77 49 24 81 7C 56 98 80 7C 14 8E EF 77
     
  19. FD 8F D2 77 46 BE 80 7C D2 D1 D2 77 DB 5E EF 77 6B F5 D2 77 30 AE 80 7C 04 F7 D2 77 AA 60 82 7C
     
  20. 06 2F 81 7C 05 02 18 5D 77 5D EF 77 2F FB D2 77 12 D3 D2 77 D3 CE D2 77 22 B2 D2 77 D0 D8 EF 77
     
  21. AD 2F 81 7C B0 C8 D2 77 C4 D2 D2 77 9C F6 D4 77 DF 06 18 5D 5F B5 80 7C 06 62 83 7C 3F AE D1 77
     
  22. EF 70 87 7C 27 D4 D2 77 05 80 D6 77 B8 96 D1 77 39 4B 0F 77 1D 9A 80 7C F9 C7 D2 77 1E 98 80 7C
     
  23. 42 8C D1 77 56 6A EF 77 F4 C7 17 5D BD FD 80 7C 9D 08 83 7C BA 14 D3 77 7B 1F D3 77 91 BE 80 7C
     
  24. 5E C3 D2 77 EC A3 0F 77 5B EA EF 77 78 8E D1 77 4C B7 EF 77 BF FC 80 7C A1 2C 1B 5D F6 E8 D2 77
     
  25. 42 78 DA 77 C9 2F 81 7C E0 10 92 7C 17 6C DA 77 90 F7 82 7C F2 D2 80 7C F5 2D 1B 5D EA 07 D5 77
     
  26. 45 88 D2 77 C9 2F 81 7C EF 19 BD 77 B8 97 80 7C C1 60 83 7C 0E 97 D1 77 69 38 81 7C 80 84 18 5D
     
  27. 17 0E 81 7C 06 F3 D2 77 A9 FF 80 7C 45 A0 80 7C 42 78 DA 77 17 6C DA 77 BE E9 EF 77 44 FD EF 77
     
  28. 25 8D EF 77 5E AE D6 77 88 9C 80 7C EF 61 EF 77 A6 51 0F 77 00 10 92 7C B8 97 80 7C 17 0E 81 7C
     
  29. F2 1E 80 7C A7 A0 80 7C DA 94 D1 77 F1 AE D1 77 19 BF 80 7C 95 C5 D2 77 D6 2B 1B 5D AE A5 D2 77
     
  30. 64 A1 80 7C D1 4C 83 7C 13 93 D2 77 6E 2B 81 7C EA E7 D2 77 E0 10 92 7C A1 6A EF 77 5F B5 80 7C
     
  31. 28 1A 80 7C D7 00 D3 77 1D 9A 80 7C 1B 2C 1B 5D 40 A3 D2 77 F4 AA EF 77 5D 94 D1 77 C1 61 EF 77
     
  32. 6E AC 80 7C 6A 12 81 7C 9C 8F D1 77 28 8E D1 77 D7 9B 80 7C F6 97 80 7C B4 F9 D4 77 45 DF EF 77
     
  33. FD 68 18 5D C5 2E 1B 5D 0C 94 D1 77 67 EE 80 7C 61 BA 80 7C EC 90 EF 77 11 12 D3 77 BD 1A D3 77
     
  34. 61 BA 80 7C 65 F9 D4 77 49 98 D2 77 39 FF D2 77 A5 9F EF 77 C8 98 D2 77 DD 02 83 7C 50 49 0F 77
     
  35. 22 2D 1B 5D 9D C2 D2 77 4B B8 EF 77 71 FE D2 77 1E 53 D6 77 A5 A4 80 7C 11 90 D2 77 28 8B EF 77
     
  36. 4E 97 D2 77 81 9F 80 7C 71 5A EF 77 40 1A BD 77 D8 03 18 5D FA 6B EF 77 80 8A D1 77 6A 3E 86 7C
     
  37. 70 5B EF 77 1A A2 EF 77 FE 98 D2 77 8C 39 81 7C 7B 1D 80 7C 79 6F EF 77 A4 AE F2 77 12 D3 D2 77
     
  38. 87 F7 D2 77 E6 2D 81 7C F0 48 0F 77 D5 98 D2 77 29 82 83 7C 47 9F F1 77 9B 86 EF 77 42 00 D3 77
     
  39. 23 AD EF 77 99 2A 81 7C E0 5F EF 77 2E 8C D1 77 73 86 D2 77 FF EB D3 77 9F AC 80 7C 01 F6 D1 77
     
  40. 80 48 0F 77 FD AA D2 77 F1 DF 18 5D 00 00 D3 77 74 9B 80 7C 32 86 EF 77 39 F5 D2 77 EC 87 EF 77
     
  41. C6 B3 D2 77 C2 F3 D2 77 AB 8E D1 77 F2 F2 D2 77 50 F7 D2 77 90 70 F0 77 4E F2 D4 77 DA B8 81 7C
     
  42. 6C D0 D3 77 F6 F3 D4 77 B0 99 80 7C 6E FA D2 77 3A E3 17 5D 7D A9 D2 77 F6 99 EF 77 30 AE 80 7C
     
  43. BC 70 D5 77 5E EA D2 77 40 E9 D3 77 67 F9 D1 77 A5 AB 94 7C 94 00 D3 77 6E AC 80 7C 27 CD 80 7C
     
  44. 2E 93 80 7C E1 82 D2 77 55 AA 0F 77 12 18 80 7C A9 2F 1B 5D 56 90 D1 77 E9 8F D2 77 2A F9 D2 77
     
  45. 07 D1 80 7C A5 61 EF 77 62 62 D5 77 EA FE D2 77 56 AF D2 77 CB A0 80 7C 69 D9 EF 77 A3 89 D2 77
     
  46. 66 97 D2 77 E6 C7 F0 77 FA CA 81 7C E1 9A 80 7C 6C B6 17 5D 22 78 D2 77 D2 03 F0 77 A5 A4 80 7C
     
  47. CF 2C 1B 5D F9 BC 80 7C 3D 9E D2 77 6A 12 81 7C 46 DE D1 77 89 C6 D3 77 F6 FB D2 77 4C 7B EF 77
     
  48. 64 A8 80 7C 75 EE F0 77 7A 15 D3 77 B4 90 D2 77

5,修复IAT调用
IAT修复完了,下面要把IAT的调用格式改回原来的方式。

  1. 00453DD9    B9 F0114000               mov ecx,zp_1_4.004011F0----IAT调用的起始位置
     
  2. 00453DDE    8039 E9                   cmp byte ptr ds:[ecx],0E9
     
  3. 00453DE1    75 46                     jnz short zp_1_4.00453E29                ;继续搜索
     
  4. 00453DE3    8079 05 90                cmp byte ptr ds:[ecx+5],90
     
  5. 00453DE7    75 40                     jnz short zp_1_4.00453E29
     
  6. 00453DE9    66:8379 03 09             cmp word ptr ds:[ecx+3],9
     
  7. 00453DEE    90                        nop
     
  8. 00453DEF    74 07                     je short zp_1_4.00453DF8
     
  9. 00453DF1    66:8379 03 07             cmp word ptr ds:[ecx+3],7                ; 继续搜索
     
  10. 00453DF6    75 31                     jnz short zp_1_4.00453E29
     
  11. 00453DF8    51                        push ecx
     
  12. 00453DF9    8B59 01                   mov ebx,dword ptr ds:[ecx+1]
     
  13. 00453DFC    8D4C19 05                 lea ecx,dword ptr ds:[ecx+ebx+5]--------计算跳转目标地址
     
  14. 00453E00    8039 68                   cmp byte ptr ds:[ecx],68----------------检验是不是push 提取码的指令
     
  15. 00453E03    75 24                     jnz short zp_1_4.00453E29
     
  16. ==============================================================================
     
  17. 00453E05    FF71 01                   push dword ptr ds:[ecx+1]
     
  18. 00453E08    FF15 346FA500             call dword ptr ds:[A56F34]-----------------调用壳的IAT解密call获取IAT的地址
     
  19. 00453E0E    8B0D 8076A500             mov ecx,dword ptr ds:[A57680]
     
  20. 00453E14    8D1C81                    lea ebx,dword ptr ds:[ecx+eax*4]
     
  21. ==============================================================================
     
  22. 00453E17    59                        pop ecx
     
  23. 00453E18    8959 02                   mov dword ptr ds:[ecx+2],ebx
     
  24. 00453E1B    66:C701 FF25              mov word ptr ds:[ecx],25FF-----------------修复代码
     
  25. 00453E20    83C1 06                   add ecx,6
     
  26. 00453E23  ^ EB B9                     jmp short zp_1_4.00453DDE
     
  27. 00453E25    0000                      add byte ptr ds:[eax],al
     
  28. 00453E27    0000                      add byte ptr ds:[eax],al
     
  29. 00453E29    81F9 A3394200             cmp ecx,zp_1_4.004239A3
     
  30. 00453E2F  ^ 0F8F D7FEFFFF             jg zp_1_4.00453D0C----------------出口,跳到OEP去
     
  31. 00453E35    41                        inc ecx
     
  32. 00453E36  ^ EB A6                     jmp short zp_1_4.00453DDE-----------------继续查找
     
  33. 00453E38    90                        nop
  1. 二进制
     
  2. B9 F0 11 40 00 80 39 E9 75 46 80 79 05 90 75 40 66 83 79 03 09 90 74 07 66 83 79 03 07 75 31 51
     
  3. 8B 59 01 8D 4C 19 05 80 39 68 75 24 FF 71 01 FF 15 34 6F A5 00 8B 0D 80 76 A5 00 8D 1C 81 59 89
     
  4. 59 02 66 C7 01 FF 25 83 C1 06 EB B9 00 00 00 00 81 F9 A3 39 42 00 0F 8F D7 FE FF FF 41 EB A6 90

执行完一遍之后,大部分IAT调用都被修复了。
不过由于代码忽略了一部分调用,这是要把:
00453DE9    66:8379 03 09             cmp word ptr ds:[ecx+3],9
这里的9 改成8,然后再执行一遍就OK了!

6,修复被模拟的GetModuleHandleA函数。

这没什么技术含量,找到GetModuleHandleA的地址,然后贴到里面就OK了!

7,挪动IAT。
恩?怎么不dump呢?
因为现在程序的IAT表还在程序外面呢,我们要把它移动回程序代码里面。
先找个地方放这些IAT。从第二个区段开始就是壳代码部分了。程序运行的时候不会用到,那我们就把IAT放在第二个区段。
然后打开UIF(Universal Import Fixer)这个工具,输入加壳程序的进程ID。和新的IAT的地址。
点击Fix,就可以把IAT表全部移回来了!


8,抓取镜像
IAT修复好了,终于到了激动人心的时刻。用LordPE(记得取消勾选“从磁盘文件粘贴文件头”这个选项哦)dump下这个程序。然后用ImportREC获取IAT,重建输入表。


运行一下,发现无法初始化。囧……
用OD载入修复后的文件,发现直接停在系统领空,提示出现内存读取错误,我晕…… 看来不是代码的问题,是PE头的问题。这个PE头也残废了…… 无语。

重新勾选“从磁盘文件粘贴文件头”这个选项,再抓一次,然后重新修复。发现这回没有出现初始化错误,但仍运行不了。果然是文件头的问题。-----可是别忘了,磁盘文件的PE头也是个残疾。

别灰心哦,还记得上次那个资源表的问题么?内存中的PE头,资源表的位置是对的,而磁盘文件的PE头,资源表是错的。那好,就先修复资源表。修复了以后发现可以找到资源了。但是程序仍运行。

9,修复程序
现在只能相信自己PE头问题,继续找不能运行的原因。
OD载入,运行。几次跟踪下来,发现程序不能运行的地方居然是Delphi程序初始化代码的部分…… 见鬼了,这应该跟PE头没什么关系了的。

仔细想一下………………

明白了!刚才为了查找IAT解密call。是单步走的。是不是某些变量被初始化了,导致无法运行呢?

用另一个OD载入加壳程序,依上面的方法到OEP去,然后复制数据,然后粘贴到脱壳程序的相应位置。再搜索一下“修改的数据”
,发现果然有很多处不同~ 看来方向对了!保存脱壳文件,果然可以运行了!!

脱壳成功!


总结:
1,Delphi程序很娇气,脱壳的时候最好在OEP处脱壳,否则变量初始化以后就很容易出问题。
2,Anti-Hook保护强度并不大,老烟应该考虑把不同dll的函数放在同一个内存段里面,这样不容易修复。
3,学会自己写patch代码
4,残疾PE头+残疾PE头=健全PE头
5,ESP定律辅助断点的设置。
6,UIF的使用。

已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/decryption/348.html     欢迎订阅Eddy Blog

记住我的信息,下次不用再输入 欢迎给Eddy Blog留言