Binary Ninja Rust Hello World

- (3 min read)

Binary Ninja has experimental support for writing plugins in Rust and the provided template is a good starting point for figuring out how to write one.

This post will cover some (hopefully useful) getting started tips. A sample plugin can be found on GitHub.

rust-toolchain.toml

When this post was written, it was documented that plugins need to be compiled with Rust Nightly and that the most recent tested version was cargo 1.55.0-nightly (9233aa06c 2021-06-22). This constraint can be encoded in a rust-toolchain.toml file in your plugin directory (targets need to be changed if an operating system other than macOS is used):

[toolchain]
channel = "nightly-2021-06-22"
targets = [ "x86_64-apple-darwin", "aarch64-apple-darwin" ]

Entry Point

A simple Rust plugin would look something like this:

use binaryninja::binaryview::BinaryView;
use binaryninja::command::register;
use binaryninja::logger;
use log::{info, LevelFilter};

fn hello_world(view: &BinaryView) {
    info!("hello world from Rust!");
}

#[no_mangle]
pub extern "C" fn UIPluginInit() -> bool {
    logger::init(LevelFilter::Info).unwrap();

    register(
        "Hello World!",
        "This is a \"Hello World\" Rust plugin",
        hello_world,
    );
    true
}

UIPluginInit is the entry point of the plugin and is called when Binary Ninja launches. Any initialization code, such as registering commands, should be done within the function.

Logging

Binary Ninja integrates nicely with the standard Rust log crate for logging purposes. The logger must be initialized with the following:

use binaryninja::logger;
use log::{info, LevelFilter};
...
logger::init(LevelFilter::Info).unwrap();

The standard log macros like info! or error! can be used to record information in Binary Ninja's Log pane.

info!("hello world from Rust!");

Compiling and Using

Cargo is used to build the plugin. In my current setup, I had to explicitly compile for x86_64 as Binary Ninja is running under Rosetta 2.

cargo build --release --target x86_64-apple-darwin

Copy the built .dylib (or .so if on Linux) to the plugins directory:

cp target/x86_64-apple-darwin/release/libhello_world.dylib \
  ~/Library/Application\ Support/Binary\ Ninja/plugins/

The plugin will be registered and ready for use once Binary Ninja is launched.

API Docs

The Rust API documentation can be built by cloning the binaryninja-api repository and running cargo doc --open in the rust/ subdirectory. While still very sparsely documented, the type information in the API is still very useful when developing Rust plugins.