Anthropic-Cybersecurity-Skills 实战:使用 Ghidra 深入分析 Go 恶意软件——pclntab 解析、函数名恢复与依赖提取
Anthropic-Cybersecurity-Skills 实战使用 Ghidra 深入分析 Go 恶意软件——pclntab 解析、函数名恢复与依赖提取【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATTCK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI 20 platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-SkillsGoGolang因其跨平台编译、静态链接生成自包含二进制以及天然的逆向分析复杂度已成为恶意软件作者的高频选择。本文以仓库中的 analyzing-golang-malware-with-ghidra 技能文档为核心系统讲解如何利用 Ghidra 解析 Go 二进制中的 buildinfo 与 pclntab 结构、恢复被 strip/garble 混淆的函数名并从中提取模块依赖与恶意指标。读完本文你将掌握一套从识别 Go 二进制到输出结构化分析报告的可复现逆向工作流并可直接复用本技能目录下配套的 Python 分析脚本。背景为什么 Go 恶意软件让逆向工程师头疼Go 编译器默认静态链接产物把整个 runtime、标准库和全部第三方依赖打包进一个自包含二进制体积通常在5–15MB、包含数千个函数。这带来三个 Ghidra 用户最常遇到的难题字符串格式不同Go 字符串是指针 长度的长度前缀结构struct GoString { char *ptr; int64 length; }而非 C 风格的空字符结尾字符串Ghidra 默认的字符串识别会大量失效。符号被剥离即使二进制被 strippclntabPC Line Table中仍保留函数名、源文件与行号映射但需要专门的解析手段才能恢复。并发模式复杂goroutine、channel、interfaceitab等运行时结构让反编译器输出难以阅读。此外garble、gobuscate、go-strip等混淆工具还会把函数名替换成随机字符串或哈希进一步抬高分析门槛。针对这类样本Volexity 在 2025 年发布的GoResolver通过控制流图CFG相似度匹配把混淆函数与已知 Go 标准库/第三方包函数库比对实现函数名自动去混淆与恢复——这正是本技能工作流中恢复函数名环节的关键工具。适用场景当出现以下情况时应启用本分析流程安全事件调查中需要分析 Go 编译的恶意软件样本需要为该类样本构建检测规则或威胁狩猎查询对应 MITRE ATTCK 的 T1027 混淆、T1620 反射执行、T1140 去混淆、T1059 命令执行等技战术SOC 分析师需要标准化的分析操作规程需要验证当前安全监控对这些攻击技术的覆盖情况。本技能在 SKILL.md 的元数据中声明了与 NIST CSF 的对齐DE.AE-02 异常事件分析、RS.AN-03 分析、ID.RA-01 资产漏洞、DE.CM-01 持续监控可用于将分析结果回填到安全框架映射中。前置条件在开始前请确认以下环境与知识储备Ghidra 11.0运行于 JDK 17GoResolver 插件用于被剥离/混淆二进制的函数名恢复Go Reverse Engineering Tool Kitgo-re.tk等辅助工具链Python 3.9运行本技能目录下的辅助脚本理解 Go runtime 内部机制goroutine、channel、interface熟悉 Go 二进制结构pclntab、moduledata、itab。核心概念Go 二进制结构Go 二进制在pclntabPC Line Table中嵌入了丰富的元数据将程序计数器映射到函数名、源文件和行号——即使被剥离符号表这些元数据依然保留。moduledata结构则包含指向类型信息、itab接口方法表以及 pclntab 本身的指针。下表汇总了各关键组件的名称与常见节区详见仓库中的 standards.md组件作用常见位置pclntabPC 到函数的映射表.gopclntab或.textmoduledata运行时元数据结构.noptrdataitab接口方法表.rodatabuildinfoGo 版本与模块信息.go.buildinfotypelinks类型描述符表.rodatapclntab 的魔数随 Go 版本变化可用于快速判定编译版本魔数bytesGo 版本FB FF FF FF 00 001.2 – 1.15FA FF FF FF 00 001.16 – 1.17F1 FF FF FF 00 001.18 – 1.19F0 FF FF FF 00 001.20注不同资料对 1.18/1.20 两档魔数标注存在差异仓库内 SKILL.md 与 api-reference.md 的记录方向一致实际分析时应以 Go 源码src/runtime/symtab.go中的定义为准。被剥离二进制中的函数恢复Go 二进制即使剥离符号表pclntab 中仍保留函数名但garble等混淆工具会将函数重命名为随机字符串。GoResolver 的做法是为混淆函数计算 CFG 签名再与已知 Go 标准库和第三方包函数的签名库做相似度匹配从而还原真实名称。依赖/模块提取Go 的模块管理会把模块路径与版本字符串嵌入二进制。提取这些字符串即可发现恶意样本的第三方依赖HTTP 库、加密包、C2 框架在无需完整逆向的情况下快速推断样本能力。仓库配套脚本 agent.py 内置了一张高危包对照表例如包路径潜在能力github.com/kbinani/screenshot屏幕截图github.com/atotto/clipboard剪贴板访问github.com/go-vgo/robotgo桌面自动化 / 键盘记录github.com/miekg/dns自定义 DNS 解析C2/隧道golang.org/x/crypto/sshSSH 客户端横向移动github.com/shirou/gopsutil系统枚举github.com/Ne0nd0g/merlinMerlin C2 agentgithub.com/BishopFox/sliverSliver C2 框架github.com/traefik/yaegiGo 解释器动态执行实战工作流Step 1初始二进制分析Python先对样本做离线元数据扫描识别 Go 版本、定位 pclntab、恢复函数名并分类、提取依赖与可疑字符串。将下面脚本保存后直接运行#!/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(rbgo\d\.\d(?:\.\d)?, data[offset:offset256]) 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| rbsyscall|reflect|strings|bytes|path|time|math|sort| rbgithub\.com|golang\.org)[/\.][\w/.], ) for match in func_pattern.finditer(data): name match.group().decode(utf-8, errorsreplace) if len(name) 4 and len(name) 200: functions.append(name) return sorted(set(functions)) def extract_go_strings(data): Extract Go-style strings (pointerlength 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| rbgo\.etcd\.io|google\.golang\.org)/[^\x00\s]{5,80}) ) for match in dep_pattern.finditer(data): dep match.group().decode(utf-8, errorsreplace) 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(fUsage: {sys.argv[0]} go_binary) sys.exit(1) analyze_go_binary(sys.argv[1])该脚本的输出可直接回答三个关键问题这是什么版本的 Go 编译的主包/网络/加密函数各有多少依赖了哪些第三方模块Step 2Ghidra 内分析脚本将二进制导入 Ghidra 后在 Script Manager 中运行下面的脚本自动定位 pclntab 并打上go_pclntab标签、统计 Go 函数符号# Ghidra script (run within Ghidras 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 ptrlen, 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()配套脚本process.py 与 agent.py本技能目录还提供了两个可直接落地的工程化脚本比 SKILL.md 中的演示脚本更进一步scripts/process.py命令行工具python process.py --file malware.exe --output report.json即可把分析结果导出为结构化 JSON 报告。它整合了 pclntab 定位PCLNTAB_MAGICS、Go 版本提取、函数提取与七类分类main_logic / networking / cryptography / os_execution / file_operations / third_party / runtime并支持--output参数持久化报告。scripts/agent.py更全面的分析 Agent功能包括SHA-256 哈希计算、Shannon 熵分析、Go 二进制识别buildinfo 魔数 版本正则 gopclntab 魔数 runtime 字符串多重判据、包名提取与高危包告警、PE/ELF 节区熵分析依赖pefile/pyelftools以及混淆检测——例如识别大量 16 位以上十六进制哈希型函数名疑似 garble、gopclntab 缺失疑似被 strip/修改、runtime 字符串数量过低等信号。借助 agent.py 的混淆检测逻辑你可以快速判断样本属于以下哪一类处理状态工具技术检测特征garble函数名哈希化、字面量混淆哈希型符号、缺失调试信息gobfuscate包/函数重命名随机 8 字符名go-strip移除符号表gopclntab 条目缺失在 Ghidra 中手动定位关键结构除了脚本自动化api-reference.md 给出了手工分析的六个关键步骤Search For Strings go1.识别编译版本Search For Bytes FB FF FF FF定位 gopclntab符号表过滤main.定位入口点导航到runtime.main找到程序起点反编译器中检查 goroutine 派生点runtime.newproc将GoString结构应用到字符串引用上修正定义。Ghidra 10.3 已内置 Go 分析支持File Import导入后运行Auto Analyze含 GolangAnalyzer再通过Window Function Tags Filter go.过滤运行时函数。若内置支持不足可叠加 GoReSymMandiant恢复类型与函数元数据与 redressGo 逆向工具集-src重建源码树、-pkg列出包、-type类型信息、-string提取字符串、-interface接口类型等外部脚本。标准化的分析工作流仓库中的 workflows.md 把整个分析过程抽象为三条可复用流程流程一被剥离二进制的恢复[Stripped Go Binary] -- [Find pclntab] -- [Recover Function Names] | v [Apply GoResolver] -- [Deobfuscate Names] | v [Categorize Functions]流程二完整 Ghidra 分析[Go Binary] -- [Import to Ghidra] -- [Run Go Analysis Scripts] | v [Fix String References] | v [Identify main Package] | v [Analyze C2/Network Logic]流程三基于依赖的能力评估[Go Binary] -- [Extract Module Info] -- [List Dependencies] | v [Map to Capabilities] | v [Prioritize Analysis]三条流程的核心思想一致先用 pclntab 恢复函数名再按包归属分类最后以依赖和能力评估引导深度逆向的优先级——尤其当函数名被混淆时依赖列表往往是推断样本能力的最快路径。输出结构化分析报告完成分析后推荐按 assets/template.md 的报告模板输出结论包含以下板块样本信息SHA-256、文件大小、Go 版本、架构amd64/arm64/386、是否被 strip、是否被混淆garble 等恢复的函数按 main / networking / crypto / os/exec / third-party 分类统计数量与关键函数依赖清单模块路径与用途C2 基础设施URL / IP / 域名指标处置建议如封锁识别出的 C2 基础设施、为 Go 函数特征编写 YARA 规则、监控同类 Go 二进制编译产物。常见 Go 恶意软件家族速查在交叉比对时可参考 api-reference.md 与 standards.md 收录的已知 Go 恶意家族特征SliverC2 implant依赖 protobuf/grpc/mtls、MerlinC2 agent依赖 http2/jose/websocket、GeaconGo 版 Cobalt Strike beacon、GoBruteforcer、Kaiji 与 Chaos botnetGo 实现、BianLian勒索软件crypto/aes filepath.Walk、Royal基于 goroutine 的并行加密勒索软件等。命中这些包路径或函数特征往往能在函数级逆向之前就锁定家族归属。验证标准完成整套分析后用以下标准自检结果是否达标从二进制中成功提取 Go 版本与构建信息定位并解析 pclntab恢复函数名识别出第三方依赖推断出恶意软件能力枚举 main 包函数为定向分析提供入口网络、加密、OS 执行类函数完成分类Ghidra 分析正确标记 Go 运行时结构如go_pclntab。全部通过即可将结论沉淀为检测规则、威胁狩猎查询或事件响应报告回填到本仓库 mappings 目录所维护的 MITRE ATTCK / NIST CSF 框架映射中。【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATTCK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI 20 platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考