vm
# 虚拟化混淆
虚拟混淆手段整理。
这里整理下目前对于虚拟混淆的一些想法,
大多数的想法和思路来自ctf赛题和tigress挑战。
# vm
首先是vm本身开始说, 虚拟机的设计本身,牵扯到虚拟机本身对于opcode->handler的调度, 和虚拟机内部对于循环判断函数调用的调度。
# vm机器和应对思路
主要来说有寄存器机器和栈机器两类,
如果说手动编写反汇编脚本,然后一点点处理的话,两者的区别不太大,
如果使用miasm等符号执行/动态符号执行框架处理的话, 目前寄存器机器的反汇编脚本,直接把每个寄存器都设置为符号值, 处理起来会比较舒服, 栈机器目前我没学到啥手段。
但是两者都可以通过这些框架获取类似反编译脚本,也区别不算太大。
这是简单的虚拟机相关结构,
设置好的虚拟指令,opcode/bytecode的指令流, 虚拟栈, 虚拟pc指针,虚拟sp指针,
指令对应的解释器, 最上面的调度器,每个指令对应的handler,
details
简单说下两个机器区别在于对于运算的实现,比如1+2
寄存器机器:
regA = 1
regB = 2
regA += regB
2
3
栈机器:
push 1
push 2
add
2
3
其中的add是, 将栈顶两个值弹出,相加后结果压栈。
# 对vm的调度
对于opcode -> handler的映射关系。
一般比较常见的是while + switch组合的虚拟机, 在tigress-challenge中设置了六种对vm的调度。这里也简单笔记。
switch :
转换/分发, 最常见的方式, 一般opcode->handler会一对一,而且映射比较简单,
while (1){
switch (prog[pc]) {
opcode1:
handler1;
break;
opcode2:
handler2;
break;
.......
}
}
2
3
4
5
6
7
8
9
10
11
ifnest :
连续if-else, 这个类似switch的方式:
while (1) {
if (prog[pc]==op1)
handler1;
else if (prog[pc]==op2)
handler2;
else if …
}
2
3
4
5
6
7
direct :
直接跳转, 分成一个个小段, 然后运行最后直接跳转到下一个应该的handler去运行。
goto *prog[pc];
opcode1:
handler1;
goto *prog[pc];
opcode2:
handler2;
goto *prog[pc];
....
2
3
4
5
6
7
8
9
10
11
warning
对这个模式存在一些小疑惑,目前只是在tigress中看到相关思路, 但是没看到对应的实现。
indirect :
间接跳转, 比上个直接跳转增加了个表, 通过表进行跳转,这样的情况下,opcode->handler会因为表的原因打乱,也可能存在多对一情况。
goto *jtab[prog[pc]];
handler1;
goto *jtab[prog[pc]];
handler2;
goto *jtab[prog[pc]];
2
3
4
5
6
7
call :
情况每个handler设置一个函数,检索和函数调用的方式对opcode调用不同的函数,应该也是opcode->handler一对一映射,
void op1fun(){handler1}
void op2fun(){handler2}
.....
call *prog[pc]();
2
3
4
5
linear, binary, interpolation :
线性运算 插入值, 这里是在top做一个opcode->handler映射,然后跳转到对应handler运行,运行后跳转回到top继续。这种情况因为映射的关系,很容易造成多对一的情况,并且对应的位置比前面几个情况更难把握。
top:
goto *(searchalg(map,prog[pc]));
handler1;
goto top;
handler2;
goto top;
2
3
4
5
6
7
8
tip
tigress-challenge0-0就是这样的处理,应该是比较复杂的方式,
当时的反汇编脚本先写了对应的映射,然后又写对应handler。
# vm内的调度
vm内的调度主要是修正pc指针,实现跳转,通过跳转和比较实现if和for,
通过引入简单的帧等结构保存和修复, pc指针,虚拟栈,sp指针等,实现函数调用。
# 特殊手段
这些手段都是在tigress项目中看到的,其中的一些目前还不能理解,但有一些类似于普通的小混淆手段在vm中的表现, 在这里记录下。
# vm内的opcode自修改
每次调用进入vm都会修正一部分opcode然后返回,并在最后
# vm调度器的花指令
插入不透明谓词, 对调度器位置进行混淆。