hyperchem 发表于 2009-3-12 11:20

吾爱破解周年献礼----攻破ZProtect IAT保护最后的堡垒---Anti-Hook

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

1.到OEP去
对于这个版本来说,单纯的是ESP定律不再适用,什么意思呢?如果仅仅下硬件断点是断不下来的,我们需要一种辅助断点方式、
先单步走,仍然是走到pushad 以后下hr esp。然后Ctrl+G 输入GetModuleHandleA
到这里来7C80B731 >8BFF            mov edi,edi
7C80B733    55            push ebp
7C80B734    8BEC            mov ebp,esp
7C80B736    837D 08 00      cmp dword ptr ss:,0
7C80B73A    74 18         je short kernel32.7C80B754<--- 在这里下F2断点.
7C80B73C    FF75 08         push dword ptr ss:
7C80B73F    E8 C0290000   call kernel32.7C80E104
7C80B744    85C0            test eax,eax
7C80B746    74 08         je short kernel32.7C80B750
7C80B748    FF70 04         push dword ptr ds:
7C80B74B    E8 7D2D0000   call kernel32.GetModuleHandleW
7C80B750    5D            pop ebp解释一下为什么要这么下.GetModuleHandleA这个函数在壳的运行中是至关重要的,调用的次数非常的频繁,而且即便是过了OEP以后,主程序初始化的时候也会调用这个函数,也就是说,我们即便不能到达OEP,也可能到达OEP附近。所以用这个断点来辅助我们找OEP。

断点下好以后,F9运行,注意看反汇编窗口EIP的位置。数次之后,就会断在下面的代码上:00A70447^\E9 5929FFFF   jmp 00A62DA5这就是ESP定律应该执行到的位置。

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

再走两步就到了这里,这就是OEP,标准的Delphi入口00453D0C    55            push ebp
00453D0D    8BEC            mov ebp,esp
00453D0F    83C4 F0         add esp,-10
00453D12    B8 2C3B4500   mov eax,zp_1_4.00453B2C
00453D17    E8 441FFBFF   call zp_1_4.00405C60
00453D1C    A1 58504500   mov eax,dword ptr ds:
00453D21    8B00            mov eax,dword ptr ds:
00453D23    E8 74E3FFFF   call zp_1_4.0045209C
00453D28    8B0D 38514500   mov ecx,dword ptr ds:            ; zp_1_4.00456BFC
00453D2E    A1 58504500   mov eax,dword ptr ds:
00453D33    8B00            mov eax,dword ptr ds:
00453D35    8B15 3C364500   mov edx,dword ptr ds:            ; zp_1_4.00453688
00453D3B    E8 74E3FFFF   call zp_1_4.004520B4
00453D40    A1 58504500   mov eax,dword ptr ds:
00453D45    8B00            mov eax,dword ptr ds:
00453D47    E8 E8E3FFFF   call zp_1_4.00452134
00453D4C    E8 0B00FBFF   call zp_1_4.00403D5C上面是比较中规中矩的方法,下面介绍一种比较取巧的方法。

直接在OD中运行程序。然后到00401000去,分析一下代码。00401000   /04104000      dd zp_1_4.00401004
00401004   \03            db 03
00401005   .07            db 07
00401006   .42 6F 6F 6C 6>ascii "Boolean"
0040100D      01            db 01
0040100E      00            db 00
0040100F      00            db 00
00401010      00            db 00
00401011      00            db 00
00401012      01            db 01
00401013      00            db 00
00401014      00            db 00
00401015      00            db 00
00401016      00104000      dd zp_1_4.00401000
0040101A   .05            db 05
0040101B   .46 61 6C 73 6>ascii "False"
00401020   .04            db 04
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调用有两处。00405B9C   $- FF25 E4714500 jmp dword ptr ds: ds:=00A425D0
00401264   $- FF25 6C714500 jmp dword ptr ds: ds:=00A425D0可见两处调用是同一个伪IAT。

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

