Post

Compiler

Compiler

Hola bandita, ¿cómo están? El día de hoy les traigo la guía para la máquina easy de TryHackMe Compiled, que debo decir, fue un poco una pesadilla, pero eso lo verán más adelante. Así que sin más, ¿por qué no empezamos? Advertencia, no hay capturas de pantalla (sadly) porque solo a mi se me ocurre hacer máquinas a las 9pm y terminé casi a las 12 am.


Primero tenemos un simple y pequeño binario que solo mostraba un prompt pidiendo una contraseña. Probaba “123”, “password”, “admin”… y siempre la misma respuesta: “Try again!”. Como ya he hecho la lección de malware analysis, lo primero que hice fue mandar un string, usualmente encuentras cosas básicas, pero quizá algo útil.

1
2
3
4
bash

strings Compiled

Entre el output aparecía “StringsForNoobs”, y obviamente me sentí ofendida, pero con esto deduje que los trings no nos iban a ayudar mucho (o eso era lo que pensaba, oh, boy, how wrong I was). Así que cambié completamente de enfoque, si strings no me daba, entonces debía ir al mero core del asunto. Había que desamblarlo y aquí, señores, señoritas, señorites, es cuando las cosas se ponen serias.

1
2
3
bash

cutter Compiled 

Cuando analicé el desensamblado, encontré algo interesante. El programa no estaba cargando ningún string desde la sección de datos. En lugar de eso, movía valores hexadecimales directamente a los registros:

1
2
3
4
5
6
7
assembly

movabs rax, 0x4973676e69727453
movabs rdx, 0x626f6f4e726f4673
mov qword [rbp-0x48], rax
mov qword [rbp-0x40], rdx
mov word [rbp-0x38], 0x73

Aquí es donde recordé algo crucial sobre cómo las computadoras almacenan la información. Estos valores estaban en little-endian. Tenía que convertir esos hexas a texto, pero leyendo los bytes al revés. Usé Python para descifrarlo:

1
2
3
4
5
6
hex_strings = ["4973676e69727453", "626f6f4e726f4673", "73"]
for h in hex_strings:
    bytes_obj = bytes.fromhex(h)
    print(bytes_obj[::-1].decode('ascii'))

Y apareció ante mí: “StringsIsForNoobs”. ¡Eureka! Bueno, medio eureka, porque todavía no funcionaba cuando lo probaba directamente.

Resulta que había otra capa de misterio. Siguiendo el análisis del desensamblado, encontré el scanf:

1
2
3
assembly

lea rdi, [format_string]  ; "DoYouEven%sCTF"

¡Ajá! Esas palabras no eran solo texto decorativo. El formato completo era “DoYouEven%sCTF”, donde “%s” era mi input. Era como si me dieran un formulario con partes ya escritas y un espacio en blanco en medio.

Pero la trampa más elegante venía después. El programa hacía no una, sino tres comparaciones diferentes con strcmp. Usé gdb para poner breakpoints y seguirlas:

1
2
3
4
5
6
bash

gdb ./Compiled
break *strcmp
run

Las dos primeras comparaciones eran puro teatro: comparaban mi entrada con “__dso_handle” pero usaban js y jle - saltos condicionales que no buscan igualdad, solo relaciones de orden. Era como un guardia que te pide decir un número, no para ver si es correcto, sino para ver si sabes contar.

La tercera comparación era la que importaba. Ahí sí usaba jne - jump if not equal - y comparaba exactamente con la cadena que había construido con esos valores hexadecimales: “StringsIsForNoobs”.

Fue como armar un rompecabezas donde todas las piezas finalmente encajaron. La contraseña completa tenía que respetar el formato del scanf y pasar todas las validaciones:

1
2
3
4
5
6
bash

./Compiled
Password: DoYouEvenStringsIsForNoobsCTF
Correct!

¡Funcionó! Este reto me enseñó que el reverse engineering no es solo sobre herramientas, sino sobre pensamiento crítico. No se trata de qué comandos ejecutar, sino de entender el flujo del programa, cómo manipula los datos en memoria, y qué trucos usa para esconder información.

Cada comando que usé - strings, objdump, gdb, Python para decodificar hex - era solo un pincel en el cuadro completo. La verdadera habilidad estaba en saber cuándo usarlo y, más importante, cómo interpretar lo que me mostraba.

¿Y ustedes? ¿Han tenido esa experiencia de descubrir que lo obvio era una trampa? ¿O de encontrar que una herramienta en la que confiaban les estaba mostrando solo parte de la verdad? Cuéntenme en los comentarios sus historias de debugging y reverse engineering. Y si quieren ver más análisis donde desarmamos binarios capa por capa, suscríbanse - porque cada reto es una nueva historia por descifrar juntos.

