summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2024-11-11 22:37:14 -0500
committerMason Reed <mason@vector35.com>2024-11-11 22:37:40 -0500
commit607da4f8e32617b17d0f4549b49baf9610797f18 (patch)
tree99058629430a187f482ffcd68766ac339952f868 /plugins
parent189ec853d318526e6b31f25ee4e39c52a6715a5f (diff)
WARP: More easily adjustable binja settings
Also fixes the issue of running sigem without already enabling WARP previously.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/warp/src/bin/sigem.rs113
1 files changed, 34 insertions, 79 deletions
diff --git a/plugins/warp/src/bin/sigem.rs b/plugins/warp/src/bin/sigem.rs
index 38cec17e..f13b56f4 100644
--- a/plugins/warp/src/bin/sigem.rs
+++ b/plugins/warp/src/bin/sigem.rs
@@ -10,9 +10,10 @@ use rayon::prelude::*;
use binaryninja::binaryview::{BinaryView, BinaryViewExt};
use binaryninja::function::Function as BNFunction;
use binaryninja::rc::Guard as BNGuard;
-use serde_json::json;
+use serde_json::{json, Value};
use walkdir::WalkDir;
use warp::signature::Data;
+use binaryninja::settings::Settings;
use warp_ninja::cache::{cached_type_references, register_cache_destructor};
#[derive(Parser, Debug)]
@@ -48,12 +49,28 @@ struct Args {
debug_info: Option<PathBuf>,
}
+fn default_settings(bn_settings: &Settings) -> Value {
+ let mut settings = json!({
+ "analysis.linearSweep.autorun": false,
+ "analysis.signatureMatcher.autorun": false,
+ "analysis.mode": "full",
+ });
+
+ // If WARP is enabled we must turn it off to prevent matching on other stuff.
+ if bn_settings.contains("analysis.warp.matcher") {
+ settings["analysis.warp.matcher"] = json!(false);
+ settings["analysis.warp.guid"] = json!(false);
+ }
+
+ settings
+}
+
fn main() {
let args = Args::parse();
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
// If no output file was given, just prepend binary with extension sbin
- let output_file = args.output.unwrap_or(args.path.with_extension("sbin"));
+ let output_file = args.output.unwrap_or(args.path.to_owned()).with_extension("sbin");
if output_file.exists() && !args.overwrite.unwrap_or(false) {
log::info!("Output file already exists, skipping... {:?}", output_file);
@@ -64,7 +81,7 @@ fn main() {
let _headless_session = binaryninja::headless::Session::new();
// Adjust the amount of worker threads so that we can actually free BinaryViews.
- let bn_settings = binaryninja::settings::Settings::new("");
+ let bn_settings = Settings::new("");
let worker_count = rayon::current_num_threads() * 4;
log::debug!("Adjusting Binary Ninja worker count to {}...", worker_count);
bn_settings.set_integer(
@@ -76,10 +93,12 @@ fn main() {
// Make sure caches are flushed when the views get destructed.
register_cache_destructor();
+
+ let settings = default_settings(&bn_settings);
log::info!("Creating functions for {:?}...", args.path);
let start = std::time::Instant::now();
- let data = data_from_file(&args.path)
+ let data = data_from_file(&settings, &args.path)
.expect("Failed to read data, check your license and Binary Ninja version!");
log::info!("Functions created in {:?}", start.elapsed());
@@ -128,7 +147,7 @@ fn data_from_view(view: &BinaryView) -> Data {
data
}
-fn data_from_archive<R: Read>(mut archive: Archive<R>) -> Option<Data> {
+fn data_from_archive<R: Read>(settings: &Value, mut archive: Archive<R>) -> Option<Data> {
// TODO: I feel like this is a hack...
let temp_dir = tempdir::TempDir::new("tmp_archive").ok()?;
// Iterate through the entries in the ar file and make a temp dir with them
@@ -159,14 +178,14 @@ fn data_from_archive<R: Read>(mut archive: Archive<R>) -> Option<Data> {
.into_par_iter()
.filter_map(|path| {
log::debug!("Creating data for ENTRY {:?}...", path);
- data_from_file(&path)
+ data_from_file(settings, &path)
})
.collect::<Vec<_>>();
Some(Data::merge(entry_data))
}
-fn data_from_directory(dir: PathBuf) -> Option<Data> {
+fn data_from_directory(settings: &Value, dir: PathBuf) -> Option<Data> {
let files = WalkDir::new(dir)
.into_iter()
.filter_map(|e| {
@@ -183,7 +202,7 @@ fn data_from_directory(dir: PathBuf) -> Option<Data> {
.into_par_iter()
.filter_map(|path| {
log::info!("Creating data for FILE {:?}...", path);
- data_from_file(&path)
+ data_from_file(settings, &path)
})
.collect::<Vec<_>>();
@@ -195,33 +214,22 @@ fn data_from_directory(dir: PathBuf) -> Option<Data> {
}
// TODO: Pass settings.
-fn data_from_file(path: &Path) -> Option<Data> {
- // TODO: Add external debug info files.
- // TODO: Support IDB's through debug info
- let settings_json = json!({
- "analysis.linearSweep.autorun": false,
- "analysis.signatureMatcher.autorun": false,
- "analysis.mode": "full",
- // We don't need these
- "analysis.warp.matcher": false,
- "analysis.warp.guid": false,
- });
-
+fn data_from_file(settings: &Value, path: &Path) -> Option<Data> {
match path.extension() {
Some(ext) if ext == "a" || ext == "lib" || ext == "rlib" => {
let archive_file = File::open(path).expect("Failed to open archive file");
let archive = Archive::new(archive_file);
- data_from_archive(archive)
+ data_from_archive(settings, archive)
}
Some(ext) if ext == "sbin" => {
let contents = std::fs::read(path).ok()?;
Data::from_bytes(&contents)
}
- _ if path.is_dir() => data_from_directory(path.into()),
+ _ if path.is_dir() => data_from_directory(settings, path.into()),
_ => {
let path_str = path.to_str().unwrap();
let view =
- binaryninja::load_with_options(path_str, true, Some(settings_json.to_string()))?;
+ binaryninja::load_with_options(path_str, true, Some(settings.to_string()))?;
let data = data_from_view(&view);
view.file().close();
Some(data)
@@ -232,74 +240,21 @@ fn data_from_file(path: &Path) -> Option<Data> {
#[cfg(test)]
mod tests {
use super::*;
- use warp::r#type::guid::TypeGUID;
- use warp_ninja::convert::from_bn_type;
-
#[test]
fn test_data_from_file() {
env_logger::init();
// TODO: Store oracles here to get more out of this test.
let out_dir = env!("OUT_DIR").parse::<PathBuf>().unwrap();
let _headless_session = binaryninja::headless::Session::new();
+ let bn_settings = Settings::new("");
+ let settings = default_settings(&bn_settings);
for entry in std::fs::read_dir(out_dir).expect("Failed to read OUT_DIR") {
let entry = entry.expect("Failed to read directory entry");
let path = entry.path();
if path.is_file() {
- let result = data_from_file(&path);
+ let result = data_from_file(&settings, &path);
assert!(result.is_some());
}
}
}
-
- #[test]
- fn check_for_leaks() {
- let session = binaryninja::headless::Session::new();
- let out_dir = env!("OUT_DIR").parse::<PathBuf>().unwrap();
- for entry in std::fs::read_dir(out_dir).expect("Failed to read OUT_DIR") {
- let entry = entry.expect("Failed to read directory entry");
- let path = entry.path();
- if path.is_file() {
- if let Some(inital_bv) = session.load(path.to_str().unwrap()) {
- let result = data_from_file(&path);
- assert!(result.is_some());
- // Hold on to a reference to the core to prevent view getting dropped in worker thread.
- let core_ref = inital_bv
- .functions()
- .iter()
- .next()
- .map(|f| f.unresolved_stack_adjustment_graph());
- // Drop the file and view.
- inital_bv.file().close();
- std::mem::drop(inital_bv);
- let initial_memory_info = binaryninja::memory_info();
- if let Some(second_bv) = session.load(path.to_str().unwrap()) {
- let result = data_from_file(&path);
- assert!(result.is_some());
- // Hold on to a reference to the core to prevent view getting dropped in worker thread.
- let core_ref = second_bv
- .functions()
- .iter()
- .next()
- .map(|f| f.unresolved_stack_adjustment_graph());
- // Drop the file and view.
- second_bv.file().close();
- std::mem::drop(second_bv);
- let final_memory_info = binaryninja::memory_info();
- for info in initial_memory_info {
- let initial_count = info.1;
- if let Some(&final_count) = final_memory_info.get(&info.0) {
- assert!(
- final_count <= initial_count,
- "{}: final objects {} vs initial objects {}",
- info.0,
- final_count,
- initial_count
- );
- }
- }
- }
- }
- }
- }
- }
}