Merge pull request #7 from YamatoSecurity/feature/powershell

Add: DeepBlueCLI PowerShell's rules
一旦、whitelistを引数で受け取る実装でマージします。
この部分はのちほど改修予定。
This commit is contained in:
nishikawaakira
2020-10-09 18:55:22 +09:00
committed by GitHub
4 changed files with 89 additions and 6 deletions

View File

@@ -1,7 +1,9 @@
extern crate csv;
extern crate quick_xml;
use crate::detections::application;
use crate::detections::common;
use crate::detections::powershell;
use crate::detections::security;
use crate::detections::sysmon;
use crate::detections::system;
@@ -9,6 +11,8 @@ use crate::models::event;
use evtx::EvtxParser;
use quick_xml::de::DeError;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::prelude::*;
#[derive(Debug)]
pub struct Detection {
@@ -28,6 +32,13 @@ impl Detection {
let mut system = system::System::new();
let mut application = application::Application::new();
let mut sysmon = sysmon::Sysmon::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 {
@@ -45,6 +56,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, &mut rdr);
} else if channel == "Microsoft-Windows-Sysmon/Operational" {
&sysmon.detection(event_id, &event.system, event_data);
} else {

View File

@@ -1,6 +1,7 @@
mod application;
mod common;
pub mod detection;
mod powershell;
mod security;
mod sysmon;
mod system;

View File

@@ -0,0 +1,67 @@
use crate::detections::utils;
use crate::models::event;
use regex::Regex;
use std::collections::HashMap;
extern crate csv;
pub struct PowerShell {}
impl PowerShell {
pub fn new() -> PowerShell {
PowerShell {}
}
pub fn detection(
&mut self,
event_id: String,
_system: &event::System,
event_data: HashMap<String, String>,
rdr: &mut csv::Reader<&[u8]>,
) {
if event_id == "4103" {
&self.execute_pipeline(&event_data, rdr);
} else if event_id == "4104" {
&self.execute_remote_command(&event_data, rdr);
}
}
fn execute_pipeline(
&mut self,
event_data: &HashMap<String, String>,
rdr: &mut csv::Reader<&[u8]>,
) {
// パイプライン実行をしています
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_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);
}
}
}
fn execute_remote_command(
&mut self,
event_data: &HashMap<String, String>,
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);
if let Some(_) = message_num {
utils::check_command(4104, &commandline, 1000, 0, &default, &default, rdr);
}
}
}

View File

@@ -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,9 @@ 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());
//test return with whitelist.
utils::check_command(
1,
@@ -234,7 +236,7 @@ mod tests {
100,
"dir",
"dir",
rdr,
&mut rdr,
);
}
}