diff options
| author | Mason Reed <mason@vector35.com> | 2025-07-13 14:39:14 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-07-15 12:34:43 -0400 |
| commit | 4a49ba509bdc0b4ffa650fc8461738c2085161c7 (patch) | |
| tree | 0c55d84afde06cfe1416f8f199df985b41a0f1ff /plugins/warp/src/plugin | |
| parent | 9c80b724bc28eca0b1b4fad1b955d4fd2ba48ab5 (diff) | |
[WARP] Add network container
This is going to be disabled by default on this upcoming stable, however users may enable it once we deploy the public server. The data from the server is done through `Container::fetch_functions` independent of the nonblocking function lookup functions.
The sidebar has been updated to drive fetching so that when users navigate to a new function the fetcher will kick off. This fetcher operates on a separate thread, in the event of a user navigating to many functions before the current fetch has completed they all will be batched together in a single fetch.
Networked container currently is limited to just function prototypes, other type information separate from the function object will be omitted.
Diffstat (limited to 'plugins/warp/src/plugin')
| -rw-r--r-- | plugins/warp/src/plugin/ffi/container.rs | 21 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/settings.rs | 28 | ||||
| -rw-r--r-- | plugins/warp/src/plugin/workflow.rs | 17 |
3 files changed, 48 insertions, 18 deletions
diff --git a/plugins/warp/src/plugin/ffi/container.rs b/plugins/warp/src/plugin/ffi/container.rs index 21ad4dc0..4de6bab3 100644 --- a/plugins/warp/src/plugin/ffi/container.rs +++ b/plugins/warp/src/plugin/ffi/container.rs @@ -36,6 +36,27 @@ pub unsafe extern "C" fn BNWARPContainerGetName(container: *mut BNWARPContainer) } #[no_mangle] +pub unsafe extern "C" fn BNWARPContainerFetchFunctions( + container: *mut BNWARPContainer, + target: *mut BNWARPTarget, + guids: *const BNWARPFunctionGUID, + count: usize, +) { + let arc_container = ManuallyDrop::new(Arc::from_raw(container)); + let Ok(mut container) = arc_container.write() else { + return; + }; + + let target = unsafe { ManuallyDrop::new(Arc::from_raw(target)) }; + + let guids = unsafe { std::slice::from_raw_parts(guids, count) }; + + if let Err(e) = container.fetch_functions(&target, guids) { + log::error!("Failed to fetch functions: {}", e); + } +} + +#[no_mangle] pub unsafe extern "C" fn BNWARPContainerGetSources( container: *mut BNWARPContainer, count: *mut usize, diff --git a/plugins/warp/src/plugin/settings.rs b/plugins/warp/src/plugin/settings.rs index 6cd2e0cc..489deb23 100644 --- a/plugins/warp/src/plugin/settings.rs +++ b/plugins/warp/src/plugin/settings.rs @@ -19,7 +19,7 @@ pub struct PluginSettings { /// The API key to use for the selected WARP server, if not specified, you will be unable to push data and may be rate-limited. /// /// This is set to [PluginSettings::SERVER_API_KEY_DEFAULT] by default. - pub server_api_key: String, + pub server_api_key: Option<String>, /// Whether to allow networked WARP requests. Turning this off will not disable local WARP functionality. /// /// This is set to [PluginSettings::ENABLE_SERVER_DEFAULT] by default. @@ -33,9 +33,9 @@ impl PluginSettings { pub const LOAD_USER_FILES_SETTING: &'static str = "analysis.warp.loadUserFiles"; pub const SERVER_URL_DEFAULT: &'static str = "https://warp.binary.ninja"; pub const SERVER_URL_SETTING: &'static str = "analysis.warp.serverUrl"; - pub const SERVER_API_KEY_DEFAULT: &'static str = ""; + pub const SERVER_API_KEY_DEFAULT: Option<String> = None; pub const SERVER_API_KEY_SETTING: &'static str = "analysis.warp.serverApiKey"; - pub const ENABLE_SERVER_DEFAULT: bool = true; + pub const ENABLE_SERVER_DEFAULT: bool = false; pub const ENABLE_SERVER_SETTING: &'static str = "network.enableWARP"; pub fn register(bn_settings: &mut BNSettings) { @@ -44,7 +44,8 @@ impl PluginSettings { "type" : "boolean", "default" : Self::LOAD_BUNDLED_FILES_DEFAULT, "description" : "Whether to load bundled WARP files on startup. Turn this off if you want to manually load them.", - "ignore" : ["SettingsProjectScope", "SettingsResourceScope"] + "ignore" : ["SettingsProjectScope", "SettingsResourceScope"], + "requiresRestart" : true }); bn_settings.register_setting_json( Self::LOAD_BUNDLED_FILES_SETTING, @@ -55,7 +56,8 @@ impl PluginSettings { "type" : "boolean", "default" : Self::LOAD_USER_FILES_DEFAULT, "description" : "Whether to load user WARP files on startup. Turn this off if you want to manually load them.", - "ignore" : ["SettingsProjectScope", "SettingsResourceScope"] + "ignore" : ["SettingsProjectScope", "SettingsResourceScope"], + "requiresRestart" : true }); bn_settings.register_setting_json( Self::LOAD_USER_FILES_SETTING, @@ -66,7 +68,8 @@ impl PluginSettings { "type" : "string", "default" : Self::SERVER_URL_DEFAULT, "description" : "The WARP server to use.", - "ignore" : ["SettingsProjectScope", "SettingsResourceScope"] + "ignore" : ["SettingsProjectScope", "SettingsResourceScope"], + "requiresRestart" : true }); bn_settings.register_setting_json(Self::SERVER_URL_SETTING, &server_url_prop.to_string()); let server_api_key_prop = json!({ @@ -75,7 +78,8 @@ impl PluginSettings { "default" : Self::SERVER_API_KEY_DEFAULT, "description" : "The API key to use for the selected WARP server, if not specified you will be unable to push data, and may be rate limited.", "ignore" : ["SettingsProjectScope", "SettingsResourceScope"], - "hidden": true + "hidden": true, + "requiresRestart" : true }); bn_settings.register_setting_json( Self::SERVER_API_KEY_SETTING, @@ -86,7 +90,8 @@ impl PluginSettings { "type" : "boolean", "default" : Self::ENABLE_SERVER_DEFAULT, "description" : "Whether or not to allow networked WARP requests. Turning this off will not disable local WARP functionality.", - "ignore" : ["SettingsProjectScope", "SettingsResourceScope"] + "ignore" : ["SettingsProjectScope", "SettingsResourceScope"], + "requiresRestart" : true }); bn_settings.register_setting_json( Self::ENABLE_SERVER_SETTING, @@ -107,7 +112,10 @@ impl PluginSettings { settings.server_url = bn_settings.get_string(Self::SERVER_URL_SETTING); } if bn_settings.contains(Self::SERVER_API_KEY_SETTING) { - settings.server_url = bn_settings.get_string(Self::SERVER_API_KEY_SETTING); + let server_api_key_str = bn_settings.get_string(Self::SERVER_API_KEY_SETTING); + if !server_api_key_str.is_empty() { + settings.server_api_key = Some(server_api_key_str); + } } if bn_settings.contains(Self::ENABLE_SERVER_SETTING) { settings.enable_server = bn_settings.get_bool(Self::ENABLE_SERVER_SETTING); @@ -122,7 +130,7 @@ impl Default for PluginSettings { load_bundled_files: PluginSettings::LOAD_BUNDLED_FILES_DEFAULT, load_user_files: PluginSettings::LOAD_USER_FILES_DEFAULT, server_url: PluginSettings::SERVER_URL_DEFAULT.to_string(), - server_api_key: PluginSettings::SERVER_API_KEY_DEFAULT.to_string(), + server_api_key: PluginSettings::SERVER_API_KEY_DEFAULT, enable_server: PluginSettings::ENABLE_SERVER_DEFAULT, } } diff --git a/plugins/warp/src/plugin/workflow.rs b/plugins/warp/src/plugin/workflow.rs index 2d76222c..c2f82bd9 100644 --- a/plugins/warp/src/plugin/workflow.rs +++ b/plugins/warp/src/plugin/workflow.rs @@ -60,6 +60,15 @@ impl Command for RunMatcher { fn action(&self, view: &BinaryView) { let view = view.to_owned(); std::thread::spawn(move || { + // For embedded targets the user may not have set the sections up. + // Alert the user if we have no actual regions (+1 comes from the synthetic section). + let regions = relocatable_regions(&view); + if regions.len() <= 1 && view.memory_map().is_activated() { + log::warn!( + "No relocatable regions found, for best results please define sections for the binary!" + ); + } + run_matcher(&view); }); } @@ -75,14 +84,6 @@ pub fn run_matcher(view: &BinaryView) { let _ = get_warp_tag_type(view); view.file().forget_undo_actions(&undo_id); - // Alert the user if we have no actual regions (one comes from the synthetic section). - let regions = relocatable_regions(view); - if regions.len() <= 1 && view.memory_map().is_activated() { - log::warn!( - "No relocatable regions found, for best results please define sections for the binary!" - ); - } - // Then we want to actually find matching functions. let background_task = BackgroundTask::new("Matching on WARP functions...", true); let start = Instant::now(); |
