From b183e615962d8f5c2faa6c07bf98b2ef35613036 Mon Sep 17 00:00:00 2001 From: akiranishikawa Date: Fri, 20 Nov 2020 16:32:40 +0900 Subject: [PATCH] add regexes and whitelist functions --- src/detections/system.rs | 6 +-- src/detections/utils.rs | 111 +++++++++++++++++++++++++++++++++------ 2 files changed, 99 insertions(+), 18 deletions(-) diff --git a/src/detections/system.rs b/src/detections/system.rs index 14619d60..68ab263c 100644 --- a/src/detections/system.rs +++ b/src/detections/system.rs @@ -30,7 +30,7 @@ impl System { let default = String::from(""); let servicename = &event_data.get("ServiceName").unwrap_or(&default); let commandline = &event_data.get("ImagePath").unwrap_or(&default); - let text = utils::check_regex(&servicename, 1); + let text = utils::check_regex_old(&servicename, 1); if !text.is_empty() { println!("Message : New Service Created"); println!("Command : {}", commandline); @@ -56,7 +56,7 @@ impl System { println!("Message : Interactive service warning"); println!("Results : Service name: {}", servicename); println!("Results : Malware (and some third party software) trigger this warning"); - println!("{}", utils::check_regex(&servicename, 1)); + println!("{}", utils::check_regex_old(&servicename, 1)); } fn suspicious_service_name(&mut self, event_id: &String, event_data: &HashMap) { @@ -66,7 +66,7 @@ impl System { let default = String::from(""); let servicename = &event_data.get("param1").unwrap_or(&default); - let text = utils::check_regex(&servicename, 1); + let text = utils::check_regex_old(&servicename, 1); if !text.is_empty() { println!("Message : Suspicious Service Name"); println!("Results : Service name: {}", servicename); diff --git a/src/detections/utils.rs b/src/detections/utils.rs index 2e7026e0..728d3199 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -5,6 +5,7 @@ extern crate regex; use crate::detections::configs; use flate2::read::GzDecoder; use regex::Regex; +use std::fs::File; use std::io::prelude::*; use std::str; use std::string::String; @@ -20,17 +21,9 @@ pub fn check_command( let mut text = "".to_string(); let mut base64 = "".to_string(); - let empty = "".to_string(); - for line in configs::singleton().whitelist { - let r_str = line.get(0).unwrap_or(&empty); - if r_str.is_empty() { - continue; - } - - let r = Regex::new(r_str); - if r.is_ok() && r.unwrap().is_match(commandline) { - return; - } + let ret = check_whitelist(commandline, "whitelist.txt"); + if (ret) { + return; } if commandline.len() > minlength { @@ -39,7 +32,7 @@ pub fn check_command( text.push_str("bytes\n"); } text.push_str(&check_obfu(commandline)); - text.push_str(&check_regex(commandline, 0)); + text.push_str(&check_regex_old(commandline, 0)); text.push_str(&check_creator(commandline, creator)); if Regex::new(r"\-enc.*[A-Za-z0-9/+=]{100}") .unwrap() @@ -71,7 +64,10 @@ pub fn check_command( println!("Decoded : {}", str::from_utf8(decoded.as_slice()).unwrap()); text.push_str("Base64-encoded function\n"); text.push_str(&check_obfu(str::from_utf8(decoded.as_slice()).unwrap())); - text.push_str(&check_regex(str::from_utf8(decoded.as_slice()).unwrap(), 0)); + text.push_str(&check_regex_old( + str::from_utf8(decoded.as_slice()).unwrap(), + 0, + )); } } } @@ -126,7 +122,7 @@ fn check_obfu(string: &str) -> std::string::String { return obfutext; } -pub fn check_regex(string: &str, r#type: usize) -> std::string::String { +pub fn check_regex_old(string: &str, r#type: usize) -> std::string::String { let empty = "".to_string(); let mut regextext = "".to_string(); for line in configs::singleton().regex { @@ -157,6 +153,79 @@ pub fn check_regex(string: &str, r#type: usize) -> std::string::String { return regextext; } +pub fn check_regex(string: &str, r#type: usize, regex_path: &str) -> std::string::String { + let empty = "".to_string(); + let mut regextext = "".to_string(); + let regex_list = read_csv(regex_path); + for line in regex_list { + let type_str = line.get(0).unwrap_or(&empty); + if type_str != &r#type.to_string() { + continue; + } + + let regex_str = line.get(1).unwrap_or(&empty); + if regex_str.is_empty() { + continue; + } + + let re = Regex::new(regex_str); + if re.is_err() || re.unwrap().is_match(string) == false { + continue; + } + + let text = line.get(2).unwrap_or(&empty); + if text.is_empty() { + continue; + } + + regextext.push_str(text); + regextext.push_str("\n"); + } + + return regextext; +} + +pub fn check_whitelist(target: &str, whitelist_path: &str) -> bool { + let empty = "".to_string(); + let whitelist = read_csv(whitelist_path); + for line in whitelist { + let r_str = line.get(0).unwrap_or(&empty); + if r_str.is_empty() { + continue; + } + + let r = Regex::new(r_str); + if r.is_ok() && r.unwrap().is_match(target) { + return true; + } + } + + return false; +} + +fn read_csv(filename: &str) -> Vec> { + let mut f = File::open(filename).expect("file not found!!!"); + let mut contents: String = String::new(); + let mut ret = vec![]; + if f.read_to_string(&mut contents).is_err() { + return ret; + } + + let mut rdr = csv::Reader::from_reader(contents.as_bytes()); + rdr.records().for_each(|r| { + if r.is_err() { + return; + } + + let line = r.unwrap(); + let mut v = vec![]; + line.iter().for_each(|s| v.push(s.to_string())); + ret.push(v); + }); + + return ret; +} + fn check_creator(command: &str, creator: &str) -> std::string::String { let mut creatortext = "".to_string(); if !creator.is_empty() { @@ -180,8 +249,11 @@ mod tests { use crate::detections::utils; #[test] fn test_check_regex() { - let regextext = utils::check_regex("\\cvtres.exe", 0); + let regextext = utils::check_regex("\\cvtres.exe", 0, "regexes.txt"); assert!(regextext == "Resource File To COFF Object Conversion Utility cvtres.exe\n"); + + let regextext = utils::check_regex("\\hogehoge.exe", 0, "regexes.txt"); + assert!(regextext == ""); } #[test] @@ -212,4 +284,13 @@ mod tests { "dir", ); } + + #[test] + fn test_check_whitelist() { + let commandline = "\"C:\\Program Files\\Google\\Update\\GoogleUpdate.exe\""; + assert!(true == utils::check_whitelist(commandline, "whitelist.txt")); + + let commandline = "\"C:\\Program Files\\Google\\Update\\GoogleUpdate2.exe\""; + assert!(false == utils::check_whitelist(commandline, "whitelist.txt")); + } }