Communitygithub.com

Análisis de Malware Go con Ghidra

Realiza ingeniería inversa de malware compilado en Go utilizando Ghidra, mediante el análisis de la estructura buildinfo del binario.

¿Qué es Análisis de Malware Go con Ghidra?

Esta habilidad está diseñada para analistas de seguridad e ingenieros inversos que necesitan examinar binarios maliciosos escritos en Go (Golang). Go se ha vuelto popular entre los autores de malware debido a su compilación cruzada, enlace estático y la complejidad que introduce para la ingeniería inversa. La habilidad proporciona un flujo de trabajo completo: desde el análisis inicial del binario para extraer metadatos (versión de Go, tabla pclntab, nombres de funciones) hasta el uso de scripts de Ghidra para etiquetar estructuras del runtime de Go, recuperar nombres de funciones (incluso en binarios ofuscados con herramientas como garble) y extraer dependencias de terceros. Incluye scripts de Python para análisis preliminar y un script de Ghidra para análisis automatizado dentro de la herramienta. Funciona en plataformas Linux, macOS y Windows, y es útil para crear reglas de detección, realizar búsquedas de amenazas o validar la cobertura de monitoreo contra técnicas de ataque que utilizan malware Go.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/analyzing-golang-malware-with-ghidra

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Análisis de Malware Golang con Ghidra

Resumen

Go (Golang) se ha convertido en un lenguaje popular para los autores de malware debido a sus capacidades de compilación cruzada, enlace estático que produce binarios autónomos y la complejidad que introduce para la ingeniería inversa. Los binarios Go contienen todo el runtime, la biblioteca estándar y todas las dependencias enlazadas estáticamente, lo que da como resultado binarios grandes (a menudo de 5 a 15 MB) con miles de funciones. Ghidra tiene dificultades con los formatos de cadena específicos de Go (no terminados en nulo), nombres de funciones eliminados y patrones de concurrencia de goroutines. Herramientas especializadas como GoResolver (Volexity, 2025) utilizan similitud de grafos de flujo de control para desofuscar y recuperar automáticamente nombres de funciones en binarios Go ofuscados o sin símbolos.

Cuándo Usar

  • Al investigar incidentes de seguridad que requieran analizar malware Golang con Ghidra
  • Al construir reglas de detección o consultas de búsqueda de amenazas para este dominio
  • Cuando los analistas de SOC necesiten procedimientos estructurados para este tipo de análisis
  • Al validar la cobertura de monitoreo de seguridad para técnicas de ataque relacionadas

Requisitos Previos

  • Ghidra 11.0+ con JDK 17+
  • Plugin GoResolver (para recuperación de nombres de funciones)
  • Go Reverse Engineering Tool Kit (go-re.tk)
  • Python 3.9+ para scripts auxiliares
  • Comprensión de los componentes internos del runtime de Go (goroutines, canales, interfaces)
  • Familiaridad con la estructura de los binarios Go (pclntab, moduledata, itab)

Conceptos Clave

Estructura del Binario Go

Los binarios Go incrustan metadatos enriquecidos en la estructura pclntab (Tabla de Líneas de PC), que asigna contadores de programa a nombres de funciones, archivos fuente y números de línea. Incluso los binarios sin símbolos conservan estos metadatos. La estructura moduledata contiene punteros a información de tipos, itabs (tablas de interfaz) y el propio pclntab. Las cadenas Go se almacenan como un par puntero-longitud en lugar de cadenas C terminadas en nulo.

Recuperación de Funciones en Binarios Sin Símbolos

A pesar de eliminar las tablas de símbolos, los binarios Go retienen los nombres de las funciones dentro del pclntab. Sin embargo, herramientas de ofuscación como garble renombran las funciones con cadenas aleatorias. GoResolver aborda esto calculando firmas de grafos de flujo de control de funciones ofuscadas y comparándolas con una base de datos de funciones conocidas de la biblioteca estándar de Go y paquetes de terceros.

Extracción de Dependencias (Crate)

La gestión de dependencias de Go incrusta rutas de módulos y cadenas de versión en el binario. Extraer estas revela las dependencias de terceros del malware (bibliotecas HTTP, paquetes de cifrado, frameworks C2), lo que proporciona información sobre las capacidades sin necesidad de una ingeniería inversa completa.

