xchg2pwn

xchg2pwn


Entusiasta del reversing y desarrollo de exploits



HackTheBox

Questionnaire



Enumeración


Además de un host se nos proporciona un zip que al descomprimirlo nos deja 2 archivos, lo que parece ser un binario compilado para linux y su codigo en C

❯ ls
 test   test.c

❯ ./test
Enter payload here: test  

❯ cat test.c
#include <stdio.h>
#include <stdlib.h>

/*
This is not the challenge, just a template to answer the questions.  
To get the flag, answer the questions. 
There is no bug in the questionnaire.
*/

void gg(){
    system("cat flag.txt");
}

void vuln(){
    char buffer[0x20] = {0};
    fprintf(stdout, "\nEnter payload here: ");
    fgets(buffer, 0x100, stdin);
}

void main(){
    vuln();
}


0x1


Al conectarnos con netcat al host y puerto que se nos proporciona un texto explicando (que he omitido) y después nos pregunta si el binario es de 32 o 64 bits

❯ netcat 46.101.98.159 34192

This is a simple questionnaire to get started with the basics.

<----snip---->

[*] Question number 0x1:

Is this a '32-bit' or '64-bit' ELF? (e.g. 1337-bit)

>> 

Con el comando file podemos ver que es un ejecutable de linux para 64 bits

❯ file test
test: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5a83587fbda6ad7b1aeee2d59f027a882bf2a429, for GNU/Linux 3.2.0, not stripped  

Enviamos la respuesta como se nos muestra en la pregunta y nos dice que es correcta

[*] Question number 0x1:

Is this a '32-bit' or '64-bit' ELF? (e.g. 1337-bit)  

>> 64-bit

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x2


Nos devuelve una nueva pregunta, es si el linked del binario es dinamyc o static

[*] Question number 0x2:

What's the linking of the binary? (e.g. static, dynamic)  

>>

En el output del comando file, nos dice que es dinamyc asi que lo enviamos

[*] Question number 0x2:

What's the linking of the binary? (e.g. static, dynamic)  

>> dynamic

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x3


La siguiente pregunta que nos dan es si es un binario stripped o not stripped

[*] Question number 0x3:

Is the binary 'stripped' or 'not stripped'?  

>>

Nuevamente el output anterior del comando file nos da la respuesta, la enviamos

[*] Question number 0x3:

Is the binary 'stripped' or 'not stripped'?  

>> not stripped

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x4


La siguiente nos pregunta que protecciones tiene y nos muestra algunos ejemplos

[*] Question number 0x4:

Which protections are enabled (Canary, NX, PIE, Fortify)?  

>>

Esto podemos verlo con checksec, el binario tiene todas las protecciones desactivadas excepto NX, No Execute que evita la ejecución de shellcode

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

Enviamos la respuesta con la unica proteccion, nos devuelve que es correcta

[*] Question number 0x4:

Which protections are enabled (Canary, NX, PIE, Fortify)?  

>> NX

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x5


Nos muestra otro texto y nos lleva a la pregunta 5 la cual es el nombre de la función personalizada qu es vulnerable que se llama desde la función principal main()

<----snip---->

[*] Question number 0x5:

What is the name of the custom function that gets called inside `main()`? (e.g. vulnerable_function())  

>>

Si leemos el codigo .c podemos ver que el nombre la función que se llama es vuln()

void main(){  
    vuln();
}

Enviamos el nombre de la función y nuevamente se nos devuelve que es correcta

[*] Question number 0x5:

What is the name of the custom function that gets called inside `main()`? (e.g. vulnerable_function())  

>> vuln()

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x6


Ahora se nos pide ya sea en hex o decimal el valor del tamaño del buffer definido

[*] Question number 0x6:

What is the size of the 'buffer' (in hex or decimal)?  

>>

En el codigo c vemos que el tamaño es 0x20 o 32 bytes si lo pasamos a decimal

void vuln(){
    char buffer[0x20] = {0};
    fprintf(stdout, "\nEnter payload here: ");  
    fgets(buffer, 0x100, stdin);
}

