Redress v1.0.0 Released

It’s been over two years since the first public release of redress and a lot has changed since then. Redress has finally reached version 1.0. This release includes many surface and under the hood changes. One of the obvious changes is the user interface which has been rewritten to make it easier to use.

The Go Reverse Engineering Tool Kit (GoRE) has had a lot of improvements during the last few months and redress is taking advantage of these improvements. Some of these improvements are:

  • Improved compiler version detection.
  • A rewritten type parser.
  • Improved package type classification (part of the main module vs a 3rd party module).
  • Support for position-independent executables (PIE).
  • Improved source code line number estimation and performance improvements.
  • Extraction of GoRoot.

Some of the major changes in redress are described in more detail below. If you instead just want to download the latest release and get started on analyzing Go binaries, you can download it from the Github release page.

New CLI Interface

The biggest change introduced in version 1.0.0 is the new command-line interface (CLI). The new CLI uses github.com/spf13/cobra which is a very powerful CLI library. Instead of using flags to invoke different actions, redress now uses subcommands. A list of available commands is shown by running redress help.

______         _                  
| ___ \       | |                 
| |_/ /___  __| |_ __ ___ ___ ___ 
|    // _ \/ _  | '__/ _ / __/ __|
| |\ |  __| (_| | | |  __\__ \__ \
\_| \_\___|\__,_|_|  \___|___|___/

Usage:
  redress [command]

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

Flags:
  -h, --help   help for redress

Use "redress [command] --help" for more information about a command.

The new version command has been updated to also include the version of GoRE used and which Go compiler compiled redress.

% redress version
______         _                  
| ___ \       | |                 
| |_/ /___  __| |_ __ ___ ___ ___ 
|    // _ \/ _  | '__/ _ / __/ __|
| |\ |  __| (_| | | |  __\__ \__ \
\_| \_\___|\__,_|_|  \___|___|___/
                                 

Version:  v1.0.0
GoRE:     v0.10.0
Go:       go1.16.9

Cobra has built-in support to generate autocompletion scripts for different shells. Redress is taking advantage of this feature to allow users to improve their workflow. The redress completion command has documentation for generating the scripts for bash, fish, PowerShell and, zsh shells.

% redress completion

Generate the autocompletion script for redress for the specified shell.
See each sub-command's help for details on how to use the generated script.

Usage:
  redress completion [command]

Available Commands:
  bash        generate the autocompletion script for bash
  fish        generate the autocompletion script for fish
  powershell  generate the autocompletion script for powershell
  zsh         generate the autocompletion script for zsh

Flags:
  -h, --help   help for completion

Use "redress completion [command] --help" for more information about a command.

New Info Command

A new info command has been added to provide a summary of the Go binary. In addition to OS, architecture, and compiler version used, it will also list the number of packages found in the main module, standard library, and 3rd party (vendor) modules.

% redress info ./redress
OS         macOS
Arch       amd64
Compiler   1.16.9 (2021-10-07)
Build ID   zgmd-lmQA6Ipziftv7si/mBDAfSgMYd1EfQtEsCeH/z4f6fjE_ip0456wW0XaI/ySyk1vcbXU33XMpfZJx3
GoRoot     go
Main root  github.com/goretk/redress
# main     1
# std      63
# vendor   8

Package and Type Information

The package flag has been moved to a subcommand.

% redress pkg ./redress -v
Packages:
Name  Version
----  -------
main  

Vendors:
Name                            Version
----                            -------
github.com/TcM1911/r2g2         v0.3.2
github.com/cheynewallace/tabby  v1.1.1
github.com/goretk/gore          v0.10.0
github.com/goretk/gore/extern   v0.10.0
github.com/spf13/cobra          v1.2.1
github.com/spf13/pflag          v1.0.5
golang.org/x/arch/x86/x86asm    v0.0.0-20210923205945-b76863e36670
golang.org/x/mod/semver         v0.5.1

Same with the type flag.

% redress types -h               
List Types

Redress can display different type data found in the binary. Interfaces can be
extracted with the "interface" argument while structures can be extracted with
the "struct" argument.

By default, standard library types are filtered out. These can be included
by also providing the standard library flag.

Method definitions for types can be included by using the method flag.

It is also possible to print all types in the binary by using the "all"
argument.

Redress tries to detect the version of the compiler that produced the binary.
If this process fails, a fallback version can be provided.

Usage:
  redress types {struct|interface|all} path/to/go/file [flags]

Aliases:
  types, type, typ, t

Flags:
  -h, --help             help for types
  -m, --methods          Include method definitions.
  -s, --std              Include standard library packages.
  -v, --vendor           Include 3rd party/vendor packages.
      --version string   Fallback compiler version. (default "go1.16")

Source Code Projection

The source projection functionality has been moved under the source command. As part of this move, a new flag (include) was added. With this flag, a user can tell redress to include the given packages in addition to the main module packages in the output. This is a good flag to use when redress has a hard time identifying if a package is part of a vendor module or the main module. In this scenario, it will usually get classified as an unknown package.

% redress src -h
Source Code Projection

Construct a source code tree layout based on the metadata found in the binary.
The output includes the package name and its folder location at compile time.
For each file, the functions defined within are printed. The output also
includes auto generated functions produced by the compiler. For each function,
redress tries to guess the starting and ending line number.
	Folder -> File -> Function -> Line

By default, standard library and 3rd party packages are excluded but can be
included by providing the flags "std", "vendor", and/or "unknown". It is also
possible to include individual packages with the "include" flag.

Usage:
  redress source path/to/go/file [flags]

Aliases:
  source, src, s

Flags:
  -h, --help              help for source
  -i, --include strings   Include the following packages. Can be provided as a comma-separated list or via providing the flag multiple times.
  -s, --std               Include standard library packages.
  -u, --unknown           Include unidentified packages.
  -v, --vendor            Include 3rd party/vendor packages.

Radare2 Integration

The radare2 integration has also been improved. Before this release, redress had different behavior if it was running from within radare2 or standalone. This has now changed and all the subcommands are available all the time. If an r2 command is executed when not from within radare2, redress will print out a warning that the command needs to be executed from within a radare2 instance.

% redress r2 -h
Use redress with in r2.

Usage:
  redress r2 [command]

Aliases:
  r2, radare, radare2, r

Available Commands:
  init        Perform the initial analysis
  line        Annotate function with source lines.
  strarr      Print string array.
  type        Print type definition.

Flags:
  -h, --help   help for r2

Use "redress r2 [command] --help" for more information about a command.

To use redress from within radare2, execute it via the #!pipe command. A recommendation is to run #!pipe redress r2 init when first opening a Go file. This command will mark and name all the functions, add types as symbols and analyze the main.main and all init functions recursively. With Go binaries having a lot of functions, redress tries to only analyze the most important functions to speed up the process.

[0x01069740]> #!pipe redress r2 init
Compiler version: go1.16.9 (2021-10-07T19:49:45Z)
73 packages found.
5198 function symbols found
Analyzing all init functions.
Analyzing all main.main.
2886 type symbols found

Source Line Annotation

One of the powerful annotations that redress can add is the source line information. This command will annotate which source code file and line number the instructions were generated from. It will only show when either the file or line number is changed to reduce the number of annotations. Here is an example below of redress’s main function.

#!pipe redress r2 line
:> pdf
            ;-- fcn.main.main:
            ; CODE XREF from sym._main.main @ 0x12553d4
┌ 185: sym._main.main ();
│           ; var int64_t var_8h @ rsp+0x8
│           ; var int64_t var_10h @ rsp+0x10
│           ; var int64_t var_18h @ rsp+0x18
│           ; var int64_t var_20h @ rsp+0x20
│           ; var int64_t var_40h @ rsp+0x40
│           ; var int64_t var_48h @ rsp+0x48
│           ; var int64_t var_50h @ rsp+0x50
│       ┌─> 0x01255320      65488b0c2530.  mov rcx, qword gs:[0x30]
│       ╎   0x01255329      483b6110       cmp rsp, qword [rcx + 0x10]
│      ┌──< 0x0125532d      0f869c000000   jbe github.com_goretk_redress_main.go:24
│      │╎   0x01255333      4883ec58       sub rsp, 0x58
│      │╎   0x01255337      48896c2450     mov qword [var_50h], rbp
│      │╎   0x0125533c      488d6c2450     lea rbp, [var_50h]
│      │╎   0x01255341      488b0580c623.  mov rax, qword [sym._main.rootCmd] ; [0x14919c8:8]=0x1498ac0
│      │╎   ;-- github.com_spf13_cobra_v1.2.1_command.go:902:
│      │╎   0x01255348      48890424       mov qword [rsp], rax
│      │╎   0x0125534c      e82fadf0ff     call sym._github.com_spf13_cobra._Command_.ExecuteC
│      │╎   0x01255351      488b442410     mov rax, qword [var_10h]
│      │╎   0x01255356      488b4c2418     mov rcx, qword [var_18h]
│      │╎   ;-- github.com_goretk_redress_main.go:25:
│      │╎   0x0125535b      48837c241000   cmp qword [var_10h], 0
│     ┌───< 0x01255361      7462           je 0x12553c5
│     ││╎   ;-- github.com_goretk_redress_main.go:26:
│     ││╎   0x01255363      0f57c0         xorps xmm0, xmm0
│     ││╎   0x01255366      0f11442440     movups xmmword [var_40h], xmm0
│     ││╎   0x0125536b      4885c0         test rax, rax
│    ┌────< 0x0125536e      7404           je 0x1255374
│    │││╎   0x01255370      488b4008       mov rax, qword [rax + 8]
│    └────> 0x01255374      4889442440     mov qword [var_40h], rax
│     ││╎   0x01255379      48894c2448     mov qword [var_48h], rcx
│     ││╎   0x0125537e      488b051b8f24.  mov rax, qword [sym._os.Stderr] ; [0x149e2a0:8]=0
│     ││╎   0x01255385      488d0d2c790e.  lea rcx, sym._go.itab.os.File_io.Writer ; 0x133ccb8 ; " \x99)\x01"
│     ││╎   0x0125538c      48890c24       mov qword [rsp], rcx
│     ││╎   0x01255390      4889442408     mov qword [var_8h], rax
│     ││╎   0x01255395      488d442440     lea rax, [var_40h]
│     ││╎   0x0125539a      4889442410     mov qword [var_10h], rax
│     ││╎   0x0125539f      48c744241801.  mov qword [var_18h], 1
│     ││╎   0x012553a8      48c744242001.  mov qword [var_20h], 1
│     ││╎   0x012553b1      e88abce7ff     call sym._fmt.Fprintln
│     ││╎   ;-- github.com_goretk_redress_main.go:27:
│     ││╎   0x012553b6      48c704240100.  mov qword [rsp], 1
│     ││╎   0x012553be      6690           nop
│     ││╎   0x012553c0      e8db6de7ff     call sym._os.Exit
│     └───> 0x012553c5      488b6c2450     mov rbp, qword [var_50h]
│      │╎   0x012553ca      4883c458       add rsp, 0x58
│      │╎   0x012553ce      c3             ret
│      │╎   ;-- github.com_goretk_redress_main.go:24:
│      └──> 0x012553cf      e8cc11e1ff     call sym._runtime.morestack_noctxt
└       └─< 0x012553d4      e947ffffff     jmp sym._main.main

Other Changes

Redress 1.0.0 uses GoRE version 0.10.0 which also has had a lot of changes since it was initially released. The type parsing has been completely rewritten to improve performance and accuracy. The detection of which compiler version has been used has also been improved.

Redress has new functionality for new experimental commands. These are under the experimental subcommand, which is not shown in the help printout. These commands are not covered by the 1.0 guarantee and can change between versions.

% redress experiment
Experimental functionality

The following commands are experimental and may change or removed
in the future.

Usage:
  redress experiment [command]

Aliases:
  experiment, exp, x

Available Commands:
  mod         Display go mod info.

Flags:
  -h, --help   help for experiment

Use "redress experiment [command] --help" for more information about a command.

One experimental function that is included in this release is the functionality to list the go.mod information, it is available in the binary. The following code snippet shows an example of what the output can look like.

% redress x mod redress 
Type  Name                            Version                             Replaced by  Hash
----  ----                            -------                             -----------  ----
main  github.com/goretk/redress       (devel)                                          
dep   github.com/TcM1911/r2g2         v0.3.2                                           h1:v+MaRN0sAGZsVP3+CC8WlL1psWZfAQwL5oTzSeF0K0s=
dep   github.com/cheynewallace/tabby  v1.1.1                                           h1:JvUR8waht4Y0S3JF17G6Vhyt+FRhnqVCkk8l4YrOU54=
dep   github.com/goretk/gore          v0.10.0                                          h1:ewk402Z0cBTSe+DB5ooBa8CsEAnEWE+E8cbJS7heqyM=
dep   github.com/spf13/cobra          v1.2.1                                           h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
dep   github.com/spf13/pflag          v1.0.5                                           h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
dep   golang.org/x/arch               v0.0.0-20210923205945-b76863e36670               h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
dep   golang.org/x/mod                v0.5.1                                           h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=

Where to Get

Get released binaries for Linux, macOS, and Windows on the Github Release page.