Ingeniería inversa con Ghidra

Ingeniería inversa con Ghidra

La ingeniería inversa con Ghidra es una de las técnicas más utilizadas dentro del análisis de malware, el reversing de software y la ciberseguridad ofensiva. Su capacidad para desensamblar binarios, reconstruir funciones y analizar código sin acceso al source code permite investigar amenazas reales, detectar comportamientos ocultos y comprender cómo funciona un ejecutable internamente.

Actualmente, equipos Red Team, analistas de malware y laboratorios de threat intelligence utilizan Ghidra para analizar ransomware, loaders, droppers o herramientas ofensivas avanzadas. A lo largo de este artículo veremos cómo funciona Ghidra, cómo se utiliza en análisis de binarios y por qué se ha consolidado como una de las herramientas de ingeniería inversa más relevantes dentro de la ciberseguridad actual.

Qué es la ingeniería inversa con Ghidra

La ingeniería inversa con Ghidra consiste en analizar un programa sin acceso al código fuente para comprender cómo funciona internamente. Este proceso permite reconstruir funciones, identificar llamadas críticas, estudiar el flujo de ejecución y detectar comportamientos ocultos dentro de un binario. En ciberseguridad, este enfoque es clave para investigar malware, validar vulnerabilidades o entender herramientas ofensivas utilizadas en ataques reales.

Ghidra destaca porque combina desensamblado de código, decompilación y análisis estructural dentro de un mismo entorno. El desensamblador trabaja directamente sobre instrucciones assembly ejecutadas por la CPU, mientras el decompiler reconstruye una representación más cercana a lenguajes de alto nivel. Esta combinación acelera enormemente el análisis de binarios, ya que permite alternar entre precisión técnica y comprensión funcional del programa.

Dentro de la ciberseguridad ofensiva, el reverse engineering con Ghidra se utiliza para desmontar ransomware, loaders, implantes, droppers o herramientas utilizadas por grupos APT. También permite detectar mecanismos de persistencia, técnicas anti análisis, cifrado personalizado o comunicaciones C2 ocultas dentro del software analizado. Por eso, Ghidra es una de las herramientas de ingeniería inversa más utilizadas en laboratorios de malware y equipos especializados de threat intelligence.

Ghidra se utiliza habitualmente en escenarios donde el analista necesita desmontar el comportamiento interno de un ejecutable, identificar funciones ocultas o reconstruir la lógica de un binario sospechoso. Dentro de estos entornos, es especialmente habitual encontrarlo en:

  • Análisis de malware para estudiar ransomware, loaders o implantes utilizados en ataques reales.
  • Reversing de software orientado a comprender validaciones internas, cifrado o funcionamiento de aplicaciones.
  • Auditorías ofensivas donde se analizan binarios vulnerables o mecanismos de protección.
  • Investigación de amenazas vinculadas a grupos APT, malware persistente o tooling ofensivo avanzado.
  • Análisis de binarios sospechosos utilizados en campañas de phishing, intrusiones o entornos comprometidos.

La ingeniería inversa con Ghidra permite analizar malware, reconstruir binarios y detectar comportamientos ocultos mediante desensamblado, decompilación y análisis avanzado de código ejecutable

Cómo instalar Ghidra correctamente

La instalación de Ghidra es bastante sencilla, aunque conviene preparar correctamente el entorno para evitar errores durante el análisis de binarios o problemas de compatibilidad en sesiones largas de reversing. A diferencia de otras herramientas de ingeniería inversa, Ghidra no utiliza un instalador tradicional, sino que funciona como una suite portable basada en Java.

Antes de descargar Ghidra, es importante validar varios elementos básicos del entorno:

  • Versión actualizada de Java JDK.
  • Sistema operativo compatible.
  • Permisos de ejecución.
  • Espacio suficiente para proyectos y muestras.
  • Entorno aislado para análisis de malware.

La descarga debe realizarse siempre desde el repositorio oficial de la NSA para evitar binarios manipulados o versiones alteradas. En entornos de ciberseguridad ofensiva, verificar hashes SHA256 forma parte de las prácticas habituales antes de trabajar con herramientas críticas de análisis.

El proceso de instalación cambia ligeramente según el sistema operativo utilizado:

  • Windows utiliza ghidraRun.bat.
  • Linux trabaja normalmente con ghidraRun.
  • macOS requiere validar permisos desde seguridad del sistema.

Una vez ejecutado por primera vez, Ghidra crea el workspace inicial y prepara el entorno de proyectos para comenzar el análisis estático de ejecutables, librerías o malware. A partir de ese momento, el laboratorio ya queda listo para importar binarios, ejecutar autoanálisis y comenzar procesos de ingeniería inversa sobre muestras reales.

