如何判断一个ELF文件是不是Go ELF文件?

How to determine if an ELF file is a Go ELF file?

我需要确定给定的 ELF 文件是否源自 Go。根据this link:

$ readelf -a traefik.stripped | grep "\.note\.go\.buildid"

这是否比 go 的原生方式差:

$ go tool buildid traefik.stripped
oPIWoPjqt1P3rttpA3ee/ByNXPhvgS37nIoJY-HYB/8b25JYXrgktA-FYgU5MU/0Posfq41xZW9BEPEG4Ub

这两种方法是否保证适用于剥离的二进制文件?

提到的部分是 NOTE 部分:

$ readelf -a traefik.stripped | grep "\.note\.go\.buildid" | sed -n "1,1p"
  [11] .note.go.buildid  NOTE             0000000000400f9c  00000f9c

显然 NOTE 部分有时可能会被删除以减小大小 (related):

objcopy --remove-section=.note.go.buildid traefik.stripped traefik.super.stripped

删除提到的部分似乎不会损害整个二进制文件的完整性

关于使用标准的 go 工具,该部分应该在那里,但是有一种方法可以隐藏二进制文件的 go 性质,而不会产生任何恶意。使用 upx 减小二进制文件的大小将完全隐藏二进制文件的 go 性质,因为 upx 可以处理任何语言的二进制文件。

I need to determine whether a given ELF file originated from Go

一般来说不可能。什么是 Go 二进制文件和什么不是 Go 二进制文件并没有明确定义,充分优化的 Go 二进制文件最终可能只包含一些指令。例如。在 x86_64 上,您可能会得到一条 HLT 指令。

how come strip itself doesn't remove this section?

这个部分(实际上 every 部分)不是执行所必需的——你可以删除 all 部分,二进制文件仍然会工作。

此部分用于帮助开发人员识别特定构建。 strip 默认情况下 不会删除它 因为这会破坏本节的目的,但它肯定 可以 这样做。

can an innocent go developer build a golang ELF and accidentally remove this (redundant??) section

当然可以。开发者可以 运行 损坏的 strip 版本,或者他可以使用 strip --strip-all 别名 strip,或者他可以使用其他一些 ELF post-processing工具,或者他可以使用 UPX,或者...