3,接下来找IAT的解密call
F7单步走,一直走,直到走进一处IAT调用的代码后,记录下面的代码。
根据我第一篇的分析,下面就是解密call了00A643E5    FF15 346FA500   call dword ptr ds: 这个就是解密call了~
00A6D63D    8B0D 8076A500   mov ecx,dword ptr ds:--这里装的是伪IAT的地址
00A64674    85C9            test ecx,ecx
00A59940    8BF0            mov esi,eax
00A5AF4D   /0F84 55910000   je 00A640A8
00A5B842    A1 8476A500   mov eax,dword ptr ds:
00A673CA    2BC1            sub eax,ecx
00A6C6F8    C1F8 02         sar eax,2
00A5C550    3BF0            cmp esi,eax
00A63FFF^\0F82 5981FFFF   jb 00A5C15E
00A5C15E    8B0CB1          mov ecx,dword ptr ds:--这里就是获得函数地址了
00A5C901    894C24 2C       mov dword ptr ss:,ecx
00A68A0B    5E            pop esi
00A58F96    C2 0400         retn 4
00A620FF    61            popad
00A653E4    C3            retn----------这里返回到API执行 但是代码被复制到内存,无法知道真正的内存地址了。
找到解密call了 我们就可以修复IAT调用了~ 到伪IAT一看 发现IAT被Hook了~
伪IAT的开始地址是00A85D48
结束地址是00A86314
这个地址 对于同一台机器和同一个OD,是不变的~

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

4,修复Anti-Hook

下面就是伪IAT了(部分,全本见附件)00A85D4800BE9719
00A85D4C00BE8F1F
00A85D5000DBB1DE
00A85D5400BEB19C
00A85D5800EAFE01
00A85D5C00BE42ED
00A85D6000DBB5EA
00A85D6400AB2446
00A85D6800BF0277
00A85D6C00BE9ED9
00A85D7000BED226
00A85D7400AB9F81
00A85D7800AE60DB不过首先要先修复被Hook的API地址。

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

Dword CopyMemorySize
Dword CopyDllBase
Dword CopyMemoryBase

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

00A84CFC00090000
00A84D0077D10000user32.77D10000
00A84D0400BD0000

00A84D08000A9000
00A84D0C77DA0000advapi32.77DA0000
00A84D1000C60000

00A84D140008B000
00A84D18770F0000oleaut32.770F0000
00A84D1C00D10000

00A84D2000008000
00A84D2477BD0000version.77BD0000
00A84D2800DA0000

00A84D2C00049000
00A84D3077EF0000gdi32.77EF0000
00A84D3400DB0000

00A84D380009A000
00A84D3C5D170000comctl32.5D170000
00A84D4000E00000

00A84D4400093000
00A84D487C920000ntdll.7C920000
00A84D4C00EA0000

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

在这里找一段代码,二进制复制,然后在内存中查找这段二进制00AB24D6    68 C09A837C   push 7C839AC0
00AB24DB    64:A1 00000000mov eax,dword ptr fs:
00AB24E1    50            push eax
00AB24E2    8B4424 10       mov eax,dword ptr ss:
00AB24E6    896C24 10       mov dword ptr ss:,ebp
00AB24EA    8D6C24 10       lea ebp,dword ptr ss:
00AB24EE    2BE0            sub esp,eax
00AB24F0    53            push ebx
00AB24F1    56            push esi
00AB24F2    57            push edi
00AB24F3    8B45 F8         mov eax,dword ptr ss:
00AB24F6    8965 E8         mov dword ptr ss:,esp
00AB24F9    50            push eax
00AB24FA    8B45 FC         mov eax,dword ptr ss:
00AB24FD    C745 FC FFFFFFF>mov dword ptr ss:,-1
00AB2504    8945 F8         mov dword ptr ss:,eax
00AB2507    8D45 F0         lea eax,dword ptr ss:
00AB250A    64:A3 00000000mov dword ptr fs:,eax
00AB2510    C3            retn


