AVILX

REVERSING WRITEUP · HACK THE BOX · 2026

Behind the Scenes

Fragmentación de strings en .rodata — Anti-análisis estático

PlataformaHack The Box
CategoríaReversing
DificultadVery Easy
AnalistaJesús Ávila (Avilx)
Fecha10 de Octubre 2026
Portafolioavilx.dev
FLAG OBTENIDA REVERSING · ASSEMBLY · HTB · x86-64

Documentación de aprendizaje en reversing | Entorno controlado

Información del Binario

Campo Valor
Nombrebehindthescenes
TipoELF 64-bit LSB pie executable
Arquitecturax86-64
Enlazadodynamically linked
Strippednot stripped
BuildIDe60ae4c886619b869178148afd12d0a5428bfe18
Stack CanaryCanary Found
NXEnabled
PIEPIE Enabled
RELROFull RELRO
Nota
Este binario tiene las cuatro protecciones principales activas: canary, NX, PIE y Full RELRO. Al ser not stripped, los símbolos de funciones permanecen visibles en objdump y GDB. Esto no es relevante para la solución, pero es parte del flujo estándar de reconocimiento. Entre los símbolos aparece segill_sigaction, lo que indica que el binario instala un signal handler — probablemente para dificultar el debugging dinámico con GDB.

Reconocimiento

Análisis inicial

strings

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

strncmp
strlen
sigemptyset
sigaction
> HTB{%s}
segill_sigaction
main
Hallazgo
El comando strings no reveló ningún password. Sí apareció el formato de salida > HTB{%s}, lo que confirma que el binario construye la flag con printf a partir de lo que ingresemos. También aparecen sigemptyset y sigaction, funciones para instalar signal handlers — una técnica común para complicar el análisis dinámico. La ausencia del password en strings es intencional.

Ejecución inicial

$ ./behindthescenes
./challenge <password>
Hallazgo
El binario espera un argumento posicional. No hay prompt interactivo; el password se pasa directamente en la línea de comandos como ./behindthescenes <password>.

Inspección de .rodata

Al no aparecer el password con strings, el siguiente paso fue inspeccionar directamente la sección .rodata en hexadecimal:

$ objdump -s -j .rodata ./behindthescenes

Contents of section .rodata:
2000 01000200 2e2f6368 616c6c65 6e676520  ...../challenge
2010 3c706173 73776f72 643e0049 747a005f  <password>.Itz._
2020 306e004c 795f0055 4432003e 20485442  0n.Ly_.UD2.> HTB
2030 7b25737d 0a00                        {%s}..

La clave para leer este dump está en entender la columna ASCII del lado derecho. En C, todo string termina con el byte 0x00. Ese byte no tiene representación imprimible, por lo que objdump lo muestra como un punto . en la columna derecha. Cada punto es un delimitador entre un string y el siguiente.

Leyendo la columna ASCII con los puntos como separadores:

Offset String Observación
0x2008./challenge <password>Mensaje de uso
0x2018ItzFragmento 1
`0x201c` `_0n` Fragmento 2 `0x2020` `Ly_` Fragmento 3 `0x2024` `UD2` Fragmento 4 `0x2028` `> HTB{%s}` Formato de salida :::
Hipótesis
El password está partido en cuatro strings separados en .rodata. Concatenados en el orden en que aparecen en memoria producen: Itz_0nLy_UD2. El binario los referencia por dirección individual y los une en runtime, de modo que ningún análisis estático superficial revela la credencial completa.

Solución

Password reconstruido

Itz_0nLy_UD2
PASSWORD ENCONTRADO
$ ./behindthescenes Itz_0nLy_UD2
> HTB{Itz_0nLy_UD2}
Hallazgo
La hipótesis de concatenación en orden de aparición en .rodata fue correcta. El binario respondió con la flag completa.

Por qué funciona esta técnica

La fragmentación de strings en .rodata es una técnica de anti-análisis estático. El compilador almacena cada fragmento como un literal independiente, referenciado por su dirección. El código los concatena en memoria durante la ejecución, pero ninguno de los fragmentos individuales parece una credencial a simple vista.

Desde el punto de vista del analista:

Nota
Un análisis dinámico con ltrace o GDB hubiera revelado la concatenación en runtime. El nombre del challenge — Behind the Scenes — hace referencia exactamente a esto: lo relevante no está en la superficie del binario sino detrás del análisis superficial. La ruta estática fue más formativa porque obligó a leer el hex dump manualmente.

Reflexión Final

Qué salió bien

Cuando strings no devolvió ningún password, el paso siguiente fue directo: inspeccionar .rodata con objdump -s. El razonamiento fue correcto — si el password no aparece como string completo, probablemente está fragmentado o codificado. En este caso estaba fragmentado.

La lectura del hex dump también funcionó bien una vez que quedó claro el papel del byte 0x00 como delimitador. Los puntos en la columna ASCII son exactamente eso: terminadores null de strings C.

Qué costó más

La sintaxis básica de bash para pasar argumentos posicionales a un ejecutable. Se confundió el operador de redirección > con los delimitadores < > del mensaje de uso del binario. No es un error de reversing sino de shell, pero en un flujo real cuesta tiempo.

Lecciones

  1. Cuando strings no devuelve credenciales, objdump -s -j .rodata es el siguiente paso natural.

  2. Los puntos en la columna ASCII del hex dump son bytes 0x00: delimitadores de strings en C. Leer esa columna de izquierda a derecha es suficiente para reconstruir los fragmentos.

  3. La fragmentación de strings en .rodata es una técnica de evasion real. Reconocerla en este challenge es base para identificarla en muestras de malware.

  4. El análisis dinámico (ltrace, GDB) hubiera resuelto esto más rápido, pero la ruta estática fue más formativa.

Tiempo total

Fase Tiempo
Reconocimiento con strings y checksec5 minutos
Inspección de .rodata con objdump10 minutos
Verificación y ejecución2 minutos
Total20 minutos