初探VMProtect 3.x虚拟保护壳原理(学习中。。。) 您所在的位置:网站首页 Vmp脱壳OEP 初探VMProtect 3.x虚拟保护壳原理(学习中。。。)

初探VMProtect 3.x虚拟保护壳原理(学习中。。。)

2023-11-22 10:09| 来源: 网络整理| 查看: 265

本文应该算作个人学习VMP保护的笔记,所以内容较为空泛。详细的VMP虚拟保护壳的学习可以参考文末的参考资料。

0x01 外层壳保护

使用VMProtect保护后的程序添加了两个新节区

壳代码也是虚拟化过的

image-20211230185633948

寻找OEP的方法

通过对ZwProtectVirtualMemory下断,观察栈顶对代码节下硬件执行断点(感觉略鸡肋,得知道原始函数在大致哪个范围对mainCRTstartup内使用的一些API下断点(IsProcessorFeaturePresent, GetSystemTimeAsFileTime),然后回溯找到OEP

修复IAT表

虽然能看到程序使用了哪些API,却不能通过交叉引用来静态分析,因为VMP保护后的程序导入地址是运行时动态计算的

image-20211230211131287

参考源哥用Unicorn还原IAT表的文章

image-20211230213959428

mov ebx, offset byte_407DD1 mov ebx, [ebx+198694h] lea ebx, [ebx+44C25846h] xchg ebx, [esp+0] retn [407DD1 + 198694] + 44C25846 = IAT(MessageBoxW)

image-20211231104400935

0x02 代码混淆引擎

代码混淆引起所使用的指令都是不常见的指令,我们可以一眼就识别出来比如 rcr,bt,btc,sbb,lahf等。

image-20220102150822685

code2

block

0x03 虚拟化引擎

这一部分比较复杂,我主要参考的是这篇文章 ,以x86的VMP保护为讲解例子,如果启动了VMP加外层壳VMP的handle和混淆变异的代码会在.vmp1这个节区里,否则都在.vmp0节区。

进入虚拟机的标志是push uint32 加上 call function 跳转到.vmp1的节区进行操作,在大多数情况下这个call是不会返回的,更像是一个跳转。

img

其中这个push的32位数是虚拟opcode表起始位置加密后的值。

call进去后就开始依次执行每一个handle了,在每个handle里面都存在的大量的代码混淆阻碍逆向分析。

image-20220126212411013image-20220126213041291

原文中的例子 ====================================================================== 0x7ae901: mov ecx, dword ptr [esi] 0x7ae905: lea esi, [esi + 4] 0x7ae914: movzx eax, byte ptr [ebp] 0x83e3c2: lea ebp, [ebp + 1] 0x7d7bf8: mov dword ptr [esp + eax], ecx ... 0x8429bf: add edi, ecx 0x6d015e: jmp edi ====================================================================== 0x755912: mov ecx, dword ptr [esi] 0x75591a: lea esi, [esi + 4] 0x755925: movzx eax, byte ptr [ebp] 0x6c94c6: mov dword ptr [esp + eax], ecx 0x6c94d7: lea ebp, [ebp + 4] ... 0x79cdbd: add edi, ecx 0x79cdbf: push edi 0x79cdc0: ret ====================================================================== 0x7b821a: mov ecx, dword ptr [esi] 0x7b8222: lea esi, [esi + 4] 0x7b822b: movzx eax, byte ptr [ebp] 0x7b695c: mov dword ptr [esp + eax], ecx 0x7b6966: lea ebp, [ebp + 4] ... 0x7637cb: add edi, ecx 0x78cc6a: jmp edi

我们可以详细分析每个handle的实际作用,在这篇文章中较为详细的分析了VPUSH16 [VCTX + *] 这个handle具体实现方式

0x45bf82: VUNKNOWN: (VIP = esi, VSP = ebp) # update VIP to point on operand (current VIP is pointing on opcode offset) 0x45bf82: lea esi, [esi - 1] # get the ciphered operand (1 byte) 0x45bf8c: movzx eax, byte ptr [esi] # mutated operand decryption (keychain) # NOTE : ebx contain the rolling key 0x45bf94: xor al, bl 0x45bf99: ror al, 1 0x40a4fa: dec al 0x40a505: not al 0x40a507: dec al 0x40a514: xor bl, al # push a value into vm stack from vm context # eax = 8; VCTX[8] -> [VSP-2] = VPUSH R8 0x40a51a: movzx dx, byte ptr [esp + eax] 0x40a51f: sub ebp, 2 0x40a529: mov word ptr [ebp], dx # update VIP to the next ciphered opcode offset 0x40a531: lea esi, [esi - 4] # get next ciphered opcode offset 0x40a537: mov ecx, dword ptr [esi] # mutated next handle offset decryption routine (keychain) # NOTE : ebx contain the rolling key 0x40a53e: xor ecx, ebx 0x438108: sub ecx, 0x5eac74dd 0x43810e: cmc 0x43810f: not ecx 0x41743d: bswap ecx 0x41743f: rol ecx, 1 0x4513d8: neg ecx 0x4513da: stc 0x4513db: xor ebx, ecx # update absolute handle position with the next handle offset 0x4513e0: add edi, ecx # reset the next rolling key operand 0x4752b4: lea ecx, [esp + 0x60] # jump to the next handle 0x461417: push edi 0x461418: ret VM的体系结构

VIP和VSP是存储在一个随机的寄存器中(register base),下图为VMP 上下文的包含关系图。

img

一条指令由两部分组成,一个加密的handle偏移量和它加密后的参数(操作码和操作数)

img

某段VMP例程以一个VENTER指令开始,以一个VEXIT指令结束,以下为常见的VM指令。

VENTER, VEXIT, VADDU*, VNANDU*, VNORU*, VPUSHV, VPOPR, VPOPVSP, VPUSHVSP, VPUSHI* VFETCH*, VJUMP_*, VMOV*, VSHLU*, VSHRU*, VMULU*, VDIVU*, ....0x04 参考资料

关于unicorn去搞VMP的iat那点事

Quick look around VMP 3.x

VMP导入表修复

(VMProtect 分析)跟着ida和WinDbg逛VirtualMachine

VM保护攻防



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有