summaryrefslogtreecommitdiff
path: root/rust/examples
diff options
context:
space:
mode:
authorFabian Freyer <fabian.freyer@physik.tu-berlin.de>2022-01-28 01:36:26 +0100
committerKyleMiles <krm504@nyu.edu>2022-02-14 18:45:11 -0500
commit6cd49edb317112acc73f7caeb285f4134a472d72 (patch)
tree3fc1af20b46dcb33c1ba5490193a0226e112e839 /rust/examples
parent181ad567199e5685578ecf7ad400257098c2e175 (diff)
rust: add linearview and related APIs
This should include everything required to retrieve linear disassembly for a function. * add `highest_address` method to `Function` * add `DisassemblySettings` * add text getter for `InstructionTextToken` * add `LinearViewObject`, `LinearViewCursor` * add decompilation example
Diffstat (limited to 'rust/examples')
-rw-r--r--rust/examples/decompile/Cargo.toml10
-rw-r--r--rust/examples/decompile/build.rs68
-rw-r--r--rust/examples/decompile/src/main.rs54
3 files changed, 132 insertions, 0 deletions
diff --git a/rust/examples/decompile/Cargo.toml b/rust/examples/decompile/Cargo.toml
new file mode 100644
index 00000000..2a6ac3b1
--- /dev/null
+++ b/rust/examples/decompile/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "decompile"
+version = "0.1.0"
+authors = ["Fabian Freyer <mail@fabianfreyer.de>"]
+edition = "2018"
+
+[dependencies]
+binaryninja = {path="../../"}
+clap = { version = "3.0", features = ["derive"] }
+
diff --git a/rust/examples/decompile/build.rs b/rust/examples/decompile/build.rs
new file mode 100644
index 00000000..5ba9bcde
--- /dev/null
+++ b/rust/examples/decompile/build.rs
@@ -0,0 +1,68 @@
+use std::env;
+use std::fs::File;
+use std::io::BufReader;
+use std::path::PathBuf;
+
+#[cfg(target_os = "macos")]
+static LASTRUN_PATH: (&str, &str) = ("HOME", "Library/Application Support/Binary Ninja/lastrun");
+
+#[cfg(target_os = "linux")]
+static LASTRUN_PATH: (&str, &str) = ("HOME", ".binaryninja/lastrun");
+
+#[cfg(windows)]
+static LASTRUN_PATH: (&str, &str) = ("APPDATA", "Binary Ninja\\lastrun");
+
+// Check last run location for path to BinaryNinja; Otherwise check the default install locations
+fn link_path() -> PathBuf {
+ use std::io::prelude::*;
+
+ let home = PathBuf::from(env::var(LASTRUN_PATH.0).unwrap());
+ let lastrun = PathBuf::from(&home).join(LASTRUN_PATH.1);
+
+ File::open(lastrun)
+ .and_then(|f| {
+ let mut binja_path = String::new();
+ let mut reader = BufReader::new(f);
+
+ reader.read_line(&mut binja_path)?;
+ Ok(PathBuf::from(binja_path.trim()))
+ })
+ .unwrap_or_else(|_| {
+ #[cfg(target_os = "macos")]
+ return PathBuf::from("/Applications/Binary Ninja.app/Contents/MacOS");
+
+ #[cfg(target_os = "linux")]
+ return home.join("binaryninja");
+
+ #[cfg(windows)]
+ return PathBuf::from(env::var("PROGRAMFILES").unwrap())
+ .join("Vector35\\BinaryNinja\\");
+ })
+}
+
+fn main() {
+ // Use BINARYNINJADIR first for custom BN builds/configurations (BN devs/build server), fallback on defaults
+ let install_path = env::var("BINARYNINJADIR")
+ .map(PathBuf::from)
+ .unwrap_or_else(|_| link_path());
+
+ #[cfg(target_os = "linux")]
+ println!(
+ "cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-l:libbinaryninjacore.so.1",
+ install_path.to_str().unwrap(),
+ install_path.to_str().unwrap(),
+ );
+
+ #[cfg(target_os = "macos")]
+ println!(
+ "cargo:rustc-link-arg=-Wl,-rpath,{},-L{},-lbinaryninjacore",
+ install_path.to_str().unwrap(),
+ install_path.to_str().unwrap(),
+ );
+
+ #[cfg(target_os = "windows")]
+ {
+ println!("cargo:rustc-link-lib=binaryninjacore");
+ println!("cargo:rustc-link-search={}", install_path.to_str().unwrap());
+ }
+}
diff --git a/rust/examples/decompile/src/main.rs b/rust/examples/decompile/src/main.rs
new file mode 100644
index 00000000..accb7697
--- /dev/null
+++ b/rust/examples/decompile/src/main.rs
@@ -0,0 +1,54 @@
+use binaryninja::binaryview::{BinaryView, BinaryViewBase, BinaryViewExt};
+use binaryninja::disassembly::{DisassemblyOption, DisassemblySettings};
+use binaryninja::function::Function;
+use binaryninja::linearview::{LinearViewCursor, LinearViewObject};
+
+use clap::Parser;
+
+/// Use binaryninja to decompile to C.
+#[derive(Parser, Debug)]
+#[clap(version, long_about = None)]
+struct Args {
+ /// Path to the file to decompile
+ filename: String,
+}
+
+fn decompile_to_c(view: &BinaryView, func: &Function) {
+ let mut settings = DisassemblySettings::new();
+ settings.set_option(DisassemblyOption::ShowAddress, false);
+ settings.set_option(DisassemblyOption::WaitForIL, true);
+
+ let linearview = LinearViewObject::language_representation(view, &settings);
+
+ let mut cursor = LinearViewCursor::new(&linearview);
+ cursor.seek_to_address(func.highest_address());
+
+ let last = view.get_next_linear_disassembly_lines(&mut cursor.duplicate());
+ let first = view.get_previous_linear_disassembly_lines(&mut cursor);
+
+ let lines = first.into_iter().chain(last.into_iter());
+
+ for line in lines {
+ println!("{}", line.as_ref());
+ }
+}
+
+fn main() {
+ let args = Args::parse();
+
+ eprintln!("Loading plugins...");
+ binaryninja::headless::init();
+
+ eprintln!("Loading binary...");
+ let bv = binaryninja::open_view(args.filename).expect("Couldn't open file");
+
+ eprintln!("Filename: `{}`", bv.metadata().filename());
+ eprintln!("File size: `{:#x}`", bv.len());
+ eprintln!("Function count: {}", bv.functions().len());
+
+ for func in &bv.functions() {
+ decompile_to_c(bv.as_ref(), func.as_ref());
+ }
+
+ binaryninja::headless::shutdown();
+}