skidscan 2.0.1

Quick & dirty Rust sigscanning crate
Documentation
use std::str::FromStr;

use crate::{SigScan, Signature, SignatureParseError, signature};

#[test]
fn test_signature() {
	let mut signature = Signature::default();
	signature.push_any();
	signature.push_byte(0xFF);
	assert_eq!(signature.len(), 2);
}

#[test]
fn test_sigscan() {
	let signature = Signature::from_str("55 8B EC 83 E4 F8 83 EC 78 8B 45 0C B9 ?? ?? 06 10 89 04 24 8B 45 10 89 44 24 04 8D 04 24 56 8B").unwrap();
	let bytes: &[u8] = &[
		0x00, 0x00, 0x00, 0x00, 0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45,
		0x0C, 0xB9, 0x88, 0xA1, 0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24,
		0x04, 0x8D, 0x04, 0x24, 0x56, 0x8B, 0x00, 0x00, 0x00, 0x00,
	];
	assert_eq!(bytes.sigscan(&signature).unwrap(), 4);
	assert_eq!(bytes.sigscan(&signature).unwrap(), 4);
}

#[test]
fn test_sigscan_fail() {
	let signature = Signature::from_str("00").unwrap();
	let bytes: &[u8] = &[
		0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45, 0x0C, 0xB9, 0x88, 0xA1,
		0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24, 0x04, 0x8D, 0x04, 0x24,
		0x56,
	];
	assert!(bytes.sigscan(&signature).is_none());
}

#[test]
fn test_sigscan_invalid() {
	assert_eq!(
		Signature::from_str("??        32 ?? 123 ").unwrap_err(),
		SignatureParseError::InvalidByte
	);
}

#[test]
fn test_only_any_error() {
	assert_eq!(
		Signature::from_str("??").unwrap_err(),
		SignatureParseError::OnlyAny
	);
}

#[test]
fn test_invalid_byte_error() {
	assert_eq!(
		Signature::from_str("LL").unwrap_err(),
		SignatureParseError::InvalidByte
	);
}

#[test]
fn test_empty_error() {
	assert_eq!(
		Signature::from_str("").unwrap_err(),
		SignatureParseError::Empty
	);
}

#[test]
fn test_empty_trim_error() {
	assert_eq!(
		Signature::from_str("       ").unwrap_err(),
		SignatureParseError::Empty
	);
}

#[test]
fn test_ptr_scan() {
	unsafe {
		let bytes: [u8; 32] = [
			0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45, 0x0C, 0xB9, 0x88,
			0xA1, 0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24, 0x04, 0x8D,
			0x04, 0x24, 0x56, 0xFF,
		];
		assert!(Signature::from_str("55 8B EC ?? ?? F8 83")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
			.is_some());
	}
}

#[test]
fn test_ptr_scan_sub() {
	unsafe {
		let bytes: [u8; 32] = [
			0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45, 0x0C, 0xB9, 0x88,
			0xA1, 0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24, 0x04, 0x8D,
			0x04, 0x24, 0x56, 0xFF,
		];
		assert!(Signature::from_str("24 8B 45 ?? ?? 44 24")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
			.is_some());
	}
}

#[test]
fn test_ptr_scan_sub_rewind() {
	unsafe {
		let bytes: [u8; 32] = [
			0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45, 0x0C, 0xB9, 0x88,
			0xA1, 0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24, 0x04, 0x8D,
			0x04, 0x24, 0x56, 0xFF,
		];

		let sig = Signature::from_str("24 8B 45 ?? ?? 44 24").unwrap();
		let ptr = sig
		.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
		.unwrap();

		assert_eq!(
			*ptr,
			0x24
		);

		assert_eq!(
			ptr,
			bytes.as_ptr().add(19)
		);
	}
}

#[test]
fn test_ptr_scan_sub_fail() {
	unsafe {
		let bytes: [u8; 32] = [
			0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45, 0x0C, 0xB9, 0x88,
			0xA1, 0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24, 0x04, 0x8D,
			0x04, 0x24, 0x56, 0xFF,
		];
		assert!(Signature::from_str("24 8B 45 ?? ?? 44 24 69")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
			.is_none());
	}
}

#[test]
fn test_ptr_scan_sub_oob() {
	unsafe {
		let bytes: [u8; 32] = [
			0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45, 0x0C, 0xB9, 0x88,
			0xA1, 0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24, 0x04, 0x8D,
			0x04, 0x24, 0x56, 0xFF,
		];
		assert!(Signature::from_str("8B")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(1))
			.is_none());
		assert!(Signature::from_str("55")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(1))
			.is_some());
	}
}

