Extracts usable strings from Go binaries, regardless of file format, architecture, or endian-ness.
Have you ever run strings(1) on a go binary, only to be presented with a bunch of concatenated gobbledy-gook?
That's because Go has a super-efficient way to represent strings in a binary, using pointer+length instead of null-terminated strings.
This tool understands Go binary formats and extracts strings more accurately, inspired by flare-floss which only supports Windows PE binaries, this tool extends support to every executable format supported by Go, no matter how rare.
- Supports multiple binary formats:
- ELF (Linux)
- Mach-O (macOS)
- PE (Windows)
- Plan 9 (Plan 9)
- XCOFF (AIX)
- WebAssembly (WASM)
- Full support for
GOOS=js GOARCH=wasm
- Partial support for
GOOS=wasip1 GOARCH=wasm
(compiler optimizations may eliminate some string structures)
- Full support for
- Extracts strings from Go-specific sections:
.rodata
/__rodata
- read-only data.gopclntab
/__gopclntab
- program counter line table.typelink
/__typelink
- type information.go.buildinfo
- build information (Go 1.18+)
- UTF-8 aware string extraction
- Configurable minimum string length
- Deduplication option
go install github.com/HEXXDECIMAL/gostrings@latest
# Extract strings from a Go binary
gostrings /path/to/binary
# Set minimum string length (default: 4)
gostrings -n 8 /path/to/binary
# Output only unique strings
gostrings -u /path/to/binary
# Verbose output showing which section each string came from
gostrings -v /path/to/binary
# Combine options
gostrings -v -u -n 6 /path/to/binary
When using -v
, strings are grouped by their source section:
__rodata:
strings: illegal use of non-zero Builder copied by value
fmt: unknown base; can't happen
unexpected call to os.Exit(0) during test
.gopclntab:
runtime.Gosched
runtime.goexit
import "github.com/HEXXDECIMAL/gostrings/pkg/gostrings"
opts := gostrings.Options{
MinLength: 4,
Unique: true,
Verbose: false,
}
sections, err := gostrings.Extract("/path/to/binary", opts)
if err != nil {
log.Fatal(err)
}
// Access strings by section
for _, sec := range sections {
fmt.Printf("Section: %s\n", sec.Name)
for _, str := range sec.Strings {
fmt.Printf(" %s\n", str)
}
}
// Or flatten to a simple string list
strings := gostrings.Flatten(sections)
This tool:
- Detects the binary format (ELF/Mach-O/PE/Plan 9/XCOFF/WASM) by examining magic bytes
- Locates Go-specific sections (
.rodata
,.gopclntab
,.typelink
, etc.) - Extracts strings using Go's internal
struct{ptr *byte, len int}
representation - Groups strings by their source section
- Filters by minimum length and optionally deduplicates results globally
# Run tests
make test
# Run linters
make lint
# See a comparison with standard strings command
make demo
- FLARE-FLOSS Language-Specific Strings
- Unveiling Go Strings: A Google Summer of Code Journey
- Reverse Engineering Go Binaries
Apache 2.0