Communitygithub.com

使用 Ghidra 分析 Golang 惡意軟體

透過解析 Go buildinfo 結構,對 Go 編譯的惡意軟體進行逆向工程。

使用 Ghidra 分析 Golang 惡意軟體 是什麼?

此技能提供了一套完整的工作流程,用於在 Ghidra 中分析 Golang 惡意軟體。Go 二進位檔案具有獨特的結構特徵,例如靜態連結、巨大的二進位體積以及非空終止的字串格式,這些都使得逆向工程變得複雜。此技能涵蓋了提取 Go buildinfo 資訊、定位 pclntab (PC 行表) 以恢復函式名稱、提取第三方依賴項以及辨識可疑字串的關鍵技術。它還展示了如何使用 GoResolver 等專用工具進行控制流圖相似性分析,以處理被 garble 這類工具混淆的函式。支援的平台包括 Ghidra 11.0+ 和 Python 3.9+。此技能對於分析惡意 Go 二進位檔案的 SOC 分析師、威脅研究人員和惡意軟體分析師特別有價值,因為它提供了結構化的方法來提取關鍵的可執行檔特徵和功能標記。

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

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

使用 Ghidra 分析 Golang 惡意軟體 是做什麼的?

概述

Go (Golang) 因其跨平台編譯能力、可產生自包含二進位檔案的靜態連結特性,以及為逆向工程帶來的複雜性,已成為惡意軟體作者喜愛的語言。Go 二進位檔案包含了完整的執行時期環境、標準程式庫以及所有靜態連結的依賴項,導致產生的二進位檔案通常體積龐大 (5-15MB),且包含數千個函式。Ghidra 在處理 Go 特有的字串格式 (非空終止)、剝離的符號表以及 Goroutine 並行模式時較為困難。像 GoResolver (Volexity, 2025) 這類專用工具,利用控制流圖相似性來自動去混淆並恢復被剝離或混淆的 Go 二進位檔案中的函式名稱。

使用時機

  • 在調查需要分析 Golang 惡意軟體的安全事件時
  • 在為此領域建立偵測規則或威脅獵捕查詢時
  • 當 SOC 分析師需要此分析類型的結構化程序時
  • 在驗證相關攻擊技術的安全監控覆蓋範圍時

先決條件

  • Ghidra 11.0+ 搭配 JDK 17+
  • GoResolver 插件 (用於函式名稱恢復)
  • Go 逆向工程工具包 (go-re.tk)
  • Python 3.9+ 用於輔助腳本
  • 了解 Go 執行時期內部機制 (goroutine、channel、interface)
  • 熟悉 Go 二進位結構 (pclntab、moduledata、itab)

關鍵概念

Go 二進位結構

Go 二進位檔案在 pclntab (PC 行表) 結構中嵌入了豐富的中繼資料,該結構將程式計數器對應到函式名稱、原始碼檔案和行號。即使是剝離了符號表的二進位檔案也會保留此中繼資料。moduledata 結構包含指向型別資訊、itab (介面表) 和 pclntab 本身的指標。Go 字串儲存為 (指標, 長度) 對,而非以空字元結尾的 C 字串。

剝離二進位檔案中的函式恢復

儘管剝離了符號表,Go 二進位檔案仍會在 pclntab 中保留函式名稱。然而,像 garble 這樣的混淆工具會將函式重新命名為隨機字串。GoResolver 透過計算混淆函式的控制流圖簽名,並與已知 Go 標準程式庫和第三方套件函式的資料庫進行比對來解決此問題。

套件/依賴項提取

Go 的依賴項管理將模組路徑和版本字串嵌入到二進位檔案中。提取這些資訊可以揭示惡意軟體的第三方依賴項 (HTTP 程式庫、加密套件、C2 框架),無需完整逆向工程即可了解其功能。

工作流程

第一步:初始二進位分析

#!/usr/bin/env python3
"""分析 Go 二進位檔案的中繼資料以進行惡意軟體分析。"""
import struct
import sys
import re


