关于 analyzing-go-binaries
用于分析已编译 Go 程序(包括已剥离符号的二进制文件)的逆向工程技能。它面向安全分析师和逆向工程人员,利用 Go 特有方法恢复符号、类型、依赖项并理解程序行为。
主要功能
- 01识别 Go 二进制文件及版本
- 02恢复符号和函数名称
- 03提取类型元数据与结构标签
- 04检查依赖项和构建设置
- 05审查 Go 特有安全风险
- 06分析 Go 恶意软件痕迹
适用场景
- 01初步分析陌生的 Go 可执行文件
- 02恢复服务的 API 结构
- 03检查 Go 恶意软件样本
- 04在二进制文件中查找安全问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trilwu/ secskills --skill analyzing-go-binaries安装后在 Claude Code 中输入/analyzing-go-binaries确认已加载。
详细介绍
分析 Go 二进制文件
Go 二进制文件看起来令人望而生畏:静态链接,体积达数十 MB,没有熟悉的导入项,而且经过“剥离”,导致工具显示数千个 sub_ 函数。其实并非如此。Go 自带用于运行时反射和 panic 跟踪的符号表,strip 不会将其移除。恢复符号后,这类二进制文件就成了最容易分析的目标之一。
适用场景
strings显示runtime.main、go:buildid、go.buildinfo或runtime.gopanic- “已剥离”的二进制文件有 5–50 MB,且几乎没有动态导入项
- 反汇编工具显示数千个未命名函数和难以辨认的字符串
- 分析 Go 恶意软件、Go 命令行工具或编译后的 Go 服务
不适用场景
- Rust 二进制文件——请使用
analyzing-rust-binaries;其符号恢复方式完全不同 - .NET 程序集——请使用
analyzing-dotnet-assemblies - 尚未隔离的疑似恶意软件——先使用
analyzing-malware处理环境,再回到这里 - 通用原生逆向工程——请使用
analyzing-binaries
确认是否为 Go,以及 Go 版本
strings -n 6 target | rg -m5 'go1\.[0-9]+|go:buildid|runtime\.main|GOROOT'
go version target # works on unstripped and many stripped builds
go version -m target # module list and build settings — free SBOM
go version -m 是价值最高的首条命令。它会打印带版本号的模块依赖关系图,让你在反汇编之前就能了解所用的第三方库——通常可以直接解答问题(使用了哪个 HTTP 库、哪种加密方式、哪个 C2 框架)。
Go 版本很重要,因为 pclntab 的布局在 1.2、1.16、1.18 和 1.20 版本发生过变化。工具失效通常是版本不匹配导致的,而不是二进制文件经过了强化。
恢复符号
# GoReSym — extracts pclntab, moduledata, types, and build info
GoReSym -t -d -p target > syms.json
# -t user type metadata
# -d include standard library
# -p paths
# redress — Go-aware analysis, works well when GoReSym struggles
redress info target
redress symbols target
redress types target
# Load into the disassembler
# IDA: AlphaGolang, golang_loader_assist, or the GoReSym IDA script
# Ghidra: GolangAnalyzerExtension, or gotools
# Binja: the Golang loader plugin
应用符号后,函数会显示其真实名称——
main.processRequest、crypto/tls.(*Conn).Handshake、
github.com/vendor/pkg.Function。筛选 main.* 和第三方模块路径。runtime.、internal/ 和标准库下的所有内容都是原生代码,占函数总数的 90% 以上。
jq -r '.UserFunctions[].FunctionName' syms.json | rg -v '^(runtime|internal|reflect|sync)\.' | head -40
在反汇编工具中阅读 Go 代码
了解以下四点后,Go 反汇编列表就不再难以理解:
**字符串没有终止符。**Go 字符串由指针和长度构成,因此 strings 的输出会把相邻字面量连在一起,而反汇编工具会显示指针加载操作,后跟一个长度常量。找到这对值——指针旁边的常量就是长度,可以据此从数据块中截取出正确的子字符串。
**调用约定。**在 Go 1.17 之前,所有参数和返回值都通过栈传递,而不是通过寄存器。从 1.17 开始,amd64/arm64 使用寄存器 ABI。按 C 调用约定配置的反编译器会显示错误的参数;支持 Go 的插件可以修正这一点,这也是反编译器输出看起来毫无意义的主要原因。
**接口分派。**通过接口发起的调用会经过 itab——一个包含具体类型及其方法指针的表。要解析调用目标,先找到正在加载的 itab,再读取具体类型。类型恢复工具可以为这些类型命名,从而将间接调用转换为易读的形式。
Goroutine 和 defer。go f() 会编译为以 f 为参数的 runtime.newproc,因此并发逻辑不会以直接调用的形式出现。defer 会变成 runtime.deferproc/deferreturn,使清理代码分散到与源代码不同的位置。跟踪控制流时,请检查 newproc 调用点,以免完全漏掉相关工作。
类型恢复
Go 会嵌入完整的类型描述符,以支持反射。这意味着可以恢复结构体字段名称和布局——包括可直接映射到线上协议的 JSON 标签。
redress types target | rg -A10 'type main\.'
# Struct tags like `json:"api_key"` recover the exact protocol field names
这是了解 Go 服务 API 接口或 Go 植入程序 C2 消息格式的最快途径:恢复请求和响应结构体,就能获得协议内容,无需阅读任何指令。
Go 特定安全审查
如果任务是查找漏洞,而不是理解行为,值得重点检查以下 Go 特定类别:
- 忽略错误。 对返回错误的函数使用
_ =,尤其是在认证、加密和文件操作中。 - 使用
math/rand生成安全相关值。 使用非加密随机数生成器生成令牌、会话 ID 或随机数。 - 在
tls.Config中设置InsecureSkipVerify: true。 - 使用
fmt.Sprintf构造 SQL、shell 命令或 URL。 - 共享 map 和结构体上的数据竞争——这通常是高负载下授权漏洞的根源。
- 使用 shell 调用
os/exec,或使用由输入构造的参数调用它。
如果有源代码,请使用 auditing-code-for-vulnerabilities 和
govulncheck;以上内容适用于只有二进制文件的情况。
Go 恶意软件注意事项
Go 常用于跨平台植入程序,并会留下有用的痕迹:
- 通过
go version -m获取的模块列表可以识别所用框架——网络库、加密库,有时还能识别 C2 项目本身。 - 构建路径会在符号表中泄露开发者用户名、项目名称和目录结构。
main.包的函数名称通常会保留下来,因为剥离符号不会移除pclntab,因此可以直接获得一份能力列表。- 有些样本会刻意剥离
pclntab,或使用会破坏moduledata的工具。如果 GoReSym 和 redress 都无法处理一个明显是 Go 编写的样本,请将其视为值得报告的规避迹象,并改为直接扫描类型描述符。
将 IOC 和检测结果交给 analyzing-malware 和
engineering-detections。
应拒绝的自我安慰
- “它已剥离符号,所以没有符号。”
strip不会移除pclntab。下结论前先运行 GoReSym。 - “反编译器的输出一团糟。” 它使用了错误的调用约定。请应用支持 Go 的插件。
- “有几千个函数,这得花上好几周。” 几乎全是运行时和标准库函数。筛选
main.*和供应商模块。 - “所有字符串都挤在一起了。” Go 字符串由指针和长度组成。按长度常量切分。
- “工具失败了,这个二进制文件受到了保护。” 先检查 Go 版本是否在工具支持的
pclntab版本范围内。 - “我需要追踪每个 goroutine。” 找出
runtime.newproc的调用位置,并查看传给它的函数。
参考资料
analyzing-binaries— 有关此主题的一般分类和动态分析analyzing-malware— Go 样本的遏制和 IOC 提取auditing-code-for-vulnerabilities— 存在源代码时的 Go 漏洞类别检查清单- GoReSym、redress、AlphaGolang、GolangAnalyzerExtension、
go version -m