К основному содержанию
скилл CX Codex

analyzing-golang-malware-with-ghidra — скилл для Claude Code: разбор

Разбирает Go-бинарники в Ghidra: достаёт buildinfo, pclntab, имена функций и зависимости. Нужен при анализе образца, собранного на Go.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill analyzing-golang-malware-with-ghidra -a claude-code
Открыть на GitHub

Что делает analyzing-golang-malware-with-ghidra

Скилл ведёт агента по разбору Go-малвари в Ghidra. Go-бинарники статически линкуют рантайм, стандартную библиотеку и все зависимости — отсюда размер в мегабайтах и тысячи функций, с которыми Ghidra сама по себе справляется плохо. Скилл объясняет, где в бинарнике лежит метадата и как её вытащить.

Внутри — разбор структур pclntab и moduledata, поиск buildinfo по сигнатуре и восстановление имён функций в stripped-сборках. Отдельный шаг — деобфускация garble-паков через GoResolver: он считает сигнатуры графа потока управления и сопоставляет их с базой известных функций. Ещё скилл показывает, как вытащить пути модулей и версии, чтобы по сторонним пакетам понять возможности образца без полного реверса.

Заранее понадобятся Ghidra 11.0+ с JDK 17+, плагин GoResolver, Go Reverse Engineering Tool Kit и Python 3.9+ для вспомогательных скриптов. Без понимания внутренностей рантайма Go — горутин, каналов, интерфейсов — шаги по pclntab и itab читаются тяжело, так что это не тот случай, когда скилл закрывает пробел в знаниях сам.

Какие задачи решает

  • вытащить имена функций из stripped Go-бинарника
  • найти buildinfo и определить версию Go, которой собран образец
  • снять обфускацию garble через сопоставление сигнатур CFG
  • собрать список сторонних зависимостей и версий модулей
  • отличить Go-строки от C-строк при разборе в Ghidra

Примеры запросов агенту

  • разбери этот Go-бинарник в Ghidra: найди pclntab и вытащи имена функций
  • этот образец упакован garble — восстанови имена через GoResolver
  • вытащи из бинарника пути модулей и версии зависимостей

Как установить analyzing-golang-malware-with-ghidra

1Через Skills CLI (Vercel)

npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill analyzing-golang-malware-with-ghidra -a claude-code

2Вручную: положить файлы

~/.claude/skills/analyzing-golang-malware-with-ghidra/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/analyzing-golang-malware-with-ghidra/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о analyzing-golang-malware-with-ghidra

Как установить analyzing-golang-malware-with-ghidra в Claude?

Выполните npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill analyzing-golang-malware-with-ghidra -a claude-code. После этого файл скилла окажется в ~/.claude/skills/analyzing-golang-malware-with-ghidra/SKILL.md.

Что делает analyzing-golang-malware-with-ghidra?

Проводит агента по реверсу Go-малвари в Ghidra: разбор buildinfo и pclntab, восстановление имён функций в stripped и обфусцированных сборках, извлечение модулей и типов из бинарника.

Что нужно для работы скилла?

Ghidra 11.0+ с JDK 17+, плагин GoResolver для восстановления имён, Go Reverse Engineering Tool Kit и Python 3.9+ для вспомогательных скриптов.

Исходный текст

SKILL.md · Apache-2.0
---
name: analyzing-golang-malware-with-ghidra
description: Reverse engineer Go-compiled malware in Ghidra by parsing Go buildinfo
  and pclntab structures, recovering stripped/obfuscated function names (e.g. via
  GoResolver), and extracting embedded module/dependency strings and types from Go
  binaries. Use when analyzing a Go-language malware sample, deobfuscating a garble-packed
  Go binary, or recovering function names and third-party dependencies from a stripped
  Go executable.
domain: cybersecurity
subdomain: malware-analysis
tags:
- golang
- ghidra
- reverse-engineering
- malware-analysis
- binary-analysis
- go-malware
- disassembly
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1027
- T1620
- T1140
- T1059
---
# Analyzing Golang Malware with Ghidra

## Overview

Go (Golang) has become a popular language for malware authors due to its cross-compilation capabilities, static linking that produces self-contained binaries, and the complexity it introduces for reverse engineering. Go binaries contain the entire runtime, standard library, and all dependencies statically linked, resulting in large binaries (often 5-15MB) with thousands of functions. Ghidra struggles with Go-specific string formats (non-null-terminated), stripped function names, and goroutine concurrency patterns. Specialized tools like GoResolver (Volexity, 2025) use control-flow graph similarity to automatically deobfuscate and recover function names in stripped or obfuscated Go binaries.


