【文章标题】: VProtect1.XX-1.84 unpacker
【文章作者】: wuqing1501(笨笨鼠)
【作者邮箱】: 木有
【作者主页】: 木有
【作者QQ号】: 木有
【下载地址】: 自己搜索下载
【保护方式】: VProtect默认加壳
【使用工具】: 老三样
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
在这里呢首先我先要感谢感谢NOOBY、KISSY和COOOLIE,因为KISSY和nooby 我学会了脱VMP用DLL修复的方法,通过研究NOOBY.DLL和kissy.dll我明白了这个DLL的原理,所以才有这篇文章。
今天说下VProtect1.84以下版本的脱壳方法,其实我感觉脱VP的话,nooby在脚本区公布的那个主程序1.82的脱壳脚本可以说是相当的无敌,应该可以通杀1.82以下所有的版本,但是对于高版本的话,可能需要一些修改,但是这个我没有研究过所以在这里就不多说了。我现在说另外一种方法,相信大家都看过kissy牛脱VMP的视频吧?其实我的方法就是学习kissy牛还有NOOBY牛脱VMP用DLL修复IAT的方法,但是VP和VMP有区别,因为VMP在IAT的处理过程中,只使用了一种算法就是加法,而VP为了防止kissy.dll还有nooby.dll的使用,所以在1.84以及以前的版本中都使用了三种算法,那就是:相加、异或、取反。所以我们直接用脱VMP的方法去脱VP是不行的,那两个DLL的算法都是加法,所以我们要自己写个DLL,其实这个DLL的原理,相信使用过DLL修复的人都明白的原理还是很简单的,但是我是个菜鸟,不会编程,用易语言写那个DLL最后总是因为有个问题没有解决最后没有成功,最后还是拿到了kissy.dll的源码进行了修改,在这里我先十分感谢KISSY 和COOOLIE,所以我们现在要做的工作就是:修改KISSY脱VMP的脚本,修改COOOLIE的kissy.dll的源码。
在这里我不公开kissy.dll的源码,只公开成品还有脚本,因为那个源码我基本上只修改了一下那个算法的地方所以其他的东西都还是原来的,在这里还请KISSY牛海涵。
脚本:
/* /////////////////////////////////////////////////////////////////////////////// 脚本 : VP1.XX-Vprotect 1.84 Unpacker 调试选项 : 1.设置 OllyDbg 忽略所有异常选项 2.使用海风月影全选项. 3.去掉'选项-调试设置-地址-解析修饰符号名称' 前面的勾,然后重新打开OD.跑脚本.(必须) 4.使用PhantOm保护DRX。 工具 : OllyDbg1.1, ODBGScript 1.65 感谢 : 感谢KISSY 的脚本,感谢苦力的DLL源码,感谢那些曾经帮助我的人! //////////////////////////////////////////////////////////////////////////////////// var getapi var write var addr var dword var vpro var rapi var dllname var apiname var imgbase var imgbasefromdisk var sizeofimg var tmp1 var tmp2 var tmp3 var secbase var secsize var logfile var oep var fixtype var typeadd var typexor var typenot var vmiataddr mov logfile,"FakIat.txt" ///////////////////////// //配置区 ///////////////////////// mov vmexit,008D21ED //VM出口 mov oep,0069C168 mov write,008AC492 //填充函数 mov typeadd,008A8F41 //对IAT进行SUB处理的地址 mov typexor,008AA673 //对IAT进行xor处理的地址 mov typenot,008AC257 //对IAT进行not处理的地址 ///////////////////////// cmp $VERSION, "1.64" jb odbgver GMI eip, MODULEBASE mov imgbase, $RESULT mov tmp1, [imgbase+3C] add tmp1, imgbase mov signVA, tmp1 mov imgbasefromdisk, [signVA+34] mov sizeofimg, [signVA+50] mov tmp1, signVA add tmp1, f8 mov tmp2, 0 mov tmp2, [signVA+6], 2 wrta logfile,tmp2 wrta logfile,"\r\n" last: mov secsize, [tmp1+8] mov tmp3, [tmp1+0C] add tmp3, imgbase mov secbase, tmp3 wrta logfile,secbase wrta logfile,"\r\n" wrta logfile,secsize wrta logfile,"\r\n" cmp tmp2, 1 je lab1 add tmp1, 28 sub tmp2, 1 jmp last lab1: cmp imgbasefromdisk, imgbase je lab1_1 jmp error lab1_1: bc start: bp vmexit cmp eip,oep je exit cmp eip,write je findkey cmp eip,typeadd je findkey cmp eip,typexor je findkey cmp eip,typenot je findkey esto len [ecx] cmp $RESULT,8 jb start scmpi [ecx],"ole32.dll" je loopfix scmpi [ecx],"advapi32.dll" je loopfix scmpi [ecx],"user32.dll" je loopfix scmpi [ecx],"kernel32.dll" je loopfix cmp [ecx],"oleaut32.dll" je loopfix scmpi [ecx],"advapi32.dll" je loopfix cmp [ecx],"uxtheme.dll" je loopfix scmpi [ecx],"ws2help.dll" je loopfix cmp [ecx],"ws2_32.dll" je loopfix scmpi [ecx],"winspool.dll" je loopfix cmp [ecx],"MSCTFIME.dll" je loopfix scmpi [ecx],"shell32.dll" je loopfix cmp [ecx],"shlwapi.dll" je loopfix scmpi [ecx],"GDI32.dll" je loopfix cmp [ecx],"rpcrt4.dll" je loopfix scmpi [ecx],"secur32.dll" je loopfix cmp [ecx],"msvcrt.dll" je loopfix scmpi [ecx],"version.dll" je loopfix cmp [ecx],"comctl32.dll" je loopfix scmpi [ecx],"iphlpapi.dll" je loopfix cmp [ecx],"imagehlp.dll" je loopfix scmpi [ecx],"psapi.dll" je loopfix cmp [ecx],"msctf.dll" je loopfix scmpi [ecx],"msimg32.dll" je loopfix cmp [ecx],"imm32.dll" je loopfix scmpi [ecx],"comdlg32.dll" je loopfix scmpi [ecx],"ntdll.dll" jne start loopfix: esto bp typeadd bp typexor bp typenot bp oep len [ecx] cmp $RESULT,0 je loopfix sub $RESULT,4 readstr [ecx],$RESULT mov dllname,$RESULT len [edx] cmp $RESULT,0 je loopfix readstr [edx],$RESULT mov apiname,$RESULT esto esto esto esto add eax,ecx add eax,7 mov addr,eax mov dword,[addr+7] sub eax,7 sub eax,ecx cmp dword,0 je start mov fixtype,0 wrta logfile,addr wrta logfile,"," wrta logfile,dword wrta logfile,"," wrta logfile,dllname wrta logfile,"," wrta logfile,apiname wrta logfile,"," wrta logfile,fixtype wrta logfile,"\r\n" jmp start goon: cmp eip,oep je exit bp typeadd bp typexor bp typenot bp write bp oep esto findkey: cmp eip,oep je exit cmp eip,typeadd je addkey cmp eip,typexor je xorkey cmp eip,typenot je notkey jmp goon addkey: mov fixtype,0 mov dword,[eax+ecx+10] gn edx mov dllname,$RESULT_1 mov apiname,$RESULT_2 cmp $RESULT,0 je goon bc eip bp write esto bc eip mov addr,edx jmp writetxt2 xorkey: mov fixtype,2 mov dword,[eax+edx+10] gn ecx mov dllname,$RESULT_1 mov apiname,$RESULT_2 cmp $RESULT,0 je goon bc eip bp write esto bc eip mov addr,edx jmp writetxt2 notkey: mov fixtype,1 mov dword,edx gn edx mov dllname,$RESULT_1 mov apiname,$RESULT_2 cmp $RESULT,0 je goon bc eip bp write esto bc eip mov addr,edx writetxt2: wrta logfile,addr wrta logfile,"," wrta logfile,dword wrta logfile,"," wrta logfile,dllname wrta logfile,"," wrta logfile,apiname wrta logfile,"," wrta logfile,fixtype wrta logfile,"\r\n" jmp goon error: msg "dll不支持." RET odbgver: msg "ODSCR版本要大于1.65" ret exit: bc bphwc ret
1、vmexit
也就是VP的VM出口,对于1.93以下的版本,VP加壳出来的VM出口基本上都是固定的。VM出口代码如下:
58 POP EAX 8903 MOV DWORD PTR DS:[EBX],EAX 8B07 MOV EAX,DWORD PTR DS:[EDI] 8B5F 0C MOV EBX,DWORD PTR DS:[EDI+C] 8B4F 04 MOV ECX,DWORD PTR DS:[EDI+4] 8B57 08 MOV EDX,DWORD PTR DS:[EDI+8] 8B6F 14 MOV EBP,DWORD PTR DS:[EDI+14] 8B77 18 MOV ESI,DWORD PTR DS:[EDI+18] FF77 24 PUSH DWORD PTR DS:[EDI+24] 9D POPFD 8B67 10 MOV ESP,DWORD PTR DS:[EDI+10] C747 50 0000000>MOV DWORD PTR DS:[EDI+50],0 8B7F 1C MOV EDI,DWORD PTR DS:[EDI+1C] C3 RETN
58 89 03 8B 07 8B 5F 0C 8B 4F 04 8B 57 08 8B 6F 14 8B 77 18 FF 77 24 9D 8B 67 10 C7 47 50 00 00 00 00 8B 7F 1C C3
这段代码基本上是固定的所以要找VM出口的话 这段代码中的任意一些指令都可以作为VM出口的特征码。我们需要找的VM出口就是那个RETN的地方。
2、oep
对于VP加壳的程序,寻找OEP的话我在以前的文章也有说过,NOOBY牛的脱壳脚本中也有方法,我这里再说一个就是对VirtualProtect函数下断(注意VP的检测不要在段首下F2,可以在段尾或者中间F2),F9运行,然后取消VirtualProtect断点,CODE段下内存访问断点,F9运行一般都可以到OEP!
3、write
其实就是相当于VMP中的填充函数,代码如下
8902 MOV DWORD PTR DS:[EDX],EAX
MOV DWORD PTR DS:[EDX],EAX
NOT EDX
然后CTRL+F11就可以了这样停下来后我们就可以找到这个填充函数了。
4、typeadd typexor typenot
在这里我们要先知道VP是如何处理iat的这个我在很早以前发过类似的文章都有说明的这里就不在说了,我只说对于IAT的处理算法,脚本中原来只有一个算法,所以只要知道填充地址和填充值,我们就可以用DLL计算出来API,但是VP有三种算法,所以我们要先搞清楚VP是如何处理IAT的,代码如下:
typeadd : 2B5401 10 SUB EDX,DWORD PTR DS:[ECX+EAX+10] typexor: 334C10 10 XOR ECX,DWORD PTR DS:[EAX+EDX+10] typenot: F7D2 NOT EDX
找到了这些参数基本上就算是完工了,可以跑脚本了,在这里说下我自己的一点经验吧,如果用DLL修复VP也好VMP也好,使用脚本插件的时候一定要使用1.65或者比1.65稍微大一点点比如1.67的版本,不要使用高版本哦!高版本生成的都是多行的处理起来会非常苦难,如果使用1.65版本的话,生成的IAT文件中就会有很多的“黑块”,这个黑块就是空格吧,但是有这个的存在DLL就不能正常运行,所以我们在这里要处理“黑块”。对于处于每行中最后的几个黑块是不影响DLL使用的,影响DLL的是每行中间和“,”在一块的那个黑块,所以我们可以使用文本编辑器中的替换功能,具体你使用什么软件都可以,只要他能识别出IAT文件中的黑块就可以,可以同时选中“黑块”和“,”然后在替换框那里拷贝进去,而要替换的字符那里就填写“,”,这样的话就可以把所有的影响使用的黑块全都清除掉了。
最后因为VP1.8X版本貌似为了ANTIdump会申请三个大小为8000区段用来计算IAT,所以脱壳后要dump这三个区段补到脱壳后的程序中。修正OEP和CODE段修正为可写。
至此,基本上所有的功能就算完成了,给脱壳后的文件添加DLL就可以了!
在这里我就不提供样品了,大家可以拿DEMO主程序测试!
脚本和DLL:
http://u.115.com/file/f58c2d8b07#
VProtect1.XX-1.84_unpacker.rar
--------------------------------------------------------------------------------
【经验总结】
1、多动手分析比看文章强百倍。
2、以前脱壳修复IAT的时候只要找RETN或者返回找到真实的API填充到需要修复的地方就可以了,而这次这个方式却要分析IAT的加密算法,VP1.84以下版本的算法简单没有那么多的干扰和垃圾代码,对于高版本的就不一样了很多的垃圾代码干扰分析,所以整个分析下
来很累,但是对于分析算法来说还是让自己学到不少的东西!
3、谢谢KISSY、NOOBY、COOOLIE还有曾经帮助过我的所有人!
--------------------------------------------------------------------------------
【版权声明】: 本文原创,小菜一个, 转载请注明作者并保持文章的完整, 谢谢!
2011年03月01日 10:40:16