Flujo de Trabajo

Paso 1: Análisis Inicial del Binario

#!/usr/bin/env python3
"""Analizar metadatos de un binario Go para análisis de malware."""
import struct
import sys
import re


def find_go_build_info(data):
    """Extraer información de compilación de Go del binario."""
    # Mágica de buildinfo de Go: \xff Go buildinf:
    magic = b'\xff Go buildinf:'
    offset = data.find(magic)
    if offset == -1:
        return None

    print(f"[+] Información de build de Go en offset 0x{offset:x}")

    # Extraer cadena de versión de Go cercana
    go_version = re.search(rb'go\d+\.\d+(?:\.\d+)?', data[offset:offset+256])
    if go_version:
        print(f"  Versión de Go: {go_version.group().decode()}")

    return offset


def find_pclntab(data):
    """Localizar la estructura pclntab (Tabla de Líneas de PC)."""
    # Los bytes mágicos de pclntab varían según la versión de Go
    magics = {
        b'\xfb\xff\xff\xff\x00\x00': "Go 1.2-1.15",
        b'\xfa\xff\xff\xff\x00\x00': "Go 1.16-1.17",
        b'\xf1\xff\xff\xff\x00\x00': "Go 1.18-1.19",
        b'\xf0\xff\xff\xff\x00\x00': "Go 1.20+",
    }

    for magic, version in magics.items():
        offset = data.find(magic)
        if offset != -1:
            print(f"[+] pclntab encontrado en offset 0x{offset:x} ({version})")
            return offset, version

    return None, None


def extract_function_names(data, pclntab_offset):
    """Extraer nombres de funciones del pclntab."""
    if pclntab_offset is None:
        return []

    functions = []
    # Las cadenas de nombres de funciones siguen patrones específicos
    func_pattern = re.compile(
        rb'(?:main|runtime|fmt|net|os|crypto|encoding|io|sync|'
        rb'syscall|reflect|strings|bytes|path|time|math|sort|'
        rb'github\.com|golang\.org)[/\.][\w/.]+',
    )

    for match in func_pattern.finditer(data):
        name = match.group().decode('utf-8', errors='replace')
        if len(name) > 4 and len(name) < 200:
            functions.append(name)

    return sorted(set(functions))


def extract_go_strings(data):
    """Extraer cadenas al estilo Go (pares puntero+longitud)."""
    # Las cadenas Go no terminan en nulo; extraer secuencias legibles
    strings = []
    ascii_pattern = re.compile(rb'[\x20-\x7e]{10,}')

    for match in ascii_pattern.finditer(data):
        s = match.group().decode('ascii')
        # Filtrar cadenas interesantes para malware
        interesting = [
            'http', 'https', 'tcp', 'udp', 'dns',
            'cmd', 'shell', 'exec', 'upload', 'download',
            'encrypt', 'decrypt', 'key', 'token', 'password',
            'c2', 'beacon', 'agent', 'implant', 'bot',
            'mutex', 'persist', 'registry', 'scheduled',
        ]
        if any(kw in s.lower() for kw in interesting):
            strings.append(s)

    return strings


def extract_dependencies(data):
    """Extraer dependencias de módulos Go del binario."""
    deps = []
    # Las rutas de módulos siguen el patrón: github.com/usuario/repo
    dep_pattern = re.compile(
        rb'((?:github\.com|gitlab\.com|golang\.org|gopkg\.in|'
        rb'go\.etcd\.io|google\.golang\.org)/[^\x00\s]{5,80})'
    )

    for match in dep_pattern.finditer(data):
        dep = match.group().decode('utf-8', errors='replace')
        deps.append(dep)

    unique_deps = sorted(set(deps))
    return unique_deps