7C8024D6    68 C09A837C   push kernel32.7C839AC0
7C8024DB    64:A1 00000000mov eax,dword ptr fs:
7C8024E1    50            push eax
7C8024E2    8B4424 10       mov eax,dword ptr ss:
7C8024E6    896C24 10       mov dword ptr ss:,ebp
7C8024EA    8D6C24 10       lea ebp,dword ptr ss:
7C8024EE    2BE0            sub esp,eax
7C8024F0    53            push ebx
7C8024F1    56            push esi
7C8024F2    57            push edi
7C8024F3    8B45 F8         mov eax,dword ptr ss:
7C8024F6    8965 E8         mov dword ptr ss:,esp
7C8024F9    50            push eax
7C8024FA    8B45 FC         mov eax,dword ptr ss:
7C8024FD    C745 FC FFFFFFF>mov dword ptr ss:,-1
7C802504    8945 F8         mov dword ptr ss:,eax
7C802507    8D45 F0         lea eax,dword ptr ss:
7C80250A    64:A3 00000000mov dword ptr fs:,eax
7C802510    C3            retn找到了,原来在这里。
比较一下就能看出来:代码地址相对于内存基地址的偏移是固定。这也就是为什么内存大小跟相应的dll的镜像大小相等:壳是为了保证能让所有的API都能复制到一个内存段中,所以只能申请一个跟dll的镜像一样大的内存段。

