From 2220500a9cad92859cd63dd6587cbfc8670197cc Mon Sep 17 00:00:00 2001 From: itiB Date: Mon, 5 Oct 2020 02:24:55 +0900 Subject: [PATCH 1/5] Add: DeepBlueCLI PowerShell's rules --- src/detections/detection.rs | 4 +++ src/detections/mod.rs | 1 + src/detections/powershell.rs | 51 ++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/detections/powershell.rs diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 756fcf4c..1ad2daf5 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -4,6 +4,7 @@ use crate::detections::application; use crate::detections::common; use crate::detections::security; use crate::detections::system; +use crate::detections::powershell; use crate::models::event; use evtx::EvtxParser; use quick_xml::de::DeError; @@ -26,6 +27,7 @@ impl Detection { let mut security = security::Security::new(); let mut system = system::System::new(); let mut application = application::Application::new(); + let mut powershell = powershell::PowerShell::new(); for record in parser.records() { match record { @@ -43,6 +45,8 @@ impl Detection { &system.detection(event_id, &event.system, event_data); } else if channel == "Application" { &application.detection(event_id, &event.system, event_data); + } else if channel == "Microsoft-Windows-PowerShell/Operational" { + &powershell.detection(event_id, &event.system, event_data); } else { //&other.detection(); } diff --git a/src/detections/mod.rs b/src/detections/mod.rs index ba8b0f90..af7ef760 100644 --- a/src/detections/mod.rs +++ b/src/detections/mod.rs @@ -1,6 +1,7 @@ mod application; mod common; pub mod detection; +mod powershell; mod security; mod system; mod utils; diff --git a/src/detections/powershell.rs b/src/detections/powershell.rs new file mode 100644 index 00000000..05084e62 --- /dev/null +++ b/src/detections/powershell.rs @@ -0,0 +1,51 @@ +use crate::models::event; +use std::collections::HashMap; + +pub struct PowerShell {} + +impl PowerShell { + pub fn new() -> PowerShell { + PowerShell {} + } + + pub fn detection( + &mut self, + event_id: String, + _system: &event::System, + event_data: HashMap, + ) { + if event_id == "4103" { + &self.execute_pipeline(&event_data); + } else if event_id == "4104" { + &self.execute_remote_command(&event_data); + } + } + + fn execute_pipeline(&mut self, _event_data: &HashMap) { + // PowerShell Error Code: 4103 is absent. + // ToDo: Correct Log & Check + return; + } + + fn execute_remote_command(&mut self, event_data: &HashMap) { + println!( + " + Path: {} + MessageTotal: {} + ScriptBlockText: {} + ScriptBlockId: {} + MessageNumber: {}", + event_data.get("Path").unwrap_or(&String::from("")), + event_data.get("MessageTotal").unwrap_or(&String::from("")), + event_data + .get("ScriptBlockText") + .unwrap_or(&String::from("")), + event_data + .get("ScriptBlockId") + .unwrap_or(&String::from("")), + event_data.get("MessageNumber").unwrap_or(&String::from("")), + ); + + return; + } +} From 7f2bbcc1f19c35557d14e8f9552d5021d86767a4 Mon Sep 17 00:00:00 2001 From: itiB Date: Tue, 6 Oct 2020 00:55:36 +0900 Subject: [PATCH 2/5] Update: call check_command() from PowerShell's error 4104 --- src/detections/powershell.rs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/detections/powershell.rs b/src/detections/powershell.rs index 05084e62..46b34738 100644 --- a/src/detections/powershell.rs +++ b/src/detections/powershell.rs @@ -1,5 +1,9 @@ +use crate::detections::utils; use crate::models::event; use std::collections::HashMap; +use std::fs::File; +use std::io::prelude::*; +extern crate csv; pub struct PowerShell {} @@ -28,23 +32,20 @@ impl PowerShell { } fn execute_remote_command(&mut self, event_data: &HashMap) { - println!( - " - Path: {} - MessageTotal: {} - ScriptBlockText: {} - ScriptBlockId: {} - MessageNumber: {}", - event_data.get("Path").unwrap_or(&String::from("")), - event_data.get("MessageTotal").unwrap_or(&String::from("")), - event_data - .get("ScriptBlockText") - .unwrap_or(&String::from("")), - event_data - .get("ScriptBlockId") - .unwrap_or(&String::from("")), - event_data.get("MessageNumber").unwrap_or(&String::from("")), - ); + // リモートコマンドを実行します + let default = String::from(""); + let message_num = event_data.get("MessageNumber"); + let commandline = event_data.get("ScriptBlockText").unwrap_or(&default); + + let mut f = File::open("whitelist.txt").expect("file not found"); + let mut contents = String::new(); + let _ = f.read_to_string(&mut contents); + + let rdr = csv::Reader::from_reader(contents.as_bytes()); + match message_num { + Some(_) => utils::check_command(4104, &commandline, 1000, 0, &default, &default, rdr), + _ => {} + } return; } From 8dba24554f294b5413b23cb3ecd5776cb7f77a11 Mon Sep 17 00:00:00 2001 From: itiB Date: Tue, 6 Oct 2020 23:07:53 +0900 Subject: [PATCH 3/5] Add: DeepBlueCLI PowerShell's rule for 4103 --- src/detections/powershell.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/detections/powershell.rs b/src/detections/powershell.rs index 46b34738..cf0e1b9e 100644 --- a/src/detections/powershell.rs +++ b/src/detections/powershell.rs @@ -1,5 +1,6 @@ use crate::detections::utils; use crate::models::event; +use regex::Regex; use std::collections::HashMap; use std::fs::File; use std::io::prelude::*; @@ -25,9 +26,30 @@ impl PowerShell { } } - fn execute_pipeline(&mut self, _event_data: &HashMap) { - // PowerShell Error Code: 4103 is absent. - // ToDo: Correct Log & Check + fn execute_pipeline(&mut self, event_data: &HashMap) { + // パイプライン実行をしています + let default = String::from(""); + let commandline = event_data.get("ContextInfo").unwrap_or(&default); + + if commandline.contains("Host Application") + || commandline.contains("ホスト アプリケーション") + { + let rm_before = + Regex::new("(?ms)^.*(ホスト アプリケーション|Host Application) = ").unwrap(); + let rm_after = Regex::new("(?ms)\n.*$").unwrap(); + + let temp = rm_before.replace_all(commandline, ""); + let command = rm_after.replace_all(&temp, ""); + + let mut f = File::open("whitelist.txt").expect("file not found"); + let mut contents = String::new(); + let _ = f.read_to_string(&mut contents); + + let rdr = csv::Reader::from_reader(contents.as_bytes()); + if command != "" { + utils::check_command(4103, &command, 1000, 0, &default, &default, rdr); + } + } return; } From c12090227e4fde0bc11121ef5ec3b87c3688d8e8 Mon Sep 17 00:00:00 2001 From: itiB Date: Wed, 7 Oct 2020 20:26:34 +0900 Subject: [PATCH 4/5] Fix: get rdr by reference --- src/detections/detection.rs | 13 +++++++++++-- src/detections/powershell.rs | 29 +++++++++++++---------------- src/detections/utils.rs | 15 +++++++++------ 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 1ad2daf5..683d62dd 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -2,13 +2,16 @@ extern crate quick_xml; use crate::detections::application; use crate::detections::common; +use crate::detections::powershell; use crate::detections::security; use crate::detections::system; -use crate::detections::powershell; use crate::models::event; use evtx::EvtxParser; use quick_xml::de::DeError; use std::collections::BTreeMap; +use std::fs::File; +use std::io::prelude::*; +extern crate csv; #[derive(Debug)] pub struct Detection { @@ -29,6 +32,12 @@ impl Detection { let mut application = application::Application::new(); let mut powershell = powershell::PowerShell::new(); + let mut f = File::open("whitelist.txt").expect("file not found"); + let mut contents = String::new(); + let _ = f.read_to_string(&mut contents); + + let mut rdr = csv::Reader::from_reader(contents.as_bytes()); + for record in parser.records() { match record { Ok(r) => { @@ -46,7 +55,7 @@ impl Detection { } else if channel == "Application" { &application.detection(event_id, &event.system, event_data); } else if channel == "Microsoft-Windows-PowerShell/Operational" { - &powershell.detection(event_id, &event.system, event_data); + &powershell.detection(event_id, &event.system, event_data, &mut rdr); } else { //&other.detection(); } diff --git a/src/detections/powershell.rs b/src/detections/powershell.rs index cf0e1b9e..3cc54337 100644 --- a/src/detections/powershell.rs +++ b/src/detections/powershell.rs @@ -2,8 +2,6 @@ use crate::detections::utils; use crate::models::event; use regex::Regex; use std::collections::HashMap; -use std::fs::File; -use std::io::prelude::*; extern crate csv; pub struct PowerShell {} @@ -18,15 +16,20 @@ impl PowerShell { event_id: String, _system: &event::System, event_data: HashMap, + rdr: &mut csv::Reader<&[u8]>, ) { if event_id == "4103" { - &self.execute_pipeline(&event_data); + &self.execute_pipeline(&event_data, rdr); } else if event_id == "4104" { - &self.execute_remote_command(&event_data); + &self.execute_remote_command(&event_data, rdr); } } - fn execute_pipeline(&mut self, event_data: &HashMap) { + fn execute_pipeline( + &mut self, + event_data: &HashMap, + rdr: &mut csv::Reader<&[u8]>, + ) { // パイプライン実行をしています let default = String::from(""); let commandline = event_data.get("ContextInfo").unwrap_or(&default); @@ -41,11 +44,6 @@ impl PowerShell { let temp = rm_before.replace_all(commandline, ""); let command = rm_after.replace_all(&temp, ""); - let mut f = File::open("whitelist.txt").expect("file not found"); - let mut contents = String::new(); - let _ = f.read_to_string(&mut contents); - - let rdr = csv::Reader::from_reader(contents.as_bytes()); if command != "" { utils::check_command(4103, &command, 1000, 0, &default, &default, rdr); } @@ -53,17 +51,16 @@ impl PowerShell { return; } - fn execute_remote_command(&mut self, event_data: &HashMap) { + fn execute_remote_command( + &mut self, + event_data: &HashMap, + rdr: &mut csv::Reader<&[u8]>, + ) { // リモートコマンドを実行します let default = String::from(""); let message_num = event_data.get("MessageNumber"); let commandline = event_data.get("ScriptBlockText").unwrap_or(&default); - let mut f = File::open("whitelist.txt").expect("file not found"); - let mut contents = String::new(); - let _ = f.read_to_string(&mut contents); - - let rdr = csv::Reader::from_reader(contents.as_bytes()); match message_num { Some(_) => utils::check_command(4104, &commandline, 1000, 0, &default, &default, rdr), _ => {} diff --git a/src/detections/utils.rs b/src/detections/utils.rs index 9a2ffdc3..c18378c8 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -16,7 +16,7 @@ pub fn check_command( servicecmd: usize, servicename: &str, creator: &str, - mut rdr: csv::Reader<&[u8]>, + rdr: &mut csv::Reader<&[u8]>, ) { let mut text = "".to_string(); let mut base64 = "".to_string(); @@ -148,7 +148,10 @@ fn check_obfu(string: &str) -> std::string::String { fn check_regex(string: &str, r#type: usize) -> std::string::String { let mut f = File::open("regexes.txt").expect("file not found"); let mut contents = String::new(); - f.read_to_string(&mut contents); + let ret = f.read_to_string(&mut contents); + if let Err(_) = ret { + return "".to_string(); + } let mut rdr = csv::Reader::from_reader(contents.as_bytes()); @@ -222,10 +225,10 @@ mod tests { let mut contents = String::new(); f.read_to_string(&mut contents); - let rdr = csv::Reader::from_reader(contents.as_bytes()); - utils::check_command(1, "dir", 100, 100, "dir", "dir", rdr); + let mut rdr = csv::Reader::from_reader(contents.as_bytes()); + utils::check_command(1, "dir", 100, 100, "dir", "dir", &mut rdr); - let rdr = csv::Reader::from_reader(contents.as_bytes()); + let mut rdr = csv::Reader::from_reader(contents.as_bytes()); //test return with whitelist. utils::check_command( 1, @@ -234,7 +237,7 @@ mod tests { 100, "dir", "dir", - rdr, + &mut rdr, ); } } From 5f5251a4a4e759fe63f296e5f4e25052db02af8f Mon Sep 17 00:00:00 2001 From: itiB Date: Thu, 8 Oct 2020 22:24:28 +0900 Subject: [PATCH 5/5] Fix: solve thread --- src/detections/detection.rs | 2 +- src/detections/powershell.rs | 12 ++++-------- src/detections/utils.rs | 1 - 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 683d62dd..7d61a1d4 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -1,3 +1,4 @@ +extern crate csv; extern crate quick_xml; use crate::detections::application; @@ -11,7 +12,6 @@ use quick_xml::de::DeError; use std::collections::BTreeMap; use std::fs::File; use std::io::prelude::*; -extern crate csv; #[derive(Debug)] pub struct Detection { diff --git a/src/detections/powershell.rs b/src/detections/powershell.rs index 3cc54337..df9edf53 100644 --- a/src/detections/powershell.rs +++ b/src/detections/powershell.rs @@ -41,14 +41,13 @@ impl PowerShell { Regex::new("(?ms)^.*(ホスト アプリケーション|Host Application) = ").unwrap(); let rm_after = Regex::new("(?ms)\n.*$").unwrap(); - let temp = rm_before.replace_all(commandline, ""); - let command = rm_after.replace_all(&temp, ""); + let temp_command_with_extra = rm_before.replace_all(commandline, ""); + let command = rm_after.replace_all(&temp_command_with_extra, ""); if command != "" { utils::check_command(4103, &command, 1000, 0, &default, &default, rdr); } } - return; } fn execute_remote_command( @@ -61,11 +60,8 @@ impl PowerShell { let message_num = event_data.get("MessageNumber"); let commandline = event_data.get("ScriptBlockText").unwrap_or(&default); - match message_num { - Some(_) => utils::check_command(4104, &commandline, 1000, 0, &default, &default, rdr), - _ => {} + if let Some(_) = message_num { + utils::check_command(4104, &commandline, 1000, 0, &default, &default, rdr); } - - return; } } diff --git a/src/detections/utils.rs b/src/detections/utils.rs index c18378c8..ba9aaf39 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -228,7 +228,6 @@ mod tests { let mut rdr = csv::Reader::from_reader(contents.as_bytes()); utils::check_command(1, "dir", 100, 100, "dir", "dir", &mut rdr); - let mut rdr = csv::Reader::from_reader(contents.as_bytes()); //test return with whitelist. utils::check_command( 1,