Ghidra desde cero:
ingeniería inversa de binarios sin gastarte una licencia
Malware y Reversing | unfantasmaenelsistema.com
Tienes un ejecutable y ningún código fuente. Puede ser una muestra de malware que llegó por correo, un componente propietario que se comporta raro, un firmware de un cacharro del laboratorio o un crackme de un CTF. La pregunta es siempre la misma: ¿qué hace este binario por dentro? Durante años la respuesta profesional pasaba por IDA Pro, una herramienta excelente y carísima. En 2019 la NSA liberó Ghidra, su plataforma interna de ingeniería inversa, con un descompilador que juega en esa misma liga y una licencia libre. De golpe, el análisis serio de binarios dejó de tener barrera de entrada.
Este artículo es una introducción práctica a Ghidra orientada al análisis: cómo montar un proyecto, leer el desensamblado y el pseudocódigo, moverte por las referencias cruzadas, dar nombres y tipos a las cosas para que el descompilador tenga sentido, y automatizar con scripts. El objetivo es entender qué hace un programa, no escribir exploits ni romper protecciones comerciales. Todos los ejemplos asumen un binario de laboratorio: un crackme, un reto público o un ejecutable benigno propio.
Qué aprenderás en este artículo
La diferencia entre desensamblado y descompilado, y cuánto te puedes fiar de cada uno · Cómo se estructura un proyecto de Ghidra y qué hace el auto-análisis al importar · Las ventanas que se usan a diario: Listing, Decompiler, Symbol Tree, Data Type Manager · Cómo navegar por referencias cruzadas, strings y llamadas a la API para reconstruir el flujo · Renombrar, retipar y aplicar estructuras; scripting con Python y el modo headless para lotes · Comparación rápida con radare2/rizin e IDA Free, y un flujo para triar una muestra
1. Desensamblado y descompilado: qué es cada cosa
Un binario compilado es código máquina: bytes que la CPU ejecuta directamente. La ingeniería inversa consiste en subir por esa escalera de abstracción hasta algo que un humano pueda razonar. Ghidra da dos peldaños.
El desensamblado traduce cada instrucción máquina a su mnemónico de ensamblador (`MOV`, `CALL`, `JNZ`…). Es una traducción prácticamente uno a uno y fiable: lo que ves es lo que la CPU hace. El problema es que un programa mediano son decenas de miles de instrucciones y leerlas todas no escala.
El descompilado es el salto grande: Ghidra analiza bloques de ensamblador y reconstruye una aproximación en pseudocódigo parecido a C, con variables, bucles, condicionales y llamadas a funciones. Es lo que hace que Ghidra valga la pena. Pero es una inferencia, no una verdad: el descompilador adivina tipos, se puede equivocar con el paso de parámetros, puede no reconocer una estructura y mostrarte aritmética de punteros cruda. Regla práctica: cuando el pseudocódigo y el ensamblador no cuadran, gana el ensamblador.
Cómo se leen juntos
Trabaja con la ventana Listing (ensamblador) y la ventana Decompiler abiertas a la vez · El cursor está sincronizado: al hacer clic en una línea de pseudocódigo se resaltan las instrucciones que la generan, y viceversa · Usa el pseudocódigo para entender la lógica a grandes rasgos y baja al ensamblador para confirmar los detalles que importan
2. Instalación y primer proyecto
Ghidra es una aplicación Java. Se descarga de ghidra-sre.org (o del repositorio oficial en GitHub), se descomprime y se ejecuta el lanzador; necesita un JDK reciente (17 o superior). No hay instalador ni servicio: es una carpeta portable.
# Linux / macOS: descomprimir y lanzar unzip ghidra_*.zip && cd ghidra_* ./ghidraRun # Windows ghidraRun.bat
Al arrancar creas un proyecto, que es una carpeta con uno o varios binarios y todo el trabajo de análisis asociado (nombres, comentarios, tipos). Los proyectos pueden ser no compartidos (local) o compartidos a través de un Ghidra Server, que permite que varias personas analicen el mismo conjunto de binarios con control de versiones. Para empezar, no compartido.
2.1 Importar y auto-analizar
Arrastras el binario al proyecto o usas File > Import File. Ghidra detecta el formato (PE de Windows, ELF de Linux, Mach-O, firmware en bruto…) y la arquitectura. Al abrirlo por primera vez en la herramienta CodeBrowser, ofrece ejecutar el auto-análisis: una batería de analizadores que recorren el binario identificando funciones, resolviendo llamadas, marcando strings, aplicando firmas de funciones de librería conocidas (FID) y propagando tipos de parámetros de la API.
- Acepta las opciones por defecto en tu primer análisis; son sensatas para la mayoría de binarios
- Decompiler Parameter ID mejora la detección de argumentos de función a cambio de tardar más — vale la pena dejarlo activo
- Aggressive Instruction Finder puede ayudar en binarios ofuscados o sin símbolos, pero también genera falsos positivos; actívalo solo si el análisis normal deja huecos grandes
- El análisis se puede volver a lanzar entero o por analizadores concretos desde Analysis > Auto Analyze
3. Las ventanas que vas a usar todo el rato
| Ventana | Para qué sirve |
|---|---|
| Listing | El desensamblado anotado: direcciones, bytes, instrucciones, comentarios, referencias |
| Decompiler | El pseudocódigo C de la función donde está el cursor; se regenera al vuelo |
| Symbol Tree | Índice navegable: funciones, etiquetas, imports, exports, espacios de nombres |
| Data Type Manager | Catálogo de tipos: los del binario, los de librerías y los que definas tú |
| Functions | Tabla de todas las funciones con nombre, dirección, tamaño y firma |
| Defined Strings | Todas las cadenas de texto localizadas, con su dirección y codificación |
| Bytes | Volcado hexadecimal editable, para parcheo y para ver datos en crudo |
El flujo habitual es: buscas un punto de entrada interesante (un string, un import, `main`), saltas a él en el Listing, lees el pseudocódigo en el Decompiler, y usas el Symbol Tree y las referencias cruzadas para moverte a las funciones relacionadas.
3.1 Navegación por referencias cruzadas
Las referencias cruzadas (xrefs) son la herramienta de navegación más importante. Con el cursor sobre una función, un dato o una dirección, la tecla `X` (o clic derecho > References) muestra desde dónde se usa. Así se reconstruye el flujo sin leer el binario en orden lineal:
- Ves un string sospechoso como `»clave incorrecta»` en Defined Strings → xref → llegas a la función que lo imprime, que es justo la comprobación que te interesa
- Quieres saber quién llama a `CreateProcessW` → doble clic en el import en el Symbol Tree → xrefs → todos los puntos donde el binario lanza procesos
- Doble clic en cualquier dirección salta a ella; `Alt+Izquierda` vuelve atrás, como el botón de un navegador
4. Hacer legible el pseudocódigo: nombres, tipos y estructuras
El auto-análisis te deja funciones llamadas `FUN_00401560` y variables `iVar1`, `uVar2`, `local_18`. El descompilador es tan bueno como el contexto que le das. El trabajo real del reversing es ir anotando lo que descubres para que el pseudocódigo se vuelva comprensible.
| Acción | Tecla | Efecto |
|---|---|---|
| Renombrar función o variable | L | Le pones un nombre con significado; se propaga a todas las vistas |
| Cambiar el tipo de una variable | Ctrl+L | Retipar de int a un puntero o a una estructura arregla la aritmética que se ve |
| Editar la firma de la función | F | Ajustas número, tipo y nombre de parámetros y el valor de retorno |
| Añadir comentario | ; (punto y coma) | Nota fijada a esa dirección, visible en Listing y Decompiler |
| Definir un dato | D | Marca una zona como byte, dword, string, puntero… |
| Crear una estructura | — | Data Type Manager > New > Structure, o auto-crear desde una variable |
El caso más rentable es aplicar estructuras. Cuando una función recibe un puntero y accede a `*(param_1 + 0x8)`, `*(param_1 + 0x10)`, estás viendo campos de una struct. Si defines esa struct en el Data Type Manager y retipas `param_1` a `MiStruct *`, el descompilador pasa de mostrar desplazamientos numéricos a mostrar `param_1->contador`, `param_1->nombre`. Ghidra ya trae las estructuras de la API de Windows y de la libc, así que retipar un parámetro a `PROCESS_INFORMATION *` o `stat *` desbloquea de golpe una función entera.
Retipar es iterativo
No intentes reconstruir todas las estructuras de golpe: nombra lo que entiendas, retipa lo evidente, y vuelve cuando otra función te aclare un campo · Guarda el proyecto a menudo; Ghidra no guarda solo · Los comentarios de tipo `PLATE`, `PRE` y `POST` sirven para dejar constancia de hipótesis sin contaminar la lógica
5. Reconstruir el flujo de un programa pequeño
Para un crackme típico (pide una contraseña y dice si es válida) el recorrido es casi siempre el mismo:
- Entrada: localiza `main` (o `entry` y de ahí baja) en el Symbol Tree. En binarios de Windows, `main` real suele estar unas llamadas por debajo del punto de entrada, tras el arranque del runtime
- Strings: mira Defined Strings buscando los mensajes de éxito y de error; sus xrefs te llevan al corazón de la comprobación
- La comprobación: identifica la función que compara tu entrada con algo — un `strcmp`, un bucle que transforma carácter a carácter, una llamada a una rutina de hash
- El objetivo: si es una comparación directa, la cadena esperada está ahí. Si hay una transformación, entiéndela e inviértela mentalmente o con un pequeño script
- Grafo de flujo: la vista Function Graph (icono de diagrama) muestra los bloques básicos y los saltos condicionales; es ideal para ver qué condición lleva a la rama «correcta»
Este mismo patrón —entrar por un string o un import, subir por xrefs, aislar la función clave, anotarla— es el que se aplica luego a binarios grandes; solo cambia la escala.
5.1 Parcheo básico y export
Ghidra permite editar instrucciones (clic derecho > Patch Instruction) o bytes directamente, por ejemplo para convertir un salto condicional en incondicional en un binario de laboratorio y ver el otro camino. Para volcar el resultado a un fichero ejecutable se usa File > Export Program con el formato Binary (respeta offsets) — la exportación a un PE/ELF que vuelva a arrancar es limitada y a menudo requiere retoques con otra herramienta.
6. Scripting y modo headless
Todo lo que se hace a mano se puede programar. Ghidra expone su API en Java y en Python vía Jython (Python 2.7); las versiones recientes también integran un puente para CPython 3 a través de PyGhidra. El Script Manager trae decenas de ejemplos.
# Ejemplo de script en Python (Jython) dentro de Ghidra:
# listar todas las funciones y su numero de instrucciones
fm = currentProgram.getFunctionManager()
for f in fm.getFunctions(True):
body = f.getBody()
n = currentProgram.getListing().getInstructions(body, True)
count = sum(1 for _ in n)
print('%s\t%s\t%d' % (f.getName(), f.getEntryPoint(), count))El modo headless (`analyzeHeadless`) ejecuta Ghidra sin interfaz para procesar binarios en lote: importa, auto-analiza y corre los scripts que le indiques. Es como se integra Ghidra en un pipeline de análisis de malware o en CI.
# Analizar una carpeta de muestras y correr un script sobre cada una ./support/analyzeHeadless ~/proyectos LoteMalware \ -import ~/muestras/*.bin \ -postScript ExtraerIOCs.py \ -scriptPath ~/ghidra_scripts
7. Ghidra frente a radare2/rizin e IDA
| Herramienta | Licencia | Fuerte en | Nota |
|---|---|---|---|
| Ghidra | Libre (Apache 2.0) | Descompilador multiarquitectura, proyectos colaborativos, scripting | El mejor punto de partida hoy si no pagas licencia |
| IDA Free | Gratuita, no comercial | Descompilador solo x86-64, ecosistema de plugins enorme | La versión de pago sigue siendo el estándar de la industria |
| radare2 / rizin | Libre (LGPL) | Análisis desde terminal, scripting, automatización, forense | Curva dura; rizin + Cutter dan una GUI más amable |
| Binary Ninja | Comercial (asequible) | API muy limpia, IL propio, buena UX | Alternativa de pago más barata que IDA |
No son excluyentes. Es habitual desensamblar en Ghidra por su descompilador, automatizar extracción de indicadores con rizin, y contrastar una función concreta en dos herramientas cuando el pseudocódigo no convence.
8. Un flujo para triar una muestra de laboratorio
Ante un binario desconocido en un entorno aislado, este recorrido da una primera imagen en menos de media hora:
- Antes de Ghidra: calcula el hash, mira el tipo de fichero, las cabeceras y las secciones; una sección con entropía altísima y pocos imports sugiere empaquetado (y ahí Ghidra estático se queda corto sin desempaquetar primero)
- Imports: en el Symbol Tree, revisa las funciones importadas — `WinHTTP`/`ws2_32` (red), `advapi32` de registro y servicios (persistencia), `crypt32` (cifrado), `VirtualAlloc` + `CreateThread` (inyección)
- Strings: rutas, claves de registro, nombres de dominio, mensajes, mutex; cada uno con sus xrefs
- Función de entrada: baja hasta la lógica principal y ve marcando las funciones por lo que hacen
- Anota y documenta: renombra, comenta, y exporta un pequeño informe con los indicadores (dominios, IPs, mutex, claves) que encuentres
Marco legal y de seguridad
Ejecuta y analiza únicamente binarios propios, de retos públicos, o muestras de malware dentro de un laboratorio aislado y sin salida a la red — nunca en tu equipo de trabajo · La ingeniería inversa de software de terceros puede chocar con la licencia del producto y con la normativa de propiedad intelectual; en la UE está acotada a supuestos concretos (interoperabilidad, corrección de errores, seguridad) y con matices por país · Analizar binarios para atacar sistemas ajenos, o distribuir cracks y parches de evasión de licencias, es ilícito — en España son de aplicación los artículos 197 bis, 197 ter y 264 del Código Penal, además de la normativa sobre propiedad intelectual · Este artículo cubre entender qué hace un programa con fines de análisis y defensa, no desempaquetar protecciones comerciales ni construir exploits
Referencias
ghidra-sre.org y github.com/NationalSecurityAgency/ghidra — Descarga, código y documentación · The Ghidra Book (Chris Eagle y Kara Nance, No Starch Press) — Manual de referencia completo · ghidra.re — Recursos comunitarios, cursos y colección de scripts · crackmes.one y los retos de reversing de HTB o CyberDefenders — Binarios para practicar · Cutter (rizin) — GUI libre para contrastar el análisis
Conclusión
Ghidra bajó a cero el coste de hacer ingeniería inversa en serio: un descompilador multiarquitectura solvente, proyectos colaborativos con control de versiones y una API completa para automatizar, todo con licencia libre. El pseudocódigo que genera no es la verdad absoluta —es una inferencia que hay que contrastar con el ensamblador— pero como punto de partida para entender un binario no tiene rival en su rango de precio.
El trabajo no lo hace la herramienta: lo hace el analista que va renombrando, retipando y aplicando estructuras hasta que `FUN_00401560` se convierte en `comprobar_licencia` y el desplazamiento `*(param_1 + 0x8)` se convierte en `config->servidor`. Empieza con un crackme, aprende el bucle entrar-por-string, subir-por-xrefs, aislar-la-función, anotar, y aplícalo luego a lo que importe — siempre en un laboratorio aislado y sobre binarios que tengas derecho a analizar.
unfantasmaenelsistema.com | Seguridad, sistemas y todo lo que no debería funcionar (pero funciona)

