目录
概述
结构
- vm_context(vm寄存器)
- vm_stack(vm栈)
- vm_instructions(vm指令)
流程
- vm_entry
- vm_context_init
- vm_handle
- vm_stack_restore
- vm_exit
分析
vm_entry
#保存寄存器值到vmstack
0000 | 00411D37 | 68 E49B4100 | push 419BE4 | eax: 41E029-> 41E029 ebx: | 0019FD2C: 411D35-> 419BE4 |
0001 | 00411D3C | E9 B3990700 | jmp 48B6F4 | | |
0002 | 0048B6F4 | 68 2DBA3A0F | push F3ABA2D | esp: 19FD2C-> 19FD28 | 0019FD28: 19FE08-> F3ABA2D |
0003 | 0048B6F9 | E8 5E4BFEFF | call 47025C | esp: 19FD28-> 19FD24 | 0019FD24: 41E029-> 48B6FE |
0004 | 0047025C | 57 | push edi | esp: 19FD24-> 19FD20 | 0019FD20: 41E029-> 19FE08 |
0006 | 00470260 | 51 | push ecx | esp: 19FD20-> 19FD1C | 0019FD1C: 5C0074-> 41E029 |
0008 | 00470263 | 53 | push ebx | esp: 19FD1C-> 19FD18 | 0019FD18: 730065-> 288000 |
000A | 00470267 | 56 | push esi | esp: 19FD18-> 19FD14 | 0019FD14: 74006D-> 19FD30 |
000B | 00470268 | 9C | pushfd | esp: 19FD14-> 19FD10 | 0019FD10: 76005C-> 246 |
000F | 00470272 | 52 | push edx | esp: 19FD10-> 19FD0C | 0019FD0C: 740063-> 1 |
0012 | 00470277 | 55 | push ebp | esp: 19FD0C-> 19FD08 | 0019FD08: 65006A-> 19FE08 |
0016 | 00470281 | 50 | push eax | esp: 19FD08-> 19FD04 | 0019FD04: 6F0072-> 41E029 |
0018 | 00470286 | B8 00000000 | mov eax,0 | eax: 410029-> 0 | |
001C | 00470296 | 50 | push eax | esp: 19FD04-> 19FD00 | 0019FD00: 70005F-> 0 |
------------------------------------------------------------------------------------
push 0 0019FD00 $ ==> 00000000 ....
push eax $+4 0041E029 )àA. vmtest.vmp._311FB91F_vmtest@cpp
push ebp $+8 0019FE08 .þ..
push edx $+C 00000001 ....
pushf $+10 00000246 F...
push esi $+14 0019FD30 0ý..
push ebx $+18 00356000 .`5. .PEB.InheritedAddressSpace
push ecx $+1C 0041E029 )àA. vmtest.vmp._311FB91F_vmtest@cpp
push edi $+20 0019FE08 .þ..
call_retaddr $+24 0048B6FE þ¶H. 返回到 vmtest.vmp.__guard_xfg_check_icall_fptr+6C6FA 自 vmtest.vmp.__guard_xfg_check_icall_fptr+51258
push vm_key $+28 0F3ABA2D -º:.
------------------------------------------------------------------------------------
#获取vm_key(解密后续vm_instructions)
0020 | 004702A2 | 8B7C24 28 | mov edi,dword ptr ss:[esp+28] | edi: EB003385-> F3ABA2D | 0019FD28: F3ABA2D-> F3ABA2D |
0022 | 004702A9 | 81EF 8530A157 | sub edi,57A13085 | edi: F3ABA2D-> B79989A8 | |
0023 | 004702AF | C1C7 03 | rol edi,3 | edi: B79989A8-> BCCC4D45 | |
0027 | 004702BF | 81C7 5810F37A | add edi,7AF31058 | edi: BCCC4D45-> 37BF5D9D | |
002B | 004702D0 | C1CF 03 | ror edi,3 | edi: 37BF5D9D-> A6F7EBB3 | |
002E | 004702DB | 8DBF DA42BE58 | lea edi,dword ptr ds:[edi+58BE42D | edi: A6F7EBB3-> FFB62E8D | |
0030 | 004702E4 | F7D7 | not edi | edi: FFB62E8D-> 49D172 | |
0034 | 004702F2 | 03F8 | add edi,eax | | |
#ebp作为vsp(虚拟机栈顶指针)
0038 | 004702FE | 8BEC | mov ebp,esp | ebp: DA9EADF-> 19FD00 | |
#esp作为vm_context指针
003C | 0047030A | 81EC C0000000 | sub esp,C0 | esp: 19FD00-> 19FC40 | |
#ebx存储vm_key值
0040 | 00470315 | 8BDF | mov ebx,edi | ebx: 32015A85-> 49D172 |
#esi作为vm_ip
0045 | 00470322 | 8D35 22034700 | lea esi,dword ptr ds:[470322] | esi: 6000022A-> 470322 | |
#edi作为vm_instructions指针,eax解密下一handle偏移
0047 | 0047032A | 8B07 | mov eax,dword ptr ds:[edi] | eax: FFFFFFFF-> 5660CB14 | 0049D172: 5660CB14-> 5660CB14 |
0049 | 00470332 | 8DBF 04000000 | lea edi,dword ptr ds:[edi+4] | edi: 49D172-> 49D176 | |
004A | 00470338 | 33C3 | xor eax,ebx | eax: 5660CB14-> 56291A66 | |
004C | 0048D742 | 48 | dec eax | eax: 56291A66-> 56291A65 | |
004F | 0048D74B | F7D0 | not eax | eax: 56291A65-> A9D6E59A | |
0051 | 0048D74E | 35 760E2B56 | xor eax,562B0E76 | eax: A9D6E59A-> FFFDEBEC | |
0053 | 004903F3 | F7D0 | not eax | eax: FFFDEBEC-> 21413 | |
0055 | 0048DFA3 | 48 | dec eax | eax: 21413-> 21412 | |
#ebx->vm_key更新
0057 | 0048DFA7 | 33D8 | xor ebx,eax | ebx: 49D172-> 4BC560 |
#vmhandle 跳转 |
005A | 0048DFB0 | 03F0 | add esi,eax | esi: 470322-> 491734 | |
005C | 00445E43 | FFE6 | jmp esi | |
vm_context_init
重复vpop vm[x],将vm_stack栈上保存的初始寄存器值保存到vm_context
#取vm_stack栈顶元素
005D | 00491734 | 8B5425 00 | mov edx,dword ptr ss:[ebp] | edx: 1-> 0 | 0019FD00: 0-> 0
#ebp+4 vm_stack减小
0060 | 0049173E | 81C5 04000000 | add ebp,4 | ebp: 19FD00-> 19FD04 | |
0064 | 0049174F | 0FB60F | movzx ecx,byte ptr ds:[edi] | ecx: 417C06-> BB | 0049D176: 2D77C5BB-> 2D77C5BB |
0067 | 0049175D | 81C7 01000000 | add edi,1 | edi: 49D176-> 49D177 | |
0068 | 00491763 | 32CB | xor cl,bl | ecx: BB-> DB | |
006B | 004A5868 | F6D1 | not cl | ecx: DB-> 24 | |
006D | 004A586B | D0C9 | ror cl,1 | ecx: 24-> 12 | |
006E | 004A586D | F6D1 | not cl | ecx: 12-> ED | |
006F | 004A586F | 80F1 C9 | xor cl,C9 | ecx: ED-> 24 | |
0071 | 004A5875 | 32D9 | xor bl,cl | ebx: 4BC560-> 4BC544 |
#将原vm栈顶值存储到vm_context
0073 | 004A587C | 89140C | mov dword ptr ss:[esp+ecx],edx | | 0019FC64: 0-> 0 |
#ebx->vm 下一个handle offset的加密数据
0077 | 004A588A | 8B17 | mov edx,dword ptr ds:[edi] | edx: 2EE0-> 962D77C5 | 0049D177: 962D77C5-> 962D77C5 |
#vm_instructions指向下一vm指令数据
007A | 004695D6 | 81C7 04000000 | add edi,4 | edi: 49D177-> 49D17B | |
007C | 00460CA5 | 33D3 | xor edx,ebx | edx: 962D77C5-> 9666B281 | |
007E | 0045BE64 | 81F2 7E4D7067 | xor edx,67704D7E | edx: 9666B281-> F116FFFF | |
007F | 0045BE6A | C1C2 03 | rol edx,3 | edx: F116FFFF-> 88B7FFFF | |
0081 | 0047BFB5 | 0FCA | bswap edx | edx: 88B7FFFF-> FFFFB788 | |
0083 | 00444FA0 | 4A | dec edx | edx: FFFFB788-> FFFFB787 | |
#更新ebx->vm_key
0085 | 00444FA2 | 33DA | xor ebx,edx | ebx: 4BC544-> FFB472C3 | |
0086 | 00444FA4 | 03F2 | add esi,edx | esi: 491734-> 48CEBB | |
0087 | 00444FA6 | E9 0E7AFFFF | jmp 43C9B9 | | |
0088 | 0043C9B9 | FFE6 | jmp esi | |
--------------------------------------------------------------------------
Vpop +24h 0;
Vpop +3ch eax;
Vpop +14h ebp;
Vpop +30h edx;
Vpop +4h eflags;
Vpop +1ch esi;
Vpop +0 ebx;
Vpop +8h ecx;
Vpop +10h edi;
//context init over
//stack
struct VM_Context
{
+24h 0;
+3ch eax;
+14h ebp;
+30h edx;
+4h eflags;
+1ch esi;
+0 ebx;
+8h ecx;
+10h edi;
};
struct vm_stack{
//push 0 0019FD00 $ ==> 00000000 ....
//push eax $+4 0041E029 )àA. vmtest.vmp._311FB91F_vmtest@cpp
//push ebp $+8 0019FE08 .þ..
//push edx $+C 00000001 ....
//pushf $+10 00000246 F...
//push esi $+14 0019FD30 0ý..
//push ebx $+18 00356000 .`5. .PEB.InheritedAddressSpace
//push ecx $+1C 0041E029 )àA. vmtest.vmp._311FB91F_vmtest@cpp
*vsp* //push edi $+20 0019FE08 .þ..
//call_retaddr $+24 0048B6FE þ¶H. 返回到 vmtest.vmp.__guard_xfg_check_icall_fptr+6C6FA
//push vm_key $+28 0F3ABA2D -º:.
}
------------------------------------------------------------------------------------
vm_handle
;一般而言,edi表示vm_instructions指针
; ebx表示vm_key
;而vsp、vip值则要根据vm_entry来判断
;这里ebp表示vsp,指向vm_stack栈顶,
#vpush imm4
sub ebp,4; lea ebp,[ebp-4]
mov [ebp+0],xxx
#vpush vm[x]
sub ebp 4;lea ebp,[ebp-4]
mov R,VM[X]
mov [ebp],R
;vpush 指令中会有check_vsp操作
#check_vsp
lea eax,dword ptr ss:[esp+60]
cmp ebp,eax
ja tonext_handle
#vpop vm[x]
mov R,[ebp]
add ebp 4;lea ebp,[ebp84]
mov VM[X],R
;lvsp 类似mov ebp [ebp]操作
;vpushvsp
;vadd 表示vmstack[0],vmstack[+4] 值相加,结果保存在vmstack[+4],eflags保存在vmstack[+4]
#vadd
mov r,[ebp]
add [ebp+4],r
pushfq
pop [ebp]-->ebp+0 eflag,+4 addresult
;通常操作结束后,后面紧跟vpop vm[x],将eflags保存到vmcontext[y]中,后面vsp则指向了上面的结果
;vmov 类似pop r1;pop r2; mov [r1],r2
#vmov
mov eax,dword ptr ds:[ebp]
mov edx,dword ptr ds:[ebp+4]
add ebp,8
mov dword ptr ss:[eax],edx
vm_stack_restore
Vpush vm[10h] 19FE08
Vpush vm[8] 41E029
Vpush vm[0] 288000
Vpush vm[1ch] 19FD30
Vpush vm[28h] 246
Vpush vm[30h] 1
Vpush vm[14h] 19FE08
Vpush vm[3ch] 41E029
vm_exit
vm_exit
0B83 | 004A40E7 | 8BE5 | mov esp,ebp | esp: 19FC40-> 19FD08 | |
0B85 | 004A40EF | 58 | pop eax | eax: 19FCA0-> 41E029 esp: | 0019FD08: 41E029-> 41E029 |
0B87 | 0045CAF3 | 5D | pop ebp | esp: 19FD0C-> 19FD10 ebp: | 0019FD0C: 19FE08-> 19FE08 |
0B89 | 0045CAF7 | 5A | pop edx | edx: 17001-> 1 esp: 19FD1 | 0019FD10: 1-> 1 |
0B8C | 0045CB00 | 9D | popfd | esp: 19FD14-> 19FD18 | 0019FD14: 246-> 246 |
0B8D | 0045CB01 | 5E | pop esi | esp: 19FD18-> 19FD1C esi: | 0019FD18: 19FD30-> 19FD30 |
0B8F | 00481248 | 5B | pop ebx | ebx: 48D200-> 288000 esp: | 0019FD1C: 288000-> 288000 |
0B91 | 0048124B | 59 | pop ecx | ecx: 559F253A-> 41E029 es | 0019FD20: 41E029-> 41E029 |
0B94 | 00481253 | 5F | pop edi | esp: 19FD24-> 19FD28 edi: | 0019FD24: 19FE08-> 19FE08 |
;ret
ret
举例
_RTC_CheckEsp()
;jnz short esperror
;retn
;vm_handle
vpop +20h ret 0048B6FE
vpop +34h key vm_bliock 0F3ABA2D
vpushvsp 19FD2C
vpush imm4 4
vadd --> 19FD30 ==19FD2C+4 vsp+4
vpop vm[c] eflag 216l
lvsp--mov ebp [ebp]to add_result—>ebp 19FD30
vpushvsp
vpush vm[1c] 19FD30
vpush vm[1c] 19FD30
not not and [ebp+4]FFE602CF
vpop vm[28h]->eflag FFB3332F
[ebp]FFE602CF,[ebp+4] 19FD30
vadd FFE602CF+ 19FD30== FFFFFFFF [ebp]eflag 286
vpop vm[38h] 286
vpushvsp
lvsp get FFFFFFFF
not not or [ebp+0] eflag [ebp+4] 0
vpop vm[20] eflag 246
vpop vm[34h]
vpush vm[38] 286
vpush imm4 815
not not or FFFFFFFB
vpop vm[28] 282
vpushvsp 19FD2C
lvsp ebp FFFFFFFB
not not or ->4
vpop vm[2ch] 202
vpush vm[20h] 246
vpush imm4 FFFFF7EA
not not or FFFFFDBD [ebp+4] eflag [ebp]
vpop vm[2ch] 286
vpushvsp 19FD28
lvsp [19FD28] FFFFFDBD
[ebp] FFFFFDBD [ebp+4] FFFFFDBD
not not or 242
[ebp]eflag 206
Vpop vm[34h] 206
Vadd ->242+4= 246
Vpop vm[18h] 202
Vpop vm[28h] 246
一系列操作其实就是个jcc
最终得到结果246d->eflags->11110110
ZF=1
JNZ不满足,不跳转,ret
add(1,5c)
push key 6860C86B
push retaddr 42AE36
push ebx 288000
push edx 1
push eax 41E029
push ecx 41E029
push ebp 19FE08
push edi 19FE08
pushfd->eflag 246
push esi 19FD30
push ecx 0
;ebx->vm_key
;edi->vm_ins
;ebp->vip
;esi->vsp
vpop vm[2ch] 0
vpop vm[18h] 19FD30
vpop vm[[ch] 246
vpop vm[28h] 19FE08
vpop vm[14h] 19FE08
vpop vm[8] 41E029
vpop vm[10h] 41E029
vpop vm[0] 1
vpop vm[1ch] 288000
vpop vm[3c] 42AE36
vpop vm[30h] 6860C86B
vpush vm[14h] 19FE08->orig_ebp
vpush imm4 c
vadd ch+ 19FE08= 19FE14
vpop vm[4] 216 eflag
vpush vm[14h] 19FE08—orig_ebp
vpush imm4 8
vadd 8+ 19FE08h= 19FE10
vpop vm[30h] 212 eflag
lvsp [19FE10]->1
vpop vm[3c] 1
lvsp [9FE14]->5c
vpush vm[3c] 1
vadd 1+5c=5d
vpop vm[30h] 202 eflag
vpop vm[4] 5d
vpush vm[4] 5d
vpush vm[14] 19FE08
vpush imm4 FFFFFFF8
vadd FFFFFFF8+ 19FE08
vpop vm[24h] eflag 217
vmov—> [19FE00] 5d
vpushvsp 19FD30
vpop vm[38h] 19FD30
vpush imm4 411D5A
vpush vm[2c] 0
vadd 0+ 411D5A
vpop vm[c] 206
vpush vm[1c] 288000
vpush vm[0] 1
vpush vm[4] 5d
vpush vm[8] 41E029
vpush vm[14h] 19FE08
vpush vm[28h] 19FE08
vpush vm[30h] 202
vpush vm[38h] 19FD30
pop esi
pop eflags
pop edi
pop ebp
pop ecx
pop eax
pop edx
pop ebx
ret
参考链接
VMProtect 2 - Detailed Analysis of the Virtual Machine Architecture
VMProtect 3.3.1虚拟机&代码混淆机制入门
VMProtect 3.09 虚拟机架构浅析