## When to Use

- When investigating security incidents that require analyzing golang malware with ghidra
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques

## Prerequisites

- Ghidra 11.0+ with JDK 17+
- GoResolver plugin (for function name recovery)
- Go Reverse Engineering Tool Kit (go-re.tk)
- Python 3.9+ for helper scripts
- Understanding of Go runtime internals (goroutines, channels, interfaces)
- Familiarity with Go binary structure (pclntab, moduledata, itab)

## Key Concepts

### Go Binary Structure

Go binaries embed rich metadata in the `pclntab` (PC Line Table) structure, which maps program counters to function names, source files, and line numbers. Even stripped binaries retain this metadata. The `moduledata` structure contains pointers to type information, itabs (interface tables), and the pclntab itself. Go strings are stored as a pointer-length pair rather than null-terminated C strings.

### Function Recovery in Stripped Binaries

Despite stripping symbol tables, Go binaries retain function names within the pclntab. However, obfuscation tools like garble rename functions to random strings. GoResolver addresses this by computing control-flow graph signatures of obfuscated functions and matching them against a database of known Go standard library and third-party package functions.

### Crate/Dependency Extraction

Go's dependency management embeds module paths and version strings in the binary. Extracting these reveals the malware's third-party dependencies (HTTP libraries, encryption packages, C2 frameworks), which provides insight into capabilities without full reverse engineering.

## Workflow

### Step 1: Initial Binary Analysis

```python
#!/usr/bin/env python3
"""Analyze Go binary metadata for malware analysis."""
import struct
import sys
import re


def find_go_build_info(data):
    """Extract Go build information from binary."""
    # Go buildinfo magic: \xff Go buildinf:
    magic = b'\xff Go buildinf:'
    offset = data.find(magic)
    if offset == -1:
        return None

    print(f"[+] Go build info at offset 0x{offset:x}")

    # Extract Go version string nearby
    go_version = re.search(rb'go\d+\.\d+(?:\.\d+)?', data[offset:offset+256])
    if go_version:
        print(f"  Go Version: {go_version.group().decode()}")

    return offset


def find_pclntab(data):
    """Locate the pclntab (PC Line Table) structure."""
    # pclntab magic bytes vary by Go version
    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 found at 0x{offset:x} ({version})")
            return offset, version

    return None, None


def extract_function_names(data, pclntab_offset):
    """Extract function names from pclntab."""
    if pclntab_offset is None:
        return []

    functions = []
    # Function name strings follow specific patterns
    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):
    """Extract Go-style strings (pointer+length pairs)."""
    # Go strings are not null-terminated; extract readable sequences
    strings = []
    ascii_pattern = re.compile(rb'[\x20-\x7e]{10,}')

    for match in ascii_pattern.finditer(data):
        s = match.group().decode('ascii')
        # Filter for interesting malware strings
        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):
    """Extract Go module dependencies from binary."""
    deps = []
    # Module paths follow pattern: github.com/user/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):
    """Full analysis of Go malware binary."""
    with open(filepath, 'rb') as f:
        data = f.read()

    print(f"[+] Analyzing Go binary: {filepath}")
    print(f"  File size: {len(data):,} bytes")
    print("=" * 60)

    # Build info
    find_go_build_info(data)

    # pclntab
    pclntab_offset, go_version = find_pclntab(data)

    # Functions
    functions = extract_function_names(data, pclntab_offset)
    print(f"\n[+] Recovered {len(functions)} function names")

    # Categorize functions
    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)} functions):")
            for fn in funcs[:10]:
                print(f"    {fn}")

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

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


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

### Step 2: Ghidra Analysis Script

```python
# Ghidra script (run within Ghidra's script manager)
# Save as AnalyzeGoBinary.py in Ghidra scripts directory

# @category MalwareAnalysis
# @description Analyze Go binary structure and recover metadata

def analyze_go_binary_ghidra():
    """Ghidra script for Go binary analysis."""
    from ghidra.program.model.mem import MemoryAccessException

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

    print("[+] Go Binary Analysis Script")
    print(f"  Program: {program.getName()}")

    # Find 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 found at {addr}")
            # Create label
            program.getSymbolTable().createLabel(
                addr, "go_pclntab", None,
                ghidra.program.model.symbol.SourceType.ANALYSIS
            )
            break

    # Fix Go string definitions
    # Go strings are ptr+len, not null terminated
    print("[+] Fixing Go string references...")

    # Search for function names containing package paths
    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"[+] Found {func_count} Go function symbols")