def analyze_go_binary(filepath):
    """Análisis completo de un binario de malware Go."""
    with open(filepath, 'rb') as f:
        data = f.read()

    print(f"[+] Analizando binario Go: {filepath}")
    print(f"  Tamaño del archivo: {len(data):,} bytes")
    print("=" * 60)

    # Información de compilación
    find_go_build_info(data)

    # pclntab
    pclntab_offset, go_version = find_pclntab(data)

    # Funciones
    functions = extract_function_names(data, pclntab_offset)
    print(f"\n[+] Recuperados {len(functions)} nombres de funciones")

    # Categorizar funciones
    categories = {
        "network": [], "crypto": [], "os_exec": [],
        "file_io": [], "main": [], "third_party": [],
    }
    for f in functions:
        if 'net/' in f or 'http' in f.lower():
            categories["network"].append(f)
        elif 'crypto' in f:
            categories["crypto"].append(f)
        elif 'os/exec' in f or 'syscall' in f:
            categories["os_exec"].append(f)
        elif 'os.' in f or 'io/' in f:
            categories["file_io"].append(f)
        elif f.startswith('main.'):
            categories["main"].append(f)
        elif 'github.com' in f or 'golang.org' in f:
            categories["third_party"].append(f)

    for cat, funcs in categories.items():
        if funcs:
            print(f"\n  [{cat}] ({len(funcs)} funciones):")
            for fn in funcs[:10]:
                print(f"    {fn}")

    # Dependencias
    deps = extract_dependencies(data)
    print(f"\n[+] Dependencias ({len(deps)}):")
    for dep in deps[:20]:
        print(f"    {dep}")

    # Cadenas sospechosas
    sus_strings = extract_go_strings(data)
    print(f"\n[+] Cadenas sospechosas ({len(sus_strings)}):")
    for s in sus_strings[:20]:
        print(f"    {s}")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Uso: {sys.argv[0]} <binario_go>")
        sys.exit(1)
    analyze_go_binary(sys.argv[1])

Paso 2: Script de Análisis en Ghidra

# Script de Ghidra (ejecutar dentro del administrador de scripts de Ghidra)
# Guardar como AnalyzeGoBinary.py en el directorio de scripts de Ghidra

# @category MalwareAnalysis
# @description Analizar la estructura de un binario Go y recuperar metadatos

def analyze_go_binary_ghidra():
    """Script de Ghidra para análisis de binarios Go."""
    from ghidra.program.model.mem import MemoryAccessException

    program = getCurrentProgram()
    memory = program.getMemory()
    listing = program.getListing()

    print("[+] Script de Análisis de Binario Go")
    print(f"  Programa: {program.getName()}")

    # Encontrar pclntab
    pclntab_magics = [
        bytes([0xf0, 0xff, 0xff, 0xff]),  # Go 1.20+
        bytes([0xf1, 0xff, 0xff, 0xff]),  # Go 1.18-1.19
        bytes([0xfa, 0xff, 0xff, 0xff]),  # Go 1.16-1.17
        bytes([0xfb, 0xff, 0xff, 0xff]),  # Go 1.2-1.15
    ]

    for magic in pclntab_magics:
        addr = memory.findBytes(
            program.getMinAddress(), magic, None, True, None
        )
        if addr:
            print(f"[+] pclntab encontrado en {addr}")
            # Crear etiqueta
            program.getSymbolTable().createLabel(
                addr, "go_pclntab", None,
                ghidra.program.model.symbol.SourceType.ANALYSIS
            )
            break

    # Corregir definiciones de cadenas Go
    # Las cadenas Go son ptr+len, no terminadas en nulo
    print("[+] Corrigiendo referencias a cadenas Go...")

    # Buscar nombres de funciones que contengan rutas de paquetes
    symbol_table = program.getSymbolTable()
    func_count = 0
    for symbol in symbol_table.getAllSymbols(True):
        name = symbol.getName()
        if ('.' in name and
            any(pkg in name for pkg in
                ['main.', 'runtime.', 'net.', 'crypto.', 'os.'])):
            func_count += 1

    print(f"[+] Encontrados {func_count} símbolos de funciones Go")


# Ejecutar
analyze_go_binary_ghidra()

Criterios de Validación

  • Versión de Go e información de compilación extraída del binario
  • pclntab localizado y analizado para la recuperación de nombres de funciones
  • Dependencias de terceros identificadas, revelando capacidades del malware
  • Funciones del paquete principal enumeradas para análisis dirigido
  • Funciones de red, criptografía y ejecución de SO categorizadas
  • El análisis de Ghidra etiqueta correctamente las estructuras del runtime de Go

