reoxide 0.6.2

Rust-bindings for the ReOxide decompiler extension framework
Documentation
  • Coverage
  • 1.25%
    3 out of 240 items documented0 out of 44 items with examples
  • Size
  • Source code size: 97.36 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 19.63 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 24s Average build duration of successful builds.
  • all releases: 22s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • cluosh
reoxide-0.6.2 has been yanked.

Rust-bindings for the ReOxide decompiler plugin framework

ReOxide adds a plugin system to the Ghidra decompiler, with the larger goal of eventually improving the reverse engineering process of Rust programs in open source tools. While anyone can extend the Ghidra front end through its Java and Python API, the decompiler runs as a separate C++ program. You cannot change the decompiler rules through the Java API, but you can with ReOxide. You can define your own decompiler actions or rules and better understand the inner workings of the decompiler.

Documentation

The ReOxide homepage offers a starting point for the general documentation of the project:

Examples

The reoxide Rust crate offers two different things:

  • Allow driving the Ghidra decompiler from Rust.
  • Allow writing plugins for the Ghidra decompiler using Rust.

Both require a working ReOxide setup, make sure you can run the reoxide command in the environment where you run your Rust builds from.

Driving the Ghidra decompiler from Rust

The decompile example shows how to use the decompiler driver. When you write programs by using the decompiler driver, you have to tell the program where to find the reoxide shared library, libreoxide.so. The build.rs build step should automatically link the library correctly if it can run the reoxide command, but for running the example you might have to set the LD_LIBRARY_PATH manually:

LD_LIBRARY_PATH=$(reoxide print-ld-library-path)

Start off by importing the driver functions:

use reoxide::driver::*;

Currently the driver needs a full Ghidra installation for the processor definition files. You need to set the path to the root folder of the Ghidra installation, for example:

initialize_decompiler(Path::new("/opt/ghidra"), true).unwrap();

You can also enable or disable the ReOxide plugin system with the last parameter. Afterwards you initialize a decompiler context with the raw bytes of the program and the architecture specification string from Ghidra:

let mut ctx = RawFileContext::from_bytes("x86:LE:64:default", &PROGRAM).unwrap();

Decompilation works on the function level, so you first need to define a function at the address you want to decompile:

let addr = 0x0;
ctx.define_function(addr, "fibonacci").unwrap();

Finally, you can decompile the function at the address:

let decomp = ctx.decompile_function(addr)?;
println!("{}", decomp);

Here you can see the full example source code:

use std::env;
use std::path::Path;

use reoxide::driver::*;

const PROGRAM: &[u8] = &[
    0x55, 0x48, 0x89, 0xe5, 0x53, 0x48, 0x83, 0xec, 0x18, 0x89, 0x7d, 0xec, 0x83, 0x7d, 0xec, 0x00,
    0x74, 0x06, 0x83, 0x7d, 0xec, 0x01, 0x75, 0x07, 0xb8, 0x01, 0x00, 0x00, 0x00, 0xeb, 0x1e, 0x8b,
    0x45, 0xec, 0x83, 0xe8, 0x01, 0x89, 0xc7, 0xe8, 0xfb, 0xfe, 0xff, 0xff, 0x89, 0xc3, 0x8b, 0x45,
    0xec, 0x83, 0xe8, 0x02, 0x89, 0xc7, 0xe8, 0xec, 0xfe, 0xff, 0xff, 0x01, 0xd8, 0x48, 0x8b, 0x5d,
    0xf8, 0xc9, 0xc3,
];

fn main() -> Result<(), DecompError> {
    let ghidra_dir = env::var("GHIDRA_INSTALL_DIR").expect(
        "Please provide an environment variable \
        GHIDRA_INSTALL_DIR with the path to the Ghidra root directory. \
        This is needed to find the SLEIGH specification files",
    );

    initialize_decompiler(Path::new(&ghidra_dir), true)?;
    let mut ctx = RawFileContext::from_bytes("x86:LE:64:default", &PROGRAM)?;

    let addr = 0x0;
    ctx.define_function(addr, "fib")?;
    let decomp = ctx.decompile_function(addr)?;
    println!("{}", decomp);

    Ok(())
}

Acknowledgements

Special thanks to rust-sfml and the foreign-types library for showing how to do certain FFI related things.