Skip to main content

Pattern

Struct Pattern 

Source
pub struct Pattern<'db> { /* private fields */ }
Expand description

A compiled binary search pattern that frees its kernel handle on Drop.

handle is a UniquePtr of CompiledBinpat, non-null by construction; cxx’s deleter frees the compiled_binpat_vec_t on drop. UniquePtr over an opaque type is !Send, so Pattern lives only on the kernel thread. It borrows &Database, so it can’t coexist with a write.

Implementations§

Source§

impl<'db> Pattern<'db>

Source

pub fn hex(db: &'db Database, pattern: impl AsRef<str>) -> Result<Self>

Compile an IDA-style hex signature.

Each whitespace-separated token is a hex byte (48), a byte wildcard (? or ??), or a nibble pattern with one wildcard half (4?, ?B). This grammar is parsed here, not by IDA, so a mistyped byte is a hard error rather than the silent ASCII fallback ida would give it.

§Errors

Error::PatternRejected with PatternRejection::BadToken naming the first token that is none of these, or PatternRejection::NoAnchor if every byte is a wildcard.

Examples found in repository?
examples/actor.rs (line 36)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let db = std::env::args().nth(1).expect("usage: actor <db.i64>");
11
12    // `run` -> Err on kernel setup; the app closure -> Err on an operational failure.
13    Ida::run(move |ida| -> Result<(), Error> {
14        {
15            let db = db;
16            ida.call(move |idb| idb.open(&db).call())??;
17        }
18
19        let n = ida.call(|idb| idb.functions().count())?;
20        let segs = ida.call(|idb| idb.segments().count())?;
21        println!("[app] func_count={n}  segments={segs}");
22
23        // Sig scan: build a hex pattern from the first function's opening bytes and count
24        // how often that exact sequence recurs across the image. A `Pattern` borrows the
25        // `Database`, so it is built, searched, and dropped inside a single kernel call.
26        let hits = ida.call(|idb| {
27            let Some(address) = idb.functions().next().map(|f| f.address()) else {
28                return 0;
29            };
30            let sig = idb
31                .bytes(address, 8)
32                .iter()
33                .map(|b| format!("{b:02X}"))
34                .collect::<Vec<_>>()
35                .join(" ");
36            match Pattern::hex(idb, &sig) {
37                Ok(pat) => idb.search(&pat).count(),
38                Err(_) => 0,
39            }
40        })?;
41        println!("[app] first function's opening 8 bytes recur {hits} time(s) in the image");
42
43        // Sub-workers each hold a handle clone; their calls serialize onto the kernel.
44        let mut hs = vec![];
45        for t in 0..4usize {
46            let ida = ida.clone();
47            hs.push(thread::spawn(move || {
48                let idx = t * 1000;
49                let found = ida
50                    .call(move |idb| idb.functions().nth(idx).map(|f| (f.address(), f.name())))
51                    .expect("kernel call");
52                let (address, name) = match found {
53                    Some((address, name)) => (format!("{address:#012x}"), String::from(name)),
54                    None => ("<none>".into(), "<unnamed>".into()),
55                };
56                println!("[worker {t}] function[{idx}] @ {address}  {name}");
57            }));
58        }
59        for h in hs {
60            h.join().unwrap();
61        }
62
63        ida.call(|idb| idb.close(false))?;
64        Ok(())
65    })??;
66
67    println!("\nACTOR OK (kernel on its own thread; calls marshaled from app + 4 workers)");
68    Ok(())
69}
Source

pub fn code_mask( db: &'db Database, code: &[u8], mask: impl AsRef<str>, ) -> Result<Self>

Compile from a code byte sequence and a parallel mask string.

x/X matches the byte and ?/. wildcards it, the \x..-plus-mask convention of shared sig dumps.

§Errors

Error::PatternRejected with PatternRejection::BadMaskChar for a mask character outside that set, PatternRejection::MaskMismatch for a length mismatch, or PatternRejection::NoAnchor for an all-wildcard mask.

Source§

impl<'db> Pattern<'db>

Source

pub fn bytes<'a>( db: &'db Database, data: &'a [u8], ) -> PatternBytesBuilder<'db, 'a>

Build a pattern from raw bytes.

Without mask, every byte must match. With one (same length), a mask byte is applied bitwise: 0xFF full byte, 0x00 wildcard, 0xF0 high nibble, 0x0F low nibble.

§Errors

Error::PatternRejected on a length mismatch or an all-wildcard mask.

Source

pub fn ida<I1>(db: &'db Database, pattern: I1) -> PatternIdaBuilder<'db, I1>
where I1: AsRef<str>,

Compile via IDA’s own parser: the full grammar ("..." string literals, 'c' char constants, radix-radix numbers) including its lenient ASCII fallback for bare tokens.

case_sensitive matches string literals exactly (default insensitive).

§Errors

Error::PatternRejected with PatternRejection::Unparseable when IDA rejects it outright, or PatternRejection::NoAnchor when it compiles to only wildcards.

Trait Implementations§

Source§

impl Debug for Pattern<'_>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'db> !RefUnwindSafe for Pattern<'db>

§

impl<'db> !Send for Pattern<'db>

§

impl<'db> !Sync for Pattern<'db>

§

impl<'db> !UnwindSafe for Pattern<'db>

§

impl<'db> Freeze for Pattern<'db>

§

impl<'db> Unpin for Pattern<'db>

§

impl<'db> UnsafeUnpin for Pattern<'db>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more