use std::path::PathBuf;
use yara_forge::{
patterns::FILE_HEADERS,
utils::save_rule_to_file,
validation::{scan_with_rule, validate_rule, ValidationOptions},
RuleBuilder,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let rule = RuleBuilder::new("detect_malware")
.with_tag("malware")
.with_metadata("author", "YARA Forge")
.with_metadata("description", "Detects potential malware characteristics")
.with_string("$mz_header", FILE_HEADERS[0])?
.with_string("$virtual_alloc", "VirtualAllocEx")? .with_string("$write_mem", "WriteProcessMemory")? .with_string("$create_thread", "CreateRemoteThread")? .with_condition(r#"
// Must be a PE file
$mz_header at 0 and
// Look for process injection patterns
2 of ($virtual_alloc, $write_mem, $create_thread) and
// Size constraints to avoid false positives
filesize > 1KB and filesize < 10MB
"#)
.build()?;
let rule_path = "detect_malware.yar";
save_rule_to_file(&rule, rule_path)?;
println!("Rule saved to: {}", rule_path);
println!("\nValidating rule syntax...");
let options = ValidationOptions {
timeout: 30,
..Default::default()
};
if let Err(e) = validate_rule(&rule.to_string(), &options) {
eprintln!("Rule validation failed: {}", e);
return Ok(());
}
println!("Rule validation successful!");
println!("\nScanning a single file...");
let test_file = PathBuf::from("test.exe");
if let Ok(matches) = scan_with_rule(rule_path, &test_file, &options) {
if matches.is_empty() {
println!("No matches found");
} else {
println!("Matches found:");
for m in matches {
println!(" {}", m);
}
}
}
Ok(())
}