Skip to content

Commit 6a65bc1

Browse files
committed
[Rust] Add BinaryViewExt::strings and BinaryViewExt::strings_in_range
1 parent 607ca37 commit 6a65bc1

File tree

3 files changed

+99
-1
lines changed

3 files changed

+99
-1
lines changed

rust/src/binary_view.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub type Result<R> = result::Result<R, ()>;
7676
pub type BinaryViewEventType = BNBinaryViewEventType;
7777
pub type AnalysisState = BNAnalysisState;
7878
pub type ModificationStatus = BNModificationStatus;
79+
pub type StringType = BNStringType;
7980

8081
#[allow(clippy::len_without_is_empty)]
8182
pub trait BinaryViewBase: AsRef<BinaryView> {
@@ -1905,6 +1906,38 @@ pub trait BinaryViewExt: BinaryViewBase {
19051906
let name = QualifiedName::from_owned_raw(result_name);
19061907
Some((lib, name))
19071908
}
1909+
1910+
/// Retrieve all known strings in the binary.
1911+
///
1912+
/// NOTE: This returns a list of [`StringReference`] as strings may not be representable
1913+
/// as a [`String`] or even a [`BnString`]. It is the caller's responsibility to read the underlying
1914+
/// data and convert it to a representable form.
1915+
fn strings(&self) -> Array<StringReference> {
1916+
unsafe {
1917+
let mut count = 0;
1918+
let strings = BNGetStrings(self.as_ref().handle, &mut count);
1919+
Array::new(strings, count, ())
1920+
}
1921+
}
1922+
1923+
/// Retrieve all known strings within the provided `range`.
1924+
///
1925+
/// NOTE: This returns a list of [`StringReference`] as strings may not be representable
1926+
/// as a [`String`] or even a [`BnString`]. It is the caller's responsibility to read the underlying
1927+
/// data and convert it to a representable form.
1928+
fn strings_in_range(&self, range: Range<u64>) -> Array<StringReference> {
1929+
unsafe {
1930+
let mut count = 0;
1931+
let strings = BNGetStringsInRange(
1932+
self.as_ref().handle,
1933+
range.start,
1934+
range.end - range.start,
1935+
&mut count,
1936+
);
1937+
Array::new(strings, count, ())
1938+
}
1939+
}
1940+
19081941
//
19091942
// fn type_archives(&self) -> Array<TypeArchive> {
19101943
// let mut ids: *mut *mut c_char = std::ptr::null_mut();
@@ -2190,3 +2223,46 @@ where
21902223
);
21912224
}
21922225
}
2226+
2227+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2228+
pub struct StringReference {
2229+
pub ty: StringType,
2230+
pub start: u64,
2231+
pub length: usize,
2232+
}
2233+
2234+
impl From<BNStringReference> for StringReference {
2235+
fn from(raw: BNStringReference) -> Self {
2236+
Self {
2237+
ty: raw.type_,
2238+
start: raw.start,
2239+
length: raw.length,
2240+
}
2241+
}
2242+
}
2243+
2244+
impl From<StringReference> for BNStringReference {
2245+
fn from(raw: StringReference) -> Self {
2246+
Self {
2247+
type_: raw.ty,
2248+
start: raw.start,
2249+
length: raw.length,
2250+
}
2251+
}
2252+
}
2253+
2254+
impl CoreArrayProvider for StringReference {
2255+
type Raw = BNStringReference;
2256+
type Context = ();
2257+
type Wrapped<'a> = Self;
2258+
}
2259+
2260+
unsafe impl CoreArrayProviderInner for StringReference {
2261+
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
2262+
BNFreeStringReferenceList(raw)
2263+
}
2264+
2265+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
2266+
Self::from(*raw)
2267+
}
2268+
}

rust/src/disassembly.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use crate::tags::Tag;
3333
use crate::types::Type;
3434
use crate::variable::StackVariableReference;
3535

36+
use crate::binary_view::StringType;
3637
use crate::high_level_il::HighLevelILFunction;
3738
use crate::low_level_il::function::{FunctionForm, FunctionMutability, LowLevelILFunction};
3839
use crate::medium_level_il::MediumLevelILFunction;
@@ -45,7 +46,6 @@ use std::ptr::NonNull;
4546

4647
pub type DisassemblyOption = BNDisassemblyOption;
4748
pub type InstructionTextTokenType = BNInstructionTextTokenType;
48-
pub type StringType = BNStringType;
4949

5050
#[derive(Clone, PartialEq, Debug, Default, Eq)]
5151
pub struct DisassemblyTextLine {

rust/tests/binary_view.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,25 @@ fn test_binary_saving_database() {
7070
"test"
7171
);
7272
}
73+
74+
#[test]
75+
fn test_binary_view_strings() {
76+
let _session = Session::new().expect("Failed to initialize session");
77+
let out_dir = env!("OUT_DIR").parse::<PathBuf>().unwrap();
78+
let view = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view");
79+
let image_base = view.original_image_base();
80+
assert!(view.strings().len() > 0);
81+
let str_15dc = view
82+
.strings()
83+
.iter()
84+
.find(|s| {
85+
let buffer = view
86+
.read_buffer(s.start, s.length)
87+
.expect("Failed to read string reference");
88+
let str = buffer.to_escaped_string(false, false);
89+
str.contains("Microsoft")
90+
})
91+
.expect("Failed to find string 'Microsoft (R) Optimizing Compiler'");
92+
assert_eq!(str_15dc.start, image_base + 0x15dc);
93+
assert_eq!(str_15dc.length, 33);
94+
}

0 commit comments

Comments
 (0)