From 46211711d6d59320520991a95bd169f16d3310b0 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 01:03:33 +0900 Subject: [PATCH 01/11] fixed #301 #303 #309 Squashed commit of the following: commit 617f12177fbf5066e141b5c1adf969b25c03fa3c Author: DustInDark Date: Tue Dec 21 00:57:13 2021 +0900 fix test typo and merge #301 commit 78926ebf55ae48566152c4097990ca1b1b536b53 Merge: c492ba1 83d891b Author: DustInDark Date: Tue Dec 21 00:22:55 2021 +0900 Merge branch 'main' into feature/output_errorlog_file#301 commit c492ba120a0d977d909b714c2506bd198200853b Author: DustInDark Date: Tue Dec 21 00:18:52 2021 +0900 renamed hayabusa-logs to logs commit ac018917300e535c2bfc62b6a9df081d4beb1568 Author: DustInDark Date: Mon Dec 20 23:48:48 2021 +0900 changed output file path deprecated #303 commit dcef677117555f2fac929b6d3b24ac18b5fb08fc Author: DustInDark Date: Mon Dec 20 23:47:42 2021 +0900 removed error file delete logic commit b09dec2e4a5c679c3b3c242a655f01cb3b49d490 Author: DustInDark Date: Mon Dec 20 23:46:49 2021 +0900 fixed -Q option flag #309 --- src/detections/configs.rs | 4 +-- src/detections/detection.rs | 13 +++++-- src/detections/print.rs | 69 +++++++++++++++++++++++++++++++++--- src/detections/rule/count.rs | 17 +++++++-- src/main.rs | 42 +++++++++++++++++++--- src/yaml.rs | 17 +++++++-- 6 files changed, 144 insertions(+), 18 deletions(-) diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 06f60e3d..908f1553 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -140,7 +140,7 @@ impl TargetEventTime { Err(err) => { AlertMessage::alert( &mut std::io::stderr().lock(), - format!("starttimeline field: {}", err), + format!("start-timeline field: {}", err), ) .ok(); None @@ -157,7 +157,7 @@ impl TargetEventTime { Err(err) => { AlertMessage::alert( &mut std::io::stderr().lock(), - format!("endtimeline field: {}", err), + format!("end-timeline field: {}", err), ) .ok(); None diff --git a/src/detections/detection.rs b/src/detections/detection.rs index d63a73e8..38a4c639 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -1,6 +1,7 @@ extern crate csv; use crate::detections::print::AlertMessage; +use crate::detections::print::ERROR_LOG_PATH; use crate::detections::print::MESSAGES; use crate::detections::rule; use crate::detections::rule::AggResult; @@ -11,9 +12,10 @@ use crate::yaml::ParseYaml; use hashbrown; use serde_json::Value; use std::collections::HashMap; -use tokio::{runtime::Runtime, spawn, task::JoinHandle}; - +use std::fs::OpenOptions; +use std::io::BufWriter; use std::sync::Arc; +use tokio::{runtime::Runtime, spawn, task::JoinHandle}; const DIRPATH_RULES: &str = "rules"; @@ -58,7 +60,12 @@ impl Detection { rulefile_loader.read_dir(rulespath.unwrap_or(DIRPATH_RULES), &level, exclude_ids); if result_readdir.is_err() { AlertMessage::alert( - &mut std::io::stderr().lock(), + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), format!("{}", result_readdir.unwrap_err()), ) .ok(); diff --git a/src/detections/print.rs b/src/detections/print.rs index 594aa504..5ee74dd3 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -2,13 +2,18 @@ extern crate lazy_static; use crate::detections::configs; use crate::detections::utils; use crate::detections::utils::get_serde_number_to_string; -use chrono::{DateTime, TimeZone, Utc}; +use chrono::{DateTime, Local, TimeZone, Utc}; use lazy_static::lazy_static; use regex::Regex; use serde_json::Value; use std::collections::BTreeMap; use std::collections::HashMap; +use std::env; +use std::fs::create_dir; +use std::fs::File; +use std::io::BufWriter; use std::io::{self, Write}; +use std::path::Path; use std::sync::Mutex; #[derive(Debug)] @@ -32,6 +37,15 @@ pub struct AlertMessage {} lazy_static! { pub static ref MESSAGES: Mutex = Mutex::new(Message::new()); pub static ref ALIASREGEX: Regex = Regex::new(r"%[a-zA-Z0-9-_]+%").unwrap(); + pub static ref ERROR_LOG_PATH: String = format!( + "./logs/errorlog-{}.log", + Local::now().format("%Y%m%d_%H%M%S") + ); + pub static ref QUIET_ERRORS_FLAG: bool = configs::CONFIG + .read() + .unwrap() + .args + .is_present("quiet-errors"); } impl Message { @@ -180,11 +194,56 @@ impl Message { } impl AlertMessage { - pub fn alert(w: &mut W, contents: String) -> io::Result<()> { - writeln!(w, "[ERROR] {}", contents) + ///対象のディレクトリが存在することを確認後、最初の定型文を追加して、ファイルのbufwriterを返す関数 + pub fn create_error_log(path_str: String) { + let path = Path::new(&path_str); + if !path.parent().unwrap().exists() { + create_dir(path.parent().unwrap()).ok(); + } + // 1行目は必ず実行したコマンド情報を入れておく。 + let mut ret = BufWriter::new(File::create(path).unwrap()); + + ret.write( + format!( + "user input: {:?}\n", + format_args!( + "{}", + env::args() + .map(|arg| arg) + .collect::>() + .join(" ") + ) + ) + .as_bytes(), + ) + .unwrap(); + ret.flush().ok(); } + + /// ERRORメッセージを表示する関数 + pub fn alert(w: &mut W, contents: String) -> io::Result<()> { + if !*QUIET_ERRORS_FLAG { + writeln!(w, "[ERROR] {}", contents) + } else { + Ok(()) + } + } + + /// WARNメッセージを表示する関数 pub fn warn(w: &mut W, contents: String) -> io::Result<()> { - writeln!(w, "[WARN] {}", contents) + if !*QUIET_ERRORS_FLAG { + writeln!(w, "[WARN] {}", contents) + } else { + Ok(()) + } + } + + /// エラーログへのERRORメッセージの出力数を確認して、0であったらファイルを削除する。1以上あればエラーを書き出した旨を標準出力に表示する + pub fn output_error_log_exist() { + println!( + "Generated error was output to {}. Please see the file for details.", + ERROR_LOG_PATH.to_string() + ); } } @@ -314,7 +373,7 @@ mod tests { let input = "TESTWarn!"; let stdout = std::io::stdout(); let mut stdout = stdout.lock(); - AlertMessage::alert(&mut stdout, input.to_string()).expect("[WARN] TESTWarn!"); + AlertMessage::warn(&mut stdout, input.to_string()).expect("[WARN] TESTWarn!"); } #[test] diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index c675589a..b150a916 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -1,4 +1,5 @@ use crate::detections::print::AlertMessage; +use crate::detections::print::ERROR_LOG_PATH; use crate::detections::rule::AggResult; use crate::detections::rule::AggregationParseInfo; use crate::detections::rule::Message; @@ -6,6 +7,8 @@ use crate::detections::rule::RuleNode; use chrono::{DateTime, TimeZone, Utc}; use hashbrown::HashMap; use serde_json::Value; +use std::fs::OpenOptions; +use std::io::BufWriter; use std::num::ParseIntError; use std::path::Path; @@ -183,7 +186,12 @@ impl TimeFrameInfo { tnum.retain(|c| c != 'd'); } else { AlertMessage::alert( - &mut std::io::stderr().lock(), + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), format!("Timeframe is invalid. Input value:{}", value), ) .ok(); @@ -215,7 +223,12 @@ pub fn get_sec_timeframe(timeframe: &Option) -> Option { } Err(err) => { AlertMessage::alert( - &mut std::io::stderr().lock(), + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), format!("Timeframe number is invalid. timeframe.{}", err), ) .ok(); diff --git a/src/main.rs b/src/main.rs index 50abee7d..a591dff3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use chrono::{DateTime, Local}; use evtx::{EvtxParser, ParserSettings}; use hayabusa::detections::detection::{self, EvtxRecordInfo}; use hayabusa::detections::print::AlertMessage; +use hayabusa::detections::print::ERROR_LOG_PATH; use hayabusa::detections::rule::{get_detection_keys, RuleNode}; use hayabusa::filter; use hayabusa::omikuji::Omikuji; @@ -16,6 +17,9 @@ use pbr::ProgressBar; use serde_json::Value; use std::collections::{HashMap, HashSet}; use std::fmt::Display; +use std::fs::OpenOptions; +use std::io::BufWriter; +use std::path::Path; use std::sync::Arc; use std::{ fs::{self, File}, @@ -66,6 +70,19 @@ impl App { ); return; } + if let Some(csv_path) = configs::CONFIG.read().unwrap().args.value_of("output") { + if Path::new(csv_path).exists() { + AlertMessage::alert( + &mut std::io::stderr().lock(), + format!( + " The file {} already exists. Please specify a different filename.", + csv_path + ), + ) + .ok(); + return; + } + } if let Some(filepath) = configs::CONFIG.read().unwrap().args.value_of("filepath") { if !filepath.ends_with(".evtx") { AlertMessage::alert( @@ -100,14 +117,22 @@ impl App { let analysis_duration = analysis_end_time.signed_duration_since(analysis_start_time); println!("Elapsed Time: {}", &analysis_duration.hhmmssxxx()); println!(""); + AlertMessage::output_error_log_exist(); } fn collect_evtxfiles(&self, dirpath: &str) -> Vec { let entries = fs::read_dir(dirpath); if entries.is_err() { - let stderr = std::io::stderr(); - let mut stderr = stderr.lock(); - AlertMessage::alert(&mut stderr, format!("{}", entries.unwrap_err())).ok(); + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + format!("{}", entries.unwrap_err()), + ) + .ok(); return vec![]; } @@ -206,7 +231,16 @@ impl App { evtx_filepath, record_result.unwrap_err() ); - AlertMessage::alert(&mut std::io::stderr().lock(), errmsg).ok(); + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + errmsg, + ) + .ok(); continue; } diff --git a/src/yaml.rs b/src/yaml.rs index 4411afb2..9c389714 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -3,11 +3,14 @@ extern crate yaml_rust; use crate::detections::configs; use crate::detections::print::AlertMessage; +use crate::detections::print::ERROR_LOG_PATH; use crate::filter::RuleExclude; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; +use std::fs::OpenOptions; use std::io; +use std::io::BufWriter; use std::io::{BufReader, Read}; use std::path::{Path, PathBuf}; use yaml_rust::Yaml; @@ -72,7 +75,12 @@ impl ParseYaml { let read_content = self.read_file(path); if read_content.is_err() { AlertMessage::warn( - &mut std::io::stdout().lock(), + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), format!( "fail to read file: {}\n{} ", entry.path().display(), @@ -87,7 +95,12 @@ impl ParseYaml { let yaml_contents = YamlLoader::load_from_str(&read_content.unwrap()); if yaml_contents.is_err() { AlertMessage::warn( - &mut std::io::stdout().lock(), + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), format!( "Failed to parse yml: {}\n{} ", entry.path().display(), From 20c8b2b073715b243c3a20b79fea63dce2a90549 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 01:26:46 +0900 Subject: [PATCH 02/11] added create_error_log --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index a591dff3..38ce6163 100644 --- a/src/main.rs +++ b/src/main.rs @@ -83,6 +83,7 @@ impl App { return; } } + AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); if let Some(filepath) = configs::CONFIG.read().unwrap().args.value_of("filepath") { if !filepath.ends_with(".evtx") { AlertMessage::alert( From 29ee8a590150e6223ad18a86fe0d7251c7b25221 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 01:38:25 +0900 Subject: [PATCH 03/11] added Q option --- src/detections/configs.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 908f1553..492f209e 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -68,6 +68,7 @@ fn build_app<'a>() -> ArgMatches<'a> { -t --thread-number=[NUMBER] 'Thread number (default: optimal number for performance)' -s --statistics 'Prints statistics of event IDs' -q --quiet 'Quiet mode. Do not display the launch banner' + -Q --quiet-errors 'Quiet errors mode. Do not display errors or save error logs' --contributors 'Prints the list of contributors'"; App::new(&program) .about("Hayabusa: Aiming to be the world's greatest Windows event log analysis tool!") From 33e743c8fc10e5f7e35b98bb71455667d13aaa7a Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 02:13:01 +0900 Subject: [PATCH 04/11] changed parse file error stderr to filewrite #301 --- src/detections/rule/count.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index b150a916..133b9e31 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -70,7 +70,12 @@ fn get_alias_value_in_record( } None => { AlertMessage::alert( - &mut std::io::stderr().lock(), + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), match is_by_alias { true => format!( "count by clause alias value not found in count process. rule file:{} EventID:{}", From 13494ec609a8e9e896c932823abcbc69be48531a Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 02:53:46 +0900 Subject: [PATCH 05/11] fixed tests errored no defined error file in alert function call --- src/yaml.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/yaml.rs b/src/yaml.rs index 9c389714..568f59b5 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -189,6 +189,8 @@ impl ParseYaml { #[cfg(test)] mod tests { + use crate::detections::print::AlertMessage; + use crate::detections::print::ERROR_LOG_PATH; use crate::filter; use crate::yaml; use crate::yaml::RuleExclude; @@ -198,6 +200,8 @@ mod tests { #[test] fn test_read_dir_yaml() { + AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); + let mut yaml = yaml::ParseYaml::new(); let exclude_ids = RuleExclude { no_use_rule: HashSet::new(), @@ -288,6 +292,8 @@ mod tests { } #[test] fn test_all_exclude_rules_file() { + AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); + let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/yaml"); yaml.read_dir(path.to_path_buf(), &"", &filter::exclude_ids()) @@ -296,6 +302,8 @@ mod tests { } #[test] fn test_none_exclude_rules_file() { + AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); + let mut yaml = yaml::ParseYaml::new(); let path = Path::new("test_files/rules/yaml"); let exclude_ids = RuleExclude { From 4fe66f12601ee1945c4662d53b0ce70b8f9040ae Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 08:36:11 +0900 Subject: [PATCH 06/11] fixed contributors.txt #301 --- contributors.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/contributors.txt b/contributors.txt index 8631af4c..bdbb24af 100644 --- a/contributors.txt +++ b/contributors.txt @@ -1,7 +1,6 @@ Hayabusa was possible thanks to the following people (in alphabetical order): Akira Nishikawa (@nishikawaakira): Previous lead developer, core hayabusa rule support, etc... -DustInDark(@hitenkoku): Core developer, project management, sigma count implementation, rule creation, countless feature additions and fixes, etc… Garigariganzy (@garigariganzy31): Developer, event ID statistics implementation, etc... ItiB (@itiB_S144) : Core developer, sigmac hayabusa backend, rule creation, etc... James Takai / hachiyone(@hach1yon): Current lead developer, tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, etc… @@ -17,7 +16,6 @@ Nishikawa Akira (@nishikawaakira): Lead Developer kazuminn (@k47_um1n): Core Developer itiB (@itiB_S144): Core Developer James Takai / hachiyone (@hach1yon): Core Developer -DustInDark (@hitenkoku): Core Developer garigariganzy (@garigariganzy31): Developer 7itoh (@yNitocrypto22): Developer dai (@__da13__): Developer From f1c9418ab48d1c9e0eafa4e09c34a946bc134e25 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 14:40:23 +0900 Subject: [PATCH 07/11] fixed errorlog create logic --- src/detections/detection.rs | 26 ++++++++++++++++---------- src/detections/print.rs | 22 ++++++++++------------ 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 38a4c639..92d4a3c8 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -59,16 +59,22 @@ impl Detection { let result_readdir = rulefile_loader.read_dir(rulespath.unwrap_or(DIRPATH_RULES), &level, exclude_ids); if result_readdir.is_err() { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - format!("{}", result_readdir.unwrap_err()), - ) - .ok(); + let errmsg = format!("{}", result_readdir.unwrap_err()); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + ) + .ok(); + } return vec![]; } let mut parseerror_count = rulefile_loader.errorrule_count; diff --git a/src/detections/print.rs b/src/detections/print.rs index 5ee74dd3..d2fdd691 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -196,6 +196,9 @@ impl Message { impl AlertMessage { ///対象のディレクトリが存在することを確認後、最初の定型文を追加して、ファイルのbufwriterを返す関数 pub fn create_error_log(path_str: String) { + if *QUIET_ERRORS_FLAG { + return; + } let path = Path::new(&path_str); if !path.parent().unwrap().exists() { create_dir(path.parent().unwrap()).ok(); @@ -221,25 +224,20 @@ impl AlertMessage { } /// ERRORメッセージを表示する関数 - pub fn alert(w: &mut W, contents: String) -> io::Result<()> { - if !*QUIET_ERRORS_FLAG { - writeln!(w, "[ERROR] {}", contents) - } else { - Ok(()) - } + pub fn alert(w: &mut W, contents: &String) -> io::Result<()> { + writeln!(w, "[ERROR] {}", contents) } /// WARNメッセージを表示する関数 - pub fn warn(w: &mut W, contents: String) -> io::Result<()> { - if !*QUIET_ERRORS_FLAG { - writeln!(w, "[WARN] {}", contents) - } else { - Ok(()) - } + pub fn warn(w: &mut W, contents: &String) -> io::Result<()> { + writeln!(w, "[WARN] {}", contents) } /// エラーログへのERRORメッセージの出力数を確認して、0であったらファイルを削除する。1以上あればエラーを書き出した旨を標準出力に表示する pub fn output_error_log_exist() { + if *QUIET_ERRORS_FLAG { + return; + } println!( "Generated error was output to {}. Please see the file for details.", ERROR_LOG_PATH.to_string() From bccdd8fef9a5660294857ae907baf54fcc057152 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 14:44:26 +0900 Subject: [PATCH 08/11] fixed error - changed writer from stderr to bufwriter - changed alert,warn function arg fro String to borrow-String --- src/afterfact.rs | 8 +-- src/detections/configs.rs | 9 +-- src/detections/detection.rs | 6 +- src/detections/print.rs | 17 +++-- src/detections/rule/count.rs | 118 ++++++++++++++++++++--------------- src/main.rs | 80 +++++++++++++++--------- src/yaml.rs | 65 +++++++++++-------- 7 files changed, 184 insertions(+), 119 deletions(-) diff --git a/src/afterfact.rs b/src/afterfact.rs index 8cbe21a5..3779c35c 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -36,8 +36,8 @@ pub struct DisplayFormat<'a> { pub fn after_fact() { let fn_emit_csv_err = |err: Box| { AlertMessage::alert( - &mut std::io::stderr().lock(), - format!("Failed to write CSV. {}", err), + &mut BufWriter::new(std::io::stderr().lock()), + &format!("Failed to write CSV. {}", err), ) .ok(); process::exit(1); @@ -51,8 +51,8 @@ pub fn after_fact() { Ok(file) => Box::new(BufWriter::new(file)), Err(err) => { AlertMessage::alert( - &mut std::io::stderr().lock(), - format!("Failed to open file. {}", err), + &mut BufWriter::new(std::io::stderr().lock()), + &format!("Failed to open file. {}", err), ) .ok(); process::exit(1); diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 492f209e..52c7ccd8 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -5,6 +5,7 @@ use clap::{App, AppSettings, ArgMatches}; use hashbrown::HashMap; use hashbrown::HashSet; use lazy_static::lazy_static; +use std::io::BufWriter; use std::sync::RwLock; lazy_static! { pub static ref CONFIG: RwLock = RwLock::new(ConfigReader::new()); @@ -140,8 +141,8 @@ impl TargetEventTime { Ok(dt) => Some(dt.with_timezone(&Utc)), Err(err) => { AlertMessage::alert( - &mut std::io::stderr().lock(), - format!("start-timeline field: {}", err), + &mut BufWriter::new(std::io::stderr().lock()), + &format!("start-timeline field: {}", err), ) .ok(); None @@ -157,8 +158,8 @@ impl TargetEventTime { Ok(dt) => Some(dt.with_timezone(&Utc)), Err(err) => { AlertMessage::alert( - &mut std::io::stderr().lock(), - format!("end-timeline field: {}", err), + &mut BufWriter::new(std::io::stderr().lock()), + &format!("end-timeline field: {}", err), ) .ok(); None diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 92d4a3c8..77fa1e76 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -1,8 +1,10 @@ extern crate csv; +use crate::detections::configs; use crate::detections::print::AlertMessage; use crate::detections::print::ERROR_LOG_PATH; use crate::detections::print::MESSAGES; +use crate::detections::print::QUIET_ERRORS_FLAG; use crate::detections::rule; use crate::detections::rule::AggResult; use crate::detections::rule::RuleNode; @@ -88,10 +90,10 @@ impl Detection { err_msgs_result.err().iter().for_each(|err_msgs| { let errmsg_body = format!("Failed to parse rule file. (FilePath : {})", rule.rulepath); - AlertMessage::warn(&mut std::io::stdout().lock(), errmsg_body).ok(); + AlertMessage::warn(&mut std::io::stdout().lock(), &errmsg_body).ok(); err_msgs.iter().for_each(|err_msg| { - AlertMessage::warn(&mut std::io::stdout().lock(), err_msg.to_string()).ok(); + AlertMessage::warn(&mut std::io::stdout().lock(), &err_msg.to_string()).ok(); }); parseerror_count += 1; println!(""); // 一行開けるためのprintln diff --git a/src/detections/print.rs b/src/detections/print.rs index d2fdd691..54c97738 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -249,6 +249,7 @@ impl AlertMessage { mod tests { use crate::detections::print::{AlertMessage, Message}; use serde_json::Value; + use std::io::BufWriter; #[test] fn test_create_and_append_message() { @@ -361,17 +362,21 @@ mod tests { #[test] fn test_error_message() { let input = "TEST!"; - let stdout = std::io::stdout(); - let mut stdout = stdout.lock(); - AlertMessage::alert(&mut stdout, input.to_string()).expect("[ERROR] TEST!"); + AlertMessage::alert( + &mut BufWriter::new(std::io::stdout().lock()), + &input.to_string(), + ) + .expect("[ERROR] TEST!"); } #[test] fn test_warn_message() { let input = "TESTWarn!"; - let stdout = std::io::stdout(); - let mut stdout = stdout.lock(); - AlertMessage::warn(&mut stdout, input.to_string()).expect("[WARN] TESTWarn!"); + AlertMessage::warn( + &mut BufWriter::new(std::io::stdout().lock()), + &input.to_string(), + ) + .expect("[WARN] TESTWarn!"); } #[test] diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index 133b9e31..b49759ec 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -1,5 +1,7 @@ +use crate::detections::configs; use crate::detections::print::AlertMessage; use crate::detections::print::ERROR_LOG_PATH; +use crate::detections::print::QUIET_ERRORS_FLAG; use crate::detections::rule::AggResult; use crate::detections::rule::AggregationParseInfo; use crate::detections::rule::Message; @@ -69,35 +71,41 @@ fn get_alias_value_in_record( return Some(value.to_string().replace("\"", "")); } None => { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - match is_by_alias { - true => format!( - "count by clause alias value not found in count process. rule file:{} EventID:{}", - Path::new(&rule.rulepath) - .file_name() - .unwrap() - .to_str() - .unwrap(), - utils::get_event_value(&utils::get_event_id_key(), record).unwrap() - ), - false => format!( - "count field clause alias value not found in count process. rule file:{} EventID:{}", - Path::new(&rule.rulepath) - .file_name() - .unwrap() - .to_str() - .unwrap(), - utils::get_event_value(&utils::get_event_id_key(), record).unwrap() - ), - }, - ) - .ok(); + let errmsg = match is_by_alias { + true => format!( + "count by clause alias value not found in count process. rule file:{} EventID:{}", + Path::new(&rule.rulepath) + .file_name() + .unwrap() + .to_str() + .unwrap(), + utils::get_event_value(&utils::get_event_id_key(), record).unwrap() + ), + false => format!( + "count field clause alias value not found in count process. rule file:{} EventID:{}", + Path::new(&rule.rulepath) + .file_name() + .unwrap() + .to_str() + .unwrap(), + utils::get_event_value(&utils::get_event_id_key(), record).unwrap() + ), + }; + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + ) + .ok(); + } return None; } }; @@ -190,16 +198,22 @@ impl TimeFrameInfo { ttype = "d".to_owned(); tnum.retain(|c| c != 'd'); } else { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - format!("Timeframe is invalid. Input value:{}", value), - ) - .ok(); + let errmsg = format!("Timeframe is invalid. Input value:{}", value); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + ) + .ok(); + } } return TimeFrameInfo { timetype: ttype, @@ -227,16 +241,22 @@ pub fn get_sec_timeframe(timeframe: &Option) -> Option { } } Err(err) => { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - format!("Timeframe number is invalid. timeframe.{}", err), - ) - .ok(); + let errmsg = format!("Timeframe number is invalid. timeframe. {}", err); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + ) + .ok(); + } return Option::None; } } diff --git a/src/main.rs b/src/main.rs index 38ce6163..a4c89a77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use evtx::{EvtxParser, ParserSettings}; use hayabusa::detections::detection::{self, EvtxRecordInfo}; use hayabusa::detections::print::AlertMessage; use hayabusa::detections::print::ERROR_LOG_PATH; +use hayabusa::detections::print::QUIET_ERRORS_FLAG; use hayabusa::detections::rule::{get_detection_keys, RuleNode}; use hayabusa::filter; use hayabusa::omikuji::Omikuji; @@ -73,8 +74,8 @@ impl App { if let Some(csv_path) = configs::CONFIG.read().unwrap().args.value_of("output") { if Path::new(csv_path).exists() { AlertMessage::alert( - &mut std::io::stderr().lock(), - format!( + &mut BufWriter::new(std::io::stderr().lock()), + &format!( " The file {} already exists. Please specify a different filename.", csv_path ), @@ -83,12 +84,19 @@ impl App { return; } } - AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); + if !configs::CONFIG + .read() + .unwrap() + .args + .is_present("quiet-errors") + { + AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); + } if let Some(filepath) = configs::CONFIG.read().unwrap().args.value_of("filepath") { if !filepath.ends_with(".evtx") { AlertMessage::alert( - &mut std::io::stderr().lock(), - "--filepath only accepts .evtx files.".to_owned(), + &mut BufWriter::new(std::io::stderr().lock()), + &"--filepath only accepts .evtx files.".to_string(), ) .ok(); return; @@ -98,8 +106,8 @@ impl App { let evtx_files = self.collect_evtxfiles(&directory); if evtx_files.len() == 0 { AlertMessage::alert( - &mut std::io::stderr().lock(), - "No .evtx files were found.".to_owned(), + &mut BufWriter::new(std::io::stderr().lock()), + &"No .evtx files were found.".to_string(), ) .ok(); return; @@ -124,16 +132,22 @@ impl App { fn collect_evtxfiles(&self, dirpath: &str) -> Vec { let entries = fs::read_dir(dirpath); if entries.is_err() { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - format!("{}", entries.unwrap_err()), - ) - .ok(); + let errmsg = format!("{}", entries.unwrap_err()); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + ) + .ok(); + } return vec![]; } @@ -165,7 +179,11 @@ impl App { match fs::read_to_string("./contributors.txt") { Ok(contents) => println!("{}", contents), Err(err) => { - AlertMessage::alert(&mut std::io::stderr().lock(), format!("{}", err)).ok(); + AlertMessage::alert( + &mut BufWriter::new(std::io::stderr().lock()), + &format!("{}", err), + ) + .ok(); } } } @@ -232,16 +250,22 @@ impl App { evtx_filepath, record_result.unwrap_err() ); - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - errmsg, - ) - .ok(); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg) + .ok(); + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::alert( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + ) + .ok(); + } continue; } diff --git a/src/yaml.rs b/src/yaml.rs index 568f59b5..bb59143c 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -4,6 +4,7 @@ extern crate yaml_rust; use crate::detections::configs; use crate::detections::print::AlertMessage; use crate::detections::print::ERROR_LOG_PATH; +use crate::detections::print::QUIET_ERRORS_FLAG; use crate::filter::RuleExclude; use std::collections::HashMap; use std::ffi::OsStr; @@ -74,19 +75,25 @@ impl ParseYaml { // 個別のファイルの読み込みは即終了としない。 let read_content = self.read_file(path); if read_content.is_err() { - AlertMessage::warn( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - format!( - "fail to read file: {}\n{} ", - entry.path().display(), - read_content.unwrap_err() - ), - )?; + let errmsg = format!( + "fail to read file: {}\n{} ", + entry.path().display(), + read_content.unwrap_err() + ); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::warn(&mut BufWriter::new(std::io::stderr().lock()), &errmsg)?; + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::warn( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + )?; + } self.errorrule_count += 1; return io::Result::Ok(ret); } @@ -94,19 +101,25 @@ impl ParseYaml { // ここも個別のファイルの読み込みは即終了としない。 let yaml_contents = YamlLoader::load_from_str(&read_content.unwrap()); if yaml_contents.is_err() { - AlertMessage::warn( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - format!( - "Failed to parse yml: {}\n{} ", - entry.path().display(), - yaml_contents.unwrap_err() - ), - )?; + let errmsg = format!( + "Failed to parse yml: {}\n{} ", + entry.path().display(), + yaml_contents.unwrap_err() + ); + if configs::CONFIG.read().unwrap().args.is_present("verbose") { + AlertMessage::warn(&mut BufWriter::new(std::io::stderr().lock()), &errmsg)?; + } + if !*QUIET_ERRORS_FLAG { + AlertMessage::warn( + &mut BufWriter::new( + OpenOptions::new() + .append(true) + .open(ERROR_LOG_PATH.to_string()) + .unwrap(), + ), + &errmsg, + )?; + } self.errorrule_count += 1; return io::Result::Ok(ret); } From 2b76103028bf6e85f22f9ed2145827dbc2bcffc2 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 21 Dec 2021 21:50:33 +0900 Subject: [PATCH 09/11] fixed output #301 - To save error log, created empty folder logs - fixed output --- contributors.txt | 4 +++- logs/.gitkeep | 0 src/detections/configs.rs | 2 +- src/detections/print.rs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 logs/.gitkeep diff --git a/contributors.txt b/contributors.txt index bdbb24af..03c81c17 100644 --- a/contributors.txt +++ b/contributors.txt @@ -1,9 +1,10 @@ Hayabusa was possible thanks to the following people (in alphabetical order): Akira Nishikawa (@nishikawaakira): Previous lead developer, core hayabusa rule support, etc... +DustInDark(@hitenkoku): Core Developer Garigariganzy (@garigariganzy31): Developer, event ID statistics implementation, etc... ItiB (@itiB_S144) : Core developer, sigmac hayabusa backend, rule creation, etc... -James Takai / hachiyone(@hach1yon): Current lead developer, tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, etc… +James Takai / hachiyone(@hach1yon): Current lead developer, tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, sigma count implementation etc… Kazuminn (@k47_um1n): Developer Yusuke Matsui (@apt773): AD hacking working group leader, rule testing, documentation, research, support, etc... Zach Mathis (@yamatosecurity, Yamato Security Founder): Project leader, tool and concept design, rule creation and tuning, etc… @@ -13,6 +14,7 @@ Hayabusa would not have been possible without first creating RustyBlue, so we wo Zach Mathis (@yamatosecurity, Yamato Security Founder): Project Leader Nishikawa Akira (@nishikawaakira): Lead Developer +DustInDark (@hitenkoku): Core Developer kazuminn (@k47_um1n): Core Developer itiB (@itiB_S144): Core Developer James Takai / hachiyone (@hach1yon): Core Developer diff --git a/logs/.gitkeep b/logs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 52c7ccd8..7f5c37cd 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -69,7 +69,7 @@ fn build_app<'a>() -> ArgMatches<'a> { -t --thread-number=[NUMBER] 'Thread number (default: optimal number for performance)' -s --statistics 'Prints statistics of event IDs' -q --quiet 'Quiet mode. Do not display the launch banner' - -Q --quiet-errors 'Quiet errors mode. Do not display errors or save error logs' + -Q --quiet-errors 'Quiet errors mode. Do not save error logs.' --contributors 'Prints the list of contributors'"; App::new(&program) .about("Hayabusa: Aiming to be the world's greatest Windows event log analysis tool!") diff --git a/src/detections/print.rs b/src/detections/print.rs index 54c97738..e5081ced 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -239,7 +239,7 @@ impl AlertMessage { return; } println!( - "Generated error was output to {}. Please see the file for details.", + "Errors were generated. Please check {} for details.", ERROR_LOG_PATH.to_string() ); } From 8876fc5f65536f4c0bef641b08f0bdd6d7d79b0c Mon Sep 17 00:00:00 2001 From: DustInDark Date: Wed, 22 Dec 2021 09:41:06 +0900 Subject: [PATCH 10/11] added newline --- src/detections/print.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detections/print.rs b/src/detections/print.rs index e5081ced..d7ddab4e 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -242,6 +242,7 @@ impl AlertMessage { "Errors were generated. Please check {} for details.", ERROR_LOG_PATH.to_string() ); + println!(""); } } From 3412434d99e6a8edab3d861b2f7b575cc29515ae Mon Sep 17 00:00:00 2001 From: DustInDark Date: Wed, 22 Dec 2021 14:56:10 +0900 Subject: [PATCH 11/11] fixed error --- contributors.txt | 2 -- logs/.gitkeep | 0 src/detections/detection.rs | 19 +++++--------- src/detections/print.rs | 51 ++++++++++++++++-------------------- src/detections/rule/count.rs | 45 +++++++++---------------------- src/main.rs | 44 ++++++++++--------------------- src/yaml.rs | 29 +++++++------------- 7 files changed, 65 insertions(+), 125 deletions(-) delete mode 100644 logs/.gitkeep diff --git a/contributors.txt b/contributors.txt index 03c81c17..95d6f486 100644 --- a/contributors.txt +++ b/contributors.txt @@ -1,7 +1,6 @@ Hayabusa was possible thanks to the following people (in alphabetical order): Akira Nishikawa (@nishikawaakira): Previous lead developer, core hayabusa rule support, etc... -DustInDark(@hitenkoku): Core Developer Garigariganzy (@garigariganzy31): Developer, event ID statistics implementation, etc... ItiB (@itiB_S144) : Core developer, sigmac hayabusa backend, rule creation, etc... James Takai / hachiyone(@hach1yon): Current lead developer, tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, sigma count implementation etc… @@ -14,7 +13,6 @@ Hayabusa would not have been possible without first creating RustyBlue, so we wo Zach Mathis (@yamatosecurity, Yamato Security Founder): Project Leader Nishikawa Akira (@nishikawaakira): Lead Developer -DustInDark (@hitenkoku): Core Developer kazuminn (@k47_um1n): Core Developer itiB (@itiB_S144): Core Developer James Takai / hachiyone (@hach1yon): Core Developer diff --git a/logs/.gitkeep b/logs/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 77fa1e76..f7807364 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -2,7 +2,7 @@ extern crate csv; use crate::detections::configs; use crate::detections::print::AlertMessage; -use crate::detections::print::ERROR_LOG_PATH; +use crate::detections::print::ERROR_LOG_STACK; use crate::detections::print::MESSAGES; use crate::detections::print::QUIET_ERRORS_FLAG; use crate::detections::rule; @@ -14,7 +14,6 @@ use crate::yaml::ParseYaml; use hashbrown; use serde_json::Value; use std::collections::HashMap; -use std::fs::OpenOptions; use std::io::BufWriter; use std::sync::Arc; use tokio::{runtime::Runtime, spawn, task::JoinHandle}; @@ -66,16 +65,10 @@ impl Detection { AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); } if !*QUIET_ERRORS_FLAG { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - ) - .ok(); + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[ERROR] {}", errmsg)); } return vec![]; } @@ -93,7 +86,7 @@ impl Detection { AlertMessage::warn(&mut std::io::stdout().lock(), &errmsg_body).ok(); err_msgs.iter().for_each(|err_msg| { - AlertMessage::warn(&mut std::io::stdout().lock(), &err_msg.to_string()).ok(); + AlertMessage::warn(&mut std::io::stdout().lock(), err_msg).ok(); }); parseerror_count += 1; println!(""); // 一行開けるためのprintln diff --git a/src/detections/print.rs b/src/detections/print.rs index d7ddab4e..380c2858 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -46,6 +46,7 @@ lazy_static! { .unwrap() .args .is_present("quiet-errors"); + pub static ref ERROR_LOG_STACK: Mutex> = Mutex::new(Vec::new()); } impl Message { @@ -203,24 +204,30 @@ impl AlertMessage { if !path.parent().unwrap().exists() { create_dir(path.parent().unwrap()).ok(); } - // 1行目は必ず実行したコマンド情報を入れておく。 - let mut ret = BufWriter::new(File::create(path).unwrap()); - - ret.write( - format!( - "user input: {:?}\n", - format_args!( - "{}", - env::args() - .map(|arg| arg) - .collect::>() - .join(" ") + let mut error_log_writer = BufWriter::new(File::create(path).unwrap()); + error_log_writer + .write( + format!( + "user input: {:?}\n", + format_args!( + "{}", + env::args() + .map(|arg| arg) + .collect::>() + .join(" ") + ) ) + .as_bytes(), ) - .as_bytes(), - ) - .unwrap(); - ret.flush().ok(); + .unwrap(); + for error_log in ERROR_LOG_STACK.lock().unwrap().iter() { + writeln!(error_log_writer, "{}", error_log).ok(); + } + println!( + "Errors were generated. Please check {} for details.", + ERROR_LOG_PATH.to_string() + ); + println!(""); } /// ERRORメッセージを表示する関数 @@ -232,18 +239,6 @@ impl AlertMessage { pub fn warn(w: &mut W, contents: &String) -> io::Result<()> { writeln!(w, "[WARN] {}", contents) } - - /// エラーログへのERRORメッセージの出力数を確認して、0であったらファイルを削除する。1以上あればエラーを書き出した旨を標準出力に表示する - pub fn output_error_log_exist() { - if *QUIET_ERRORS_FLAG { - return; - } - println!( - "Errors were generated. Please check {} for details.", - ERROR_LOG_PATH.to_string() - ); - println!(""); - } } #[cfg(test)] diff --git a/src/detections/rule/count.rs b/src/detections/rule/count.rs index b49759ec..5a29752b 100644 --- a/src/detections/rule/count.rs +++ b/src/detections/rule/count.rs @@ -1,6 +1,6 @@ use crate::detections::configs; use crate::detections::print::AlertMessage; -use crate::detections::print::ERROR_LOG_PATH; +use crate::detections::print::ERROR_LOG_STACK; use crate::detections::print::QUIET_ERRORS_FLAG; use crate::detections::rule::AggResult; use crate::detections::rule::AggregationParseInfo; @@ -9,7 +9,6 @@ use crate::detections::rule::RuleNode; use chrono::{DateTime, TimeZone, Utc}; use hashbrown::HashMap; use serde_json::Value; -use std::fs::OpenOptions; use std::io::BufWriter; use std::num::ParseIntError; use std::path::Path; @@ -95,16 +94,10 @@ fn get_alias_value_in_record( AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); } if !*QUIET_ERRORS_FLAG { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - ) - .ok(); + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[ERROR] {}", errmsg)); } return None; } @@ -203,16 +196,10 @@ impl TimeFrameInfo { AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); } if !*QUIET_ERRORS_FLAG { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - ) - .ok(); + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[ERROR] {}", errmsg)); } } return TimeFrameInfo { @@ -246,16 +233,10 @@ pub fn get_sec_timeframe(timeframe: &Option) -> Option { AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); } if !*QUIET_ERRORS_FLAG { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - ) - .ok(); + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[ERROR] {}", errmsg.to_string())); } return Option::None; } diff --git a/src/main.rs b/src/main.rs index a4c89a77..31cc573c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use evtx::{EvtxParser, ParserSettings}; use hayabusa::detections::detection::{self, EvtxRecordInfo}; use hayabusa::detections::print::AlertMessage; use hayabusa::detections::print::ERROR_LOG_PATH; +use hayabusa::detections::print::ERROR_LOG_STACK; use hayabusa::detections::print::QUIET_ERRORS_FLAG; use hayabusa::detections::rule::{get_detection_keys, RuleNode}; use hayabusa::filter; @@ -18,7 +19,6 @@ use pbr::ProgressBar; use serde_json::Value; use std::collections::{HashMap, HashSet}; use std::fmt::Display; -use std::fs::OpenOptions; use std::io::BufWriter; use std::path::Path; use std::sync::Arc; @@ -84,14 +84,6 @@ impl App { return; } } - if !configs::CONFIG - .read() - .unwrap() - .args - .is_present("quiet-errors") - { - AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); - } if let Some(filepath) = configs::CONFIG.read().unwrap().args.value_of("filepath") { if !filepath.ends_with(".evtx") { AlertMessage::alert( @@ -126,7 +118,11 @@ impl App { let analysis_duration = analysis_end_time.signed_duration_since(analysis_start_time); println!("Elapsed Time: {}", &analysis_duration.hhmmssxxx()); println!(""); - AlertMessage::output_error_log_exist(); + + // Qオプションを付けた場合もしくはパースのエラーがない場合はerrorのstackが9となるのでエラーログファイル自体が生成されない。 + if ERROR_LOG_STACK.lock().unwrap().len() > 0 { + AlertMessage::create_error_log(ERROR_LOG_PATH.to_string()); + } } fn collect_evtxfiles(&self, dirpath: &str) -> Vec { @@ -137,16 +133,10 @@ impl App { AlertMessage::alert(&mut BufWriter::new(std::io::stderr().lock()), &errmsg).ok(); } if !*QUIET_ERRORS_FLAG { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - ) - .ok(); + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[ERROR] {}", errmsg)); } return vec![]; } @@ -255,16 +245,10 @@ impl App { .ok(); } if !*QUIET_ERRORS_FLAG { - AlertMessage::alert( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - ) - .ok(); + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[ERROR] {}", errmsg)); } continue; } diff --git a/src/yaml.rs b/src/yaml.rs index bb59143c..005ceedf 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -3,13 +3,12 @@ extern crate yaml_rust; use crate::detections::configs; use crate::detections::print::AlertMessage; -use crate::detections::print::ERROR_LOG_PATH; +use crate::detections::print::ERROR_LOG_STACK; use crate::detections::print::QUIET_ERRORS_FLAG; use crate::filter::RuleExclude; use std::collections::HashMap; use std::ffi::OsStr; use std::fs; -use std::fs::OpenOptions; use std::io; use std::io::BufWriter; use std::io::{BufReader, Read}; @@ -84,15 +83,10 @@ impl ParseYaml { AlertMessage::warn(&mut BufWriter::new(std::io::stderr().lock()), &errmsg)?; } if !*QUIET_ERRORS_FLAG { - AlertMessage::warn( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - )?; + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[WARN] {}", errmsg)); } self.errorrule_count += 1; return io::Result::Ok(ret); @@ -110,15 +104,10 @@ impl ParseYaml { AlertMessage::warn(&mut BufWriter::new(std::io::stderr().lock()), &errmsg)?; } if !*QUIET_ERRORS_FLAG { - AlertMessage::warn( - &mut BufWriter::new( - OpenOptions::new() - .append(true) - .open(ERROR_LOG_PATH.to_string()) - .unwrap(), - ), - &errmsg, - )?; + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[WARN] {}", errmsg)); } self.errorrule_count += 1; return io::Result::Ok(ret);