En escenarios profesionales, muchos analistas trabajan con máquinas virtuales aisladas, snapshots y entornos sin conexión directa a Internet. Esta separación reduce riesgos durante el análisis de malware con Ghidra y mantiene controlado el laboratorio de reversing frente a posibles muestras maliciosas.

Primeros pasos dentro de Ghidra

Cuando se abre Ghidra por primera vez, el flujo de trabajo gira alrededor del Project Manager. Desde ahí se crean proyectos locales donde se almacenan binarios, análisis, anotaciones y modificaciones realizadas durante el proceso de ingeniería inversa. Esta estructura permite mantener organizado el reversing incluso cuando se trabaja con múltiples muestras de malware o distintos ejecutables sospechosos.

El siguiente paso consiste en importar el binario que se va a analizar. Ghidra detecta automáticamente el formato del archivo, la arquitectura utilizada y gran parte de los metadatos internos del ejecutable. Después, el sistema ejecuta el autoanálisis, una fase fundamental dentro del análisis estático porque identifica funciones, referencias cruzadas, strings, tablas de importación y estructuras básicas del programa.

A partir de ahí comienza realmente el trabajo de reverse engineering. El analista navega constantemente entre el desensamblado assembly y el decompiler para reconstruir el comportamiento interno del software. Esta combinación permite comprender mucho más rápido la lógica del binario, seguir llamadas críticas y detectar comportamientos sospechosos dentro del flujo de ejecución.

Durante las primeras sesiones de análisis es habitual trabajar sobre funciones detectadas automáticamente, imports del sistema, pseudocódigo generado por el decompiler y referencias cruzadas entre distintas regiones del ejecutable. Todo ello ayuda a construir una visión progresiva sobre cómo actúa realmente el software analizado, especialmente en escenarios relacionados con malware, loaders o herramientas ofensivas.

Conforme avanza el análisis, también es habitual renombrar funciones, añadir comentarios y redefinir estructuras internas para mejorar la legibilidad del proyecto. Esta metodología convierte el análisis de binarios en un proceso mucho más eficiente y permite construir contexto técnico sólido alrededor del comportamiento real del ejecutable.

reverse engineering con Ghidra

Análisis de malware con Ghidra

El análisis de malware con Ghidra permite estudiar el comportamiento interno de un ejecutable sin necesidad de ejecutarlo directamente. Este enfoque es fundamental dentro del análisis estático porque ayuda a identificar capacidades maliciosas, mecanismos de evasión y patrones utilizados habitualmente por amenazas actuales. A través del desensamblado de código y la decompilación, el analista reconstruye gran parte de la lógica interna del malware y obtiene indicadores útiles para detección o threat hunting.

Durante el análisis estático es habitual localizar elementos que revelan directamente cómo actúa la amenaza dentro del sistema comprometido. Entre los más habituales destacan:

  • Mecanismos de persistencia utilizados para mantener acceso tras reinicios o cierres de sesión.
  • Servidores C2 encargados de controlar remotamente el malware o recibir información robada.
  • APIs de red relacionadas con comunicaciones HTTP, sockets o transferencia de datos.
  • Rutinas de cifrado utilizadas para proteger configuraciones internas o cifrar archivos.
  • Strings ofuscadas diseñadas para ocultar dominios, rutas o comandos críticos.
  • Técnicas anti análisis orientadas a detectar sandboxes, máquinas virtuales o depuradores.
  • Procesos de inyección empleados para ejecutar código malicioso dentro de otros procesos legítimos.

Uno de los puntos más importantes dentro de la ingeniería inversa con Ghidra consiste en seguir referencias cruzadas sobre funciones sospechosas, cadenas o llamadas críticas del sistema. Esta metodología permite detectar cómo se construyen comunicaciones externas, cómo se resuelven APIs dinámicamente o cómo se ocultan determinadas funcionalidades dentro del binario.

En escenarios reales de ciberseguridad ofensiva, muchos analistas utilizan Ghidra para desmontar loaders, ransomware, droppers o implantes utilizados por grupos APT. El objetivo no se limita únicamente a comprender el malware, sino también a extraer IOCs, identificar comportamientos reutilizables y generar inteligencia útil para equipos SOC, detección avanzada o hunting proactivo. Por eso, Ghidra es una de las herramientas más utilizadas dentro de laboratorios especializados en análisis avanzado de amenazas.

Cuando el reversing se convierte en un script, un análisis manual de horas pasa a ser un proceso reproducible sobre cientos de muestras

