
GoReSym from mandiant parses Go binaries — even stripped or UPX-packed ones — to recover functions, types, file paths and compiler metadata for authorized malware analysis and defensive research.
| Tool | mandiant/GoReSym — Go symbol parser that extracts metadata, functions, types and strings from Go binaries, including stripped samples |
| Category | Binary reverse engineering / static analysis (Go, MIT license) |
| Primary Use | Recovering symbols, pclntab metadata, function boundaries and Go type information during authorized malware triage and RE of stripped Go samples |
| Safe Use | For authorized malware analysis, incident response, lab research and defensive threat-intel work on samples you are permitted to examine |
| Telemetry Note | Purely offline static analysis; leaves no trace on analyzed infrastructure and generates JSON reports that document analyst activity |
GoReSym is a cross-platform Go symbol parser from mandiant that attacks one of the most persistent annoyances in malware analysis: Go binaries that have been stripped of their symbol tables. Because the Go runtime embeds rich metadata — the pclntab, the moduledata structure, type links and interned strings — a surprising amount of information survives stripping, and GoReSym is purpose-built to excavate it. The tool extracts program metadata such as CPU architecture, OS, endianness and compiler version, alongside function metadata (start and end addresses, names, sources), filename and line-number data, and embedded structures and types. What makes it credible is its lineage: it is built directly on the open-source Go compiler and runtime code rather than reimplementing format parsing from scratch.
The architecture decision matters analytically. Instead of writing yet another PE/ELF/Mach-O parser, the authors lifted the relevant internals from the Go toolchain itself and hardened them. The README is explicit about the four areas where upstream code was extended: stripped binaries, malformed unpacked binaries such as those produced by UPX, binaries that split single data ranges across multiple sections, and the problem of locating the moduledata structure when normal discovery paths fail. Each of these is a real-world obfuscation tactic seen in Go malware, so the extension list reads like a threat-informed roadmap of what analysts actually hit.
Usage is deliberately minimal. Pre-built binaries for linux, macos and windows ship on the Releases tab, and building from source is just go build. The canonical invocation in the README is GoReSym.exe -t -d -p /path/to/input.exe, where -t recovers Go type names, -d prints standard library packages in addition to user packages, and -p extracts file paths embedded in the pclntab. Output is structured JSON keyed around Version, BuildId, Arch, TabMeta (with endianness, CpuQuantum and pointer size) and ModuleMeta (with Types, ETypes, Typelinks and ITablinks counts), followed by arrays for Types, Files, Strings, UserFunctions and StdFunctions.
The remaining flags round out the feature set nicely. -strings extracts embedded Go strings by walking the string internment table, which is far more reliable than naive string scraping. -m <virtual address> recursively dumps an RTYPE structure at a given address, useful when you already know where a type lives. -v <version string> overrides automated version detection — occasionally required for heavily stripped samples, since type parsing fails outright if the detected version is wrong. -human emits a flat text listing instead of JSON, which the README flags as especially handy for reading structure and interface types, and -about prints license information.
The disassembler integration is where the tool earns its place in an authorized workflow. The bundled IDAPython/goresym_rename.py script reads the JSON output and applies the recovered symbols and labels inside IDA Pro. In practice this transforms a stripped Go sample from an ocean of sub_140001000-style addresses into something with real function names, package boundaries and source file references — the difference between hours of manual work and a focused afternoon. Analysts working in other environments can just as easily consume the JSON directly, since it is designed as a portable intermediate artifact.
Version coverage is documented with unusual precision. GoReSym supports all combinations of ARM64 and x86/x64 across MACH-O, ELF and PE in both endiannesses. pclntab parsing reaches back to Go 1.2, moduledata location likewise, and moduledata type parsing to Go 1.5 — the README is candid that type extraction will never work on older runtimes because the moduledata table simply did not exist yet. The library handles the pre-1.2, 1.2, 1.16, 1.18 and 1.20 pclntab layouts, and recent changes added parsing support for Go 1.24 binaries while keeping compatibility with the ancient 1.2 layout.
The changelog section reveals some genuinely interesting engineering. GoReSym now attempts to locate the pclntab via a signature of the runtime_modulesinit initialization method and will repair a corrupted pclntab magic — a direct counter to malware that deliberately mangles the magic bytes to break symbol tools. DataAfterSection routines and read_memory implementations were added to support signature scanning across file formats, and moduledata scan routines were introduced to find the structure when typelink-based discovery is sabotaged. Sanity checks around loadPeTable and size guards in readStringTable prevent panics on maliciously invalid structures, referencing upstream Go bugs like golang/go#47981 — the tool assumes hostile input and tries not to die on it.
The contributions section is a frank window into the maintenance burden. Because much of the source is copied from the Go compiler's /internal tree, the authors had to strip the /internal path component and rewrite imports to github.com/mandiant/GoReSym/, then export many upstream-unexported struct fields so the extraction logic can reach them. They warn contributors to merge upstream commits manually rather than wholesale copying, and link a prior discussion with Go maintainers (golang/go#46792) about the structural awkwardness. Most new logic lives in /objfile, with objfile/internals defining the reversed internal Go structures the tool parses.
From a defensive perspective, GoReSym is squarely a tradecraft amplifier, not an attack tool. Go has become a favored language for both infostealers and red-team tooling precisely because stripping a Go binary leaves analysts with enormous, anonymous functions; a tool that systematically defeats that obfuscation shifts the economics back toward defenders and incident responders. Recovered package names and embedded file paths frequently leak build-machine directories, module names and even operator tooling hints that feed threat-intelligence reporting. The BuildId field and compiler version are also useful pivot points for clustering related samples in a corpus.
Operationally, the tool is offline and read-only with respect to targets — it touches nothing but the file you point it at, making it clean for lab environments and evidence handling. There is nothing here that facilitates compromise; the JSON it emits is documentation, and the IDA import script only renames symbols. For teams building automated triage pipelines, GoReSym slots naturally as the first stage after static identification of a sample as Go: emit JSON, fingerprint the version, extract strings and types, and hand enriched data to human analysts. With 1116 stars, an MIT license and active updates tracking new Go runtime layouts, it remains the reference implementation for Go symbol recovery in authorized security work.
mandiant/GoReSym.Educational analysis for authorized security professionals. Use only in controlled, authorized environments.
Related coverage
0 comentários:
Post a Comment
Note: Only a member of this blog may post a comment.