吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 43092|回复: 214
收起左侧

[原创] [LCG]七夕浪漫分析之旅:VMProtect与VProtect的乱序小窥[整理版]

    [复制链接]
ps520 发表于 2011-8-3 21:13
本帖最后由 ps520 于 2011-8-3 21:15 编辑

废话开头:本来发了个娱乐贴,说老毛子的乱序和VP的乱序的事,文中只分析了VMP的乱序部分。
后来在群里聊起两个的乱序框架,发现确实有必要再发一个VP的乱序框架分析,供大家比较。于是有了UpK的两篇帖子。
发LCG的时候进行了一些整理,对文中一些娱乐文字进行了修改,对附件进行了整合,供大家参考。
VP的附件中,我说Vp的例子是作者用Demo No Nag加的,然后大家都懂的是吧……呵呵。
Opinion:只有乱序,其他全部取消。附件有3个,原名是原文件,其他的按后缀对应保护壳。
vp的实例采用了VProtect 2.0.7.0 正版乱序引擎

VMP的实例采用了VMProtect 2.0.8.0正版乱序引擎

向以上两位作者致敬!
                                                             ——ps520[LCG]

在分析两个附件以后,我小小地总结了一下。

VMP的乱序特色在于,尽管增加了10多kb的体积,但真正执行的代码量其实比较轻松,所以运行效率不错。
执行的时候基本无延迟感;比较有顺序,按照其流程依次执行,几乎没有大跳转绕圈的全套,花指令较多。

VP的特色在于,增加了30kb左右的体积,执行的垃圾代码较多。框架特色是花指令多,在花指令附近基本都会插有原来的命令,
除入口外,其他地方基本对应的是一个花指令对应一行指令。在各个花指令之间,用大跳转连接,并且有多次跳转的迷惑手段。
花指令也有比较悲剧的,在后面文中贴出的代码里你可以找到。

两个的特点不同,评价很难公正地给出,就交由各位自己跟踪时判断了。

我的理解是,乱序是一种高效率的代码保护手段,它的优势在于代码变形,花指令的引入,这样让整个代码的可读性降低,从而迷惑破解者。
而这种高效率是相对于VM而言的,所以其应有一定的强度,作为普通代码的保护手段,而算法等部分还应采用VM重点保护。
乱序,个人觉得LTT的扭曲变形是最接近于这个的要求的,代码变形强度之大让人汗颜,ChinaProtect作为当年的外挂壳名不虚传。

VMProtect分析笔记:
0040109D   $ /E9 00000000   jmp ddd_vmp.004010A2                     ;  原来判断事件的入口,push ebp
004010A2   > \9C            pushfd                                   ;  保存现场,下面有几行简单的处理,我的理解,跟原代码无关的都是花啊~~~
004010A3   .  66:0FBAE5 0D  bt bp,0xD
004010A8   .  F5            cmc
004010A9   .  53            push ebx
004010AA   .  876C24 04     xchg dword ptr ss:[esp+0x4],ebp
004010AE   .  66:0FA4DD 0A  shld bp,bx,0xA
004010B3   .  8D6C24 04     lea ebp,dword ptr ss:[esp+0x4]
004010B7   .  66:0FA3DF     bt di,bx
004010BB   .  83EC 04       sub esp,0x4
004010BE   .  60            pushad
004010BF   .  60            pushad
004010C0   .  E8 00000000   call ddd_vmp.004010C5                    ;  步入看看?
004010C5   [code]0040F276    6A 00           push 0x0
0040F278    89FB            mov ebx,edi
0040F27A    66:0FB6D9       movzx bx,cl
0040F27E    60              pushad
0040F27F    C74424 1C 00000>mov dword ptr ss:[esp+0x1C],0x0
0040F287    E8 17000000     call ddd_vmp.0040F2A3
0040F28C    8D6424 38       lea esp,dword ptr ss:[esp+0x38]
0040F290    E8 DB20FFFF     call ddd_vmp.00401370                    ; 执行原来的不成立call
0040F295    2F              das
0040F296    E8 2BFFFFFF     call ddd_vmp.0040F1C6
0040F29B    0F9DC4          setge ah
0040F29E    E8 43FFFFFF     call ddd_vmp.0040F1E6
884424 0C     mov byte ptr ss:[esp+0xC],al             ;  上面不步入到这里。。你懂的,这还算花。
004010C9   .  C745 FC 00000>mov dword ptr ss:[ebp-0x4],0x0
004010D0   .  FF7424 0C     push dword ptr ss:[esp+0xC]
004010D4   .  C74424 44 30A>mov dword ptr ss:[esp+0x44],ddd_vmp.0040>;  原始代码压栈,我怎么感觉VMP只复制了代码,没变形?
004010DC   .  50            push eax
004010DD   .  FF75 FC       push dword ptr ss:[ebp-0x4]
004010E0   .  8F4424 44     pop dword ptr ss:[esp+0x44]
004010E4   .  E9 00000000   jmp ddd_vmp.004010E9                     ;  这个也叫花指令,跳转的花指令。。增加美观度
004010E9   >  9C            pushfd
004010EA   .  8D6424 48     lea esp,dword ptr ss:[esp+0x48]
004010EE   .  E8 0DFFFFFF   call ddd_vmp.00401000                    ;  貌似是文本的处理?
004010F3   .  60            pushad
004010F4   .  F5            cmc
004010F5   .  60            pushad
004010F6   .  83C4 48       add esp,0x48
004010F9   .  F8            clc
004010FA   .  83F8 00       cmp eax,0x0
004010FD   .  E9 00000000   jmp ddd_vmp.00401102
00401102    - 0F85 EFE00000 jnz ddd_vmp.0040F1F7                     ;  你们猜这个跳转干嘛的。其实这里就是原来的跳转。
这里有跳转分支,分开讨论。

