Contraseña hardcodeada
String legible o bytes globales llegan a strcmp/memcmp. Sigue xrefs y confirma la rama de éxito; no entregues la primera palabra “secreta” que veas.
No ejecutes primero. Identifica el formato, conserva hashes, reduce el programa a sus puntos de interés y sigue referencias hasta la comprobación de la flag.
Triage reproducible de ELF y PE · lectura estática con Ghidra o radare2 · criterio para pasar a GDB · reconocimiento de seis patrones escolares · una flag reconstruida desde pseudocódigo local.
Trabaja sobre una copia y registra cada hallazgo con offset o dirección. El hash identifica el artefacto exacto; no demuestra que sea benigno. No subas muestras privadas a servicios públicos de análisis.
| Etapa | Comando de lectura | Qué anotar | Corte |
|---|---|---|---|
| Identidad | file ./reto | ELF/PE, 32/64 bits, arquitectura, dinámico/estático, stripped | 1 min |
| Integridad | sha256sum ./retocertutil -hashfile reto SHA256 | hash + nombre + origen autorizado; MD5 solo como identificador legado, nunca como integridad | 1 min |
| Cadenas | strings -a -n 5 ./reto | less | éxito/error, %s, rutas, claves aparentes; luego busca sus xrefs | 3 min |
| ELF | readelf -hSWd ./retoreadelf -Ws ./reto | .text/.rodata/.data, intérprete, NEEDED, símbolos e imports | 4 min |
| ELF o PE | rabin2 -I -S -i ./reto | headers, secciones, imports; tamaños/entropía inusuales y entrypoint fuera de código normal | 4 min |
| Ruta lógica | r2 -A ./reto → afl → iz → axt | main, validadores, callers/callees y comparación que conduce al mensaje de éxito | 2 min inicial |
| Pregunta | ELF (Linux) | PE (Windows) | Decisión |
|---|---|---|---|
| Cabecera | 0x7f ELF; program/section headers; PT_INTERP | MZ + firma PE\0\0; DOS/COFF/optional headers | Confirma arquitectura y ABI antes de interpretar registros o calling convention. |
| Secciones típicas | .text, .rodata, .data, .plt/.got | .text, .rdata, .data, .idata, .rsrc | Nombres raros no prueban packing; cruza permisos, tamaño, entropía e imports. |
| Imports | libc y símbolos dinámicos; strcmp, memcmp, ptrace | DLL/IAT; lstrcmp*, memcmp, IsDebuggerPresent | Ve a xrefs de lectura de input, comparación y mensaje de éxito. |
| Estático | Headers, bytes, strings, imports, CFG, decompilado. Es reproducible y no dispara el programa. | Empieza aquí; suele bastar para contraseñas, XOR y comparaciones escolares. | |
| Dinámico | GDB observa registros/memoria de un ELF autorizado. | GDB puede servir con targets compatibles, pero el entorno Windows suele exigir otro depurador; no improvises aquí. | Úsalo solo para responder una pregunta concreta que el estático no resolvió. |
Descarga Ghidra únicamente desde el repositorio oficial de la NSA ↗. Su documentación de instalación actual pide JDK 21 de 64 bits; revisa allí los avisos de seguridad y la release vigente, sin fijar una versión de Ghidra en tus notas.
main. Busca el símbolo; si está stripped, parte del entrypoint/runtime y sigue la función pasada al arranque. Alternativamente sigue xrefs desde mensajes de éxito/error.FUN_*, variables y buffers por hipótesis explícitas: read_candidate, xor_key, expected. Corrige tipos; si una hipótesis cae, renómbrala otra vez.main/validador, xref que te llevó allí, tres nombres semánticos y una frase de dataflow. Si llevas 20 minutos renombrando helpers sin acercarte a la rama de éxito, vuelve a las cadenas e imports.
Usa como referencia el libro oficial de radare2 ↗. Los comandos siguientes abren para análisis, no escriben el archivo.
r2 -A ./reto
afl
iz
s main
pdf
pdc
-A analiza; afl lista funciones; iz lista strings; pdf muestra el desensamblado de la función y pdc una vista pseudocódigo. Si no hay main, empieza en entry0 o desde xrefs.
iz~Correct
axt @ str.Correcto
s <direccion_del_xref>
pdf @ sym.main
pdc @ sym.main
axt lista referencias hacia la dirección. Repite sobre imports como sym.imp.strcmp o sobre el buffer esperado. Nombra hallazgos con afn check_flag @ <addr> y guarda direcciones en la bitácora.
| Señal | Pregunta concreta | Observación mínima en VM |
|---|---|---|
| Valor solo existe en runtime | ¿Qué buffer queda justo antes de memcmp? | breakpoint en la comparación; inspecciona argumentos según ABI y memoria, luego termina. |
| Bucle byte a byte confuso | ¿Qué índice/byte provoca la primera divergencia? | breakpoint en el salto de fallo; registra índice, candidato y esperado. |
| Indirectas o símbolos ausentes | ¿Qué función se llama realmente? | breakpoint por dirección del call; stepi hasta el destino. |
| Anti-debug básico | ¿La rama depende de ptrace u otra comprobación? | confirma el call y la rama; explica el mecanismo antes de modificar nada. |
No abras GDB “para ver qué pasa”. Hazlo únicamente con un ELF de reto autorizado en una VM aislada y una hipótesis escrita. Si la respuesta ya está en el estático, ejecutar añade riesgo sin añadir evidencia.
String legible o bytes globales llegan a strcmp/memcmp. Sigue xrefs y confirma la rama de éxito; no entregues la primera palabra “secreta” que veas.
Loop sobre índice, fallo temprano y longitud fija. Recupera orden, terminador y transformaciones previas; cuidado con signed char y off-by-one.
15 min · tabla índice/candidato/esperadoBusca constante/clave, periodicidad e inversión. XOR se deshace con la misma operación; suma/rotación requieren respetar ancho y overflow.
18 min · reconstruye 4 bytes antes de escalarSecciones/nombres, pocos imports y entry stub sugieren packing, no lo prueban. Confirma firma y versión compatible antes de intentar desempacar una copia.
10 min · si falla, no inventes flags de upxptrace, IsDebuggerPresent, timing o lectura de estado alteran una rama. Identifica check → retorno → salto; parchear a ciegas oculta la lógica.
VMs custom, múltiples capas, drivers, ofuscación pesada o anti-VM sostenido no caben en este bloque. Conserva hash/notas y cambia de reto.
30 min sin dataflow nuevo · aparcarLee este pseudocódigo como decompilado: identifica input, transformación, esperado y condición de éxito. Resuelve a mano o con una nota local y pega la flag completa. Este ejercicio entrena lectura de dataflow; no sustituye analizar un binario, su layout, xrefs ni instrucciones.
bool check_candidate(char *candidate) {
uint8_t expected[15] = {
0x60, 0x77, 0x65, 0x58, 0x57,
0x51, 0x4a, 0x42, 0x44, 0x46,
0x7c, 0x5b, 0x4c, 0x51, 0x5e
};
if (strlen(candidate) != 15) return false;
for (int i = 0; i < 15; i++) {
if ((candidate[i] ^ 0x23) != expected[i]) return false;
}
return true;
}
Los catálogos cambian: usa categorías y criterios vigentes, no nombres congelados. No descargues una colección; elige un solo artefacto autorizado y registra su hash.
Reproduce el flujo de esta hoja sobre un binario propio trivial usando el repositorio oficial de Ghidra y el libro oficial de radare2 enlazados arriba. Debes llegar al mismo validador por decompiler y por iz → axt → pdf/pdc.
Entra por la guía oficial de picoCTF ↗, abre picoGym y filtra Reverse Engineering. Elige un reto vigente de dificultad inicial que entregue un binario; aplica el pipeline completo antes de consultar pistas.
salida: 1 flag + write-up: identidad, hash, pista, xref, transformación y corteLee primero y entra únicamente por la FAQ de crackmes.one ↗. No se enlaza ningún crackme concreto: tú validas licencia, plataforma y dificultad antes de descargar.