#[test]
fn test_ptr_scan_fail() {
	unsafe {
		let bytes: [u8; 32] = [
			0x55, 0x8B, 0xEC, 0x83, 0xE4, 0xF8, 0x83, 0xEC, 0x78, 0x8B, 0x45, 0x0C, 0xB9, 0x88,
			0xA1, 0x06, 0x10, 0x89, 0x04, 0x24, 0x8B, 0x45, 0x10, 0x89, 0x44, 0x24, 0x04, 0x8D,
			0x04, 0x24, 0x56, 0xFF,
		];
		assert!(Signature::from_str("55 8B EC ?? ?? FF FF")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
			.is_none());
	}
}

#[test]
fn test_proc_macro() {
	assert_eq!(
		Signature::from_str("FF 0E EE 00 ?? ?? 0A").unwrap(),
		signature!("FF 0E EE 00 ?? ?? 0A")
	);
}

#[test]
fn test_mixed_any() {
	Signature::from_str("FF 0E EE 00 ?? ? 0A ?").unwrap();
	Signature::from_str("FF 0E EE 00 ?? ? 0A ??").unwrap();
	Signature::from_str("FF 0E EE 00 ?? ? 0A").unwrap();
}

#[test]
fn test_ida_signature() {
	Signature::from_str("55 8B EC 83 E4 F8 83 EC 78 8B 45 0C B9 ? ? ? ? 89 04 24 8B 45 10 89 44 24 04 8D 04 24 56 8B 75 08 89 44 24 48 8B 45 14 85 C0 57 0F 45 C8 C7 44 24 ? ? ? ? ? 68 ? ? ? ? 8D 44 24 14 89 4C 24 60 50 6A 00 56 C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? E8 ? ? ? ? 8B F8 8D 44 24 20 50 56 E8 ? ? ? ? 8B 76 08 83 C4 18 8B 56 14 3B 56 18 72 08 8B 4D 08 E8 ? ? ? ? 8B C7 5F 5E 8B E5 5D C3").unwrap();
}

#[test]
fn test_ida_proc_macro_signature() {
	assert_eq!(
		Signature::from_str("55 8B EC 83 E4 F8 83 EC 78 8B 45 0C B9 ? ? ? ? 89 04 24 8B 45 10 89 44 24 04 8D 04 24 56 8B 75 08 89 44 24 48 8B 45 14 85 C0 57 0F 45 C8 C7 44 24 ? ? ? ? ? 68 ? ? ? ? 8D 44 24 14 89 4C 24 60 50 6A 00 56 C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? E8 ? ? ? ? 8B F8 8D 44 24 20 50 56 E8 ? ? ? ? 8B 76 08 83 C4 18 8B 56 14 3B 56 18 72 08 8B 4D 08 E8 ? ? ? ? 8B C7 5F 5E 8B E5 5D C3").unwrap(),
		signature!("55 8B EC 83 E4 F8 83 EC 78 8B 45 0C B9 ? ? ? ? 89 04 24 8B 45 10 89 44 24 04 8D 04 24 56 8B 75 08 89 44 24 48 8B 45 14 85 C0 57 0F 45 C8 C7 44 24 ? ? ? ? ? 68 ? ? ? ? 8D 44 24 14 89 4C 24 60 50 6A 00 56 C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? C7 44 24 ? ? ? ? ? E8 ? ? ? ? 8B F8 8D 44 24 20 50 56 E8 ? ? ? ? 8B 76 08 83 C4 18 8B 56 14 3B 56 18 72 08 8B 4D 08 E8 ? ? ? ? 8B C7 5F 5E 8B E5 5D C3")
	);
}

#[test]
fn test_sized() {
	unsafe {
		let bytes: [u8; 5] = [0xEE, 0x69, 0x42, 0xAA, 0xC5];
		assert!(Signature::from_str("EE ? ?? ? C5")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
			.is_some());
		assert!(Signature::from_str("EE ? ? ? C5")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
			.is_some());
		assert!(Signature::from_str("EE ?? ?? ?? C5")
			.unwrap()
			.scan_ptr(bytes.as_ptr(), bytes.as_ptr().add(bytes.len()))
			.is_some());
	}
}

#[test]
#[cfg(feature = "obfuscate")]
fn test_obfstr_proc_macro() {
	mod sigscan {
		pub use crate::obfstr;
	}
	assert_eq!(
		Signature::from_str("FF 0E EE 00 ?? ?? 0A").unwrap(),
		crate::obfsignature!("FF 0E EE 00 ?? ?? 0A")
	);
}