若不成立:
先0040F1F7   /E9 7A000000     jmp ddd_vmp.0040F276                     ; 假设没成立,就到这里了。这只是个跳板,执行变异部分在后面
然后,继续:
00401108   .  9C            pushfd
00401109   .  60            pushad
0040110A   .  60            pushad
0040110B   .  66:0FCB       bswap bx
0040110E   .  C74424 40 000>mov dword ptr ss:[esp+0x40],0x0
00401116   .  66:0FBED8     movsx bx,al
0040111A   .  F7D3          not ebx
0040111C   .  66:0FB6D8     movzx bx,al
00401120   .  C74424 3C 000>mov dword ptr ss:[esp+0x3C],0x0
00401128   .  E8 85E10000   call ddd_vmp.0040F2B2                    ;  这是一个神奇的call,除了花指令还有。。。
你们懂的,现在是秒了那个jnz。


00401102      90            nop                                      ;  你们猜这个跳转干嘛的。其实这里就是原来的跳转。
00401103      90            nop
00401104      90            nop
00401105      90            nop
00401106      90            nop
00401107      90            nop


NOP掉。[        DISCUZ_CODE_1        ]步入刚才那call。
0040F2B2    66:0FBEDA       movsx bx,dl                              ; 我说这些无聊代码能否无视?
0040F2B6    66:0FB6DB       movzx bx,bl
0040F2BA    C74424 3C 00000>mov dword ptr ss:[esp+0x3C],0x0
0040F2C2    88CB            mov bl,cl
0040F2C4  ^ E9 33FFFFFF     jmp ddd_vmp.0040F1FC                     ; 飞去执行成功代码
跟去看看
0040F1F7   /E9 7A000000     jmp ddd_vmp.0040F276                     ; 假设没成立,就到这里了
0040F1FC   |C6C7 F1         mov bh,0xF1                              ; 成功以后是飞到这里。对比一下,上面就是飞去错误的jmp
0040F1FF   |C74424 38 01030>mov dword ptr ss:[esp+0x38],0x80000301
0040F207   |5B              pop ebx
0040F208   |C74424 30 00000>mov dword ptr ss:[esp+0x30],0x0
0040F210   |66:0FBEDA       movsx bx,dl
0040F214   |C74424 2C 00000>mov dword ptr ss:[esp+0x2C],0x0
0040F21C   |F6D7            not bh
0040F21E   |5B              pop ebx
0040F21F   |C74424 24 04000>mov dword ptr ss:[esp+0x24],0x80000004
0040F227   |66:0FCB         bswap bx
0040F22A   |66:0FCB         bswap bx
0040F22D   |C74424 20 00000>mov dword ptr ss:[esp+0x20],0x0
0040F235   |66:0FBEDA       movsx bx,dl
0040F239   |5B              pop ebx
0040F23A   |5B              pop ebx
0040F23B   |0FB6DA          movzx ebx,dl
0040F23E   |C74424 14 34A24>mov dword ptr ss:[esp+0x14],ddd_vmp.0040>
0040F246   |66:0FCB         bswap bx
0040F249   |C74424 10 03000>mov dword ptr ss:[esp+0x10],0x3
0040F251   |5B              pop ebx
0040F252   |BB 00030000     mov ebx,0x300
0040F257   |52              push edx
0040F258   |8D6424 10       lea esp,dword ptr ss:[esp+0x10]
0040F25C   |E8 0F21FFFF     call ddd_vmp.00401370                    ; 注定又是一个神奇的call
到这里00401370   .  8B4424 10     mov eax,dword ptr ss:[esp+0x10]