Caso práctico de ingeniería inversa con Ghidra paso a paso

Un análisis real empieza siempre igual, con un ejecutable sin símbolos, una cadena sospechosa y ninguna pista sobre dónde está la lógica que importa. El caso práctico parte de un crackme escrito en C, un ejecutable ELF x86-64 que solo acepta una clave concreta. Al compilarlo sin símbolos, Ghidra lo recibe igual que recibiría un binario de terceros, sin nombres de funciones ni información de depuración.

Para reproducir el ejercicio basta con este material:

  • Compilador: GCC en Linux con -O0, para que el optimizador no integre la rutina de validación dentro de main, y -s, para eliminar la tabla de símbolos.
  • Ghidra: La versión estable más reciente, con el autoanálisis por defecto.
  • Python 3: Para escribir y validar el keygen.
  • Entorno aislado: Máquina virtual con snapshot, porque aunque la muestra sea inocua conviene no perder el hábito.

El recorrido se divide en dos fases que se repiten en casi cualquier análisis real. Primero se localiza la lógica que importa y después se reconstruye hasta poder reproducirla fuera del binario.

Del string a la función de validación

Todo empieza con el código del crackme, que se compila sin símbolos para simular un escenario realista. El código fuente y el comando de compilación son los siguientes:

#include <stdio.h>
#include <string.h>

static const unsigned char enc[8] = {
  0x19, 0x1a, 0x11, 0x0d,
  0x0b, 0x0c, 0x52, 0x57
};

static int check(const char *k)
{
  if (strlen(k) != 8)
    return 0;
  for (int i = 0; i < 8; i++)
    if ((k[i] ^ (0x5A + i)) != enc[i])
      return 0;
  return 1;
}

int main(int argc, char **argv)
{
  if (argc != 2) {
    puts("Uso: crackme <clave>");
    return 1;
  }
  if (check(argv[1]))
    puts("Clave correcta");
  else
    puts("Clave incorrecta");
  return 0;
}
$ gcc -O0 -s -o crackme crackme.c
$ file crackme
crackme: ELF 64-bit LSB pie executable,
x86-64, dynamically linked, stripped

Tras importar el binario y aceptar el autoanálisis, las cadenas son el punto de entrada natural. Si se abre la ventana Defined Strings desde el menú Window y se filtra por «Clave», aparecen los mensajes de éxito y de error. Con doble clic sobre «Clave incorrecta», el Listing salta a su posición en .rodata y muestra las referencias cruzadas (XREF) que apuntan a ella.

Esa XREF conduce a FUN_001011e7, que en realidad es main. En el decompilador se ve una llamada a FUN_00101169 cuyo valor de retorno decide qué mensaje se imprime. Ese patrón delata la rutina de validación.

Antes de profundizar conviene dejar el pseudocódigo legible:

  • Renombrar (L): Las dos funciones pasan a llamarse main y check_key.
  • Retipar (Ctrl+L): El parámetro de check_key se define como char *, si Ghidra no lo ha deducido ya de la llamada a strlen.
  • Editar la firma: Con Edit Function Signature, main recibe int argc y char **argv.

Con estos cambios, el decompilador propaga los tipos por todo el código y la función de validación queda aislada, lista para estudiar su algoritmo.

Reconstruir el algoritmo y comprobarlo

Dentro de check_key, el bucle de comparación concentra toda la lógica de la clave. En el ensamblado, el núcleo de ese bucle es el siguiente fragmento:

001011a8  movzx  eax,BYTE PTR [rax]
001011ab  movsx  eax,al
001011ae  mov    edx,DWORD PTR [rbp-0x4]
001011b1  add    edx,0x5a
001011b4  xor    eax,edx
001011b6  mov    ecx,eax
...
001011bd  lea    rdx,[DAT_00102008]
001011c4  movzx  eax,BYTE PTR [rax+rdx*1]
001011cb  cmp    ecx,eax

Una vez identificados los operandos, la lectura es directa. Cada carácter de la entrada se aplica XOR con 0x5A + i y el resultado se compara con el byte correspondiente de una tabla situada en DAT_00102008. Antes del bucle, la comparación del valor de strlen con 0x8 fija la longitud, y la condición jle frente a 0x7 confirma las ocho iteraciones. Si se retipa DAT_00102008 como byte[8], el decompilador muestra la tabla con sus valores.

Como XOR es reversible, la clave se obtiene despejando la ecuación. El keygen lee la tabla directamente del binario y aplica la operación inversa:

import sys

ENC_OFFSET = 0x2008   # DAT_00102008
ENC_LEN = 8