def find_go_build_info(data):
    """從二進位檔案中提取 Go build 資訊。"""
    # Go buildinfo 魔術字串: \xff Go buildinf:
    magic = b'\xff Go buildinf:'
    offset = data.find(magic)
    if offset == -1:
        return None

    print(f"[+] Go build 資訊位於偏移量 0x{offset:x}")

    # 在附近提取 Go 版本字串
    go_version = re.search(rb'go\d+\.\d+(?:\.\d+)?', data[offset:offset+256])
    if go_version:
        print(f"  Go 版本: {go_version.group().decode()}")

    return offset


def find_pclntab(data):
    """定位 pclntab (PC 行表) 結構。"""
    # pclntab 魔術字節因 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 位於偏移量 0x{offset:x} ({version})")
            return offset, version

    return None, None


def extract_function_names(data, pclntab_offset):
    """從 pclntab 中提取函式名稱。"""
    if pclntab_offset is None:
        return []

    functions = []
    # 函式名稱字串遵循特定模式
    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):
    """提取 Go 風格的字串 (指標+長度對)。"""
    # Go 字串不是以空字元結尾的;提取可讀的序列
    strings = []
    ascii_pattern = re.compile(rb'[\x20-\x7e]{10,}')

    for match in ascii_pattern.finditer(data):
        s = match.group().decode('ascii')
        # 過濾感興趣的惡意軟體字串
        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):
    """從二進位檔案中提取 Go 模組依賴項。"""
    deps = []
    # 模組路徑遵循模式: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):
    """對 Go 惡意軟體二進位檔案進行完整分析。"""
    with open(filepath, 'rb') as f:
        data = f.read()

    print(f"[+] 分析 Go 二進位檔案: {filepath}")
    print(f"  檔案大小: {len(data):,} 字節")
    print("=" * 60)

    # Build 資訊
    find_go_build_info(data)

    # pclntab
    pclntab_offset, go_version = find_pclntab(data)

    # 函式
    functions = extract_function_names(data, pclntab_offset)
    print(f"\n[+] 恢復了 {len(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)} 個函式):")
            for fn in funcs[:10]:
                print(f"    {fn}")

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

    # 可疑字串
    sus_strings = extract_go_strings(data)
    print(f"\n[+] 可疑字串 ({len(sus_strings)}):")
    for s in sus_strings[:20]:
        print(f"    {s}")


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

第二步:Ghidra 分析腳本

# Ghidra 腳本 (在 Ghidra 的腳本管理器中執行)
# 另存為 AnalyzeGoBinary.py 至 Ghidra 腳本目錄

# @category MalwareAnalysis
# @description 分析 Go 二進位結構並恢復中繼資料

def analyze_go_binary_ghidra():
    """用於 Go 二進位分析的 Ghidra 腳本。"""
    from ghidra.program.model.mem import MemoryAccessException

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

    print("[+] Go 二進位分析腳本")
    print(f"  程式: {program.getName()}")

    # 尋找 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 位於 {addr}")
            # 建立標籤
            program.getSymbolTable().createLabel(
                addr, "go_pclntab", None,
                ghidra.program.model.symbol.SourceType.ANALYSIS
            )
            break

    # 修正 Go 字串定義
    # Go 字串是 ptr+len,而非空終止
    print("[+] 修正 Go 字串引用...")

    # 搜尋包含套件路徑的函式名稱
    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"[+] 找到 {func_count} 個 Go 函式符號")


# 執行
analyze_go_binary_ghidra()

驗證標準

  • 從二進位檔案中提取 Go 版本和 build 資訊
  • 定位並解析 pclntab 以便恢復函式名稱
  • 識別第三方依賴項,揭示惡意軟體功能
  • 列舉主套件函式以進行有針對性的分析
  • 分類網路、加密和作業系統執行函式
  • Ghidra 分析正確標記 Go 執行時期結構

參考資料

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,

相關技能