extern crate scanner;
extern crate pelite;
use std::env;
use std::path::Path;
use std::io::{self, BufRead};
use pelite::{pe32, pe64};
use scanner::{Scanner, pat};
const HELP_TEXT: &'static str = "\
Example signature scanner; https://github.com/CasualX/scanner-rs\n\
\n\
FINDSIG <file> [sig]...\n\
\n\
file Path to the input binary to scan.\n\
sig Any number of signatures to find.\n\
\n\
If no signatures are provided, they are read line by line from stdin.\n";
fn main() {
let mut args = env::args();
args.next();
if let Some(file) = args.next() {
let path = Path::new(&file);
let file_name = path.file_name().unwrap().to_str().unwrap();
if let Ok(pe) = pe32::pefile::PeFile::open(&path) {
let scan = Scanner::from(&pe.view());
process_sigs(file_name, args, &scan, pat::parse32);
}
else if let Ok(pe) = pe64::pefile::PeFile::open(&path) {
let scan = Scanner::from(&pe.view());
process_sigs(file_name, args, &scan, pat::parse64);
}
else {
println!("File not found or not a valid PE binary.");
}
}
else {
print!("{}", HELP_TEXT);
}
}
fn process_sigs(file: &str, args: env::Args, scan: &Scanner, parse: fn(&str) -> Result<pat::Pattern, pat::PatError>) {
let mut stdin = true;
for sig in args {
parse_and_find(file, &sig, scan, parse);
stdin = false;
}
if stdin {
let stdin = io::stdin();
for sig in stdin.lock().lines().filter_map(|line| line.ok()) {
parse_and_find(file, &sig, scan, parse);
}
}
}
fn parse_and_find(file: &str, sig: &str, scan: &Scanner, parse: fn(&str) -> Result<pat::Pattern, pat::PatError>) {
match parse(sig) {
Ok(pat) => {
println!("Pattern \"{}\" matches:", sig);
for mach in scan.iter(&pat) {
println!(" {}!{}", file, mach);
}
},
Err(err) => {
println!("Pattern \"{}\" error: {:?}", sig, err);
},
}
println!("");
}