Skip to main content

Scanner

Struct Scanner 

Source
pub struct Scanner<'r> { /* private fields */ }
Expand description

Scans data in blocks

This scanner is designed for scenarios where the data to be scanned is not available as a single contiguous block of memory, but rather arrives in smaller, discrete blocks, allowing for incremental scanning.

§Examples


let rules = compile(r#"rule test { strings: $a = "abc" condition: $a }"#).unwrap();

let mut scanner = blocks::Scanner::new(&rules);

// Scan the first block of data.
scanner.scan(0, b"xabcy").unwrap();

// Scan a second block of data, which can overlap with the first.
scanner.scan(3, b"cyz").unwrap();

// Finish the scan and get the results.
let results = scanner.finish().unwrap();

assert_eq!(results.matching_rules().len(), 1);

§Limitations of Block Scanning

Block scanning works by analyzing data in chunks rather than as a whole file. This makes it useful for streaming or memory-constrained scenarios, but it comes with important limitations compared to standard scanning:

  1. Modules won’t work. Parsers for structured formats (e.g., PE, ELF) require access to the entire file and cannot be applied in block scanning mode.
  2. Other modules like hash won’t work either, as they require access to all the scanned data during the evaluation of the rule’s condition, something that can’t be guaranteed in block scanning mode. The hash functions will return undefined when used in a multi-block context.
  3. Built-in functions like uint8, uint16, uint32, etc., have the same limitation. They also return undefined in block scanning mode.
  4. The filesize keyword returns undefined in block scanning mode.
  5. Patterns won’t match across block boundaries. Every match will be completely contained within one of the blocks.

All these limitations imply that in block scanning mode you should only use rules that rely on text, hex or regex patterns.

§Data Consistency in Overlapping Blocks

When Scanner::scan is invoked multiple times with different blocks that may overlap, the user is responsible for ensuring data consistency. This means that if the same region of the original data is present in two or more overlapping blocks, the content of that region must be identical across all calls to this function.

Generally speaking, the scanner does not verify this consistency and assumes the user provides accurate and consistent data. In debug releases the scanner may try to verify this consistency, but only when some pattern matches in the overlapping region.

Implementations§

Source§

impl<'r> Scanner<'r>

Source

pub fn new(rules: &'r Rules) -> Scanner<'r>

Creates a new block scanner.

Source

pub fn match_context_size(&mut self, size: usize) -> &mut Self

Sets the context size for matches.

This specifies how many bytes at the left and right of each match will be reported by crate::Match::data_with_context. By default, the match context size is 0, which means that crate::Match::data_with_context will return exactly the same data as crate::Match::data.

Source§

impl<'r> Scanner<'r>

Source

pub fn scan(&mut self, base: usize, data: &[u8]) -> Result<&mut Self, ScanError>

Scans a block of data.

This method processes a given block of data, searching for patterns defined in the YARA rules. The base argument specifies the offset of the current block within the overall data being scanned. In most cases you will want to call this method multiple times, providing a different block on each call.

§Arguments
  • base - The starting offset of the data block within overall data being scanned.
  • data - The byte slice representing the current block of data to scan.
§Returns

A Result indicating success or a ScanError if the scan operation fails.

Source

pub fn finish(&mut self) -> Result<ScanResults<'_, 'r>, ScanError>

Finalizes the scanning process.

After all data blocks have been scanned, this method evaluates the conditions of the YARA rules and produces the final scan results.

Source

pub fn set_global<T: TryInto<Variable>>( &mut self, ident: &str, value: T, ) -> Result<&mut Self, VariableError>

Sets the value of a global variable.

The variable must has been previously defined by calling crate::Compiler::define_global, and the type it has during the definition must match the type of the new value (T).

The variable will retain the new value in subsequent scans, unless this function is called again for setting a new value.

Source

pub fn set_timeout(&mut self, timeout: Duration) -> &mut Self

Sets a timeout for scan operations.

The scan functions will return an ScanError::Timeout once the provided timeout duration has elapsed. The scanner will make every effort to stop promptly after the designated timeout duration. However, in some cases, particularly with rules containing only a few patterns, the scanner could potentially continue running for a longer period than the specified timeout.

Source

pub fn max_matches_per_pattern(&mut self, n: usize) -> &mut Self

Sets the maximum number of matches per pattern.

When some pattern reaches the maximum number of patterns it won’t produce more matches.

Source

pub fn fast_scan(&mut self, yes: bool) -> &mut Self

Enables or disables fast scan mode.

In fast scan mode, the scanner avoids tracking matches for patterns when it is not necessary (e.g. when a rule condition only performs a simple boolean check $a).

Note that using fast scan mode implies that not all matches will be reported. For instance, when iterating matches using ScanResults, you won’t get all occurrences of the pattern in the file, only the first one.

Source

pub fn console_log<F>(&mut self, callback: F) -> &mut Self
where F: FnMut(String) + 'r,

Sets a callback that is invoked every time a YARA rule calls the console module.

The callback function is invoked with a string representing the message being logged. The function can print the message to stdout, append it to a file, etc. If no callback is set these messages are ignored.

Source

pub fn slowest_rules(&self, n: usize) -> Vec<ProfilingData<'_>>

Available on crate feature rules-profiling only.

Returns profiling data for the slowest N rules.

The profiling data reflects the cumulative execution time of each rule across all scanned files. This information is useful for identifying performance bottlenecks. To reset the profiling data and start fresh for subsequent scans, use crate::Scanner::clear_profiling_data.

Source

pub fn clear_profiling_data(&mut self)

Available on crate feature rules-profiling only.

Clears all accumulated profiling data.

This method resets the profiling data collected during rule execution across scanned files. Use this to start a new profiling session, ensuring the results reflect only the data gathered after this method is called.

Trait Implementations§

Source§

impl<'r> From<Scanner<'r>> for Scanner<'r>

Source§

fn from(scanner: Scanner<'r>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<'r> !RefUnwindSafe for Scanner<'r>

§

impl<'r> !Send for Scanner<'r>

§

impl<'r> !Sync for Scanner<'r>

§

impl<'r> !UnwindSafe for Scanner<'r>

§

impl<'r> Freeze for Scanner<'r>

§

impl<'r> Unpin for Scanner<'r>

§

impl<'r> UnsafeUnpin for Scanner<'r>

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<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

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> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

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

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V