|
2、接下来看些中等强度和最大强度吧
流程和上面是一样的,到达OEP的方法一样,但是中等强度和最大强度,对IAT的加密采取了很WS的方式,代码里面全是垃圾代码,本来我想把垃圾代码全部清除,然后再单步跟的,发现那个不是一般的费劲啊,不过还是写了个脚本来清理垃圾指令。共发现5种,脚本如下:
var addr
var yeip
var temsep
var long
var addr1
huazhiliang1:
mov yeip,eip
mov addr,eip
mov addr1,eip
mov long,460000 //这里是处理的代码长度,可以自己根据实际情况修改,下面的这个参数都一样
add addr1,long
findhua1:
mov temesp,esp
find eip,#740EEB0E????????750E740C????????74F675F4#
cmp $RESULT,0
je exit1
mov eip,$RESULT
mov [eip],#909090909090909090909090909090909090909090909090#
mov esp,temesp
add eip,20
cmp eip,addr1
jg exit1
jmp findhua1
exit1:
mov eip,yeip
huazhiilang2:
var addr
var yeip
var temsep
var long
var addr1
mov yeip,eip
mov addr,eip
mov addr1,eip
mov long,460000
add addr1,long
findhua2:
mov temesp,esp
find eip,#740A7508#
cmp $RESULT,0
je exit2
mov eip,$RESULT
mov [eip],#740A75089090909090909090#
mov esp,temesp
add eip,20
cmp eip,addr1
jg exit2
jmp findhua2
exit2:
mov eip,yeip
huzhiiang3:
var addr
var yeip
var temsep
var long
var addr1
mov yeip,eip
mov addr,eip
mov addr1,eip
mov long,460000
add addr1,long
findhua3:
mov temesp,esp
find eip,#7403#
cmp $RESULT,0
je exit3
mov eip,$RESULT
mov [eip],#7403909090#
mov esp,temesp
add eip,20
cmp eip,addr1
jg exit3
jmp findhua3
exit3:
mov eip,yeip
huazhiling4:
var addr
var yeip
var temsep
var long
var addr1
mov yeip,eip
mov addr,eip
mov addr1,eip
mov long,460000
add addr1,long
findhua4:
mov temesp,esp
find eip,#c3eb08#
cmp $RESULT,0
je exit4
mov eip,$RESULT
mov [eip],#9090909090909090909090#
mov esp,temesp
add eip,20
cmp eip,addr1
jg exit4
jmp findhua4
exit4:
mov eip,yeip
var addr
var yeip
var temsep
var long
var addr1
mov yeip,eip
mov addr,eip
mov addr1,eip
mov long,460000
add addr1,long
findhua5:
mov temesp,esp
find eip,#740EEB0E????????750E740C????????????75F4????????#
cmp $RESULT,0
je exit5
mov eip,$RESULT
mov [eip],#909090909090909090909090909090909090909090909090#
mov esp,temesp
add eip,20
cmp eip,addr1
jg exit5
jmp findhua5
exit5:
mov eip,yeip
ret
既然清理垃圾指令的方法行不同,那我们只好换个方法吧,我的思路是,不管在VM中还是在垃圾指令里,程序总要返回IAT的真实地址的,也就是在垃圾指令或VM中运行过程中,寄存器中总会出现IAT的真实地址的,那我们就先看看在什么地方在那个寄存器里会出现真实的地址,寄存器是固定的还是随机的,写个小 脚本测试一下吧。
var addr
Find:
sti
mov addr,eax
mov addr,[addr]
gn addr
cmp $RESULT,0
jne zt
mov addr,ecx
mov addr,[addr]
gn addr
cmp $RESULT,0
jne zt
mov addr,ebx
mov addr,[addr]
gn addr
cmp $RESULT,0
jne zt
mov addr,edx
mov addr,[addr]
gn addr
cmp $RESULT,0
je Find
mov addr,esp
mov addr,[addr]
gn addr
cmp $RESULT,0
je Find
zt:
pause
具体的代码我就补写了,全是垃圾指令而且很多很多,当寄存器中出现IAT的真实地址的时候OD就会停下来,我们就可以分析到底最关键的出现IAT的代码是那些了!在VM中跑照样的脚本,那不是一般的慢,我都不知道今天晚上电脑跑了多长的时间才跑完的! 最后经过测试中等强度的加密方式会在壳段中以下代码的时候出现真实的地址:
对于中等强度:
0041EE71 C3 RETN
0041EE72 50 PUSH EAX
0041EE73 53 PUSH EBX ;中等强度的加密方式,在壳段中只有一处这个代码,也就是所有的IAT都要经过这里,而当程序运行到这条指令的时候,EBX中就是真实的IAT。
0041EE74 51 PUSH ECX
对于最大强度,和中等强度一样,只是关键代码和寄存器不一样而已;
0041EE71 59 POP ECX
0041EE72 5B POP EBX
0041EE73 58 POP EAX
0041EE74 8BC1 MOV EAX,ECX
0041EE76 8B4F 24 MOV ECX,DWORD PTR DS:[EDI+24]
0041EE79 51 PUSH ECX
0041EE7A 9D POPFD
0041EE7B 03C3 ADD EAX,EBX
0041EE7D 8B5F 44 MOV EBX,DWORD PTR DS:[EDI+44]
0041EE80 8903 MOV DWORD PTR DS:[EBX],EAX
0041EE82 9C PUSHFD ;//最大强度的加密方式,在壳段中只有一处这个代码,也就是所有的IAT都要经过这里,而当程序运行到这条指令的时候,EAX中就是真实的IAT。
0041EE83 58 POP EAX
而且经过测试,对于加密后的VB程序,中等强度和最大强度都存在了这个特征码,而且利用的寄存器是固定的,照样也方便写脚本了。好了有了上面的分析就可以写个脚本来查找IAT了。没有太多的分析大家看脚本吧,最好用脚本跑一下就能明白了!脚本如下:
var neicuncodebase
var neicuncodesize
var oep
var ptr
var ip1
var addr
var refaddr
var temesp
var ptr1
var code
var kebase1
var kebase2
var iataddr
mov kebase1,0040e000 //第一个壳段
mov kebase2,00507000 //第二个壳段
mov oep,eip
mov temesp,esp
findkebase1tzm2:
mov eip,kebase1
find eip, #C3505351# //中等强度的特征码,最大强度特征码为“#595B588BC18B4F24519D03C38B5F4489039C58#”
cmp $RESULT,0
je findkebase2tzm2
add $RESULT,2 //因为中等强度代码当运行到PUSH EBX 这条指令的时候,EBX是真实的地址所以这里加2,同理,对于最大强度这里应该加11
/* 0041EE71 C3 RETN
0041EE72 50 PUSH EAX
0041EE73 53 PUSH EBX ;EBX 中就是真实的IAT。
0041EE74 51 PUSH ECX
*/
bp $RESULT
findkebase2tzm2:
mov eip,kebase2
find eip, #C3505351# //中等强度的特征码,最大强度特征码为“#595B588BC18B4F24519D03C38B5F4489039C58#”
cmp $RESULT,0
je exit
add $RESULT,2 //这里同上面,好像这段脚本就没有用,因为只是用了第一个壳段
bp $RESULT
mov esp,temesp
mov eip,00401000 //查找的起始位置
mov ptr1,eip
tzm2iatfind:
mov temesp,esp
find ptr1, #e9????????# //这里查找的就是JMP xxxx
je exit
mov ptr,$RESULT
mov ptr1,ptr
mov eip,ptr
mov refaddr, ptr
sti
mov ip1, eip
mov ip1, [ip1]
and ip1, 0ff
cmp ip1, e9
jnz nextfind
sti
mov ip1, eip
mov ip1, [ip1]
and ip1, 0ff
cmp ip1, 68
jnz nextfind
cmp eip,kebase2
ja tzm2iataddrfind
cmp eip,kebase1
jb tzm2iatfind
tzm2iataddrfind:
esto
mov iataddr,ebx ;//这里就是出现IAT真实地址的寄存器,对于中等加密是EBX,对于最大强度,这里是EAX.
gn iataddr
cmp $RESULT,0
je tzm2iataddrfind
tzm2iatfix:
sub ebx,refaddr
SUB ebx,5
mov refaddr,ptr
mov [refaddr],#e9#
add refaddr,1
mov [refaddr],ebx,4
mov esp,temesp
nextfind:
add ptr1,6
jmp tzm2iatfind
exit:
mov esp,temesp
mov eip,oep
ret
这个脚本只适用于我自己加的VB程序的壳,但是处理的原理是一样的,好了分析就这么多吧,应该说没有怎么分析IAT具体是怎么加密的,只是找到了一个解密IAT的方法,由于脚本中没有做太多的判断,所以运行脚本的时候需要自己看着脚本跑,当修复完IAT后,就自己把脚本停下来,这个时候由于寄存器的值都被破坏了这样修复的程序是不能运行的,不过我们可以打开加壳的软件跑到OEP后根据没有破坏的寄存器把修复好的寄存器的值全都修改过来,然后 再用UIF修复 LP dump IR修复就可以了,一定要记住一点哦,dump 以前一定要取消那些断点啊,尤其是F2断点,由于我刚开始没有取消断点,结果DUMP 修复后的程序不能运行,跟踪后发现是F2断点的原因,DUMP后的程序F2断点的 地方变成了CC 也就INT3 。好了VP的IAT分析就到这里了,提供一下我练习的加壳后以及脱壳后的软件吧,方便像我一样的菜鸟练习。
--------------------------------------------------------------------------------
【经验总结】
1、还是自己动手一遍比看别人的文章百遍都起作用。
2、一直以为在VM中或者垃圾指令中的关键代码自己跟踪不到,结果用最笨的方法还是找到了!这就说明不管做什么只要去努力去试试总有成功的机会!
3、建议苦力在下个版本中对于中等强度和最大强度加密中取消那两个特征码,或者F9运行的时候出错那样会增大修复难度,至少现在我感觉,最大速度的加密修复速度却是最慢的!修复的时候F9运行就出错,对于寄存器的使用,是否可以借鉴别的壳改为随机的那样也增加修复难度。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于wuqing1501(笨笨鼠), 转载请注明作者并保持文章的完整, 谢谢!
2010年07月18日 AM 02:31:16
|
|