Tema 11
La ingeniería inversa permite estudiar la lógica interna de un binario sin disponer del código fuente. Con desensambladores, decompiladores y método podemos reconstruir funciones, decisiones, datos y comportamientos relevantes para el análisis de malware.
El análisis estático inicial y el análisis dinámico muestran pistas y comportamiento. La ingeniería inversa profundiza un nivel más: intenta entender cómo está construida internamente la muestra y por qué actúa de cierta manera.
Cuando una muestra cifra strings, resuelve APIs dinámicamente, oculta configuración o ejecuta rutas de código condicionadas, observar desde afuera puede no alcanzar. En esos casos, desensambladores y decompiladores ayudan a leer funciones, ramas, estructuras y datos internos.
El objetivo de este tema es aprender un método de lectura. No se trata de entender cada instrucción de un binario completo, sino de encontrar las partes relevantes y documentarlas con precisión.
Ingeniería inversa es el proceso de analizar un artefacto para comprender su diseño, funcionamiento y comportamiento. En malware, suele aplicarse a binarios, scripts, documentos maliciosos, configuraciones, protocolos o payloads extraídos.
Puede servir para:
Un desensamblador traduce bytes de máquina a instrucciones ensamblador. Un decompilador intenta elevar esas instrucciones a una representación parecida a código de alto nivel, como pseudocódigo C.
| Herramienta | Qué muestra | Límite principal |
|---|---|---|
| Desensamblador | Instrucciones, direcciones, referencias y grafos | Requiere leer bajo nivel y convenciones de llamada |
| Decompilador | Pseudocódigo, estructuras y flujo más legible | Puede inferir mal tipos, variables o lógica compleja |
| Debugger | Estado real durante ejecución | Requiere ejecutar la muestra y controlar riesgo |
La mejor lectura combina herramientas. El pseudocódigo orienta, el ensamblador confirma y el debugging valida comportamiento real.
Un flujo ordenado reduce la posibilidad de perderse en detalles irrelevantes.
Antes de abrir una muestra en una herramienta de reversing, conviene confirmar que se trabaja con una copia y que el archivo está identificado.
Los desensambladores modernos identifican funciones, referencias, strings, tablas, imports y posibles tipos. Ese análisis automático ahorra tiempo, pero no es perfecto.
Puede fallar cuando hay:
El resultado automático es una propuesta de lectura, no una verdad absoluta.
El punto de entrada es donde el loader transfiere control al programa, pero no siempre equivale a la lógica principal. En programas compilados, puede pasar por runtime, inicializadores y envoltorios antes de llegar al código relevante. En malware empaquetado, puede iniciar en el stub del packer.
Para orientarse:
Las strings son puntos de entrada útiles para navegar un binario. Una URL, ruta, mensaje, nombre de mutex o clave de registro puede llevar directamente a la función que la usa.
Las referencias cruzadas, o xrefs, muestran dónde se utiliza un dato o función. Son esenciales para responder preguntas como "¿qué código usa este dominio?" o "¿dónde se crea esta clave de registro?".
| Pista | Cómo navegar | Qué puede revelar |
|---|---|---|
| URL | Buscar xrefs hacia la string | Función de comunicación o descarga |
| Ruta de archivo | Seguir uso en llamadas de archivos | Instalación, persistencia o recolección |
| Mensaje de error | Ubicar rama que lo muestra o registra | Condición fallida o flujo alternativo |
| Nombre de API | Buscar llamadas o resolución dinámica | Capacidad técnica concreta |
Los imports y llamadas a APIs ayudan a ubicar capacidades. En reversing, interesa no solo qué API existe, sino qué datos recibe y desde qué función se llama.
Ejemplos de preguntas útiles:
Una llamada API cobra valor cuando conectamos argumentos, contexto y resultado.
Muchas muestras evitan mostrar imports claros. En lugar de importar funciones directamente, cargan bibliotecas y resuelven direcciones en tiempo de ejecución, a veces usando nombres cifrados o hashes.
Señales comunes:
El grafo de control de flujo muestra bloques básicos y saltos entre ellos. Ayuda a entender decisiones, bucles y caminos alternativos sin leer el código como una lista lineal.
En un grafo conviene observar:
El pseudocódigo facilita la lectura al mostrar estructuras parecidas a if, while, funciones y variables. Es muy útil para comprender lógica general, pero puede ocultar detalles importantes.
| Ventaja | Riesgo | Práctica recomendada |
|---|---|---|
| Lectura más rápida | Tipos inferidos incorrectos | Verificar con ensamblador en partes críticas |
| Mejor vista de estructuras | Variables artificiales o confusas | Renombrar según comportamiento confirmado |
| Facilita seguir lógica | Puede simplificar efectos de flags o casts | Revisar saltos y llamadas sensibles |
| Ayuda a documentar | Puede parecer código fuente real | Recordar que es reconstrucción aproximada |
Renombrar es una parte central del reversing. Convierte un binario desconocido en un mapa comprensible. Al principio se usan nombres tentativos; luego se refinan con evidencia.
Ejemplos de nombres útiles:
check_environment para una función que valida VM, idioma o usuario.decode_config para una rutina que descifra datos internos.create_persistence para una función que crea tarea o clave de inicio.send_beacon para una función que contacta C2 periódicamente.enumerate_files para una rutina que recorre directorios.Conviene evitar nombres demasiado seguros si la función aún no está confirmada. Un prefijo como possible_ puede ser honesto durante la exploración.
Los comentarios deben explicar lo que no es obvio. No hace falta comentar cada instrucción; sí conviene registrar hipótesis, datos importantes, condiciones y relaciones con evidencias externas.
El malware suele usar estructuras internas para configuración, comandos, claves, listas de extensiones, dominios o estados. Reconocerlas permite pasar de bytes sueltos a información organizada.
Señales de estructuras:
Muchas muestras usan rutinas simples de codificación, hashing o cifrado casero para ocultar strings y configuración. No siempre es necesario entender toda la matemática; a veces basta con ubicar entrada, salida y punto donde los datos quedan en claro.
Preguntas útiles:
La ingeniería inversa gana fuerza cuando se conecta con análisis dinámico. Lo observado en ejecución indica dónde mirar; lo leído en el binario explica por qué ocurrió.
| Hallazgo dinámico | Pregunta de reversing | Resultado esperado |
|---|---|---|
| Conexión a dominio | Dónde se construye o descifra el dominio | Configuración C2 o algoritmo de generación |
| Clave de persistencia creada | Qué función decide la ruta y el valor | Mecanismo de persistencia documentado |
| Archivo creado | Si fue extraído de recursos o descargado | Relación entre dropper y payload |
| Proceso inyectado | Qué APIs y permisos usa | Técnica de inyección y artefactos |
Si una muestra está empaquetada, el archivo en disco puede mostrar poco código real. En ese caso, el reversing estático inicial sirve para identificar el stub, pero la lógica principal puede aparecer solo después de desempaquetar en memoria.
Señales de que conviene cambiar de estrategia:
En estos casos, el análisis dinámico y el debugging ayudan a capturar el código ya desempaquetado.
La ofuscación intenta dificultar lectura. Puede cambiar nombres, ocultar strings, complicar control de flujo, insertar código basura o resolver funciones indirectamente.
Estrategias útiles:
Una de las tareas más valiosas del reversing es extraer configuración: dominios C2, claves, identificadores de campaña, intervalos de beaconing, rutas, extensiones objetivo o flags de comportamiento.
La configuración puede estar:
Los hallazgos deben ser verificables por otra persona. Una buena nota de reversing incluye dirección, función, evidencia y conclusión.
| Elemento | Contenido recomendado | Motivo |
|---|---|---|
| Dirección | RVA, VA o nombre de función renombrada | Permite ubicar el hallazgo |
| Evidencia | String, API, bloque de pseudocódigo o traza | Respalda la interpretación |
| Interpretación | Qué hace la función y con qué confianza | Comunica resultado técnico |
| Impacto | Persistencia, C2, robo, evasión, cifrado | Conecta con defensa y respuesta |
| IOC derivado | Dominio, ruta, clave, mutex, patrón | Facilita detección o búsqueda |
La ingeniería inversa permite pasar de observar efectos a comprender causas. Con método, un binario opaco empieza a revelar funciones, decisiones, configuraciones y relaciones internas que pueden convertirse en detección, mitigación y conocimiento defensivo.
En el próximo tema trabajaremos debugging de malware: breakpoints, memoria, llamadas API y flujo de ejecución, para validar hipótesis observando la muestra mientras corre.