AVILX

REVERSING WRITEUP · HACK THE BOX · 2026

Hunting License

Tres passwords: texto claro, reverse y XOR

PlataformaHack The Box
CategoríaReversing
DificultadVery Easy
Arquitecturax86-64 — Unix/Linux
AnalistaJesús Ávila (Avilx)
Fecha08 de Septiembre 2026
Portafolioavilx.dev
FLAG OBTENIDA REVERSING · ASSEMBLY · HTB · x86-64

Documentación de aprendizaje en reversing | Entorno controlado

Información del Binario

Campo Valor
Nombrelicense
TipoELF 64-bit LSB executable
Arquitecturax86-64
Enlazadodynamically linked
Strippednot stripped (70 símbolos)
Libreríalibreadline
Stack CanaryNo Canary Found
NXEnabled
PIEPIE Disabled
RELROPartial RELRO
Nota
Sin PIE las direcciones son fijas, facilitando el análisis con GDB. El binario usa libreadline para leer el input del usuario, identificable con ldd. Tiene 70 símbolos incluyendo las funciones main, exam, reverse y xor.

Reconocimiento

Análisis inicial

Strings

$ strings -a ./license | grep -v "^_Z\|GLIBC\|\.so\|\."

[Mensajes del programa]
So, you want to be a relic hunter?
Okay, first, a warmup - what's the first password?
This one's not even hidden:
PasswordNumeroUno
Not even close!
Getting harder - what's the second password?
Your final test - give me the third, and most protected, password:
Well done hunter - consider yourself certified!

[Strings sospechosos]
0wTdr0wss4P
G{zawR}wUz}r

[Funciones relevantes]
reverse
exam
main
strcmp
readline
Hallazgo
El primer password PasswordNumeroUno está en texto claro. Hay dos strings ofuscados: 0wTdr0wss4P y G{zawR}wUz}r. Existe una función reverse que sugiere que alguno de estos strings está invertido. El programa usa strcmp para comparar los passwords.

Ejecución inicial

$ ./license
So, you want to be a relic hunter?
...
Okay, first, a warmup - what's the first password?
This one's not even hidden: PasswordNumeroUno
Getting harder - what's the second password?
Hallazgo
El primer password se acepta directamente. El segundo no está visible en los strings. La función reverse probablemente invierte 0wTdr0wss4P para obtener el segundo password.

Análisis del Flujo

Password 1: texto claro

PasswordNumeroUno
Hallazgo
El primer password está hardcodeado en .rodata en texto claro, visible directamente con strings.

Password 2: función reverse()

$ python3 -c "print('0wTdr0wss4P'[::-1])"
P4ssw0rdTw0
Hallazgo
El string 0wTdr0wss4P invertido produce P4ssw0rdTw0. La función reverse() copia el string fuente al destino en orden inverso byte por byte.
Hallazgo
El segundo password es P4ssw0rdTw0, resultado de invertir 0wTdr0wss4P con la función reverse().

Password 3: XOR + GDB

El tercer password usa la función xor() con estos argumentos:

$ objdump -d -M intel ./license | grep -A 10 "call.*xor"

401353:  lea rax, [rbp-0x30]
401357:  mov ecx, 0x13          ; clave XOR = 0x13 = 19
40135c:  mov edx, 0x11          ; longitud
401361:  mov esi, 0x404070      ; fuente: G{zawR}wUz}r
401366:  mov rdi, rax           ; destino: [rbp-0x30]
401369:  call xor
Hallazgo
La clave XOR es 0x13 (valor de ecx), no 0x11 (que es la longitud en edx). Esta confusión fue un intento fallido inicial. El string cifrado G{zawR}wUz}r en 0x404070 se XORea con 0x13 y el resultado se guarda en [rbp-0x30].
Hipótesis
Se intentó decodificar manualmente con Python usando 0x11 como clave XOR pero el resultado VjkpfClfDklcn### no era un password válido. La clave correcta era 0x13.

Lectura del tercer password con GDB

    $ gdb -q ./license
    break *0x40136e
    run
    # Input: y, PasswordNumeroUno, P4ssw0rdTw0
    
    # En el stack despues del XOR:
    RSP → 'ThirdAndFinal!!!'
Hallazgo
Después de ejecutar la función xor(), pwndbg mostró el resultado directamente en el stack: ThirdAndFinal!!!. El registro RSP apuntaba al string ya descifrado antes de que el programa lo comparara con el input del usuario.
Hallazgo
El tercer password es ThirdAndFinal!!!, obtenido leyendo el stack con GDB después de la operación XOR con clave 0x13.

Conexión al Servidor

    $ nc 154.57.164.82 30540
    What is the file format of the executable?
    > ELF
    [+] Correct!
    
    What is the CPU architecture of the executable?
    > x86-64
    [+] Correct!
    
    What library is used to read lines for user answers?
    > libreadline
    [+] Correct!
    
    What is the address of the `main` function?
    > 0x401172
    [+] Correct!
    
    How many calls to `puts` are there in `main`?
    > 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?
    > 0x13
    [+] Correct!
    
    What is the third password?
    > ThirdAndFinal!!!
    [+] Correct!
    
    [+] Here is the flag: HTB{l1c3ns3_4cquir3d-hunt1ng_t1m3!}

Flag

HTB{l1c3ns3_4cquir3d-hunt1ng_t1m3!}
FLAG OBTENIDA

Reflexión Final

Qué salió bien

El reconocimiento inicial con strings identificó el primer password y los strings ofuscados. La función reverse() fue fácil de identificar por su nombre en los símbolos. El uso de GDB para leer el stack después del XOR fue la técnica más eficiente para obtener el tercer password.

Qué salió mal

La clave XOR se confundió inicialmente. El argumento edx = 0x11 es la longitud, no la clave. La clave es ecx = 0x13. Conocer el orden de los argumentos en la calling convention SysV AMD64 es crucial para no confundirlos.

También se intentó adivinar la flag en lugar de conectarse al servidor remoto, perdiendo tiempo innecesariamente.

Lecciones aprendidas

Este challenge enseñó tres niveles de ofuscación de passwords en un solo binario:

  1. Texto claro: visible directamente con strings

  2. Reverse: string invertido, recuperable con Python

  3. XOR: cifrado con clave, recuperable con GDB o Python

La diferencia entre los argumentos de una función en assembly es crítica. Siempre verificar cuál registro corresponde a cuál parámetro usando la calling convention SysV AMD64: RDI, RSI, RDX, RCX, R8, R9.

Tiempo total

Fase Tiempo
Reconocimiento inicial10 minutos
Password 1 y 210 minutos
Análisis XOR + GDB30 minutos
Conexión al servidor10 minutos
Total1 Hora