F7下去就可以执行到成功的msgbox调用。

附件是这个的例程,包括原程序和VMP乱序保护后的程序。

总结一下:
貌似VMP对单一判断的乱序保护强度不是很高?(自大了。。。。其实是猜的)

乱序貌似只是对原来的代码插入了大量的花和无效执行,而并未对原有执行进行一些变形,比如把jnz变为结果取反后je

貌似为了执行效率起见,乱序并没有将所有垃圾代码跑完,而是用jmp很有技巧地跳转,减少了垃圾代码执行过程,但也降低了乱序的强度。(个人认为吧)

调试VMP乱序的小技巧:
爆破而言,你需要做的其实很简单,F7。一般而言,乱序开始部分的call还有有法跟的,不要漏了,对于jnz\je\ja这些远跳转做好F2断点。
这样就可以进行断点的猜解。比较不错。
这个方法的好处是,只要你进入了关键代码区,一般爆破都是可以成功的。。。。。


VProtect笔记:
其实VP的乱序有规律--Zenix

调试需要的是心境,不要急躁,要认真地去对待每一个F7,当然也不是死磕,也要用好F2和F4、F8(以下省略N个OD热键)。

以下是OD调试记录,VP的代码增加到了32K,执行时较VMP乱序保护有明显延迟感,那么它是如何构建整个乱序框架的呢?

你可以用VP DEMO只M一条线,比如我这个例子就是。

跟VMP的那个例子是一样的,所以很多细节不会赘述。

原始的入口在0040109D,所以在这里先断点,然后F9跑起来,执行到这里以后,发现同样也是个jmp(群众:不是JMP那该是神马!!!)

