CTF逆向专题连载之虚拟机vm混淆(1)

  • A+
所属分类:逆向工程


什么是虚拟机混淆?

在商业上,有一种叫做VMProtect的保护软件,通过利用伪指令虚拟机将指定代码进行变形和虚拟化处理后,达到隐藏关键代码的作用,具有很高的安全性。在阅读汇编代码时如同想把一本英文书翻译成中文书,却发现书里是法文写的。
而在CTF比赛中,出题人通过自己的伪指令实现小型虚拟机,达到混淆、增大题目难度的作用。它将基于x86汇编系统中的可执行代码转换为字节码指令系统的代码,来达到不被轻易逆向和篡改的目的。简单点说就是将程序的代码转换自定义的操作码(opcode),然后在程序执行时再通过解释这些操作码,选择对应的函数执行,从而实现程序原有的功能。

注:这类虚拟机跟VMware之类的虚拟机不是同种东西。


原理

CTF逆向专题连载之虚拟机vm混淆(1)

Start:虚拟机入口,完成虚拟机环境的初始化。 

Dispatcher:调度器,解释opcode,并选择对应的handle函数执行,当handle执行完后会跳回这里,形成一个循环。

Bytecode:字节码,可执行的代码所转换成的字节码。

执行流程:

在start完成虚拟机环境的初始化->读取可执行代码相对应的字节码->传到Dispatcher(调度器)->dispatcher根据接受到的bytecode选择handler进行执行,实现某个操作。


我们先从虚拟机的简单题目加深对虚拟机的理解。

WxyVM1

首先拖入ida中,查看main函数,F5

CTF逆向专题连载之虚拟机vm混淆(1)

之后我们进入关键函数sub_4005B6中

CTF逆向专题连载之虚拟机vm混淆(1)

可以看到如上图的结构,与前边的原理图可以对应上。


查看F5之后的代码


__int64 sub_4005B6(){  unsigned int v0; // ST04_4  __int64 result; // rax  signed int i; // [rsp+0h] [rbp-10h]  char v3; // [rsp+8h] [rbp-8h]
for ( i = 0; i <= 14999; i += 3 ) { v0 = byte_6010C0[i]; // 循环上每次加3,取到的值包括 1 2 3.用脚本取值,再用脚本判断这么多值里有哪些 发现是 123 v3 = byte_6010C0[i + 2]; result = v0; // 指示运算方式 switch ( v0 ) // v0决定操作方式 // result决定操作输入的哪一位 // v3决定操作的值 { case 1u: result = byte_6010C0[i + 1]; // 指示操作的哪一位 *(&input + result) += v3; // 指示运算数 break; case 2u: result = byte_6010C0[i + 1]; *(&input + result) -= v3; break; case 3u: result = byte_6010C0[i + 1]; *(&input + result) ^= v3; break; case 4u: result = byte_6010C0[i + 1]; *(&input + result) *= v3; break; case 5u: result = byte_6010C0[i + 1]; *(&input + result) ^= *(&input + byte_6010C0[i + 2]); break; default: continue; } } return result;}
由此可知:
1.vm题目在F5下有着switch case这样的语法;
2.计算是通过在byte_6010C0的数据进行计算的,因此我们可以直接通过idapython取到相应地址的值,直接进行计算。脚本如下:
str_list=[4294967236,52,34,4294967217,4294967251,17,4294967191,7,4294967259,55,4294967236,6,29,4294967292,91,4294967277,4294967192,4294967263,4294967188,4294967256,4294967219,4294967172,4294967244,8]addr = 0x6010C0for i in range(14997,-1,-3):    v0 = Byte(addr+i)    v3 = Byte(addr+i+2)    result = Byte(addr + i + 1) #     # result = v0    if v0 == 1:        str_list[result] -= v3    if v0 == 2:        str_list[result] += v3    if v0 == 3:        str_list[result] ^=v3
for i in range(len(str_list)): str_list[i] &= 0xff # 防溢出
print(''.join(map(chr, str_list)))


总结

  1. vm类题目有明显的特征:一般情况下,在F5下有while/switch case 这样的语法。

  2. 该题是简单的vm类题目,先通过该题了解一下vm题目的构造,以便在后边遇上vm类题目时可以分辨出题目类型。之后会有相应的vm题目考点以及解决办法的文章。


题目链接:

链接:https://pan.baidu.com/s/11OeT3TVC7ZJrlqi4PKqjwQ

提取码:9qcc

(题目出自南邮CTF练习平台)


本文始发于微信公众号(山石网科安全技术研究院):CTF逆向专题连载之虚拟机vm混淆(1)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: