diff options
| author | Mason Reed <mason@vector35.com> | 2024-10-23 20:47:31 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2024-10-24 17:03:11 -0400 |
| commit | e151425087b6c0ee8c4d099bfc2d6d1268201db0 (patch) | |
| tree | 25160cf81aa6d650cf1497a078acc50f0062757c /plugins/warp/src/plugin/apply.rs | |
| parent | 0f53c21d6a7abbfd48fd59ec7c15586f02777b7e (diff) | |
Add WARP integration
https://github.com/Vector35/warp/
Diffstat (limited to 'plugins/warp/src/plugin/apply.rs')
| -rw-r--r-- | plugins/warp/src/plugin/apply.rs | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/plugins/warp/src/plugin/apply.rs b/plugins/warp/src/plugin/apply.rs new file mode 100644 index 00000000..56c09d77 --- /dev/null +++ b/plugins/warp/src/plugin/apply.rs @@ -0,0 +1,82 @@ +use std::collections::HashMap; +use std::time::Instant; + +use crate::cache::cached_function_guid; +use crate::plugin::on_matched_function; +use binaryninja::binaryview::{BinaryView, BinaryViewExt}; +use binaryninja::command::Command; +use rayon::prelude::*; +use warp::signature::function::{Function, FunctionGUID}; + +pub struct ApplySignatureFile; + +// TODO: All this should do is insert data into the Matcher. this is leftover code. +impl Command for ApplySignatureFile { + fn action(&self, view: &BinaryView) { + // TODO: Start bulk modification + // TODO: view.begin_bulk_modify_symbols(); + let Some(file) = + binaryninja::interaction::get_open_filename_input("Apply Signature File", "*.sbin") + else { + return; + }; + + // TODO: signature files also need to store type information. + + let Ok(data) = std::fs::read(&file) else { + log::error!("Could not read signature file: {:?}", file); + return; + }; + + let Some(data) = warp::signature::Data::from_bytes(&data) else { + log::error!("Could not get data from signature file: {:?}", file); + return; + }; + + // TODO: Turn Vec<Function> to HashSet so that functions with the same symbol and type get eliminated. + let data_functions: HashMap<FunctionGUID, Vec<Function>> = + data.functions + .into_iter() + .fold(HashMap::new(), |mut acc, func| { + #[allow(clippy::unwrap_or_default)] + acc.entry(func.guid).or_insert_with(Vec::new).push(func); + acc + }); + + let background_task = binaryninja::backgroundtask::BackgroundTask::new( + format!("Applying signatures from {:?}", file), + true, + ) + .unwrap(); + + let funcs = view.functions(); + let start = Instant::now(); + + background_task + .set_progress_text(format!("Building {} patterns to lookup...", funcs.len())); + + // TODO: Redo this. + let single_matched = funcs + .par_iter() + .filter_map(|func| { + let llil = func.low_level_il_if_available()?; + let pattern = cached_function_guid(&func, &llil)?; + Some((func, data_functions.get(&pattern)?)) + }) + .filter(|(_, sig)| sig.len() == 1) + .collect::<Vec<_>>(); + + background_task.set_progress_text(format!("Applying {} matches...", single_matched.len())); + for (func, matched) in single_matched { + on_matched_function(&func, &matched[0]); + } + + log::info!("Signature application took {:?}", start.elapsed()); + + background_task.finish(); + } + + fn valid(&self, _view: &BinaryView) -> bool { + true + } +} |
