-
-
Notifications
You must be signed in to change notification settings - Fork 0
disrobe recovers symbols from stripped and garbled Go binaries across PE, ELF, and Mach-O by parsing the Go runtime's own metadata tables. The deliverable is symbols, types, and embedded data, not source bodies.
| Layer | Coverage |
|---|---|
| Binary formats | PE, ELF, Mach-O |
| pclntab | Header eras go1.2, go1.16, go1.18, and go1.20, located structurally even when the magic word has been stomped |
| Symbol recovery |
pclntab function table, moduledata, typelinks/itablinks type metadata, buildversion
|
| Obfuscation | garble report graded None / Detected / Partial / Full, with per-scheme literal-recovery statistics |
| Embedded data |
embed.FS usage report and directive extraction |
| Debug info | DWARF report when the sections survive |
disrobe go recover app --out app-go.json
disrobe go info apprecover writes the full analysis JSON (default ./out/<stem>-go.json); info prints the fingerprint without writing anything. Output shape (illustrative):
go recover: OK
input: app
image kind: elf
ptr size: 8
pclntab ver: go1.20
buildversion: go1.26.3
funcs: ...
packages: ...
garble: None
embed.FS: used=true directives=...
wrote: ./out/app-go.json
info adds the stripped-binary fingerprint: whether the symbol table was stripped, how many functions were still recovered from pclntab, and the stdlib-name ratio that feeds the garble grading.
The garble report separates a real wall from a tooling boundary. Standard-library names survive in pclntab and are recovered, while hashed user identifiers stay walled: garble hashes them with a keyed HMAC-SHA256 over a build seed that is not in the binary, so the original names are information-theoretically gone and are reported as a name_recovery_wall rather than guessed at.
The garble -literals string encryption is a different story and is not a one-time pad. Each literal is decrypted by an init-time thunk whose key material is itself compiled into the binary, so the plaintext is statically recoverable by emulating that thunk. For the simple obfuscator disrobe does exactly this: garble emits both the key[] and data[] byte arrays as rodata []byte literals and the runtime loop computes plaintext = data <op> key (op in XOR/ADD/SUB), so disrobe locates the adjacent equal-length blob pair, applies the inverse op, strips the junk padding, and bridges the scattered external-key byte-mutations. Recovery is counted per scheme (plain_ascii, single_xor, single_add, single_sub, repeating_xor, garble_simple) and the simple-scheme scan only runs once garble is positively detected, so a normal Go binary is never mined for phantom literals. The residual boundary is concrete rather than information-theoretic: the external-key mutation index and op live as immediate operands in the decrypt thunk's machine code (not in rodata), and the swap/split/shuffle/seed obfuscators wrap each literal in its own control flow, so byte-exact recovery of heavily mutated or control-flow obfuscated literals needs full decrypt-thunk emulation over the .text immediates. The key material is present in the file in every case, which is what makes this a depth boundary and not a wall.
The pass is validated against a go1.26.3 fixture, and the test suite gates type-name recovery at >= 85% on that fixture. UPX-on-Go chains automatically: disrobe auto unpacks the UPX layer first, then recovers the Go symbols underneath.
This wiki is generated from docs/src in the disrobe repository by scripts/wiki_sync.py. Edit the docs there, not the wiki pages here.
Getting started
Architecture
- Overview
- The five-rung IR ladder
- Passes and the capability model
- The chain runner
- The .dr envelope
- LLM sidecar and provenance
Reverse-engineering toolkit
Language and format guides
- Python
- JavaScript / TypeScript
- WebAssembly
- JVM and Android
- .NET / CIL
- Native (PE / ELF / Mach-O)
- Go
- Lua
- PHP
- Ruby
- BEAM (Erlang / Elixir)
- Swift / Objective-C
- ActionScript 3 / Flash
- Mobile (Hermes / Flutter)
- Python pickle
- Shell / PowerShell
- Containers and archives
Reference
- CLI overview
- Global flags
- Command reference
- Project configuration
- Batch directory processing
- Run reports
- Analysis-depth commands
- Diff and guard tooling
- The daemon: HTTP, gRPC, LSP, MCP
- Use it as a library
- Python bindings
- The browser playground
- Forensics and malware-safety posture
- Threat model
Integrations
Project