kissy 发表于 2009-5-10 18:57

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

wellen 发表于 2009-5-10 20:25

好文章收藏了

wellen 发表于 2009-5-10 20:28

看了lz的文章又看了看Nooby以前的文章让我茅塞顿开 谢谢前辈了

170077000 发表于 2009-5-10 21:05

唉高手真的太多了我学习开发的时候别学了破解 等我也学破解吧别人玩壳我也玩壳吗别人又VM了怎么都跟不上 开发的人难破解的人也难

zzage 发表于 2009-5-10 21:16

~终于露面了啊你...打你屁股!

Hmily 发表于 2009-5-10 22:05

汗,这个代码字体太丑了,一定要换下,不然代码都不工整~把这么帅的代码都搞丑了~

小生我怕怕 发表于 2009-5-10 22:11

强大,好文啊,一定要好好学习下!

open5858 发表于 2009-5-10 23:29

學習的不夠只看懂前面一小段
感謝樓主分享,要再努力學習才行

什么也不是 发表于 2009-5-11 09:39

{:299_843:}
   在 一蓑 已目睹大牛风采了...再次膜拜

cokago 发表于 2009-5-11 23:00

没仔细看,留个帖子,下回看!
谢谢作者的帖子!
页: [1] 2 3 4 5
查看完整版本: VMProtect1.8主程序脱壳分析