Referencias

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

abusing-dpapi-for-credential-access

Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys) online or offline using SharpDPAPI, SharpChrome, Mimikatz, or Impacket

abusing-shadow-credentials-for-privesc

Take over Active Directory accounts by writing attacker-controlled public keys to msDS-KeyCredentialLink (Shadow Credentials) with pyWhisker, Whisker, or Certipy, then authenticate via PKINIT to recover the target

achieving-cmmc-level-2-compliance

>-

acquiring-disk-image-with-dd-and-dcfldd

Create forensically sound bit-for-bit disk images with dd or dcfldd on a Linux forensic workstation, preserving evidence integrity through hash verification (MD5/SHA) during acquisition. Use when imaging a suspect drive, USB device, or memory card for investigation, preserving volatile disk evidence during incident response, or producing a verified copy for legal or law-enforcement proceedings before any destructive analysis.

analyzing-active-directory-acl-abuse

Detect dangerous ACL misconfigurations in Active Directory using ldap3

analyzing-android-malware-with-apktool

Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.

analyzing-api-gateway-access-logs

Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect

analyzing-apt-group-with-mitre-navigator

Query ATT&CK data with attackcti, mitreattack-python, and stix2, then build MITRE ATT&CK Navigator layers and multi-layer heatmap overlays mapping one or more APT groups

analyzing-azure-activity-logs-for-threats

Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query

analyzing-bootkit-and-rootkit-samples

Analyzes bootkit and advanced rootkit malware infecting the Master

analyzing-browser-forensics-with-hindsight

Parse Chromium-based browser databases with Hindsight to extract and correlate browsing history, downloads, cookies, cached content, autofill data, saved passwords, and extensions from Chrome, Edge, Brave, Opera, and Vivaldi into a unified timeline (XLSX, JSON, or SQLite output). Use during incident response, insider-threat investigations, or criminal cases when you need to reconstruct a user

analyzing-campaign-attribution-evidence

Systematically evaluate cyber-campaign evidence to attribute an operation to a threat actor, using the Diamond Model and Analysis of Competing Hypotheses (ACH) to weigh infrastructure overlaps, TTP consistency, malware code similarity, and timing/language artifacts into confidence-weighted attribution assessments. Use when an incident investigation needs a defensible attribution confidence level.

analyzing-certificate-transparency-for-phishing

Monitor Certificate Transparency logs using crt.sh and Certstream to

analyzing-cloud-storage-access-patterns

Detect abnormal access in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics for after-hours bulk downloads, new-IP access, and API-call spikes (e.g. GetObject) via statistical baselines and time-series anomaly detection. Use when investigating suspected cloud data exfiltration or building related detection rules.

analyzing-cobalt-strike-beacon-configuration

Extract and analyze Cobalt Strike beacon configuration from PE files

analyzing-cobaltstrike-malleable-c2-profiles

Parse and analyze Cobalt Strike Malleable C2 profiles with dissect.cobaltstrike (profiles and beacon-payload configs) and pyMalleableC2 (AST parsing) to extract HTTP/DNS transforms, URIs, headers, sleep/jitter, and injection behavior, then generate network detection signatures. Use when reverse-engineering a captured malleable profile or building detections against Cobalt Strike Beacon traffic.

analyzing-command-and-control-communication

Analyzes malware C2 communication over HTTP, HTTPS, DNS, and custom

analyzing-cyber-kill-chain

Analyzes intrusion activity against the Lockheed Martin Cyber Kill Chain

analyzing-disk-image-with-autopsy

Perform comprehensive forensic analysis of raw (dd), E01, or AFF disk images with Autopsy and The Sleuth Kit, recovering deleted files, examining metadata and embedded artifacts, keyword searching, and building investigation timelines with visual reports. Use for structured analysis of a forensic disk image or when stakeholders need visual reports from evidence.

analyzing-dns-logs-for-exfiltration

Analyzes DNS query logs to detect data exfiltration via DNS tunneling,

Skills relacionados