Datos del reto
| Campo | Valor |
|---|---|
| CTF | Taipanbyte CTF |
| Reto | Secret (Reversing) |
| Categoría | Reversing |
| Archivo | secret.tb |
| Flag | TB{reverse_engineering_is_cool} |
Descripción del reto
We found a binary that checks the flag. The program takes a string, does something with it, and tells you whether the flag is correct or not. Find the flag.
Reconocimiento
$ file secret.tb
secret.tb: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped
- Tipo: ejecutable ELF 64-bit, enlazado dinámicamente.
- Not stripped: hay símbolos (nombres de funciones), lo que facilita el análisis.
Con strings secret.tb aparecen, entre otras: Enter flag: , TB{reverse_engineering_is_cool}, Correct! Flag is , Wrong flag.. En los símbolos (nm): main, hex_decode. Con esto ya se puede sospechar que la flag es TB{reverse_engineering_is_cool}.
Análisis de la vulnerabilidad
Flujo del programa (desensamblado de main)
- Imprime
"Enter flag: "y lee una línea → input. - Construye un
std::stringdesde la constante en.rodata: "TB{reverse_engineering_is_cool}". - Primera transformación: cada carácter de esa constante →
c XOR 0x42→ string xored. - xored se convierte a hexadecimal (2 caracteres por byte) → hex_str.
hex_decode(hex_str)→ decoded (vuelve a ser la secuencia "xored").- Segunda transformación: cada byte de decoded →
byte XOR 0x42→ expected (vuelve a ser la constante). - Comparación:
input == expected. Si son iguales imprime "Correct! Flag is" y la flag; si no, "Wrong flag."
Es decir: expected = "TB{reverse_engineering_is_cool}" (la constante del binario). El programa compara la entrada del usuario con esa misma string. La flag está en texto plano en .rodata; el XOR y el hex son solo una vuelta innecesaria para la comparación final.
Dónde está la flag en el binario
La constante está en la sección .rodata, justo después de "Enter flag: ":
$ xxd -s 0x5010 -l 48 secret.tb
00005010: 666c 6167 3a20 0000 5442 7b72 6576 6572 flag: ..TB{rever
00005020: 7365 5f65 6e67 696e 6565 7269 6e67 5f69 se_engineering_i
00005030: 735f 636f 6f6c 7d00 2530 3278 0043 6f72 s_cool}.%02x.Cor
Función hex_decode
Toma un string en hex (pares 0-9a-fA-F), convierte cada par a un byte con strtol(..., 16) y concatena. Es la decodificación estándar de hexadecimal a bytes.
Explotación
Opción 1 – Enumeración rápida: strings secret.tb y localizar la cadena con formato de flag TB{...}.
Opción 2 – Comprobar con el binario:
chmod +x secret.tb
echo 'TB{reverse_engineering_is_cool}' | ./secret.tb
Salida esperada: Correct! Flag is TB{reverse_engineering_is_cool}
Flag
TB{reverse_engineering_is_cool}
Lecciones aprendidas
- Binarios not stripped exponen símbolos que facilitan el análisis.
- La flag puede estar en claro en
.rodata; transformaciones (XOR, hex) a veces solo ofuscan la comparación directa. - Herramientas:
file,strings,nm,objdump -d -M intel,objdump -s -j .rodata,xxd. Opcional: Ghidra o IDA.