了解了这些,修复的方法就呼之欲出了。
伪IAT中的API地址其实都是真的,只是基地址不对,只要减去当前的基地址,再加上原来的基地址就一些OK了!!00453D6C    BE 485DA800   mov esi,0A85D48                        ; 伪IAT的开始地址
00453D71    81FE 1863A800   cmp esi,0A86318                        ; 伪IAT的结束位置
00453D77    68 0000AB00   push 0AB0000
00453D7C    68 0000BD00   push 0BD0000
00453D81    68 0000C600   push 0C60000
00453D86    68 0000D100   push 0D10000
00453D8B    68 0000DA00   push 0DA0000
00453D90    68 0000DB00   push 0DB0000
00453D95    68 0000E000   push 0E00000
00453D9A    68 0000EA00   push 0EA0000
00453D9F    68 0000F400   push 0F40000                           ; 这些是每个dll的代码所在的内存段,具体参见笔记
===========================================================================================
00453DA4    72 05         jb short zp_1_4.00453DAB
00453DA6    E9 07010000   jmp zp_1_4.00453EB2                      ; 出口,在这里下好断点~
00453DAB    8B06            mov eax,dword ptr ds:
00453DAD    3E:3B4424 20    cmp eax,dword ptr ds:
00453DB2    72 4E         jb short zp_1_4.00453E02               ; 出错口
00453DB4    3E:3B4424 1C    cmp eax,dword ptr ds:
00453DB9    72 52         jb short zp_1_4.00453E0D
00453DBB    3E:3B4424 18    cmp eax,dword ptr ds:
00453DC0    72 57         jb short zp_1_4.00453E19
00453DC2    3E:3B4424 14    cmp eax,dword ptr ds:
00453DC7    72 5C         jb short zp_1_4.00453E25
00453DC9    3E:3B4424 10    cmp eax,dword ptr ds:
00453DCE    72 61         jb short zp_1_4.00453E31
00453DD0    3E:3B4424 0C    cmp eax,dword ptr ds:
00453DD5    72 66         jb short zp_1_4.00453E3D
00453DD7    3E:3B4424 08    cmp eax,dword ptr ds:
00453DDC    72 6B         jb short zp_1_4.00453E49
00453DDE    3E:3B4424 04    cmp eax,dword ptr ds:
00453DE3    72 70         jb short zp_1_4.00453E55
00453DE5    3E:3B0424       cmp eax,dword ptr ds:
00453DE9    72 76         jb short zp_1_4.00453E61
00453DEB    BB A8000000   mov ebx,0A8
00453DF0    8BEC            mov ebp,esp
00453DF2    3E:8B4D 00      mov ecx,dword ptr ds:
00453DF6    290E            sub dword ptr ds:,ecx
00453DF8    E8 00000000   call zp_1_4.00453DFD
00453DFD    5A            pop edx
00453DFE    03D3            add edx,ebx
00453E00    FFD2            call edx
00453E02    83C6 04         add esi,4
00453E05    81FE 1863A800   cmp esi,0A86318
00453E0B^ EB 97         jmp short zp_1_4.00453DA4
=====================================================================================
00453E0D    3E:8D6C24 20    lea ebp,dword ptr ds:
00453E12    BB 70000000   mov ebx,70                               ; ebx中的值是函数的偏移,主要是为了代码的可移植性
00453E17^ EB D9         jmp short zp_1_4.00453DF2
00453E19    3E:8D6C24 1C    lea ebp,dword ptr ds:
00453E1E    BB 77000000   mov ebx,77
00453E23^ EB CD         jmp short zp_1_4.00453DF2
00453E25    3E:8D6C24 18    lea ebp,dword ptr ds:
00453E2A    BB 7E000000   mov ebx,7E
00453E2F^ EB C1         jmp short zp_1_4.00453DF2
00453E31    3E:8D6C24 14    lea ebp,dword ptr ds:
00453E36    BB 85000000   mov ebx,85
00453E3B^ EB B5         jmp short zp_1_4.00453DF2
00453E3D    3E:8D6C24 10    lea ebp,dword ptr ds:
00453E42    BB 8C000000   mov ebx,8C
00453E47^ EB A9         jmp short zp_1_4.00453DF2
00453E49    3E:8D6C24 0C    lea ebp,dword ptr ds:
00453E4E    BB 93000000   mov ebx,93
00453E53^ EB 9D         jmp short zp_1_4.00453DF2
00453E55    3E:8D6C24 08    lea ebp,dword ptr ds:
00453E5A    BB 9A000000   mov ebx,9A
00453E5F^ EB 91         jmp short zp_1_4.00453DF2
00453E61    3E:8D6C24 04    lea ebp,dword ptr ds:
00453E66    BB A1000000   mov ebx,0A1
00453E6B^ EB 85         jmp short zp_1_4.00453DF2
================================================================================================
00453E6D    8106 0000807C   add dword ptr ds:,7C800000          ; 下面是每个dll的真实基址
00453E73    C3            retn
00453E74    8106 0000D177   add dword ptr ds:,77D10000
00453E7A    C3            retn
00453E7B    8106 0000DA77   add dword ptr ds:,77DA0000
00453E81    C3            retn
00453E82    8106 00000F77   add dword ptr ds:,770F0000
00453E88    C3            retn
00453E89    8106 0000BD77   add dword ptr ds:,77BD0000
00453E8F    C3            retn
00453E90    8106 0000EF77   add dword ptr ds:,77EF0000
00453E96    C3            retn
00453E97    8106 0000175D   add dword ptr ds:,5D170000
00453E9D    C3            retn
00453E9E    8106 0000927C   add dword ptr ds:,7C920000
00453EA4    C3            retn
00453EA5    8106 0000597D   add dword ptr ds:,7D590000
00453EAB    C3            retn二进制
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
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
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
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
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
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
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
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
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
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了。00A85D4877D29719user32.PtInRect
00A85D4C77D28F1Fuser32.IntersectRect
00A85D5077EFB1DEgdi32.GetDIBColorTable
00A85D5477D2B19Cuser32.DestroyWindow
00A85D587C92FE01ntdll.RtlGetLastWin32Error
00A85D5C77D242EDuser32.SetForegroundWindow
00A85D6077EFB5EAgdi32.CreatePalette
00A85D647C802446kernel32.Sleep
00A85D6877D30277user32.OpenClipboard
00A85D6C77D29ED9user32.GetKeyState
00A85D7077D2D226user32.GetKeyboardState
00A85D747C809F81kernel32.InitializeCriticalSection
00A85D787C8360DBkernel32.GlobalFindAtomA
00A85D7C77EF700Agdi32.CreateCompatibleBitmap
00A85D8077D30D96user32.EmptyClipboard
00A85D8477D297FFuser32.IsIconic
00A85D885D1B2C59comctl32.ImageList_BeginDragIAT的二进制
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
64 A8 80 7C 75 EE F0 77 7A 15 D3 77 B4 90 D2 775,修复IAT调用
IAT修复完了,下面要把IAT的调用格式改回原来的方式。00453DD9    B9 F0114000               mov ecx,zp_1_4.004011F0----IAT调用的起始位置
00453DDE    8039 E9                   cmp byte ptr ds:,0E9
00453DE1    75 46                     jnz short zp_1_4.00453E29                ;继续搜索
00453DE3    8079 05 90                cmp byte ptr ds:,90
00453DE7    75 40                     jnz short zp_1_4.00453E29
00453DE9    66:8379 03 09             cmp word ptr ds:,9
00453DEE    90                        nop
00453DEF    74 07                     je short zp_1_4.00453DF8
00453DF1    66:8379 03 07             cmp word ptr ds:,7                ; 继续搜索
00453DF6    75 31                     jnz short zp_1_4.00453E29
00453DF8    51                        push ecx
00453DF9    8B59 01                   mov ebx,dword ptr ds:
00453DFC    8D4C19 05               lea ecx,dword ptr ds:--------计算跳转目标地址
00453E00    8039 68                   cmp byte ptr ds:,68----------------检验是不是push 提取码的指令
00453E03    75 24                     jnz short zp_1_4.00453E29
==============================================================================
00453E05    FF71 01                   push dword ptr ds:
00453E08    FF15 346FA500             call dword ptr ds:-----------------调用壳的IAT解密call获取IAT的地址
00453E0E    8B0D 8076A500             mov ecx,dword ptr ds:
00453E14    8D1C81                  lea ebx,dword ptr ds:
==============================================================================
00453E17    59                        pop ecx
00453E18    8959 02                   mov dword ptr ds:,ebx
00453E1B    66:C701 FF25            mov word ptr ds:,25FF-----------------修复代码
00453E20    83C1 06                   add ecx,6
00453E23^ EB B9                     jmp short zp_1_4.00453DDE
00453E25    0000                      add byte ptr ds:,al
00453E27    0000                      add byte ptr ds:,al
00453E29    81F9 A3394200             cmp ecx,zp_1_4.004239A3
00453E2F^ 0F8F D7FEFFFF             jg zp_1_4.00453D0C----------------出口,跳到OEP去
00453E35    41                        inc ecx
00453E36^ EB A6                     jmp short zp_1_4.00453DDE-----------------继续查找
00453E38    90                        nop二进制
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
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
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:,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的使用。

注意:这个CrackMe的按钮事件代码被ZProtect混淆了。下次再讲如何修复这种代码混淆。

To Be Continued...

wgz001 发表于 2009-3-12 11:26

学习大牛的作品
今天是个好日子

:loveliness:

qq513701092 发表于 2009-3-12 11:25

终于ZP...................

老万 发表于 2009-3-12 11:38

谢谢楼主分享,学习了。

Peace 发表于 2009-3-12 11:46

佩服

什么也不是 发表于 2009-3-12 11:50


膜拜大牛...

一风 发表于 2009-3-12 12:23

学习......

zhang0101 发表于 2009-3-12 12:37

牛   不甚明白...........

YeMelody 发表于 2009-3-12 12:42

很强i。。在此拜过

xdct 发表于 2009-3-12 13:55

学习学习~~
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 吾爱破解周年献礼----攻破ZProtect IAT保护最后的堡垒---Anti-Hook