summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rust/src/binary_view.rs76
-rw-r--r--rust/src/disassembly.rs2
-rw-r--r--rust/tests/binary_view.rs22
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);
+}