diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index e546e39ce..4398808ee 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -1,6 +1,6 @@ # 変更点 -## v1.4.0 [2022/XX/XX] +## v1.4.0 [2022/06/26] **新機能:** @@ -9,15 +9,16 @@ **改善:** +- ルール内に`details`フィールドがないときに、`rules/config/default_details.txt`に設定されたデフォルトの出力を行えるようにした。 (#359) (@hitenkoku) - Clap Crateパッケージの更新 (#413) (@hitenkoku) - オプションの指定がないときに、`--help`と同じ画面出力を行うように変更した。(#387) (@hitenkoku) -- ルール内に`details`フィールドがないときに、`rules/config/default_details.txt`に設定されたデフォルトの出力を行えるようにした。 (#359) (@hitenkoku) - hayabusa.exeをカレントワーキングディレクトリ以外から動作できるようにした。 (#592) (@hitenkoku) - `output` オプションで指定されファイルのサイズを出力するようにした。 (#595) (@hitenkoku) **バグ修正:** -- XXX +- カラー出力で長い出力があった場合にエラーが出て終了する問題を修正した。 (#603) (@hitenkoku) +- `Excluded rules`の合計で`rules/tools/sigmac/testfiles`配下のテストルールも入っていたので、無視するようにした。 (#602) (@hitenkoku) ## v1.3.2 [2022/06/13] diff --git a/CHANGELOG.md b/CHANGELOG.md index 946125385..2e2237090 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changes -## v1.4.0 [2022/XX/XX] +## v1.4.0 [2022/06/26] **New Features:** @@ -9,16 +9,16 @@ **Enhancements:** +- Added default details output based on `rules/config/default_details.txt` when no `details` field in a rule is specified. (i.e. Sigma rules) (#359) (@hitenkoku) - Updated clap crate package to version 3. (#413) (@hitnekoku) - Updated the default usage and help menu. (#387) (@hitenkoku) -- Added default details output based on `rules/config/default_details.txt` when no `details` field in a rule is specified. (i.e. Sigma rules) (#359) (@hitenkoku) - Hayabusa can be run from any directory, not just from the current directory. (#592) (@hitenkoku) - Added saved file size output when `output` is specified. (#595) (@hitenkoku) -- Ignored loading yml file in `rules/tools/sigmac/testfiles`. (#602) (@hitenkoku) **Bug Fixes:** -- XXX +- Fixed output error and program termination when long output is displayed with color. (#603) (@hitenkoku) +- Ignore loading yml files in `rules/tools/sigmac/testfiles` to fix `Excluded rules` count. (#602) (@hitenkoku) ## v1.3.2 [2022/06/13] diff --git a/rules b/rules index 8c14d12be..2e7e8c8dd 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit 8c14d12be3f2d08721eee6db7238058fdaca3ce6 +Subproject commit 2e7e8c8dd4caf18dc9dc16dfff4b7935d57f2ccc diff --git a/src/afterfact.rs b/src/afterfact.rs index 7bcd148b3..7e1047b19 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -288,18 +288,20 @@ fn emit_csv( //ヘッダーのみを出力 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)), + write_color_buffer( + &disp_wtr, + get_writable_color(None), + &_get_serialized_disp_output(None), + true, ) .ok(); - write!( - disp_wtr_buf, - "{}", - _get_serialized_disp_output(Some(dispformat)) + plus_header = false; + } + write_color_buffer( + &disp_wtr, + get_writable_color(_get_output_color(&color_map, &detect_info.level)), + &_get_serialized_disp_output(Some(dispformat)), + false, ) .ok(); } else { @@ -359,7 +361,6 @@ fn emit_csv( } } if displayflag { - disp_wtr.print(&disp_wtr_buf)?; println!(); } else { wtr.flush()?; @@ -389,6 +390,7 @@ fn emit_csv( &disp_wtr, get_writable_color(Some(Color::Green)), "Results Summary:", + true, ) .ok(); @@ -412,6 +414,7 @@ fn emit_csv( &disp_wtr, get_writable_color(None), &format!("Total events: {}", all_record_cnt), + true, ) .ok(); write_color_buffer( @@ -421,6 +424,7 @@ fn emit_csv( "Data reduction: {} events ({:.2}%)", reducted_record_cnt, reducted_percent ), + true, ) .ok(); println!(); @@ -477,7 +481,7 @@ fn _get_serialized_disp_output(dispformat: Option) -> String { if configs::CONFIG.read().unwrap().args.full_data { titles.push("RecordInformation"); } - return format!("{}\n", titles.join("|")); + return titles.join("|"); } let mut disp_serializer = csv::WriterBuilder::new() .double_quote(false) @@ -527,8 +531,9 @@ fn _print_unique_results( "{} {}: {}", head_word, tail_word, - counts_by_level.iter().sum::() + counts_by_level.iter().sum::(), ), + true, ) .ok(); @@ -544,6 +549,7 @@ fn _print_unique_results( &BufferWriter::stdout(ColorChoice::Always), _get_output_color(color_map, level_name), &output_raw_str, + true, ) .ok(); } @@ -827,7 +833,7 @@ mod tests { let test_timestamp = Utc .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") .unwrap(); - let expect_header = "Timestamp|Computer|Channel|EventID|Level|RecordID|RuleTitle|Details\n"; + let expect_header = "Timestamp|Computer|Channel|EventID|Level|RecordID|RuleTitle|Details"; let expect_tz = test_timestamp.with_timezone(&Local); let expect_no_header = expect_tz @@ -851,7 +857,7 @@ mod tests { + "|" + test_recinfo + "\n"; - assert_eq!(_get_serialized_disp_output(None,), expect_header); + assert_eq!(_get_serialized_disp_output(None), expect_header); assert_eq!( _get_serialized_disp_output(Some(DisplayFormat { timestamp: &format_time(&test_timestamp, false), diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 597fce32c..a507c2dc0 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -394,6 +394,7 @@ impl Detection { &BufferWriter::stdout(ColorChoice::Always), Some(Color::Red), &format!("Rule parsing errors: {}", err_rc), + true, ) .ok(); } @@ -421,6 +422,7 @@ impl Detection { rate, deprecated_flag ), + true, ) .ok(); } @@ -434,6 +436,7 @@ impl Detection { &BufferWriter::stdout(ColorChoice::Always), None, &format!("{} rules: {}", key, value), + true, ) .ok(); }); diff --git a/src/detections/print.rs b/src/detections/print.rs index fe9d49bf1..b92ecdbb2 100644 --- a/src/detections/print.rs +++ b/src/detections/print.rs @@ -334,6 +334,7 @@ impl AlertMessage { &BufferWriter::stderr(ColorChoice::Always), None, &format!("[ERROR] {}", contents), + true, ) } @@ -343,6 +344,7 @@ impl AlertMessage { &BufferWriter::stderr(ColorChoice::Always), None, &format!("[WARN] {}", contents), + true, ) } } diff --git a/src/detections/utils.rs b/src/detections/utils.rs index 85f45c369..49236e4ae 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -256,10 +256,15 @@ pub fn write_color_buffer( wtr: &BufferWriter, color: Option, output_str: &str, + newline_flag: bool, ) -> io::Result<()> { let mut buf = wtr.buffer(); buf.set_color(ColorSpec::new().set_fg(color)).ok(); - writeln!(buf, "{}", output_str).ok(); + if newline_flag { + writeln!(buf, "{}", output_str).ok(); + } else { + write!(buf, "{}", output_str).ok(); + } wtr.print(&buf) } diff --git a/src/main.rs b/src/main.rs index 4c7c684eb..7cb27c644 100644 --- a/src/main.rs +++ b/src/main.rs @@ -126,6 +126,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, "Rules updated successfully.", + true, ) .ok(); } @@ -195,6 +196,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, "Generating Event ID Statistics", + true, ) .ok(); println!(); @@ -204,6 +206,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, "Generating Logons Summary", + true, ) .ok(); println!(); @@ -287,6 +290,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, &configs::CONFIG.read().unwrap().headless_help, + true, ) .ok(); return; @@ -299,6 +303,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, &format!("Elapsed Time: {}", &analysis_duration.hhmmssxxx()), + true, ) .ok(); println!(); @@ -351,17 +356,30 @@ impl App { ) .ok(); }); - write_color_buffer(&BufferWriter::stdout(ColorChoice::Always), None, &output).ok(); + write_color_buffer( + &BufferWriter::stdout(ColorChoice::Always), + None, + &output, + true, + ) + .ok(); } else { //標準出力の場合 let output = "The following pivot keywords were found:".to_string(); - write_color_buffer(&BufferWriter::stdout(ColorChoice::Always), None, &output).ok(); + write_color_buffer( + &BufferWriter::stdout(ColorChoice::Always), + None, + &output, + true, + ) + .ok(); pivot_key_unions.iter().for_each(|(key, pivot_keyword)| { write_color_buffer( &BufferWriter::stdout(ColorChoice::Always), None, &create_output(String::default(), key, pivot_keyword), + true, ) .ok(); }); @@ -447,8 +465,13 @@ impl App { fn print_contributors(&self) { match fs::read_to_string(CURRENT_EXE_PATH.join("contributors.txt")) { Ok(contents) => { - write_color_buffer(&BufferWriter::stdout(ColorChoice::Always), None, &contents) - .ok(); + write_color_buffer( + &BufferWriter::stdout(ColorChoice::Always), + None, + &contents, + true, + ) + .ok(); } Err(err) => { AlertMessage::alert(&format!("{}", err)).ok(); @@ -467,6 +490,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, &format!("Analyzing event files: {:?}", evtx_files.len()), + true, ) .ok(); @@ -693,6 +717,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), output_color, &content, + true, ) .ok(); } @@ -710,7 +735,13 @@ impl App { Some(path) => { let egg_path = CURRENT_EXE_PATH.join(path); let content = fs::read_to_string(egg_path).unwrap_or_default(); - write_color_buffer(&BufferWriter::stdout(ColorChoice::Always), None, &content).ok(); + write_color_buffer( + &BufferWriter::stdout(ColorChoice::Always), + None, + &content, + true, + ) + .ok(); } } } @@ -728,6 +759,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, "Attempting to git clone the hayabusa-rules repository into the rules folder.", + true, ) .ok(); // execution git clone of hayabusa-rules repository when failed open hayabusa repository. @@ -911,6 +943,7 @@ impl App { "[Updated] {} (Modified: {} | Path: {})", tmp[0], tmp[1], tmp[2] ), + true, ) .ok(); } @@ -925,6 +958,7 @@ impl App { &BufferWriter::stdout(ColorChoice::Always), None, "You currently have the latest rules.", + true, ) .ok(); Ok("You currently have the latest rules.".to_string()) diff --git a/src/options/level_tuning.rs b/src/options/level_tuning.rs index c7a7bf80a..797a0b3b1 100644 --- a/src/options/level_tuning.rs +++ b/src/options/level_tuning.rs @@ -62,6 +62,7 @@ impl LevelTuning { &BufferWriter::stdout(ColorChoice::Always), None, &format!("path: {}", path), + true, ) .ok(); let mut content = match fs::read_to_string(&path) { @@ -101,6 +102,7 @@ impl LevelTuning { rule["level"].as_str().unwrap(), new_level ), + true, ) .ok(); }