首页
社区
课程
招聘
[转帖]VMProtect, Part 0: Basics 作者: RolfRolles
发表于: 2011-9-10 18:23 6823

[转帖]VMProtect, Part 0: Basics 作者: RolfRolles

2011-9-10 18:23
6823
看完这段基本上能了解VMP的工作方式了
VMProtect is a virtualization protector.  Like other protections in the genre, among others ReWolf's x86 Virtualizer and CodeVirtualizer, it works by disassembling the x86 bytecode of the target executable and compiling it into a proprietary, polymorphic bytecode which is executed in a custom interpreter at run-time.  This is unlike the traditional notions of packing, in which the x86 bytecode is simply encrypted and/or compressed:  with virtualization, the original x86 bytecode in the protected areas is gone, never to be seen again.  Or so the idea goes.

If you've never looked at VMProtect before, I encourage you to take a five-minute look in IDA (here's a sample packed binary).  As far as VMs go, it is particularly skeletal and easily comprehended.  The difficulty lies in recreating working x86 bytecode from the VM bytecode.  Here's a two-minute analysis of its dispatcher.

  push  edi                        ; push all registers
  push  ecx
  push  edx
  push  esi
  push  ebp
  push  ebx
  push  eax
  push  edx
  pushf
  push  0                          ; imagebase fixup
  mov   esi, [esp+8+arg_0]         ; esi = pointer to VM bytecode
  mov   ebp, esp                   ; ebp = VM's "stack" pointer
  sub   esp, 0C0h
  mov   edi, esp                   ; edi = "scratch" data area

VM__FOLLOW__Update:
  add   esi, [ebp+0]

VM__FOLLOW__Regular:
  mov   al, [esi]                  ; read a byte from EIP
  movzx eax, al
  sub   esi, -1                    ; increment EIP
  jmp   ds:VM__HandlerTable[eax*4] ; execute instruction handler

A feature worth discussing is the "scratch space", referenced by the register edi throughout the dispatch loop.  This is a 16-dword-sized area on the stack where VMProtect saves the registers upon entering the VM, modifies them throughout the course of a basic block, and from whence it restores the registers upon exit.  For each basic block protected by the VM, the layout of the registers in the scratch space can potentially be different.

Here's a disassembly of some instruction handlers.  Notice that A) VMProtect is a stack machine and that B) each handler -- though consisting of scant few instructions -- performs several tasks, e.g. popping several values, performing multiple operations, pushing one or more values.

#00:  x = [EIP-1] & 0x3C; y = popd; [edi+x] = y

.text:00427251   and   al, 3Ch        ; al = instruction number
.text:00427254   mov   edx, [ebp+0]   ; grab a dword off the stack
.text:00427257   add   ebp, 4         ; pop the stack
.text:0042725A   mov   [edi+eax], edx ; store the dword in the scratch space

#01:  x = [EIP-1] & 0x3C; y = [edi+x]; pushd y

.vmp0:0046B0EB   and   al, 3Ch        ; al = instruction number
.vmp0:0046B0EE   mov   edx, [edi+eax] ; grab a dword out of the scratch space
.vmp0:0046B0F1   sub   ebp, 4         ; subtract 4 from the stack pointer
.vmp0:0046B0F4   mov   [ebp+0], edx   ; push the dword onto the stack

#02:  x = popw, y = popw, z = x + y, pushw z, pushf

.text:004271FB   mov   ax, [ebp+0]       ; pop a word off the stack
.text:004271FF   sub   ebp, 2
.text:00427202   add   [ebp+4], ax       ; add it to another word on the stack
.text:00427206   pushf               
.text:00427207   pop   dword ptr [ebp+0] ; push the flags

#03:  x = [EIP++]; w = popw; [edi+x] = Byte(w)

.vmp0:0046B02A   movzx eax, byte ptr [esi] ; read a byte from EIP
.vmp0:0046B02D   mov   dx, [ebp+0]         ; pop a word off the stack
.vmp0:0046B031   inc   esi                 ; EIP++
.vmp0:0046B032   add   ebp, 2              ; adjust stack pointer
.vmp0:0046B035   mov   [edi+eax], dl       ; write a byte into the scratch area

#04:  x = popd, y = popw, z = x << y, pushd z, pushf

.vmp0:0046B095   mov   eax, [ebp+0]      ; pop a dword off the stack
.vmp0:0046B098   mov   cl, [ebp+4]       ; pop a word off the stack
.vmp0:0046B09B   sub   ebp, 2
.vmp0:0046B09E   shr   eax, cl           ; shr the dword by the word
.vmp0:0046B0A0   mov   [ebp+4], eax      ; push the result
.vmp0:0046B0A3   pushf
.vmp0:0046B0A4   pop   dword ptr [ebp+0] ; push the flags

#05:  x = popd, pushd ss:[x]

.vmp0:0046B5F7   mov   eax, [ebp+0]  ; pop a dword off the stack
.vmp0:0046B5FA   mov   eax, ss:[eax] ; read a dword from ss
.vmp0:0046B5FD   mov   [ebp+0], eax  ; push that dword

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
英文看不懂,从代码可以看出是较早版本的方式了,其实现在一样,不过加多了点垃圾,

至于模拟的整体原理一直没变,或者换了个方式表达
2011-9-10 23:55
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
支持邓韬:)
2011-9-11 00:50
0
雪    币: 1981
活跃值: (771)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
4
神奇的vmp1.2
2011-9-11 09:11
0
雪    币: 220
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
呵呵 确实老版本了
2011-9-11 09:41
0
游客
登录 | 注册 方可回帖
返回
//