diff --git a/src/afterfact.rs b/src/afterfact.rs index ecc9507e..393b3611 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -15,6 +15,7 @@ use std::process; pub struct CsvFormat<'a> { time: &'a str, filepath: &'a str, + level: &'a str, title: &'a str, message: &'a str, } @@ -78,6 +79,7 @@ fn emit_csv(writer: &mut W) -> Result<(), Box> { wtr.serialize(CsvFormat { time: &format_time(time), filepath: &detect_info.filepath, + level: &detect_info.level, title: &detect_info.title, message: &detect_info.detail, })?; @@ -112,6 +114,7 @@ fn test_emit_csv() { use std::fs::{read_to_string, remove_file}; let testfilepath: &str = "test.evtx"; let test_title = "test_title"; + let test_level = "high"; let output = "pokepoke"; { let mut messages = print::MESSAGES.lock().unwrap(); @@ -134,6 +137,7 @@ fn test_emit_csv() { messages.insert( testfilepath.to_string(), &event, + test_level.to_string(), test_title.to_string(), output.to_string(), ); @@ -143,11 +147,13 @@ fn test_emit_csv() { .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") .unwrap(); let expect_tz = expect_time.with_timezone(&Local); - let expect = "Time,Filepath,Title,Message\n".to_string() + let expect = "Time,Filepath,Level,Title,Message\n".to_string() + &expect_tz.clone().format("%Y-%m-%dT%H:%M:%S%:z").to_string() + "," + testfilepath + "," + + test_level + + "," + test_title + "," + output diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 2b595ce5..a43a94d2 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -157,6 +157,7 @@ impl Detection { MESSAGES.lock().unwrap().insert( record_info.evtx_filepath.to_string(), &record_info.record, + rule.yaml["level"].as_str().unwrap_or("").to_string(), rule.yaml["title"].as_str().unwrap_or("").to_string(), rule.yaml["output"].as_str().unwrap_or("").to_string(), ); @@ -168,6 +169,7 @@ impl Detection { MESSAGES.lock().unwrap().insert_message( agg_result.filepath, agg_result.start_timedate, + rule.yaml["level"].as_str().unwrap_or("").to_string(), rule.yaml["title"].as_str().unwrap_or("").to_string(), output.to_string(), ) diff --git a/src/detections/print.rs b/src/detections/print.rs index 22640a93..228c9464 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -17,6 +17,7 @@ pub struct Message { #[derive(Debug, Clone)] pub struct DetectInfo { pub filepath: String, + pub level: String, pub title: String, pub detail: String, } @@ -38,11 +39,13 @@ impl Message { &mut self, target_file: String, event_time: DateTime, + level: String, event_title: String, event_detail: String, ) { let detect_info = DetectInfo { filepath: target_file, + level: level, title: event_title, detail: event_detail, }; @@ -63,13 +66,14 @@ impl Message { &mut self, target_file: String, event_record: &Value, + level: String, event_title: String, output: String, ) { let message = &self.parse_message(event_record, output); let default_time = Utc.ymd(1970, 1, 1).and_hms(0, 0, 0); let time = Message::get_event_time(event_record).unwrap_or(default_time); - self.insert_message(target_file, time, event_title, message.to_string()) + self.insert_message(target_file, time, level, event_title, message.to_string()) } fn parse_message(&mut self, event_record: &Value, output: String) -> String { @@ -192,6 +196,7 @@ mod tests { message.insert( "a".to_string(), &event_record_1, + "high".to_string(), "test1".to_string(), "CommandLine1: %CommandLine%".to_string(), ); @@ -214,6 +219,7 @@ mod tests { message.insert( "a".to_string(), &event_record_2, + "high".to_string(), "test2".to_string(), "CommandLine2: %CommandLine%".to_string(), ); @@ -236,6 +242,7 @@ mod tests { message.insert( "a".to_string(), &event_record_3, + "high".to_string(), "test3".to_string(), "CommandLine3: %CommandLine%".to_string(), ); @@ -253,13 +260,14 @@ mod tests { message.insert( "a".to_string(), &event_record_4, + "medium".to_string(), "test4".to_string(), "CommandLine4: %CommandLine%".to_string(), ); let display = format!("{}", format_args!("{:?}", message)); println!("display::::{}", display); - let expect = "Message { map: {1970-01-01T00:00:00Z: [DetectInfo { filepath: \"a\", title: \"test4\", detail: \"CommandLine4: hoge\" }], 1996-02-27T01:05:01Z: [DetectInfo { filepath: \"a\", title: \"test1\", detail: \"CommandLine1: hoge\" }, DetectInfo { filepath: \"a\", title: \"test2\", detail: \"CommandLine2: hoge\" }], 2000-01-21T09:06:01Z: [DetectInfo { filepath: \"a\", title: \"test3\", detail: \"CommandLine3: hoge\" }]} }"; + let expect = "Message { map: {1970-01-01T00:00:00Z: [DetectInfo { filepath: \"a\", level: \"medium\", title: \"test4\", detail: \"CommandLine4: hoge\" }], 1996-02-27T01:05:01Z: [DetectInfo { filepath: \"a\", level: \"high\", title: \"test1\", detail: \"CommandLine1: hoge\" }, DetectInfo { filepath: \"a\", level: \"high\", title: \"test2\", detail: \"CommandLine2: hoge\" }], 2000-01-21T09:06:01Z: [DetectInfo { filepath: \"a\", level: \"high\", title: \"test3\", detail: \"CommandLine3: hoge\" }]} }"; assert_eq!(display, expect); }