CLI tool
goretk/redress avatar
goretk/redress

redress: recovering what the linker threw away

Redress - A tool for analyzing stripped Go binaries

1,191 stars68 forksGoAGPL-3.0

At a glance

What is it?
redress analyses Go binaries that have been stripped of their symbol table, extracting the package list, type information, module data and source projections that the Go build system leaves behind. It runs standalone or inside radare2 through r2pipe, and the AGPL-licensed project releases a new build most weeks.
Who is it for?
Adopt redress if you analyse Go binaries that have been stripped, for example malware samples, binaries from a supply chain incident, or a build you cannot rebuild from source, and start with redress info and redress packages to get the build metadata before drilling into types and source.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A Go binary still contains a lot after stripping

redress is a tool for analysing stripped Go binaries compiled with the Go compiler. It extracts data from the binary and uses it to reconstruct symbols and performs analysis, which the README describes with the pun it is built around, essentially trying to re-dress a stripped binary.

The reason the tool works at all is a property of how Go binaries are built. The Go compiler leaves behind a great deal of structured information about the program, the module list, the type information, the paths of the source directories, and the metadata of the build itself. Stripping removes the ordinary symbol table, which is what a reverse engineer usually wants, but the Go-specific structures are a different matter and are what redress goes after.

The examples in the README use a real sample, a macOS cryptominer launcher called pplauncher with the hash f94ca9b1b01a7b06f19afaac3fbe0a43075c775a, which the README says was first reported by Malwarebytes. Using a documented malware sample rather than a toy binary is the right choice for a tool like this, since the point is to show what an analyst would actually see.

The source layout reflects the decomposition of the work. There is a file per concern at the top level, with main.go, info.go, pkg.go, type.go, src.go, moduledata.go, r2.go and exp.go, which is a readable map of what the tool can extract.

Two modes, and the binary notices which one it is in

The tool has two operation modes, and the README makes an unusual point about it: the binary is aware of its environment and behaves accordingly.

The first mode is standalone, where the binary is executed on its own. The second is used when the binary is executed from within radare2 via r2pipe. So the same program, pointed at the same file, behaves differently depending on whether it is a child process of a reverse engineering session or a command you typed.

That matters for the workflow. A standalone run gives you the reports. The radare2 mode gives the same information inside an existing reverse engineering session, where you are already looking at functions and strings, and the tool's output becomes part of that picture rather than a separate artefact to cross-reference.

The dependency list supports the second mode. The module github.com/goretk/redress depends on github.com/TcM1911/r2g2, along with goretk/gore for the Go-specific binary parsing, cobra for the command line, and the tabby table renderer for the output. The indirect dependencies include blacktop/go-dwarf and go-macho for the binary formats and golang.org/x/arch for the architecture handling. The Go version required is 1.21.

There is also a.devcontainer/ directory at the root, which is a hint that developing the tool is expected to happen in a container with the right toolchain rather than on a bare machine.

The command set, and the policy of printing more than asked

The command list is short and each one maps to a category of recovered information:

code
Usage:
  redress [command]

Available Commands:
  completion  generate the autocompletion script for the specified shell
  gomod       Display go mod information.
  help        Help about any command
  info        Print summary information.
  moduledata  Display sections extracted from the moduledata structure.
  packages    List packages.
  r2          Use redress with in r2.
  source      Source Code Projection.
  types       List types.
  version     Display redress version information.

The behaviour policy is stated and is worth noting for anyone scripting against the tool. It is possible to use multiple flags to extract different data, and if no flags are given, no data is extracted. The stated idea is to print more information than what is asked by the user.

That last point is a deliberate choice for an investigative tool. A reverse engineer who asks for the package list usually wants to know more, and the extra context is cheap to print and often saves a second run. The counterpoint is that a pipeline built on the tool has to cope with the extra output, which is the usual tension between tools designed for humans and tools designed for machines.

The completion command is a cobra built-in, and the version command exists because the tool is released frequently and the version of the binary matters when comparing results across samples.

Packages: yours, the standard library, and vendored code

The packages command is the one the README spends most of its space on, and its default behaviour is the interesting part. Redress tries to only print the packages that are part of the project and skips standard library and third party library packages, so the default output is short:

code
% redress packages pplauncher
Packages:
Name  Version
----  -------
main

The README is honest about the failure mode. Sometimes redress fails to classify a package, and in that case the unclassified packages can be printed by also providing the --unknown flag, which adds an Unknown Packages section to the output.

The other two flags widen the scope. The --std flag includes the standard library, and --vendor includes the third party packages, and the example output shows how the vendored entries are named, with paths like vendor/golang_org/x/net/route, and the standard library listing package by package from bufio through unicode. The --filepath flag adds the folder locations, and the example shows a main package built from a path under a git workspace and standard library entries pointing into the Go installation's src directory.

