Método 1
Una vez descomprimido el zip
solo nos deja un compilado llamado license
Al ejecutarlo nos da a escoger entre (y/n)
enviamos y
, después nos pregunta una contraseña, nos dice que no esta oculta, si enviamos una incorrecta simplemente sale
❯ ./license
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: 123
Not even close!
Podemos analizarlo con ida
donde a la derecha podemos ver el codigo main en c
El codigo comprueba que hayamos introducido y
si es asi llama a la función exam()
int __fastcall main(int argc, const char **argv, const char **envp)
{
char input; // [rsp+Fh] [rbp-1h]
puts("So, you want to be a relic hunter?");
puts("First, you're going to need your license, and for that you need to pass the exam.");
puts("It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)");
input = getchar();
if ( input != 'y' && input != 'Y' && input != '\n' )
{
puts("Not many are...");
exit(-1);
}
exam("It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)", argv);
puts("Well done hunter - consider yourself certified!");
return 0;
}
Podemos ver exam
como todas las demas funciones igual que hicimos con el main
void exam()
{
char password3[8]; // [rsp+0h] [rbp-30h] BYREF
char password2[8]; // [rsp+1Ch] [rbp-14h] BYREF
char *password; // [rsp+28h] [rbp-8h]
password = (char *)readline("Okay, first, a warmup - what's the first password? This one's not even hidden: ");
if ( strcmp(password, "PasswordNumeroUno") )
{
puts("Not even close!");
exit(-1);
}
free(password);
*(_QWORD *)password2 = 0LL;
reverse(password2, t, 11LL);
password = (char *)readline("Getting harder - what's the second password? ");
if ( strcmp(password, password2) )
{
puts("You've got it all backwards...");
exit(-1);
}
free(password);
*(_QWORD *)password3 = 0LL;
xor(password3, &t2, 17LL, 19LL);
password = (char *)readline("Your final test - give me the third, and most protected, password: ");
if ( strcmp(password, password3) )
{
puts("Failed at the final hurdle!");
exit(-1);
}
free(password);
}
Para la primera contraseña muestra un mensaje con readline
y el input que recibe lo almacena en password
despues lo compara con la string PasswordNumeroUno
strcmp(password, "PasswordNumeroUno")
Podemos comprobarlo ejecutando el binario al enviar la contraseña que obtuvimos nos pide la segunda contraseña, quiere decir que esta es correcta
Okay, first, a warmup - what's the first password? This one's not even hidden: PasswordNumeroUno
Getting harder - what's the second password?
En la segunda contraseña lo que hace es usar la función reverse
pasandole como argumento t
que es el valor y 11
que es la longitud, despues almacena el resultado en password2
, despues recibe el input y lo compara con lo que vale
reverse(password2, t, 11LL);
strcmp(password, password2)
La variable t
no podemos verla en el c pero la vemos representada al hacer clic
Sabemos que le da la vuelta, asi que podemos hacer el proceso inverso con rev
❯ echo 0wTdr0wss4P | rev
P4ssw0rdTw0
De nuevo podemos comprobarla en el binario enviandola y recibiendo otro input
Getting harder - what's the second password? P4ssw0rdTw0
Your final test - give me the third, and most protected, password:
Para la contraseña 3 lo que hace es usar la función xor
usando 19
como key y 17 como longitud lo almacena el password3
despues lo compara con nuestro input
xor(password3, &t2, 17LL, 19LL);
strcmp(password, password3)
Para obtener t2
podemos ver sus valores en hexadecimal haciendo clic sobre el
En un script de python
definimos el valor de t2
y lo basamos a formato bytes
, despues hacemos el xor
usando 19
como clave y mostramos el resultado de ello
#!/usr/bin/python3
t2 = bytes.fromhex("477b7a6177527d77557a7d727f32323213")
key = 19
result = bytes([i ^ key for i in t2])
print(result.decode())
Al ejecutarlo nos muestra la contraseña que podemos comprobar en el binario
❯ python3 exploit.py
ThirdAndFinal!!!
Your final test - give me the third, and most protected, password: ThirdAndFinal!!!
Well done hunter - consider yourself certified!
Método 2
Otra forma es con gdb
haciendo breakpoints
en cada uno de los strcmp
para ver la comparación, para ver las direcciones donde lo llama usamos objdump
❯ objdump -d license | grep 'call.*strcmp'
4012ac: e8 af fd ff ff call 401060 <strcmp@plt>
401316: e8 45 fd ff ff call 401060 <strcmp@plt>
40138a: e8 d1 fc ff ff call 401060 <strcmp@plt>
Abrimos el programa con gdb
y definimos un breakpoints
en la primera llamada a strcmp
, corremos el programa enviando y
para seguir y cualquier contraseña
❯ gdb -q license
Reading symbols from license...
(No debugging symbols found in license)
pwndbg> break *0x4012ac
Breakpoint 1 at 0x4012ac
pwndbg> run
Starting program: /home/kali/license
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: password
Breakpoint 1, 0x00000000004012ac in exam ()
pwndbg>
Como nos detenemos en el breakpoint en el disasm
deberiamos ver la llamada a strcmp
con los argumentos que son nuestra contraseña y la que se espera
pwndbg> context disasm
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────[ DISASM / x86-64 / set emulate on ]───────────────────────
► 0x4012ac <exam+34> call strcmp@plt <strcmp@plt>
s1: 0x425770 ◂— 'password'
s2: 0x402170 ◂— 'PasswordNumeroUno'
0x4012b1 <exam+39> test eax, eax
0x4012b3 <exam+41> je exam+63 <exam+63>
0x4012b5 <exam+43> mov edi, 0x402182
0x4012ba <exam+48> call puts@plt <puts@plt>
0x4012bf <exam+53> mov edi, 0xffffffff
0x4012c4 <exam+58> call exit@plt <exit@plt>
──────────────────────────────────────────────────────────────────────────────────
pwndbg>
Hacemos lo mismo esta vez enviando la primera contraseña y asi vemos la segunda
❯ gdb -q license
Reading symbols from license...
(No debugging symbols found in license)
pwndbg> break *0x401316
Breakpoint 1 at 0x401316
pwndbg> run
Starting program: /home/kali/license
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: PasswordNumeroUno
Getting harder - what's the second password? password
Breakpoint 2, 0x0000000000401316 in exam ()
pwndbg> context disasm
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────[ DISASM / x86-64 / set emulate on ]───────────────────────
► 0x401316 <exam+140> call strcmp@plt <strcmp@plt>
s1: 0x424f90 ◂— 'password'
s2: 0x7fffffffe4ec ◂— 'P4ssw0rdTw0'
0x40131b <exam+145> test eax, eax
0x40131d <exam+147> je exam+169 <exam+169>
0x40131f <exam+149> mov edi, 0x4021c8
0x401324 <exam+154> call puts@plt <puts@plt>
0x401329 <exam+159> mov edi, 0xffffffff
0x40132e <exam+164> call exit@plt <exit@plt>
──────────────────────────────────────────────────────────────────────────────────
pwndbg>
Repetimos el mismo proceso y obtenemos la ultima contraseña ThirdAndFinal!!!
❯ gdb -q license
Reading symbols from license...
(No debugging symbols found in license)
pwndbg> break *0x40138a
Breakpoint 1 at 0x40138a
pwndbg> run
Starting program: /home/kali/license
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: PasswordNumeroUno
Getting harder - what's the second password? P4ssw0rdTw0
Your final test - give me the third, and most protected, password: password
Breakpoint 1, 0x000000000040138a in exam ()
pwndbg> context disasm
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────[ DISASM / x86-64 / set emulate on ]───────────────────────
► 0x40138a <exam+256> call strcmp@plt <strcmp@plt>
s1: 0x425770 ◂— 'password'
s2: 0x7fffffffe4d0 ◂— 'ThirdAndFinal!!!'
0x40138f <exam+261> test eax, eax
0x401391 <exam+263> je exam+285 <exam+285>
0x401393 <exam+265> mov edi, 0x40222c
0x401398 <exam+270> call puts@plt <puts@plt>
0x40139d <exam+275> mov edi, 0xffffffff
0x4013a2 <exam+280> call exit@plt <exit@plt>
──────────────────────────────────────────────────────────────────────────────────
Método 3
Los metodos anteriores son bastante bonitos y todo pero hay una forma mas facil con ltrace
filtrando por strcmp
enviamos el y
cuando nos pregunte la contraseña enviamos 123
, nos mostrara con el strcmp
la comparacion que hace, podemos ver la string que espera que es la primera contraseña PasswordNumeroUno
❯ ltrace -e strcmp ./license
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: 123
license->strcmp("123", "PasswordNumeroUno") = -31
Not even close!
+++ exited (status 255) +++
license->strcmp("123", "PasswordNumeroUno") = -31
Repetimos el proceso esta vez enviando la primera contraseña despues del y
, cuando nos pide la segunda enviamos nuevamente la string 123
, al enviarlo esto nos devolvera de nuevo el strcmp
pero ahora con la segunda contraseña P4ssw0rdTw0
❯ ltrace -e strcmp ./license
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: PasswordNumeroUno
license->strcmp("PasswordNumeroUno", "PasswordNumeroUno") = 0
Getting harder - what's the second password? 123
license->strcmp("123", "P4ssw0rdTw0") = -31
You've got it all backwards...
+++ exited (status 255) +++
De nuevo repetimos ahora enviando y
ademas de las 2 contraseñas, nos mostrara el strcmp
esta vez con la tercera contraseña que es la final ThirdAndFinal!!!
❯ ltrace -e strcmp ./license
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: PasswordNumeroUno
license->strcmp("PasswordNumeroUno", "PasswordNumeroUno") = 0
Getting harder - what's the second password? P4ssw0rdTw0
license->strcmp("P4ssw0rdTw0", "P4ssw0rdTw0") = 0
Your final test - give me the third, and most protected, password: 123
license->strcmp("123", "ThirdAndFinal!!!") = -35
Failed at the final hurdle!
+++ exited (status 255) +++
Enviamos todas las contraseñas, nos devuelve que nos consideremos certificados
❯ ./license
So, you want to be a relic hunter?
First, you're going to need your license, and for that you need to pass the exam.
It's short, but it's not for the faint of heart. Are you up to the challenge?! (y/n)
y
Okay, first, a warmup - what's the first password? This one's not even hidden: PasswordNumeroUno
Getting harder - what's the second password? P4ssw0rdTw0
Your final test - give me the third, and most protected, password: ThirdAndFinal!!!
Well done hunter - consider yourself certified!
Cuestionario
Nos conectamos con netcat
a el host proporcionado por hackthebox y al responder las preguntas de acuerdo a lo que explotamos se nos devuelve finalmente la flag
❯ netcat 165.141.104.69 30427
What is the file format of the executable?
> ELF
[+] Correct!
What is the CPU architecture of the executable?
> amd64
[+] Correct!
What library is used to read lines for user answers? (`ldd` may help)
> libreadline.so.8
[+] Correct!
What is the address of the `main` function?
> 0x401172
[+] Correct!
How many calls to `puts` are there in `main`? (using a decompiler may help)
> 5
[+] Correct!
What is the first password?
> PasswordNumeroUno
[+] Correct!
What is the reversed form of the second password?
> 0wTdr0wss4P
[+] Correct!
What is the real second password?
> P4ssw0rdTw0
[+] Correct!
What is the XOR key used to encode the third password?
> 19
[+] Correct!
What is the third password?
> ThirdAndFinal!!!
[+] Correct!
[+] Here is the flag: `HTB{l1c3ns3_4cquir3d-hunt1ng_t1m3!}`