我也想学 VMpwn
感谢南梦师傅博客 南梦爷爷博客
虚拟机保护的pwn
当我们 拿到 一个 虚拟机的 pwn的时候 先看看函数的逻辑
是很多 分支 或者说很多 switch 语句
这样 很大可能说明了 这很有可能是一个 虚拟机 或者是一个 解释器
vm 解释器的 基本认识
寄存器
PC
程序计数器,他存放的是一个内存地址,该地址中存放着 下一条 要执行的计算机指令SP
指针寄存器,永远指向当前栈顶。BP
基质指针。也是用于指向栈的某些位置,在调用函数的时候会用到它AX
通用寄存器,我们的虚拟机中,它用于存放一条指令执行后的结果
在程序中 PC
的初始值指向目标代码的 main
函数
指令集
虚拟机定义的时候 会定义一个 全局变量的 枚举类型 里面有我们需要的指令
如 :MOV
,ADD
之类的
通过例题学习
ciscn 2019 华东南 pwn Virtual
题目分析
刚开始的 malloc_all 里面会记录我们的 的输入 的不同段开始的地址 和 对应的 参数个数
例如:stack
在 store 函数中 有个 move 函数 会把我们的输入保存到我们 开始时创建的 对应chunk 中
- 首先输入
name
和instruction
- 让进入到主要函数 以
\n\r\t被分割
将我们 输入的instruction
分为一组一组的指令 - 分别根据 匹配到的指令将 对应的 值 放入
ptr
数组中 - 程序一共有
push
pop
add
sub
mul
div
load
save
这几个指令
分析得到这里是 给虚拟机 布置指令
void __fastcall ins_stack(__int64 some_data, char *ins)
{
int idx; // [rsp+18h] [rbp-18h]
int i; // [rsp+1Ch] [rbp-14h]
const char *part1; // [rsp+20h] [rbp-10h]
_QWORD *ptr; // [rsp+28h] [rbp-8h]
if ( some_data )
{
ptr = malloc_0(8LL * *(some_data + 8));
idx = 0;
for ( part1 = strtok(ins, delim); idx < *(some_data + 8) && part1; part1 = strtok(0LL, delim) )// \n\r\t被分割
//
{
if ( !strcmp(part1, "push") )
{
ptr[idx] = 0x11LL;
}
else if ( !strcmp(part1, "pop") )
{
ptr[idx] = 0x12LL;
}
else if ( !strcmp(part1, "add") )
{
ptr[idx] = 0x21LL;
}
else if ( !strcmp(part1, "sub") )
{
ptr[idx] = 0x22LL;
}
else if ( !strcmp(part1, "mul") )
{
ptr[idx] = 0x23LL;
}
else if ( !strcmp(part1, "div") )
{
ptr[idx] = 0x24LL;
}
else if ( !strcmp(part1, "load") )
{
ptr[idx] = 0x31LL;
}
else if ( !strcmp(part1, "save") )
{
ptr[idx] = 0x32LL;
}
else
{
ptr[idx] = '\xFF';
}
++idx;
}
for ( i = idx - 1; i >= 0 && mov(some_data, ptr[i]); --i )
;
free(ptr);
}
}
mov 函数
signed __int64 __fastcall mov(chunk *data, __int64 ptr)
{
int idx; // [rsp+1Ch] [rbp-4h]
if ( !data )
return 0LL;
idx = data->idx + 1;
if ( idx == data->size )
return 0LL;
*(data->section_ptr + 8LL * idx) = ptr;
data->idx = idx;
return 1LL;
}
- 然后会到另一个函数,给栈上布置参数
- 也是用
\n\r\t被分割
将我们的输入 然后保存在虚拟的栈上
```
点击收藏 | 1
关注 | 1