这个壳到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程序了。 |
|