The standard library listing is more than a curiosity. Those paths are fingerprints. The example shows entries pointing at /usr/local/Cellar/go/1.10/libexec/src, which is a Homebrew installation path on macOS, and the same tool reporting a GoRoot in that location tells an analyst something about the machine the binary was built on.

Build metadata, moduledata, types and source projection

The info command gives the summary: the compiler version and the date it was released, the build ID, the GoRoot, and the folder path for the main package, followed by counts of the main, standard and vendor packages. The example output shows a binary built with Go 1.10 released on 2018-02-16, a build ID, the GoRoot, and a main root path under a git workspace, which in this case names the project the binary came from.

The moduledata command displays sections extracted from the moduledata structure, the Go runtime's own description of the loaded modules, which is where the package and type information lives.

The types command lists types, and the source command is described as Source Code Projection, which is the most interesting of the set. It reconstructs a projection of the original source from the information in the binary, which for a Go binary is unusually feasible because the file paths, the line tables and the type information are all still present even when the symbols are stripped.

Taken together, these commands let an analyst move from a black box to a partial white box: the build identity first, then the dependency picture, then the types, then whatever source can be projected. The gomod command displays the go mod information for the binary, which is the same idea applied to the module graph.

Where redress is the wrong tool

The first wrong-tool case is a binary that is not Go. The entire mechanism depends on the Go build layout, the moduledata structure and the type metadata, so on a C or Rust or stripped C++ binary the tool has nothing to work with.

The second is a Go binary built with a toolchain that has changed the structures. The tool is version-sensitive by nature, because the metadata layout it parses is an implementation detail of a specific compiler release, and the example in the README is a Go 1.10 binary from 2018. A very recent Go release may present a layout the parser has not been taught, and the failure is likely to be quiet, in the form of packages that fail to classify and types that do not appear.

The third is expecting a full restoration. Redress reconstructs symbols and structure, but the output is a report and a projection, not a working debug session with a reconstructed symbol table in the original format. An analyst who needs to step through the original code with a debugger wants more than this tool provides.

There is a fourth consideration, and it is about the analyst rather than the tool. The tool works on binaries, including malicious ones, so a workflow that runs it over unknown samples needs the samples handled in a way that does not run them. Redress itself only reads the file, but the surrounding process has to be careful.

AGPL-3.0, version 1.2.95, and releases most weeks

The project is licensed under AGPL-3.0, with the LICENSE file at the repository root. For a tool whose output is often part of an internal analysis pipeline, the copyleft terms are worth reading before you build it into a commercial workflow.

The release cadence is the standout operational fact. v1.2.95 was released on 2026-10-15, v1.2.94 on 2026-10-14 and v1.2.93 on 2026-10-10. Versions in the 1.2 line with a new number every few days is a project that is being kept in step with the Go toolchain, which is the sensible reaction to the fact that a parser of compiler internals has to follow those internals.

The last push was on 2026-10-15, the same day as the newest release, and the default branch is develop rather than a stable branch, so the repository's tip is where the work lands. A team that wants a stable point should pin a released version rather than track the branch.

The remaining structure is a small Go project with the usual supporting files, a Makefile, a .github/ directory for the workflows, a .devcontainer/ for the development environment, and the per-concern source files at the root, which makes it easy to see which part of the extraction you are reading about.

Editorial conclusion

Adopt redress if you analyse Go binaries that have been stripped, for example malware samples, binaries from a supply chain incident, or a build you cannot rebuild from source, and start with redress info and redress packages to get the build metadata before drilling into types and source. Do not adopt it for a non-Go binary, since the whole mechanism depends on the Go build layout, and do not expect it to reconstruct a fully working debug session, since it re-derives names and structure rather than restoring a linker symbol table. Before you rely on it, note that the tool is AGPL-3.0, so read the licence before you build it into a commercial workflow, and check the release you pin, since the project ships frequent versions and the default branch is develop rather than a stable branch.

Frequently asked questions

What does redress extract from a Go binary?

It reconstructs symbols and analyses the binary using the data Go binaries retain. The commands cover summary information, the go mod information, sections extracted from the moduledata structure, the package list, the type list and a source code projection.

How do I list the packages in a stripped Go binary with redress?

Run redress packages on the binary, which by default prints only the packages belonging to the project and skips the standard library and third party ones. The --unknown flag shows packages that failed to classify, --std and --vendor widen the scope, and --filepath adds the folder locations.

Can redress be used inside radare2?

Yes. The tool has two operation modes, standalone and a second mode used when the binary is executed from within radare2 via r2pipe, and the binary is aware of its environment and behaves accordingly.

What licence is redress released under?

AGPL-3.0, with the LICENSE file at the repository root. The most recent listed release is v1.2.95, dated 2026-10-15, with the last push on the same day and the default branch set to develop.

Official sources

  1. goretk/redress on GitHub
  2. Issues
  3. License: AGPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/goretk-redress.svg)](https://hysenlabs.com/projects/goretk-redress)

Was this useful?