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>
impl<'db> Pattern<'db>
Sourcepub fn hex(db: &'db Database, pattern: impl AsRef<str>) -> Result<Self>
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?
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}Sourcepub fn code_mask(
db: &'db Database,
code: &[u8],
mask: impl AsRef<str>,
) -> Result<Self>
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>
impl<'db> Pattern<'db>
Sourcepub fn bytes<'a>(
db: &'db Database,
data: &'a [u8],
) -> PatternBytesBuilder<'db, 'a>
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.
Sourcepub fn ida<I1>(db: &'db Database, pattern: I1) -> PatternIdaBuilder<'db, I1>
pub fn ida<I1>(db: &'db Database, pattern: I1) -> PatternIdaBuilder<'db, I1>
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.