VMProtect1.8主程序脱壳分析
本帖最后由 kissy 于 2009-5-10 18:59 编辑我还以为在这里贴过的 找半天没找到 汗....我的错我的错
NOOBY牛已经玩得差不多了 我来补一刀 ^_^
手中没有正式版的试炼品 只好拿1.8DEMO主程序看 时间比较久了 忘得差不多 如果分析有误 请各位见谅
勾上SOD全部选项 载入VMPROTECT.EXE 停在TLS入口 ALT+M看到基址为00010000
bp VirtualProtect+13 F9 4次后看到解码了 到00011000看看FF25被弄成了什么样子
VMP主程序是DELPHI写的 因此只关注FF25类IAT 而不用关注 CALL 和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 ,#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,
LEA EXX,
这个CALL里用到以下3条
002ADE81 BD 56720500 mov ebp,57256
002ADE8A 8BAD AF693000 mov ebp,dword ptr ss:
0034A300 8DAD 626F45AB lea ebp,dword ptr ss:
前面2条合起来指向一个DWORD 和最后一条组装成最终的函数地址
===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:
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:,1
00011444 74 05 je short 0001144B ; 0001144B
00011446 0FB75C24 30 movzx ebx,word ptr ss:
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
loop:
inc fi
find fi,#FF7424??C2??00#
cmp $RESULT,0
je UPX1//继续在UPX1段寻找
add $RESULT,4
mov fi,$RESULT
wrta sFile,fi //记录
wrta sFile,"\r\n"
bp fi下断
jmp loop
UPX1:
cmp fi,00289000//UPX1段VA
jae exit
mov fi,00289000 //循环
jmp loop
exit:
ret
然后记录所有IAT和IAT调用经过这种结构的返回地址 并分别记录FF25型IAT和IAT调用的地址
在下断和跟踪的过程中 发现有一些指向了UPX0段 而代码段里被VM处理过的 也会指向UPX0段 为了避免与VM混淆 于是我记录下所有指向UPX0段的CALL 然后手工分离出VMCALL和IAT调用CALL 这样也给后续的修复工作提供了便利 所幸的是 这样的IAT并不多 只有十个左右
记录FF25型IAT和真实函数:
var fi
var sFile
var tmp
mov sFile,"FF25.TXT"
mov fi,00011000
loop:
inc fi
find fi,#E8??????00??8BC0#
//找CALL XX
// XX--此处VMP随机填充的一个字节
//MOV EAX,EAX结构
cmp $RESULT,0
je exit
mov fi,$RESULT
gci fi,DESTINATION
cmp $RESULT,289000
jb loop
cmp $RESULT,3DE000//判断目标地址是否在UPX1段
jae loop
wrta sFile,fi //记录IAT地址
wrta sFile,"\r\n"
mov eip,fi
esto
mov tmp,
wrta sFile,tmp//记录真实函数地址
wrta sFile,"\r\n"
jmp loop
同样方法记录IAT调用及其对应函数地址 记为zhizhen.txt .
我的思路是这样的:
1.首先修复FF25
2.通过FF25指向的函数地址到IAT调用CALL对应的记录文件中查找 最后将对应的IAT调用的指针指向FF25型IAT.
因为OLLYSCR中的REV指令对操作时,会自动过滤前面的0,只好找雪雪写了一个小工具来取反,打包在附件中。分别对FF25.TXT全部取反,对ZHIZHEN.TXT隔行取反,方便脚本的操作。保存结果为FF25.BIN和ZHIZHEN.BIN。
修复FF25:
var tmp
var neicun
var neicun1
alloc 2000
mov neicun,$RESULT
lm neicun,2000,"ff25.bin"
mov neicun1,neicun
mov tmp,
eval "jmp {tmp}"
asm ,$RESULT //修复第一个
loop:
add neicun,8
cmp ,0
je exit
mov tmp, //+4处为真实函数地址
eval "jmp {tmp}"
asm ,$RESULT //将原FF25CALL修复成JMP XX
jmp loop
exit:
free neicun1,2000
ret
脚本运行完毕后 用UIF修复直接调用为FF25 记录修复后IAT的RVA
修复IAT调用:
var fi
var search
var str
var neicun
var neicun1
mov search,00011000
alloc 8000
mov neicun,$RESULT
lm neicun,8000,"zhizhen.bin"//载入
mov neicun1,neicun
loop:
mov neicun,neicun1
mov str,0
inc search
find search,#FF25# //在CODE段寻找FF25类IAT
cmp $RESULT,0
je exit
mov search,$RESULT
cmp ,010E0000//010E0000为UIF修复后的IAT RVA
jb loop
cmp ,010E0800//本例中IAT大小为800
jae loop
GCI search,DESTINATION
mov fi,$RESULT
eval "#{fi}#"//真实函数地址转换成查找值
mov str,$RESULT
find neicun1,str,8000//在IAT调用文件中查找相同函数
cmp $RESULT,0
je loop
mov neicun,$RESULT
sub neicun,4
mov tmp,//指针定位到对应的IAT调用
eval "call {search}"
asm tmp,$RESULT//将IAT调用指向真实的FF25
add neicun,8//第一次修复 偷懒 直接写了个过程
find://循环修复IAT调用
find neicun,str,8000
cmp $RESULT,0
je loop
mov neicun,$RESULT
sub neicun,4
mov tmp,
eval "call {search}"
asm tmp,$RESULT
add neicun,8
jmp find
exit:
ret
至此IAT修复完毕
找到OEP:001E4C68
修复OEP:
001E4C68 55 push ebp
001E4C69 8BEC mov ebp,esp
001E4C6B 83C4 F4 add esp,-0C
001E4C6E B8 A0471E00 mov eax,1E47A0
001E4C73 E8 702FE3FF call 00017BE8 ; 00017BE8
001E4C78 A1 84901E00 mov eax,dword ptr ds:
001E4C7D 8B00 mov eax,dword ptr ds:
001E4C7F E8 3425E8FF call 000671B8 ; 000671B8
001E4C84 A1 84901E00 mov eax,dword ptr ds:
001E4C89 8B00 mov eax,dword ptr ds:
001E4C8B BA E04C1E00 mov edx,1E4CE0 ; ASCII "VMProtect"
001E4C90 E8 2721E8FF call 00066DBC ; 00066DBC
001E4C95 8B0D A4901E00 mov ecx,dword ptr ds: ; VMProted.001ED1F0
001E4C9B A1 84901E00 mov eax,dword ptr ds:
001E4CA0 8B00 mov eax,dword ptr ds:
001E4CA2 8B15 B8011800 mov edx,dword ptr ds: ; VMProted.00180204
001E4CA8 E8 2325E8FF call 000671D0 ; 000671D0
001E4CAD 8B0D B08F1E00 mov ecx,dword ptr ds: ; VMProted.001EDDC4
001E4CB3 A1 84901E00 mov eax,dword ptr ds:
001E4CB8 8B00 mov eax,dword ptr ds:
001E4CBA 8B15 C02E1D00 mov edx,dword ptr ds: ; VMProted.001D2F0C
001E4CC0 E8 0B25E8FF call 000671D0 ; 000671D0
001E4CC5 A1 84901E00 mov eax,dword ptr ds:
001E4CCA 8B00 mov eax,dword ptr ds:
001E4CCC E8 7F25E8FF call 00067250 ; 00067250
001E4CD1 E8 76F2E2FF call 00013F4C ; 00013F4C
001E4CD6 0000 add byte ptr ds:,al
001E4CD8 FFFF ??? ; Unknown command
001E4CDA FFFF ??? ; Unknown command
001E4CDC 0900 or dword ptr ds:,eax
001E4CDE 0000 add byte ptr ds:,al
001E4CE0 56 push esi
001E4CE1 4D dec ebp
001E4CE2 50 push eax
001E4CE3 72 6F jb short 001E4D54 ; 001E4D54
001E4CE5 74 65 je short 001E4D4C ; 001E4D4C
001E4CE7 637400 00 arpl word ptr ds:,si
001E4CEB 0000 add byte ptr ds:,al
修复几处VM:
00017BE8 50 push eax
00017BE9 6A 00 push 0
00017BEB E8 F8FEFFFF call 00017AE8 ; 00017AE8
00017BF0 BA 08511E00 mov edx,1E5108
00017BF5 52 push edx
00017BF6 8905 DCA41E00 mov dword ptr ds:,eax
00017BFC 8942 04 mov dword ptr ds:,eax
00017BFF C742 08 0000000>mov dword ptr ds:,0
00017C06 C742 0C 0000000>mov dword ptr ds:,0
00017C0D E8 8AFFFFFF call 00017B9C ; 00017B9C
00017C12 5A pop edx
00017C13 58 pop eax
00017C14 E8 27C2FFFF call 00013E40 ; 00013E40
00017C19 C3 retn
00013E40 8905 ACA41E00 mov dword ptr ds:,eax
00013E46 31C0 xor eax,eax
00013E48 8905 B0A41E00 mov dword ptr ds:,eax
00013E4E 8915 B4A41E00 mov dword ptr ds:,edx
00013E54 8B42 04 mov eax,dword ptr ds:
00013E57 8905 20A01E00 mov dword ptr ds:,eax
00013E5D E8 D6FEFFFF call 00013D38 ; 00013D38
00013E62 C605 28A01E00 0>mov byte ptr ds:,0
00013E69 E8 72FFFFFF call 00013DE0 ; 00013DE0
00013E6E C3 retn
00017B9C 53 push ebx
00017B9D 81C4 F8FEFFFF add esp,-108
00017BA3 68 05010000 push 105
00017BA8 8D4424 04 lea eax,dword ptr ss:
00017BAC 50 push eax
00017BAD A1 DCA41E00 mov eax,dword ptr ds:
00017BB2 50 push eax
00017BB3 E8 28FFFFFF call 00017AE0 ; 00017AE0
00017BB8 8BC4 mov eax,esp
00017BBA E8 C5EDFFFF call 00016984 ; 00016984
00017BBF 8BD8 mov ebx,eax
00017BC1 891D 18511E00 mov dword ptr ds:,ebx
00017BC7 85DB test ebx,ebx
00017BC9 75 0A jnz short 00017BD5 ; 00017BD5
00017BCB A1 0C511E00 mov eax,dword ptr ds:
00017BD0 A3 18511E00 mov dword ptr ds:,eax
00017BD5 B8 08511E00 mov eax,1E5108
00017BDA E8 BDF0FFFF call 00016C9C ; 00016C9C
00017BDF 81C4 08010000 add esp,108
00017BE5 5B pop ebx
00017BE6 C3 retn
001A5E44 55 push ebp
001A5E45 8BEC mov ebp,esp
001A5E47 33C9 xor ecx,ecx
001A5E49 51 push ecx
001A5E4A 51 push ecx
001A5E4B 51 push ecx
001A5E4C 51 push ecx
001A5E4D 53 push ebx
001A5E4E 8BD8 mov ebx,eax
001A5E50 33C0 xor eax,eax
001A5E52 55 push ebp
001A5E53 68 E25F1A00 push 1A5FE2
001A5E58 64:FF30 push dword ptr fs:
001A5E5B 64:8920 mov dword ptr fs:,esp
001A5E5E 8D55 FC lea edx,dword ptr ss:
001A5E61 8B43 58 mov eax,dword ptr ds:
001A5E64 E8 1F8CE8FF call 0002EA88 ; 0002EA88
001A5E69 8B55 FC mov edx,dword ptr ss:
001A5E6C 8B83 FC020000 mov eax,dword ptr ds:
001A5E72 8B40 58 mov eax,dword ptr ds:
001A5E75 E8 268CE8FF call 0002EAA0 ; 0002EAA0
001A5E7A 8B15 30921E00 mov edx,dword ptr ds: ; VMProted.001ECBB4
001A5E80 8B92 94000000 mov edx,dword ptr ds:
001A5E86 8BC3 mov eax,ebx
001A5E88 E8 E716EAFF call 00047574 ; 00047574
001A5E8D 8B15 30921E00 mov edx,dword ptr ds: ; VMProted.001ECBB4
001A5E93 8B92 68010000 mov edx,dword ptr ds:
001A5E99 8B83 E8020000 mov eax,dword ptr ds:
001A5E9F E8 D016EAFF call 00047574 ; 00047574
001A5EA4 BA 885F1A00 mov edx,1A5F88 ; ASCII "VMProtect Professional v 1.8 "
//省略部分 详见附件脚本
DUMP-FIX
运行DUMP_.EXE 正常运行 发现界面上的选项全部都成了乱码 无奈对照NOOBY牛的1.7版 修复以下过程
001D607C 55 push ebp
001D607D 8BEC mov ebp,esp
001D607F 81C4 8CFEFFFF add esp,-174
001D6085 53 push ebx
001D6086 56 push esi
001D6087 57 push edi
001D6088 33C9 xor ecx,ecx
001D608A 898D 8CFEFFFF mov dword ptr ss:,ecx
001D6090 894D FC mov dword ptr ss:,ecx
001D6093 894D F8 mov dword ptr ss:,ecx
001D6096 8BD8 mov ebx,eax
001D6098 BF C8DD1E00 mov edi,1EDDC8
001D609D 33C0 xor eax,eax
001D609F 55 push ebp
001D60A0 68 06661D00 push 1D6606
001D60A5 64:FF30 push dword ptr fs:
001D60A8 64:8920 mov dword ptr fs:,esp
001D60AB BA 1C661D00 mov edx,1D661C ; ASCII "VMProtect Professional v 1.8 "
//省略部分 详见附件脚本
此过程将近600字节 膜拜一下生猛的NOOBY 我对照1.7修复都花了近2个小时 人肉的力量啊~~~
剩下几个VM过程没有处理 CPUID? 补区? 水平和精力有限 见谅 ^_^
捣鼓一番后没有乱码了 不过加壳的时候提示出错不再看了 等儿童节
怕文章写得太乱 录了段视频
抛砖引玉 期待简单的处理方法
衷心感谢雪落的瞬间 NOOBY GOLDSUN A_P 啊cr fly 海风月影 cyto Κūйɡβǐм 等众位朋友在我学习过程中给予的无私帮助与支持.^_^
Kissy
www.unpack.cn
www.52pojie.cn
PS:附件传不上来 给外链好了
http://rapidshare.com/files/226988771/Vmprotect1.8__20027___31243___24207___33073___22771___20998___26512_.rar 好文章收藏了 看了lz的文章又看了看Nooby以前的文章让我茅塞顿开 谢谢前辈了 唉高手真的太多了我学习开发的时候别学了破解 等我也学破解吧别人玩壳我也玩壳吗别人又VM了怎么都跟不上 开发的人难破解的人也难 ~终于露面了啊你...打你屁股! 汗,这个代码字体太丑了,一定要换下,不然代码都不工整~把这么帅的代码都搞丑了~ 强大,好文啊,一定要好好学习下! 學習的不夠只看懂前面一小段
感謝樓主分享,要再努力學習才行 {:299_843:}
在 一蓑 已目睹大牛风采了...再次膜拜 没仔细看,留个帖子,下回看!
谢谢作者的帖子!