Saltar al contenido

Ghidra desde cero: ingeniería inversa de binarios sin gastarte una licencia

    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

    VentanaPara qué sirve
    ListingEl desensamblado anotado: direcciones, bytes, instrucciones, comentarios, referencias
    DecompilerEl 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 ManagerCatálogo de tipos: los del binario, los de librerías y los que definas tú
    FunctionsTabla de todas las funciones con nombre, dirección, tamaño y firma
    Defined StringsTodas las cadenas de texto localizadas, con su dirección y codificación
    BytesVolcado 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ónTeclaEfecto
    Renombrar función o variableLLe pones un nombre con significado; se propaga a todas las vistas
    Cambiar el tipo de una variableCtrl+LRetipar de int a un puntero o a una estructura arregla la aritmética que se ve
    Editar la firma de la funciónFAjustas 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 datoDMarca 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

    HerramientaLicenciaFuerte enNota
    GhidraLibre (Apache 2.0)Descompilador multiarquitectura, proyectos colaborativos, scriptingEl mejor punto de partida hoy si no pagas licencia
    IDA FreeGratuita, no comercialDescompilador solo x86-64, ecosistema de plugins enormeLa versión de pago sigue siendo el estándar de la industria
    radare2 / rizinLibre (LGPL)Análisis desde terminal, scripting, automatización, forenseCurva dura; rizin + Cutter dan una GUI más amable
    Binary NinjaComercial (asequible)API muy limpia, IL propio, buena UXAlternativa 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)

    Resumen de privacidad

    Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible. La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudar a nuestro equipo a comprender qué secciones de la web encuentras más interesantes y útiles.