F7一下,就到这里了……
00410DD0    68 8D8C22F5     push 0xF5228C8D
00410DD5    9C              pushfd
00410DD6    814424 04 C37C1>add dword ptr ss:[esp+0x4],0xB1E7CC3
00410DDE    9D              popfd
00410DDF    C3              retn
童鞋,你觉得这个好看么。。。。好看?那你等着吧,你会碰见很多的……
ctrl+F8,到这里
0041094D    696420 68 DCCD0>imul esp,dword ptr ds:[eax+0x68],0xFA04C>
00410955    9C              pushfd
00410956    814424 04 446E3>add dword ptr ss:[esp+0x4],0x63C6E44
0041095E    9D              popfd
0041095F    C3              retn
继续……Ctrl+F8,跑啊跑~
00413C20    68 6A0D30AE     push 0xAE300D6A
00413C25    9C              pushfd
00413C26    814424 04 D63A1>add dword ptr ss:[esp+0x4],0x52113AD6
00413C2E    9D              popfd
00413C2F    C3              retn
貌似有4个这样的push|pushfd|add dword|popfd|retn
就可以到这里了:
0040F800    60              pushad
0040F801    9C              pushfd
0040F802    03C3            add eax,ebx
0040F804    9D              popfd
0040F805    61              popad
0040F806  ^ E9 65FBFFFF     jmp ddd_VP.0040F370
VP的特点在于,貌似是这样的。你会在2块地方被jmp远跳到处乱引,然后在一堆花中执行原代码。那么继续:
0040F800    60              pushad
0040F801    9C              pushfd
0040F802    03C3            add eax,ebx
0040F804    9D              popfd
0040F805    61              popad
0040F806  ^ E9 65FBFFFF     jmp ddd_VP.0040F370                      ; 这个飞跃只是个意外。
0040F367  ^\E9 94FEFFFF     jmp ddd_VP.0040F200
0040F36C    697F 71 3E55E91>imul edi,dword ptr ds:[edi+0x71],0x1AE95>
0040F373    0000            add byte ptr ds:[eax],al
0040F375    004E 43         add byte ptr ds:[esi+0x43],cl
0040F378    386D 3E         cmp byte ptr ss:[ebp+0x3E],ch
识别的问题,原来是个 jmp、。
0040F390    68 4CC940C4     push 0xC440C94C
0040F395    9C              pushfd
0040F396    814424 04 04290>add dword ptr ss:[esp+0x4],0x3C002904
0040F39E    9D              popfd
0040F39F    C3              retn
0040F250    50              push eax                                 ; 这里貌似执行了点原代码
0040F251    B8 04041818     mov eax,0x18180404
0040F256    58              pop eax
0040F257  ^ E9 34FFFFFF     jmp ddd_VP.0040F190
0040F18C    EA 21B17F9C 535>jmp far 5B53:9C7FB121
0040F193    9D              popfd
0040F194    8BEC            mov ebp,esp
0040F191    53              push ebx
0040F192    5B              pop ebx
0040F193    9D              popfd
0040F194    8BEC            mov ebp,esp
0040F196    E9 15010000     jmp ddd_VP.0040F2B0
貌似又在悄悄地原代码了
0040F2B6  ^\E9 75FEFFFF     jmp ddd_VP.0040F130  飞跃无处不在
0040F130   /E9 CB010000     jmp ddd_VP.0040F300
但你又跳开就是不对了。
0040F2FD    6B4D 24 60      imul ecx,dword ptr ss:[ebp+0x24],0x60
0040F301    90              nop
0040F302    61              popad
0040F303    C745 FC 0000000>mov dword ptr ss:[ebp-0x4],0x0
0040F30A  ^ E9 21FDFFFF     jmp ddd_VP.0040F030
0040F210    9C              pushfd
0040F211    53              push ebx
0040F212    5B              pop ebx
0040F213    9D              popfd
0040F214    68 30A24000     push ddd_VP.0040A230                     ; ASCII "123"
0040F219  ^ E9 E2FDFFFF     jmp ddd_VP.0040F000
很明显又在偷偷执行原代码
0040F000    50              push eax                                 ; ddd_VP.0040114C
0040F001    8D0418          lea eax,dword ptr ds:[eax+ebx]
0040F004    58              pop eax
0040F005    FF75 FC         push dword ptr ss:[ebp-0x4]
0040F008    E9 73030000     jmp ddd_VP.0040F380
少贴点代码比较好。
在VMP中我们常见到的是call ,retn,在VP这里,漫天都是jmp啊……
0040F380    50              push eax                                 ; ddd_VP.0040114C
0040F381    8D0418          lea eax,dword ptr ds:[eax+ebx]
0040F384    58              pop eax
0040F385  ^ E9 F6FEFFFF     jmp ddd_VP.0040F280
0040F280    60              pushad
0040F281    90              nop
0040F282    61              popad
0040F283    E8 781DFFFF     call ddd_VP.00401000
半天遇到个call,进去看看。F7
00401000   .  8B5424 04     mov edx,dword ptr ss:[esp+0x4]
00401004   .  8B4C24 08     mov ecx,dword ptr ss:[esp+0x8]
00401008   .  85D2          test edx,edx
0040100A   .  75 0D         jnz Xddd_VP.00401019
0040100C   .  33C0          xor eax,eax
0040100E   .  85C9          test ecx,ecx
00401010   .  74 06         je Xddd_VP.00401018
00401012   .  8039 00       cmp byte ptr ds:[ecx],0x0
00401015   .  74 01         je Xddd_VP.00401018
00401017   .  48            dec eax
00401018   >  C3            retn
貌似是黑月的文本处理函数。。。忘鸟……
这里省略一些F7。。。。
0040F090    51              push ecx                                 ; ddd_VP.0040A230
0040F091    59              pop ecx
0040F092    0F85 38000000   jnz ddd_VP.0040F0D0                      ; 关键跳。。
飞了半天,终于到关键跳了,先让成立,我们去看看其他代码。
初步看了下,貌似是很乱的说。。但跟一会就会有个call,进去就是switch.那是黑月的一个特点。。。


