From 0df42b67ba479d1dd440770cd07595c76a239a1f Mon Sep 17 00:00:00 2001 From: DustInDark Date: Fri, 3 Jun 2022 20:49:26 +0900 Subject: [PATCH] output saving results message (#563) * added Results Summary title #561 * added results message when output option is enabled. #561 * version number update * added newline * removed newline * tuned output #561 * fixed bug that console output table header color is same with 1st row color #561 * cargo fmt --- CHANGELOG-Japanese.md | 1 + CHANGELOG.md | 1 + Cargo.lock | 4 +-- Cargo.toml | 2 +- src/afterfact.rs | 76 ++++++++++++++++++--------------------- src/detections/configs.rs | 2 +- src/main.rs | 5 +++ 7 files changed, 46 insertions(+), 45 deletions(-) diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 19854b5c..18158e85 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -19,6 +19,7 @@ - ロゴの色を変更した (#537) (@hitenkoku) - Channelの列にchannel_abbrevations.txtに記載されていないチャンネルも表示するようにした。(#553) (@hitenkoku) - `Ignored rules`として集計されていた`Exclude rules`、`Noisy rules`、`Deprecated rules`に分けて表示するようにした。 (#556) (@hitenkoku) +- `output`オプションが指定されているときに、ファイル出力中のメッセージを表示するようにした。 (#561) (@hitenkoku) **バグ修正:** diff --git a/CHANGELOG.md b/CHANGELOG.md index 26fc99fd..8b5e68bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Changed logo color. (#537) (@hitenkoku) - Display the original `Channel` name when not specified in `channel_abbrevations.txt`. (#553) (@hitenkoku) - Display separately `Ignored rules` to `Exclude rules`, `Noisy rules`, and `Deprecated rules`. (#556) (@hitenkoku) +- Display results messge when `output` option is set. (#561) (@hitenkoku) **Bug Fixes:** diff --git a/Cargo.lock b/Cargo.lock index c78aba8f..6cf865b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -935,9 +935,9 @@ dependencies = [ [[package]] name = "hayabusa" -version = "1.3.0-dev" +version = "1.3.0" dependencies = [ - "base64 0.13.0", + "base64 0.10.1", "bytesize", "chrono", "clap 2.34.0", diff --git a/Cargo.toml b/Cargo.toml index 65e99fb0..6cb92b36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hayabusa" -version = "1.3.0-dev" +version = "1.3.0" authors = ["Yamato Security @SecurityYamato"] edition = "2021" diff --git a/src/afterfact.rs b/src/afterfact.rs index da9df573..719c9734 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -195,9 +195,10 @@ fn emit_csv( ) -> io::Result<()> { let disp_wtr = BufferWriter::stdout(ColorChoice::Always); let mut disp_wtr_buf = disp_wtr.buffer(); - let mut wtr = csv::WriterBuilder::new().from_writer(writer); + disp_wtr_buf.set_color(ColorSpec::new().set_fg(None)).ok(); + let messages = print::MESSAGES.lock().unwrap(); // level is devided by "Critical","High","Medium","Low","Informational","Undefined". let mut total_detect_counts_by_level: Vec = vec![0; 6]; @@ -222,8 +223,9 @@ fn emit_csv( detect_counts_by_date_and_level.insert(level_init.to_string(), HashMap::new()); detect_counts_by_computer_and_level.insert(level_init.to_string(), HashMap::new()); } - - println!(); + if displayflag { + println!(); + } let mut timestamps: Vec = Vec::new(); let mut plus_header = true; let mut detected_record_idset: HashSet = HashSet::new(); @@ -263,6 +265,11 @@ fn emit_csv( record_i_d: record_id.as_deref(), }; + //ヘッダーのみを出力 + if plus_header { + write!(disp_wtr_buf, "{}", _get_serialized_disp_output(None)).ok(); + plus_header = false; + } disp_wtr_buf .set_color( ColorSpec::new().set_fg(_get_output_color(&color_map, &detect_info.level)), @@ -271,10 +278,9 @@ fn emit_csv( write!( disp_wtr_buf, "{}", - _get_serialized_disp_output(dispformat, plus_header) + _get_serialized_disp_output(Some(dispformat)) ) .ok(); - plus_header = false; } else { // csv output format wtr.serialize(CsvFormat { @@ -333,10 +339,15 @@ fn emit_csv( } if displayflag { disp_wtr.print(&disp_wtr_buf)?; + println!(); } else { wtr.flush()?; } - println!(); + + disp_wtr_buf.clear(); + disp_wtr_buf.set_color(ColorSpec::new().set_fg(None)).ok(); + writeln!(disp_wtr_buf, "Results Summary:").ok(); + disp_wtr.print(&disp_wtr_buf).ok(); let size = terminal_size(); let terminal_width = match size { @@ -393,15 +404,18 @@ enum ColPos { Other, } -fn _get_serialized_disp_output(dispformat: DisplayFormat, plus_header: bool) -> String { +fn _get_serialized_disp_output(dispformat: Option) -> String { + if dispformat.is_none() { + return "Timestamp|Computer|Channel|EventID|Level|RuleTitle|Details|RecordID|RecordInformation\n".to_string(); + } let mut disp_serializer = csv::WriterBuilder::new() .double_quote(false) .quote_style(QuoteStyle::Never) .delimiter(b'|') - .has_headers(plus_header) + .has_headers(false) .from_writer(vec![]); - disp_serializer.serialize(dispformat).ok(); + disp_serializer.serialize(dispformat.unwrap()).ok(); String::from_utf8(disp_serializer.into_inner().unwrap_or_default()).unwrap_or_default() } @@ -737,39 +751,19 @@ mod tests { + "|" + test_recinfo + "\n"; - let expect_with_header = expect_header.to_string() + &expect_no_header; + assert_eq!(_get_serialized_disp_output(None,), expect_header); assert_eq!( - _get_serialized_disp_output( - DisplayFormat { - timestamp: &format_time(&test_timestamp), - level: test_level, - computer: test_computername, - event_i_d: test_eventid, - channel: test_channel, - rule_title: test_title, - details: output, - record_information: Some(test_recinfo), - record_i_d: Some(test_recid), - }, - true - ), - expect_with_header - ); - assert_eq!( - _get_serialized_disp_output( - DisplayFormat { - timestamp: &format_time(&test_timestamp), - level: test_level, - computer: test_computername, - event_i_d: test_eventid, - channel: test_channel, - rule_title: test_title, - details: output, - record_information: Some(test_recinfo), - record_i_d: Some(test_recid), - }, - false - ), + _get_serialized_disp_output(Some(DisplayFormat { + timestamp: &format_time(&test_timestamp), + level: test_level, + computer: test_computername, + event_i_d: test_eventid, + channel: test_channel, + rule_title: test_title, + details: output, + record_information: Some(test_recinfo), + record_i_d: Some(test_recid), + })), expect_no_header ); } diff --git a/src/detections/configs.rs b/src/detections/configs.rs index a9f1cbed..6e686841 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -98,7 +98,7 @@ fn build_app<'a>() -> ArgMatches<'a> { --contributors 'Prints the list of contributors.'"; App::new(&program) .about("Hayabusa: Aiming to be the world's greatest Windows event log analysis tool!") - .version("1.3.0-dev") + .version("1.3.0") .author("Yamato Security (https://github.com/Yamato-Security/hayabusa) @SecurityYamato") .setting(AppSettings::VersionlessSubcommands) .arg( diff --git a/src/main.rs b/src/main.rs index 98e72f5e..cb18dec4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -482,6 +482,11 @@ impl App { total_records += cnt_tmp; pb.inc(); } + if configs::CONFIG.read().unwrap().args.is_present("output") { + println!(); + println!(); + println!("Analysis finished. Please wait while the results are being saved."); + } println!(); detection.add_aggcondition_msges(&self.rt); if !(*STATISTICS_FLAG || *LOGONSUMMARY_FLAG || *PIVOT_KEYWORD_LIST_FLAG) {