Podemos enviar los valores 0x20 o 32 ambos deberian devolvernos que es correcto

[*] Question number 0x6:

What is the size of the 'buffer' (in hex or decimal)?

>> 0x20

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x7


Ahora se nos pregunta cual es la función que nunca se llama nos muestra el ejemplo

[*] Question number 0x7:

Which custom function is never called? (e.g. vuln())  

>>

En el codigo c podemos ver que podemos ver que esta es la función llamada gg()

void gg(){
    system("cat flag.txt");  
}

Enviamos el nombre de la función como respuesta y nos devuelve que es correcta

[*] Question number 0x7:

Which custom function is never called? (e.g. vuln())  

>> gg()

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x8


Ahora nos pregunta cual es la funcion estándar que es vulnerable a Buffer Overflow

[*] Question number 0x8:

What is the name of the standard function that could trigger a Buffer Overflow? (e.g. fprintf())  

>>

La función vulnerable se encuentra en vuln() es fgets aunque hay otros como strcpy

void vuln(){
    char buffer[0x20] = {0};
    fprintf(stdout, "\nEnter payload here: ");  
    fgets(buffer, 0x100, stdin);
}

Enviamos el nombre de la función como el ejemplo y nos devuelve que es correcta

[*] Question number 0x8:

What is the name of the standard function that could trigger a Buffer Overflow? (e.g. fprintf())  

>> fgets()

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0x9


Ahora se nos pregunta la cantidad de bytes necesarios para corromper el programa

[*] Question number 0x9:

Insert 30, then 39, then 40 'A's in the program and see the output.

After how many bytes a Segmentation Fault occurs (in hex or decimal)?  

>>

Con ayuda de gdb con pwndbg instalado podemos crear un patron de 50 caracteres especialmente diseñados usando la función cyclic, una vez creado corremos el programa pasandole el input cuando lo pida y el programa corrompe

❯ gdb -q test
Reading symbols from test...
(No debugging symbols found in test)
pwndbg> cyclic 50
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaaga
pwndbg> run
Starting program: /home/kali/test
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".  

Enter payload here: aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaaga

Program received signal SIGSEGV, Segmentation fault.
0x00000000004011f9 in vuln ()
pwndbg>

Ahora buscamos el contenido de la dirección rsp y con cyclic -l buscamos el offset que nos dice son 40 bytes antes de que corrompa el programa

pwndbg> x/gx $rsp
0x7fffffffe578:	0x6161616161616166
pwndbg> cyclic -l 0x6161616161616166
Finding cyclic pattern of 8 bytes: b'faaaaaaa' (hex: 0x6661616161616161)  
Found at offset 40
pwndbg>

Simplemente enviamos como respuesta la cantidad de bytes, nos devuelve correcto

[*] Question number 0x9:

Insert 30, then 39, then 40 'A's in the program and see the output.

After how many bytes a Segmentation Fault occurs (in hex or decimal)?  

>> 40

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠  


0xa


Para la pregunta final se nos pregunta el valor de la dirección de la función gg()

[*] Question number 0xa:

What is the address of 'gg()' in hex? (e.g. 0x401337)  

>>

Nuevamente abrimos gdb y con la funcion propia print function podemos apuntar a la función gg y nos muestra su dirección que tiene el valor 0x401176

❯ gdb -q test
Reading symbols from test...
(No debugging symbols found in test)
pwndbg> print gg
$1 = {<text variable, no debug info>} 0x401176 <gg>  
pwndbg>

Al enviar la direccion nos dice que es correcto y finalmente se nos devuelve la flag

[*] Question number 0xa:

What is the address of 'gg()' in hex? (e.g. 0x401337)

>> 0x401176

♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠
♠                   ♠
♠      Correct      ♠
♠                   ♠
♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠ ♠

Great job! It's high time you solved your first challenge! Here is the flag!  

HTB{l34rn_th3_b451c5_b3f0r4_u_5t4rt}