VMP1.8主程序脱壳分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VMProtect1.8主程序脱壳分析
NOOBY牛已经玩得差不多了我来补一刀 ^_^
手中没有正式版的试炼品只好拿1.8DEMO主程序看时间比较久了忘得差不多如果分析有误请各位见谅
勾上SOD全部选项载入VMPROTECT.EXE 停在TLS入口 ALT+M看到基址为00010000
bp VirtualProtect+13 F9 4次后看到解码了到00011000看看FF25被弄成了什么样子
VMP主程序是DELPHI写的因此只关注FF25类IAT 而不用关注 CALL [XX]和MOV EXX,XX/CALL XX这些使得针对性的IAT修复工作减少了不少体力活
引用:
00011278 55 push ebp
00011279 E8 30C52800 call 0029D7AE ; 0029D7AE
0001127E 8BC0 mov eax,eax
00011280 50 push eax
00011281 E8 E8E92700 call 0028FC6E ; 0028FC6E
00011286 8BC0 mov eax,eax
00011288 55 push ebp
00011289 E8 5B333700 call 003845E9 ; 003845E9
0001128E 8BC0 mov eax,eax
00011290 52 push edx
00011291 E8 FBE02C00 call 002DF391 ; 002DF391
被错位了写段脚本恢复FF25的错位
引用:
luanxu:
inc search
find search,#E8??????008BC0#
cmp $RESULT,0
je exit
mov search,$RESULT
GCI search,DESTINATION
cmp $RESULT,001F3000 //UPX0-VA
jb luanxu
cmp $RESULT,003DE000 //UPX2-VA
jae luanxu
GCI search,COMMAND
dec search
mov [search],#909090909090#
asm search,$RESULT
jmp luanxu
修复后:
引用:
00011278 E8 31C52800 call 0029D7AE ; 0029D7AE
0001127D 90 nop
0001127E 8BC0 mov eax,eax
00011280 E8 E9E92700 call 0028FC6E ; 0028FC6E
00011285 90 nop
00011286 8BC0 mov eax,eax
00011288 E8 5C333700 call 003845E9 ; 003845E9
0001128D 90 nop
0001128E 8BC0 mov eax,eax
00011290 E8 FCE02C00 call 002DF391 ; 002DF391
00011295 90 nop
找个CALL跟跟看有什么新花样 EIP到00011278 单步什么都不用看只看3条
引用:
MOV EXX,A
LEA EXX,[EXX+B]
LEA EXX,[EXX+C]
这个CALL里用到以下3条
引用:
002ADE81 BD 56720500 mov ebp,57256
002ADE8A 8BAD AF693000 mov ebp,dword ptr ss:[ebp+3069AF]
0034A300 8DAD 626F45AB lea ebp,dword ptr ss:[ebp+AB456F62]
前面2条合起来指向一个DWORD 和最后一条组装成最终的函数地址
引用:
[A+B]=[57256+3069AF]=[0035DC05]=D13B2C85----记为R1
R1+AB456F62=7C809BE7--指向我本机的kernel32.CloseHandle NOOBY牛的视频里找的就是这个视频里面最后生成的LOG文件里面每一行的4个成员后面2个一目了然是真实函数以及对应的DLL 前面2个则是A+B,C了这里VMP把A+B拆分成了A和B 使得我们难以在第一次看到A或者B时就能确定是哪个函数(关于NOOBY的VMP1.8脚本可能会另外撰文补充或者等NOOBY牛的BIN ^_^)
经过这3条之后最终函数的真实地址保存在EXX中这里的EXX不是固定的给
通用脚本编写增加不少难度
最后保存在EXX中的函数会通过一个
引用:
push dword ptr ss:[esp+D]
retn E
结构返回真实API地址这里的D,E也不是固定的
看完FF25后再来看看IAT调用一般的DELPHI程序第一处IAT调用CALL便是这个
引用:
00011430 53 push ebx
00011431 83C4 BC add esp,-44
00011434 BB 0A000000 mov ebx,0A
00011439 54 push esp
0001143A E8 260E3A00 call 003B2265 ; 003B2265
0001143F F64424 2C 01 test byte ptr ss:[esp+2C],1
00011444 74 05 je short 0001144B ; 0001144B
00011446 0FB75C24 30 movzx ebx,word ptr ss:[esp+30]
0001144B 8BC3 mov eax,ebx
0001144D 83C4 44 add esp,44
00011450 5B pop ebx
00011451 C3 retn
0001143A处的CALL应该指向FF25型的GetStartupInfoA 然而这里指向的地址003B2265落在UPX1段分析过程略最终知道 VMP把它和FF25型IAT用了同样的方法处理直接指向了真实函数这样使我们的修复工作变得很尴尬因为IAT 和IAT调用都通过CALL指向壳段而FF25修复后占6个字节 IAT调用CALL则只占5个字节如果不分开处理最终会覆盖后面的一字节而且VMP对于每一个函数哪怕是相同的函数都会分配不同的过程来单独处理
基于避免与VM正面对抗的想法以及前面提到的种种困难和尴尬我只好用一种尴尬的方法来处理----"云断点"
前面提到的每个函数会通过一个PUSH/RETN结构返回真实地址于是我选择对UPX1段所有的这种结构下断最终找到下了几百个断点是为"云断点"
云断点:
引用:
mov fi,001F3000 //001F3000为UPX0段VA