diff options
| author | Mason Reed <mason@vector35.com> | 2024-10-28 21:20:03 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2024-10-28 21:21:55 -0400 |
| commit | a38d13f32326b72e59503a8280f610c52e018366 (patch) | |
| tree | 44ea154e651489cc3d3e5a5fb5d17f894ace784d /plugins/warp/src/plugin | |
| parent | 08f1c49f0cb7f74d0f50dcf60289e974ae9d5c3a (diff) | |
Refactor WARP to use a module workflow for matching
Also flush caches on view destruction and improve performance
Diffstat (limited to 'plugins/warp/src/plugin')
| -rw-r--r-- | plugins/warp/src/plugin/create.rs | 8 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/types.rs | 2 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/workflow.rs | 66 |
3 files changed, 54 insertions, 22 deletions
diff --git a/plugins/warp/src/plugin/create.rs b/plugins/warp/src/plugin/create.rs index b404ae1c..966c69ca 100644 --- a/plugins/warp/src/plugin/create.rs +++ b/plugins/warp/src/plugin/create.rs @@ -1,5 +1,6 @@ use crate::cache::cached_function; use crate::convert::from_bn_type; +use crate::matcher::invalidate_function_matcher_cache; use binaryninja::binaryview::{BinaryView, BinaryViewExt}; use binaryninja::command::Command; use rayon::prelude::*; @@ -15,7 +16,6 @@ pub struct CreateSignatureFile; impl Command for CreateSignatureFile { fn action(&self, view: &BinaryView) { let mut signature_dir = binaryninja::user_directory().unwrap().join("signatures/"); - // TODO: This needs to split out each platform into its own bucket... if let Some(default_plat) = view.default_platform() { // If there is a default platform, put the signature in there. signature_dir.push(default_plat.name().to_string()); @@ -53,7 +53,11 @@ impl Command for CreateSignatureFile { // TODO: Should we overwrite? Prompt user. if let Ok(mut file) = std::fs::File::create(&save_file) { match file.write_all(&data.to_bytes()) { - Ok(_) => log::info!("Signature file saved successfully."), + Ok(_) => { + log::info!("Signature file saved successfully."); + // Force rebuild platform matcher. + invalidate_function_matcher_cache(); + } Err(e) => log::error!("Failed to write data to signature file: {:?}", e), } } else { diff --git a/plugins/warp/src/plugin/types.rs b/plugins/warp/src/plugin/types.rs index ecb60428..5ddff403 100644 --- a/plugins/warp/src/plugin/types.rs +++ b/plugins/warp/src/plugin/types.rs @@ -23,7 +23,7 @@ impl Command for LoadTypesCommand { log::error!("Could not get data from signature file: {:?}", file); return; }; - + let Some(arch) = view.default_arch() else { log::error!("Could not get default architecture"); return; diff --git a/plugins/warp/src/plugin/workflow.rs b/plugins/warp/src/plugin/workflow.rs index da8473f0..bd47c117 100644 --- a/plugins/warp/src/plugin/workflow.rs +++ b/plugins/warp/src/plugin/workflow.rs @@ -1,38 +1,66 @@ -use crate::matcher::cached_function_match; +use crate::cache::cached_function_guid; +use crate::matcher::cached_function_matcher; +use binaryninja::backgroundtask::BackgroundTask; +use binaryninja::binaryview::BinaryViewExt; use binaryninja::llil; use binaryninja::workflow::{Activity, AnalysisContext, Workflow}; +use std::time::Instant; -const MATCHER_ACTIVITY_NAME: &str = "analysis.plugins.WARPMatcher"; +const MATCHER_ACTIVITY_NAME: &str = "analysis.plugins.warp.matcher"; // NOTE: runOnce is off because previously matched functions need info applied. const MATCHER_ACTIVITY_CONFIG: &str = r#"{ - "name": "analysis.plugins.WARPMatcher", + "name": "analysis.plugins.warp.matcher", "title" : "WARP Matcher", "description": "This analysis step applies WARP info to matched functions...", "eligibility": { - "auto": { "default": true }, + "auto": {}, "runOnce": false } }"#; -pub fn insert_matcher_workflow() { +const GUID_ACTIVITY_NAME: &str = "analysis.plugins.warp.guid"; +const GUID_ACTIVITY_CONFIG: &str = r#"{ + "name": "analysis.plugins.warp.guid", + "title" : "WARP GUID Generator", + "description": "This analysis step generates the GUID for all analyzed functions...", + "eligibility": { + "auto": {}, + "runOnce": true + } +}"#; + +pub fn insert_workflow() { let matcher_activity = |ctx: &AnalysisContext| { - let function = ctx.function(); - if function.has_user_annotations() { - // User has touched the function, stop trying to match on it! - return; - } + let view = ctx.view(); + let background_task = BackgroundTask::new("Matching on functions...", false).unwrap(); + let start = Instant::now(); + view.functions() + .iter() + .for_each(|function| cached_function_matcher(&function)); + log::info!("Function matching took {:?}", start.elapsed()); + background_task.finish(); + }; + let guid_activity = |ctx: &AnalysisContext| { + let function = ctx.function(); if let Some(llil) = unsafe { ctx.llil_function::<llil::NonSSA<llil::RegularNonSSA>>() } { - cached_function_match(&function, &llil); + cached_function_guid(&function, &llil); } }; - let meta_workflow = Workflow::new_from_copy("core.function.metaAnalysis"); - let activity = Activity::new_with_action(MATCHER_ACTIVITY_CONFIG, matcher_activity); - meta_workflow.register_activity(&activity).unwrap(); - meta_workflow.insert( - "core.function.runFunctionRecognizers", - [MATCHER_ACTIVITY_NAME], - ); - meta_workflow.register().unwrap(); + let function_meta_workflow = Workflow::new_from_copy("core.function.metaAnalysis"); + let guid_activity = Activity::new_with_action(GUID_ACTIVITY_CONFIG, guid_activity); + function_meta_workflow + .register_activity(&guid_activity) + .unwrap(); + function_meta_workflow.insert("core.function.runFunctionRecognizers", [GUID_ACTIVITY_NAME]); + function_meta_workflow.register().unwrap(); + + let module_meta_workflow = Workflow::new_from_copy("core.module.metaAnalysis"); + let matcher_activity = Activity::new_with_action(MATCHER_ACTIVITY_CONFIG, matcher_activity); + module_meta_workflow + .register_activity(&matcher_activity) + .unwrap(); + module_meta_workflow.insert("core.module.notifyCompletion", [MATCHER_ACTIVITY_NAME]); + module_meta_workflow.register().unwrap(); } |