# Execute
analyze_go_binary_ghidra()
```

## Validation Criteria

- Go version and build information extracted from binary
- pclntab located and parsed for function name recovery
- Third-party dependencies identified revealing malware capabilities
- Main package functions enumerated for targeted analysis
- Network, crypto, and OS exec functions categorized
- Ghidra analysis correctly labels Go runtime structures

## References

- [CUJO AI - Reverse Engineering Go Binaries with Ghidra](https://cujo.com/blog/reverse-engineering-go-binaries-with-ghidra/)
- [Volexity GoResolver](https://www.volexity.com/blog/2025/04/01/goresolver-using-control-flow-graph-similarity-to-deobfuscate-golang-binaries-automatically/)
- [Go Reverse Engineering Tool Kit](https://go-re.tk/about/)
- [SentinelOne AlphaGolang](https://www.sentinelone.com/labs/alphagolang-a-step-by-step-go-malware-reversing-methodology-for-ida-pro/)
- [Go Binary Reversing Notes](https://gist.github.com/0xdevalias/4e430914124c3fd2c51cb7ac2801acba)

© mahipal · Apache-2.0 · mukul975/Anthropic-Cybersecurity-Skills

Похожие скиллы

Всё по теме «Безопасность» →
ghidra-headless trailofbits Скилл запускает headless-анализатор Ghidra и вытаскивает из бинаря функции, строки, символы и граф вызовов. Пригодится, когда исходников нет, а разобрать надо. CX Codex +1 507установок binary-analysis-patterns Dávid Balatoni Скилл помогает разбирать дизассемблированный код, восстанавливать логику программ и находить знакомые шаблоны в бинарных файлах. CX Codex 10 900установок ghidra mitsuhiko Запускает headless-анализ исполняемых файлов через Ghidra, декомпилирует код в Си и извлекает строки или символы. Пригодится при исследовании прошивок и программ без графического интерфейса. CX Codex +1 652установок ctf-reverse ljagiello Справочник по реверс-инжинирингу для CTF: помогает агенту разбирать скомпилированные бинарники, распаковывать протекторы и анализировать виртуальные машины. CX Codex +1 10 100установок code-obfuscation-deobfuscation yaklang Скилл помогает анализировать и снимать защиту в нативных бинарниках: от мусорного кода и непрозрачных предикатов до виртуализации и сплющивания графа потока управления. CX Codex +1 4 000установок reverse-engineer sickn33 Скилл задаёт методику реверс-инжиниринга бинарных файлов: статический и динамический анализ, поиск паттернов и скрипты для декомпиляторов. CX Codex +1 892установок

Из того же набора89

analyzing-kubernetes-audit-logs Разбирает audit-логи kube-apiserver в формате JSON lines и находит exec в под, чтение секретов, правки RBAC и анонимный доступ. CX Codex +1 450установок analyzing-sbom-for-supply-chain-vulnerabilities Разбирает SBOM в форматах CycloneDX и SPDX, сверяет компоненты с базой CVE через NVD 2.0 API и строит граф зависимостей. Пригодится, когда нужно оценить риски сторонних библиотек. CX Codex +1 444установок abusing-dpapi-for-credential-access Руководство по извлечению секретов Windows DPAPI: сохранённых паролей Credential Manager, кук браузеров и ключей. Пригодится на пентестах после получения доступа к хосту. CX Codex +1 442установок analyzing-linux-kernel-rootkits Скилл ищет признаки руткитов уровня ядра в дампах памяти Linux и на работающей системе. Пригодится для расследований и форензики. CX Codex +1 442установок analyzing-network-packets-with-scapy Скилл направляет анализ сетевых пакетов через Scapy: от разбора pcap до поиска аномального трафика. Нужен для авторизованного тестирования и сетевой криминалистики. CX Codex +1 441установок analyzing-ios-app-security-with-objection Скилл для runtime-тестирования iOS-приложений через Objection и Frida: дамп keychain, обход SSL pinning, проверка защиты от джейлбрейка. CX Codex +1 436установок implementing-secret-scanning-with-gitleaks Скилл помогает настроить Gitleaks для поиска секретов в Git-репозитории и блокировать их попадание в историю. Нужен для локальных хуков и CI/CD. CX Codex +1 439установок testing-for-json-web-token-vulnerabilities Пошаговое руководство для агента по аудиту JWT: поиск обхода проверки подписи, подмена RS256 на HS256, инъекции в kid и перебор секретов. CX Codex +1 431установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой