Skip to main content

Crate goblin_sigscan

Crate goblin_sigscan 

Source
Expand description

Goblin-powered multi-format pattern scanning with pelite-style signatures.

goblin-sigscan combines:

  • pelite-inspired pattern syntax and semantics,
  • scanner APIs over PE/ELF/Mach binaries,
  • compile-time (pattern!) and runtime (pattern::parse) pattern parsing.

This crate’s design and pattern language are heavily inspired by pelite. See the original project by casualx: https://github.com/CasualX/pelite and https://docs.rs/pelite/latest/pelite/pattern/.

§Docs map

§Pattern Scanner Tutorial

§1) Parse a pattern

Runtime parse:

use goblin_sigscan::pattern;

let atoms = pattern::parse("48 8B ? ? ? ? 48 89")?;
assert!(atoms.len() >= 3);

Compile-time parse via macro:

let atoms = goblin_sigscan::pattern!("48 8B ? ? ? ? 48 89");
assert!(!atoms.is_empty());

§2) Size your save buffer correctly

Save-slot length and semantics are the easiest API to misuse.

  • Use pattern::save_len for parsed atom slices.
  • For prepared patterns, use PreparedPattern::required_slots.
  • Parsed patterns always include an implicit Save(0), so slot 0 is always the match start cursor (RVA/VA/mapped offset based on wrapper).
  • Extra tail elements in larger save buffers are left untouched.
use goblin_sigscan::pattern;

let atoms = pattern::parse("e8 ${'}")?;
let mut save = vec![0u64; pattern::save_len(&atoms)];
assert!(save.len() >= 2);

§3) Scan binary code ranges

use std::error::Error;

use goblin_sigscan::{pattern, pe64::PeFile};

fn main() -> Result<(), Box<dyn Error>> {
    // Provide real module bytes from your target binary in production code.
    let bytes: &[u8] = &[];
    let file = PeFile::from_bytes(bytes)?;
    let atoms = pattern::parse("48 8B ? ? ? ? 48 89")?;
    let mut save = vec![0u64; pattern::save_len(&atoms)];
    let mut matches = file.scanner().matches_code(&atoms);
    if matches.next(&mut save) {
        let match_start = save[0];
        let _ = match_start;
    }
    Ok(())
}

§4) Reuse prepared patterns for repeated scans

use std::error::Error;

use goblin_sigscan::{pattern, pe64::PeFile};

fn main() -> Result<(), Box<dyn Error>> {
    // Provide real module bytes from your target binary in production code.
    let bytes: &[u8] = &[];
    let file = PeFile::from_bytes(bytes)?;
    let atoms = pattern::parse("e8 ${'}")?;
    let prepared = file.scanner().prepare_pattern(&atoms);
    let mut save = vec![0u64; prepared.required_slots()];
    let _is_unique = file.scanner().finds_prepared(&prepared, &mut save);
    Ok(())
}

§5) Syntax tutorial

For full syntax semantics and examples, use the canonical parser tutorial: goblin_sigscan_pattern::parse.

The goblin_sigscan::pattern module is a re-export convenience surface: crate::pattern.

§Common pitfalls

  • Allocating save too short for the parsed pattern.
  • Assuming slot 0 is optional (it is always present for parsed patterns).
  • Forgetting that [a-b] uses an exclusive upper parse convention (b - 1 is the maximum encoded skip).
  • Comparing benchmark runs with mismatched sample settings.

For benchmark methodology guidance, see scripts/README.md in the repo.

Modules§

elf
mach
pattern
Pattern syntax onboarding for pelite-style signatures.
pe64

Macros§

pattern
Compile-time pattern parser.

Structs§

CodeSpan
Matches
Stateful matcher produced by Scanner::matches_code.
PreparedPattern
Reusable scanner metadata and atoms for repeated scans.
Ptr
Typed mapped pointer into a parsed binary image.
Scanner
Pattern scanner over a BinaryView.

Traits§

BinaryView
Read-only view over a mapped binary image for scanner execution.
FromLeBytes
Primitive type that can be decoded from little-endian bytes.
MappedAddressView
Shared mapped-address helpers used by PE/ELF/Mach wrappers.
Pod
Marker trait for plain-old-data values that can be read from bytes.
TypedView
Typed read helpers for any mapped-address view.

Type Aliases§

Offset
Va
Virtual address compatibility alias.