def keygen(path):
    with open(path, "rb") as f:
        f.seek(ENC_OFFSET)
        enc = f.read(ENC_LEN)
    # k[i] ^ (0x5A + i) == enc[i]
    # => k[i] = enc[i] ^ (0x5A + i)
    return "".join(chr(b ^ (0x5A + i))
                   for i, b in enumerate(enc))

if __name__ == "__main__":
    print(keygen(sys.argv[1]))

Para validarlo, el resultado se prueba contra el propio binario:

$ python3 keygen.py crackme
CAMPUS26
$ ./crackme CAMPUS26
Clave correcta

Cuando el algoritmo no es reversible, la alternativa es parchear el binario. El salto que decide el resultado está en main y se neutraliza en tres pasos:

  • Instrucción original: JZ 0x0010123e en 0x0010122b, con los bytes 74 11.
  • Parche: Con Patch Instruction (Ctrl+Shift+G) se sustituye por dos NOP y la ejecución continúa siempre hacia «Clave correcta».
  • Exportación: Con la opción Export Program del menú File y el formato Original File se genera el ejecutable modificado.

El parche demuestra que se entiende el flujo, pero el keygen demuestra que se entiende el algoritmo. Ese es el nivel que conviene automatizar en cuanto el análisis se repite sobre decenas de binarios.

Reverse engineering avanzado con Ghidra

A medida que el análisis avanza, Ghidra deja de utilizarse únicamente como herramienta de desensamblado y pasa a convertirse en una plataforma completa de reversing avanzado. En entornos profesionales, los analistas trabajan constantemente con scripting, automatización y personalización del análisis para acelerar tareas repetitivas, mejorar la clasificación de muestras y reconstruir comportamientos complejos dentro del binario.

La Ghidra API permite interactuar directamente con funciones, referencias, estructuras internas y resultados del decompiler. Gracias a ello, es posible automatizar procesos de análisis de malware, generar etiquetados automáticos o construir workflows adaptados a necesidades concretas dentro de laboratorios de threat intelligence y equipos especializados en ingeniería inversa. Además, el soporte para proyectos colaborativos facilita que varios analistas trabajen simultáneamente sobre la misma muestra, compartiendo anotaciones, comentarios y reconstrucciones del flujo interno del malware.

En entornos profesionales, Ghidra suele utilizarse para:

  • Automatizar análisis repetitivos sobre grandes volúmenes de muestras o familias de malware similares.
  • Etiquetar funciones sospechosas relacionadas con cifrado, persistencia o comunicaciones maliciosas.
  • Extraer IOCs útiles para detección avanzada, threat hunting o correlación de amenazas.
  • Comparar muestras diferentes para identificar reutilización de código o variaciones dentro de una campaña.
  • Acelerar procesos de ingeniería inversa mediante scripting, workflows automatizados y análisis estructural.

Con PyGhidra, que desde Ghidra 12.0 ejecuta por defecto los scripts de Python, el caso práctico anterior se automatiza en pocas líneas y sin interfaz gráfica. El siguiente script localiza la cadena, sigue sus XREF y decompila la función de validación:

# trace_check.py
# @runtime PyGhidra
# Uso sin interfaz grafica
# python3 -m pyghidra crackme trace_check.py
from ghidra.app.decompiler import DecompInterface

ifc = DecompInterface()
ifc.openProgram(currentProgram)

addr = find("Clave incorrecta")
for ref in getReferencesTo(addr):
    src = ref.getFromAddress()
    caller = getFunctionContaining(src)
    if caller is None:
        continue
    print("[XREF] %s en %s" % (src, caller))
    for fn in caller.getCalledFunctions(monitor):
        if fn.isThunk() or fn.isExternal():
            continue
        res = ifc.decompileFunction(fn, 60, monitor)
        print(res.getDecompiledFunction().getC())

ifc.dispose()

Este tipo de capacidades marca una diferencia enorme frente a análisis puramente manuales, especialmente cuando se trabaja con malware avanzado, técnicas anti análisis o amenazas utilizadas por grupos organizados. En este escenario, dominar workflows reales de reversing, automatización y análisis estructural de binarios forma parte de las competencias más demandadas dentro de la ciberseguridad ofensiva, un enfoque que se trabaja directamente en el Máster en Análisis de Malware y Reversing a través de laboratorios técnicos, reversing real y análisis avanzado de amenazas.

Utiliza las teclas de flecha arriba y abajo para cambiar el tamaño del panel de la caja meta.

Rellena el formulario para dominar el reversing profesional con el Máster en Análisis de Malware y Reversing