三种方法手动修复CRYPToCRACk's PE Protector 0.9.3的IAT

[复制链接]
查看1777 | 回复0 | 2011-12-23 19:27:17 | 显示全部楼层 |阅读模式
这个壳到OEP很简单,两次断点法就可以了,OEP入口为
004271B0    55                push ebp
004271B1    8BEC              mov ebp,esp
004271B3    6A FF             push -1
004271B5    68 600E4500       push CrypToCr.00450E60
004271BA    68 C8924200       push CrypToCr.004292C8
004271BF    64:A1 00000000    mov eax,dword ptr fs:[0]
004271C5    50                push eax
004271C6    64:8925 00000000  mov dword ptr fs:[0],esp
004271CD    83C4 A8           add esp,-58
004271D0    53                push ebx
004271D1    56                push esi
004271D2    57                push edi
004271D3    8965 E8           mov dword ptr ss:[ebp-18],esp
004271D6    FF15 DC0A4600     call dword ptr ds:[460ADC]                                                    ; CrypToCr.0046B823
004271DC    33D2              xor edx,edx
004271DE    8AD4              mov dl,ah
004271E0    8915 34E64500     mov dword ptr ds:[45E634],edx
先把它DUMP下来。
在004271D6 处右键选择“数据窗口中跟随”----->“内存”
在数据窗口中找到IAT的起始和结束地址如下
IAT START: 00460818
IAT END:    00460F1C
下面分别介绍用三种方法来修复IAT。
第一种,让壳自己来还原IAT。
先找一个IAT来看看
在数据窗口中
00460818  0046C7BA  CrypToCr.0046C7BA
0046081C  0046C7C7  CrypToCr.0046C7C7
00460820  0046C7D4  CrypToCr.0046C7D4
00460824  0046C7E1  CrypToCr.0046C7E1
00460828  0046C7EE  CrypToCr.0046C7EE
我们来找第一个00460818,用到这个IAT的时候,肯定是CALL DWORD PTR DS:[00460818]
也就是CALL 0046C7BA,现在我们看一下0046C7BA处的代码,CTRL+G 输入0046C7BA
0046C7BA    68 4A33EDEC       push ECED334A
0046C7BF    810424 5313B988   add dword ptr ss:[esp],88B91353
0046C7C6    C3                retn
0046C7C7    68 9C37D79F       push 9FD7379C
0046C7CC    812C24 95EE302A   sub dword ptr ss:[esp],2A30EE95
0046C7D3    C3                retn
0046C7D4    68 EE0DDABD       push BDDA0DEE
0046C7D9    813424 87197CC8   xor dword ptr ss:[esp],C87C1987
0046C7E0    C3                retn
0046C7E1    68 40B64794       push 9447B640
0046C7E6    810424 735E5EE1   add dword ptr ss:[esp],E15E5E73
0046C7ED    C3                retn
0046C7EE    68 92307242       push 42723092
0046C7F3    812C24 A3E7CBCC   sub dword ptr ss:[esp],CCCBE7A3
0046C7FA    C3                retn
我们在0046C7BA处新建EIP,也就是让壳来自己来跑也IAT来。然后单步两下,到retn处,这时个你会发现
0012FF88       75A6469D  ADVAPI32.RegCloseKey
0012FF8C       76F7ED6C  返回到 kernel32.76F7ED6C
也就是当RETN之后,就会去执行原来的IAT了,这个地址的IAT就为75A6469D  ADVAPI32.RegCloseKey。
而这个值正好是ESP地址所指向的值。
所以这个时候我们就可以在数据窗口中,手工将00460818  0046C7BA  CrypToCr.0046C7BA改为00460818  75A6469D  ADVAPI32.RegCloseKey
这样00460818的指针就修复好了。同理,我们也可以一样修复其它的指针了。
当然这样一个一个用手工会很麻烦,但是我们可以写一个脚本,跑一下脚本就一下子就可以搞定了。脚本如下:
VAR iatstart
VAR iatend
VAR temp
mov iatstart,00460818 //iat起始地址
build:
CMP [iatstart],0  //如果IAT地址的值 为0就不用修复
JE jia
MOV eip,[iatstart]   //IAT加密语句起始位置新建EIP,也就是PUSH的地方
STO         //单步两下到达RETN处
STO
MOV temp,[esp]
MOV [iatstart],temp   //ESP地址的值,就为真的IAT值。
ADD esp,4
CMP iatstart, 00460f1c    //iat 结束地址
JAE finish
JMP jia
jia:
add iatstart ,4
JMP build
finish:
RET
第二种方法,
分析出壳加密IAT的算法,再把逆回来。
先来分析一下,壳是怎么样加密IAT的
0046C7BA    68 4A33EDEC       push ECED334A
0046C7BF    810424 5313B988   add dword ptr ss:[esp],88B91353
0046C7C6    C3                retn
0046C7C7    68 9C37D79F       push 9FD7379C
0046C7CC    812C24 95EE302A   sub dword ptr ss:[esp],2A30EE95
0046C7D3    C3                retn
0046C7D4    68 EE0DDABD       push BDDA0DEE
0046C7D9    813424 87197CC8   xor dword ptr ss:[esp],C87C1987
0046C7E0    C3                retn
0046C7E1    68 40B64794       push 9447B640
0046C7E6    810424 735E5EE1   add dword ptr ss:[esp],E15E5E73
0046C7ED    C3                retn
0046C7EE    68 92307242       push 42723092
0046C7F3    812C24 A3E7CBCC   sub dword ptr ss:[esp],CCCBE7A3
0046C7FA    C3                retn
上面有三种情况,
我们先看第一个
0046C7BA    68 4A33EDEC       push ECED334A
0046C7BF    810424 5313B988   add dword ptr ss:[esp],0046C7C6    C3                retn
前面讲过,retn就是ESP地址的值。
如   push ECED334A 然后RETN的话,那么RETN就是ECED334A。也就是[ESP]=ECED334A
好我们先分析这三句的意思。
第一句,PUSH ECED334A( [esp]=ECED334A)
第二句  add dword ptr ss:[esp],88B91353,也就是[ESP]=[ESP]+88B91353
第三句 retn, 返回到[ESP],  [ESP]就是IAT的真实值
另外两种加密不同的是两个参数不同,和把ADD换成了SUB和XOR。如果我们再把两个参数找到规律,那么就可以搞定了。
其实参数是可以定位的。
[00460818]=0046C7BA
byte:[0046C7BA]=68
42723092=[0046C7BA+1]
88B91353也可以定位。 SUB,ADD,XOR也可以定位的。
综合一下,我们可以写下如下的代码进行patch.
mov eax,00460818
START:
mov ebx,[eax]
cmp ebx,0
je jia4
add ebx,1
mov ecx,[ebx]   //ecx为push值
cmp [ebx+5],2c   比较EBX是2C还是,34或者是04,也就是次判断是ADD,SUB,XOR。
je jian
cmp [ebx+5],34
je huo
add ecx,[ebx+7]  //[ebX+7]为第二个参数
huo:
xor ecx,[ebx+7]
mov [eax],ecx
jia4:
add eax,4
mov [eax],ecx
jmp START:
上面的代码写到OD里,需要自已整理一下.
前面两种方法都是到达OEP之后修复,下面的第三种方法是在到达OEP之前修复。
用OD重载程序,然后在数据窗口,对00460818下硬件访问断点。看着寄存器窗口,按SHIFT+F9.当寄存器窗口出现
EAX 75A6469D ADVAPI32.RegCloseKey
ECX 00000000
EDX 00460818 CrypToCr.00460818
EBX 00400000 CrypToCr.00400000
ESP 0012FF7C
EBP 75A50000 ADVAPI32.75A50000
ESI 00460078 CrypToCr.00460078
EDI 0046C7BA CrypToCr.0046C7BA
EIP 0046B33B CrypToCr.0046B33B
此时EAX的值 就是正确的IAT了。此时是停在0046B33B如下,
0046B334    8B7C24 04         mov edi,dword ptr ss:[esp+4]
0046B338    893C8A            mov dword ptr ds:[edx+ecx*4],edi
0046B33B    807F 05 55        cmp byte ptr ds:[edi+5],55
0046B33F    73 0C             jnb short CrypToCr.0046B34D
0046B341    2B47 01           sub eax,dword ptr ds:[edi+1]
0046B344    C747 05 81042400  mov dword ptr ds:[edi+5],240481
0046B34B    EB 1E             jmp short CrypToCr.0046B36B
在0046B338处下硬件执行断点,在OEP处也下一下硬件执行断点。
重载程序运行,断在0046B338时,将 mov dword ptr ds:[edx+ecx*4],edi改成 mov dword ptr ds:[edx+ecx*4],EAX。再运行程序,停在OEP之时,所有的IAT就修复了。可以直接用LOADPE,和IMPORTREC来DUMP程序了。
发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则