nop掉jnz。继续:
0040F2E1    8D0418          lea eax,dword ptr ds:[eax+ebx]
0040F2E4    58              pop eax
0040F2E5    68 01030080     push 0x80000301                          ; 悄悄压栈参数。你懂的
0040F2EA  ^ E9 B1FFFFFF     jmp ddd_VP.0040F2A0
0040F3E2    03C3            add eax,ebx
0040F3E4    9D              popfd
0040F3E5    61              popad
0040F3E6    6A 00           push 0x0                                 ; 又一个参数被悄悄压栈了
0040F3E8  ^ E9 B3FFFFFF     jmp ddd_VP.0040F3A0
0040F3B0    51              push ecx                                 ; ddd_VP.0040A230
0040F3B1    59              pop ecx
0040F3B2    68 00000000     push 0x0
0040F3B7  ^ E9 A4FCFFFF     jmp ddd_VP.0040F060
0040F060    68 04000080     push 0x80000004
0040F065    E9 46010000     jmp ddd_VP.0040F1B0
参数4也到位了。
然后就是call鸟。。。

本文只是对整体的VP进行了简单的介绍,大家可以看到VP的一些特色。大家都懂的……




结尾说一句:该回复的回复,该加分的加分,七夕节礼物,希望送我个妹子。。

test.rar

105.36 KB, 下载次数: 162, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 8热心值 +8 收起 理由
heyanrong + 1 好东西
三页 + 1 好.学习了...
狐狸爱葡萄 + 1 恩,菜鸟看不懂,加分吧!
Smoke + 1 膜拜PS神牛~
fozhongren + 1 好东西
热火朝天 + 1 谢谢@Thanks!
missviola + 1 感谢您的分析,[吾爱破解]有你更精彩!
低调(d-iao) + 1 只能那么多 嘿嘿...

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

37566454 发表于 2011-8-3 21:18
呵呵 板凳拿来 学习啦~ 520大牛!
 楼主| ps520 发表于 2011-8-3 21:16
本帖最后由 ps520 于 2011-8-3 21:18 编辑

VP部分省略了很多代码,原因是都是些重复的花指令,没什么展示意义。比如call|retn类型和jmp到处飞的那种。

补充一下,由于明年就要高考了,所以上的时间少之又少,不能经常来LCG逛了。很抱歉哪~

VProtect作为中国新生代的保护壳,希望大家能够更多的接触,调试,对这款壳有更多的评价,促进中国保护壳的发展。


点评

人才啊  发表于 2011-8-5 13:30
xf3087 发表于 2011-8-3 21:24
ximo 发表于 2011-8-3 21:29
据说楼主最近很嚣张,要开除去冷静一下了。
Smoke 发表于 2011-8-3 21:29
{:1_912:}膜拜pS神牛~
低调(d-iao) 发表于 2011-8-3 21:35
个人认为VP乱序会比VMP好看些 至少加密结构会比较好掌握
把原代码一句一句的与JMP插一起 嘿嘿
 楼主| ps520 发表于 2011-8-3 21:59
低调(d-iao) 发表于 2011-8-3 21:35
个人认为VP乱序会比VMP好看些 至少加密结构会比较好掌握
把原代码一句一句的与JMP插一起 嘿嘿

正如Zenix所言,VP可能在乱序上更有规律些。所以觉得看起来更容易点。

 楼主| ps520 发表于 2011-8-3 22:00
本帖最后由 ps520 于 2011-8-3 22:00 编辑
ximo 发表于 2011-8-3 21:29
据说楼主最近很嚣张,要开除去冷静一下了。


据说细末哥最近更新Fixer不勤快,要被xx了~
低调(d-iao) 发表于 2011-8-3 22:03
ps520 发表于 2011-8-3 21:59
正如Zenix所言,VP可能在乱序上更有规律些。所以觉得看起来更容易点。

哈..至于VMP就像个穴位图 7经8脉处处通 过程都必经过大脑
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-18 04:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表