Glosario de Comandos para Análisis de Binarios

ComandoUso/ParámetrosDescripciónEjemplo Práctico
stringsstrings [binario]Extrae strings legibles de un binariostrings Compiled para buscar contraseñas hardcodeadas
gdbgdb ./[binario]Debugger interactivo para análisis dinámicogdb ./Compiled para ejecutar paso a paso
break (gdb)break *[función] o break *[dirección]Coloca breakpoint en función/direcciónbreak *main o break *0x400500
run (gdb)run [args]Ejecuta el programa dentro del debuggerrun o con argumentos run "test"
info registersinfo registers en gdbMuestra estado de registros del CPUinfo registers para ver RAX, RBP, RSP, etc.
x (examine)x/[n][formato] [dirección]Examina memoria en gdbx/20x $rsp muestra 20 valores hex desde stack
disasdisas [función] en gdbDesensambla función específicadisas main para ver código de main
python hex decodepython3 -c "bytes.fromhex('...')[::-1].decode()"Convierte hex a texto (little-endian)Para decodificar 4973676e69727453"StringsI"
xxdxxd [archivo] \| head -nVisualizador hexadecimalxxd Compiled \| head -20 para ver header
hexdumphexdump -C [archivo] \| lessHexdump con ASCIIhexdump -C Compiled \| less para navegar
filefile [binario]Identifica tipo de archivo/arquitecturafile Compiled para ver si es ELF 64-bit
checksecchecksec [binario]Analiza protecciones de seguridadchecksec Compiled para ASLR, NX, Canary, etc.
readelfreadelf -a [binario]Información detallada de ELFreadelf -s Compiled para tabla de símbolos
ltraceltrace ./[binario]Traza llamadas a libreríasltrace ./Compiled para ver strcmp/scanf
stracestrace ./[binario]Traza llamadas al sistemastrace ./Compiled para syscalls de I/O
gccgcc -o output archivo.cCompila código Cgcc -g -o test test.c con símbolos debug
radare2r2 [binario]Framework de análisis de binariosr2 -AAA Compiled para análisis automático
ghidra(GUI)Herramienta gráfica de descompilaciónDescompila assembly a pseudocódigo C
nmnm [binario]Lista símbolos del binarionm Compiled para funciones/variables
lddldd [binario]Muestra dependencias de libreríasldd Compiled para ver libc, libm, etc.
sizesize [binario]Muestra tamaño de seccionessize Compiled para .text, .data, .bss
stripstrip [binario]Elimina símbolos de debuggingstrip Compiled hace más difícil el reversing
objcopyobjcopy --dump-section .text=out.text [binario]Extrae secciones específicasPara extraer solo el código ejecutable
grepgrep -r "palabra" [dir]Búsqueda en archivosgrep -r "strcmp" desensamblado.txt
awkawk '/pattern/ {print $1}'Procesamiento de textoPara filtrar output de objdump
sedsed 's/buscar/reemplazar/g'Editor de streamPara limpiar output de análisis
diffdiff archivo1 archivo2Compara archivosdiff original.txt modificado.txt
md5summd5sum [archivo]Checksum MD5md5sum Compiled para integridad
sha256sumsha256sum [archivo]Checksum SHA256Para verificar binarios descargados
objdump (headers)objdump -f [binario]Muestra header del archivoobjdump -f Compiled para entry point
readelf (headers)readelf -h [binario]Header ELFreadelf -h Compiled información básica
psps aux \| grep [proceso]Lista procesosPara encontrar PID de proceso en ejecución
killkill -9 [PID]Termina procesoPara matar proceso colgado
timetime ./[binario]Mide tiempo de ejecucióntime ./Compiled para profiling básico

Flujos de Comando Típicos

Análisis Inicial Rápido:

1
2
3
file target_binary
strings target_binary | head -50
checksec target_binary

Desensamblado para Buscar Funciones:

1
2
objdump -d target_binary | grep -A 20 "<main>:"
objdump -d target_binary | grep -n "strcmp"

Sesión de Debugging Básica:

1
2
3
4
5
gdb ./target_binary
(gdb) break *main
(gdb) run
(gdb) disas
(gdb) continue

Extraer y Decodificar Strings Ocultas:

1
2
3
4
# Buscar valores hex en objdump
objdump -d target_binary | grep -B2 -A2 "mov.*0x"
# Decodificar con Python
python3 -c "print(bytes.fromhex('41424344')[::-1].decode('ascii'))"
This post is licensed under CC BY 4.0 by the author.