A comprehensive collection of Binary Ninja scripts and structure definitions for analyzing Go binaries across versions 1.2 through 1.26. This toolkit enables automated function name recovery and metadata analysis even in stripped or obfuscated Go malware.
Go binaries embed rich runtime metadata that survives the stripping process, making them uniquely analyzable compared to traditional C/C++ binaries. This toolkit leverages Go's internal structures (pclntab, moduledata, type information) to automate reverse engineering workflows.
Key capabilities:
- Automatic Go version detection (1.2-1.26)
- Function name recovery from stripped binaries
- Case for obfuscated binaries (missing magic numbers)
- Cross-version compatibility with adaptive parsing
- Version-aware parsing: Automatically detects and adapts to Go versions from 1.2 through 1.26
- Complete function recovery: Renames all functions with fully qualified package names
- Binary Ninja (Commercial or Personal license)
- Tested on version 5.3+
- Python 3.8+
- Clone this repository:
git clone https://github.com/azhlm/Go-Binary-Analysis-Toolkit.git- No additional Python packages required - all dependencies are built into Binary Ninja.
go-binary-analysis/
├── README.md # This file
├── go12.c # Go 1.2-1.15 structures
├── go116.c # Go 1.16-1.17 structures
├── go118.c # Go 1.18-1.19 structures
├── go120.c # Go 1.20+ structures
├── parse_pclnTab.py # Main analysis script
├── recover.py # Case study: obfuscated backdoorrecovery example
└── test_calling_convention.go # Example code from blog
For standard Go binaries with intact metadata:
- Open your Go binary in Binary Ninja
- Open the File → Run script...
- Choose the main analysis script
Output:
Valid pclnTable version type 1.2 found at address: 0x4d16c0
Defined pclnTable at address: 0x4d16c0
Defined ftab at address: 0x4d16d0
Searching for moduledata using pclnTab address: C0 16 4D 00 00 00 00 00
Defined moduledata at address: 0x52a360
Renamed function at address: 0x401000 to go.buildid
Renamed function at address: 0x401080 to internal/cpu.Initialize
Renamed function at address: 0x4010e0 to internal/cpu.processOptions
Renamed function at address: 0x401840 to internal/cpu.indexByte
Renamed function at address: 0x401880 to internal/cpu.doinit
Renamed function at address: 0x401ca0 to internal/cpu.cpuid
Renamed function at address: 0x401cc0 to internal/cpu.xgetbv
Renamed function at address: 0x401ce0 to type..eq.internal/cpu.CacheLinePad
The structures/ directory contains C header files defining Go's internal data structures for each version range. These are automatically loaded by the scripts based on detected Go version.
struct pclnTable- Simple header with embedded ftabstruct ftab- Absolute addressing for function entriesstruct _func- Function metadata with inline namesstruct moduledata- Monolithic structure
struct pcHeader- Extended header with offset tablesstruct ftab- Absolute addressing (transitional)struct _func- Metadata with separated namesstruct moduledata- Dedicated funcnametab slice
struct pcHeader- Added textStart fieldstruct ftab- Relative addressing (entryoff)struct _func- Relative entry offsetsstruct moduledata- PIE-compatible structure
struct pcHeader- Magic 0xFFFFFFF1struct ftab- 32-bit relative offsetsstruct _func- Compact representationstruct moduledata- Added covctrs/ecovctrs fields
Note: Go 1.26+ deprecates pcHeader.textStart - scripts automatically fall back to moduledata.text.
Main automation script for standard Go binary analysis.
Classes:
PcLineTable- Detects and parses pclntab across all versionsModuleData- Locates moduledata and extracts metadata
Key Methods:
# PcLineTable methods
find_pclnTab() # Auto-detect version and locate pclntab
find_pclnTab_1_2() # Search for Go 1.2-1.15
find_pclnTab_1_16() # Search for Go 1.16-1.17
find_pclnTab_1_18() # Search for Go 1.18-1.19
find_pclnTab_1_20() # Search for Go 1.20+
# ModuleData methods
find_moduledata() # Locate via pclntab pointer chasing
rename_functions() # Apply names to all functions
extract_types() # (Future) Type information recoverySpecialized script for case Study: The recover.py script demonstrates recovery techniques for a real-world backdoor sample where the pcHeader magic number was deliberately invalid to evade detection tools like GoReSym.
Features:
- Pattern-based pcHeader detection (when magic numbers obfuscated)
- Type name heuristics for version detection
- Structural validation via textStart
- Manual reconstruction of corrupted metadata
Use Cases:
- Malware with stripped magic numbers
- Custom Go compiler builds
- Packed/encrypted binaries (after unpacking)
- Anti-analysis techniques targeting metadata
This toolkit is based on research detailed in the companion blog post "Reverse Engineering Go Binaries: A Comprehensive Guide to Metadata Analysis". The blog covers:
- Go Internal ABI: Dual calling convention system (ABI0 vs ABIInternal)
- pclntab Structure: Evolution across Go versions with detailed structure definitions
- Moduledata Analysis: Pointer-chasing techniques and field extraction
- Type Information: rtype structure and kind enumeration
- Case Study: Real-world obfuscated backdoor analysis
Read the full blog: blog/Golang_Malware_Analysis.md
| Go Version | Magic Number | Status | Notes |
|---|---|---|---|
| 1.2-1.15 | 0xFFFFFFFB | ✅ Full support | Legacy format, simple structures |
| 1.16-1.17 | 0xFFFFFFFA | ✅ Full support | Transitional, funcnametab introduced |
| 1.18-1.19 | 0xFFFFFFF0 | ✅ Full support | PIE support, relative addressing |
| 1.20-1.25 | 0xFFFFFFF1 | ✅ Full support | Modern format |
| 1.26+ | 0xFFFFFFF1 | ✅ Full support | textStart deprecated, uses moduledata.text |
- Dynamic libraries: Scripts focus on statically linked binaries (most common for malware)
- Assembly functions: Wrapper functions don't have ftab entries (expected behavior)
Star this repo if you find it useful for your Go malware analysis workflows! 🌟