diff options
| -rw-r--r-- | rust/src/binary_view.rs | 76 | ||||
| -rw-r--r-- | rust/src/disassembly.rs | 2 | ||||
| -rw-r--r-- | rust/tests/binary_view.rs | 22 |
3 files changed, 99 insertions, 1 deletions
diff --git a/rust/src/binary_view.rs b/rust/src/binary_view.rs index 822c421a..0a1a380b 100644 --- a/rust/src/binary_view.rs +++ b/rust/src/binary_view.rs @@ -76,6 +76,7 @@ pub type Result<R> = result::Result<R, ()>; pub type BinaryViewEventType = BNBinaryViewEventType; pub type AnalysisState = BNAnalysisState; pub type ModificationStatus = BNModificationStatus; +pub type StringType = BNStringType; #[allow(clippy::len_without_is_empty)] pub trait BinaryViewBase: AsRef<BinaryView> { @@ -1905,6 +1906,38 @@ pub trait BinaryViewExt: BinaryViewBase { let name = QualifiedName::from_owned_raw(result_name); Some((lib, name)) } + + /// Retrieve all known strings in the binary. + /// + /// NOTE: This returns a list of [`StringReference`] as strings may not be representable + /// as a [`String`] or even a [`BnString`]. It is the caller's responsibility to read the underlying + /// data and convert it to a representable form. + fn strings(&self) -> Array<StringReference> { + unsafe { + let mut count = 0; + let strings = BNGetStrings(self.as_ref().handle, &mut count); + Array::new(strings, count, ()) + } + } + + /// Retrieve all known strings within the provided `range`. + /// + /// NOTE: This returns a list of [`StringReference`] as strings may not be representable + /// as a [`String`] or even a [`BnString`]. It is the caller's responsibility to read the underlying + /// data and convert it to a representable form. + fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> { + unsafe { + let mut count = 0; + let strings = BNGetStringsInRange( + self.as_ref().handle, + range.start, + range.end - range.start, + &mut count, + ); + Array::new(strings, count, ()) + } + } + // // fn type_archives(&self) -> Array<TypeArchive> { // let mut ids: *mut *mut c_char = std::ptr::null_mut(); @@ -2190,3 +2223,46 @@ where ); } } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct StringReference { + pub ty: StringType, + pub start: u64, + pub length: usize, +} + +impl From<BNStringReference> for StringReference { + fn from(raw: BNStringReference) -> Self { + Self { + ty: raw.type_, + start: raw.start, + length: raw.length, + } + } +} + +impl From<StringReference> for BNStringReference { + fn from(raw: StringReference) -> Self { + Self { + type_: raw.ty, + start: raw.start, + length: raw.length, + } + } +} + +impl CoreArrayProvider for StringReference { + type Raw = BNStringReference; + type Context = (); + type Wrapped<'a> = Self; +} + +unsafe impl CoreArrayProviderInner for StringReference { + unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) { + BNFreeStringReferenceList(raw) + } + + unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> { + Self::from(*raw) + } +} diff --git a/rust/src/disassembly.rs b/rust/src/disassembly.rs index 973fd57c..ab25ce1d 100644 --- a/rust/src/disassembly.rs +++ b/rust/src/disassembly.rs @@ -33,6 +33,7 @@ use crate::tags::Tag; use crate::types::Type; use crate::variable::StackVariableReference; +use crate::binary_view::StringType; use crate::high_level_il::HighLevelILFunction; use crate::low_level_il::function::{FunctionForm, FunctionMutability, LowLevelILFunction}; use crate::medium_level_il::MediumLevelILFunction; @@ -45,7 +46,6 @@ use std::ptr::NonNull; pub type DisassemblyOption = BNDisassemblyOption; pub type InstructionTextTokenType = BNInstructionTextTokenType; -pub type StringType = BNStringType; #[derive(Clone, PartialEq, Debug, Default, Eq)] pub struct DisassemblyTextLine { diff --git a/rust/tests/binary_view.rs b/rust/tests/binary_view.rs index a2407253..dbe47941 100644 --- a/rust/tests/binary_view.rs +++ b/rust/tests/binary_view.rs @@ -70,3 +70,25 @@ fn test_binary_saving_database() { "test" ); } + +#[test] +fn test_binary_view_strings() { + let _session = Session::new().expect("Failed to initialize session"); + let out_dir = env!("OUT_DIR").parse::<PathBuf>().unwrap(); + let view = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view"); + let image_base = view.original_image_base(); + assert!(view.strings().len() > 0); + let str_15dc = view + .strings() + .iter() + .find(|s| { + let buffer = view + .read_buffer(s.start, s.length) + .expect("Failed to read string reference"); + let str = buffer.to_escaped_string(false, false); + str.contains("Microsoft") + }) + .expect("Failed to find string 'Microsoft (R) Optimizing Compiler'"); + assert_eq!(str_15dc.start, image_base + 0x15dc); + assert_eq!(str_15dc.length, 33); +} |
