Merge pull request #604 from Yamato-Security/603-bug-non-utf-8-byte-sequences-error-with-color-output
bug non utf 8 byte sequences error with color output
This commit is contained in:
@@ -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]
|
||||
|
||||
|
||||
+4
-4
@@ -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]
|
||||
|
||||
|
||||
+1
-1
Submodule rules updated: 8c14d12be3...2e7e8c8dd4
+21
-15
@@ -288,18 +288,20 @@ fn emit_csv<W: std::io::Write>(
|
||||
|
||||
//ヘッダーのみを出力
|
||||
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<W: std::io::Write>(
|
||||
}
|
||||
}
|
||||
if displayflag {
|
||||
disp_wtr.print(&disp_wtr_buf)?;
|
||||
println!();
|
||||
} else {
|
||||
wtr.flush()?;
|
||||
@@ -389,6 +390,7 @@ fn emit_csv<W: std::io::Write>(
|
||||
&disp_wtr,
|
||||
get_writable_color(Some(Color::Green)),
|
||||
"Results Summary:",
|
||||
true,
|
||||
)
|
||||
.ok();
|
||||
|
||||
@@ -412,6 +414,7 @@ fn emit_csv<W: std::io::Write>(
|
||||
&disp_wtr,
|
||||
get_writable_color(None),
|
||||
&format!("Total events: {}", all_record_cnt),
|
||||
true,
|
||||
)
|
||||
.ok();
|
||||
write_color_buffer(
|
||||
@@ -421,6 +424,7 @@ fn emit_csv<W: std::io::Write>(
|
||||
"Data reduction: {} events ({:.2}%)",
|
||||
reducted_record_cnt, reducted_percent
|
||||
),
|
||||
true,
|
||||
)
|
||||
.ok();
|
||||
println!();
|
||||
@@ -477,7 +481,7 @@ fn _get_serialized_disp_output(dispformat: Option<DisplayFormat>) -> 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::<u128>()
|
||||
counts_by_level.iter().sum::<u128>(),
|
||||
),
|
||||
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),
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,10 +256,15 @@ pub fn write_color_buffer(
|
||||
wtr: &BufferWriter,
|
||||
color: Option<Color>,
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
+39
-5
@@ -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())
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user