本来只有一道heack,但似乎原版检查比较松弛导致大量非预期解,从而出现了heack_revenge抛去原版能够通过巧合的手段非预期解,本题的堆栈结合可以说是个很综合的题目首先检查elf的保护放入IDA中查看 可以看到是一个菜单题,其中第一个选项就可以看到栈溢出 我们可以观察到间接索引v4位于buf的高地址,可以被覆使用如下payload覆盖v4低字节,可以跳过canary直接修改返回地址payload=b'a'*0x103+p8(0x17)+p64(ret_addr)但是由于保护全开,我们还需要libc的地址观察game函数,发现有很多打印函数printf使用了%lu的格式化符号,所以可以假设通过将fight_dragon跳转到这些打印函数中将残留在寄存器中的libc地址打印出来 不巧的是二者有两个字节不一样,由于PIE遵循页对其机制,我们还需要爆破半个字节(1/16)当我们成功返回到printf时,观察gdb发现,rsi中正好有个libc地址 此时我们就得到了libc,再次溢出后构造ROP即可getshellelf的保护和逻辑没有变化,只是增加了栈溢出长度的限制(p8(xx))与溢出次数(1次)的限制 我们回头观察game函数中的奇怪的三个赋值操作 这使得text片段中出现了一些特定的机器码序列,我们可以通过这个联想到magic gadget:通过对text错位得到特殊功能的gadget我们在gdb中观察一下pop rbp算是附近最特殊的gadget,可以进行栈迁移,但是搞清这个gadget的具体作用我们还需要继续审计代码在case 5中,维护着一个堆块管理系统note_system(s);包含add,free和show操作,本身不存在漏洞,堆块管理数组位于game函数的栈帧内通过gdb或IDA观察可以发现堆块管理数组位于game函数栈帧的低地址处如果此时回到game后调用栈溢出函数,返回到pop rbp,我们就可以把rbp设置为堆地址,实现栈迁移 此时如果我们能在堆中写入ROP,再从game中返回就可以控制执行流 chunk[0]指向的地址会被设置为RBP,由于rbp被改变,最开始的chunk_list会改变,我们就无法直接操作原始chunk[0]如果我们可以溢出写比rbp低地址处的堆块,我们就最终可以控制RSP本题的重中之重便是 临时变量的地址是根据rbp决定的知道了这一点,原本game中看似无用的选项便可以称为改变,泄露heap中数值的工具经过简单的堆风水后我们便可以让unsortbins的fd指针与这几个栈变量重合,打印出libc地址同时我们还可以将chunk头的size域与v3重合,这样可以让某个堆块大小变大,再经过free与malloc操作即可实现堆溢出把ROP写到chunk[0]中此时我们可以看到,成功堆溢出,将ROP写到chunk[0]中 此时退出note_system,返回game便可以指向ROP [*] '/home/zer00ne/Desktop/New Folder/pwn'
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-287610.htm
[原创]L3CTF-2025:heack
209 浏览
0 回复
暂无回复,快来抢沙发吧!