diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 9cc9c02d..a1c85d64 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -12,6 +12,7 @@ - 結果概要を出力しないようにするために `--no-summary` オプションを追加した。 (#672) (@hitenkoku) - 結果概要の表示を短縮させた。 (#675 #678) (@hitenkoku) - channel_abbreviations.txtによるChannelフィールドのチェックを大文字小文字の区別をなくした。 (#685) (@hitenkoku) +- 出力結果の区切り文字を`|`から`‖`に変更した。 (#687) (@hitenkoku) - 結果概要の検知数と総イベント数の数に色付けを行い見やすくした。 (#690) (@hitenkoku) **バグ修正:** diff --git a/CHANGELOG.md b/CHANGELOG.md index 43550d70..4205496c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Added `--no-summary` option to not display the results summary. (#672) (@hitenkoku) - Made the results summary more compact. (#675 #678) (@hitenkoku) - Made Channel field in channel_abbreviations.txt case-insensitive. (#685) (@hitenkoku) +- Changed pipe separator character in output from `|` to `‖`. (#687) (@hitenkoku) - Added color to Saved alerts and events / Total events analyzed. (#690) (@hitenkoku) **Bug Fixes:** diff --git a/rules b/rules index 5364222c..a9be6f9d 160000 --- a/rules +++ b/rules @@ -1 +1 @@ -Subproject commit 5364222c5459472d8ecbd46c49b482172be9d184 +Subproject commit a9be6f9dcd3b8942bb5c45abb9de1941dd22b1bb diff --git a/src/afterfact.rs b/src/afterfact.rs index 68a2ef55..320b906b 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -469,17 +469,23 @@ fn _get_serialized_disp_output(data: &LinkedHashMap, header: boo let data_length = &data.len(); let mut ret: Vec = vec![]; if header { - for k in data.keys() { - ret.push(k.to_owned()); + for (i, k) in data.keys().enumerate() { + if i == 0 { + ret.push(_format_cellpos(k, ColPos::First)) + } else if i == data_length - 1 { + ret.push(_format_cellpos(k, ColPos::Last)) + } else { + ret.push(_format_cellpos(k, ColPos::Other)) + } } } else { for (i, (_, v)) in data.iter().enumerate() { if i == 0 { - ret.push(_format_cellpos(v, ColPos::First)) + ret.push(_format_cellpos(v, ColPos::First).replace('|', "🦅")) } else if i == data_length - 1 { - ret.push(_format_cellpos(v, ColPos::Last)) + ret.push(_format_cellpos(v, ColPos::Last).replace('|', "🦅")) } else { - ret.push(_format_cellpos(v, ColPos::Other)) + ret.push(_format_cellpos(v, ColPos::Other).replace('|', "🦅")) } } } @@ -491,7 +497,10 @@ fn _get_serialized_disp_output(data: &LinkedHashMap, header: boo .from_writer(vec![]); disp_serializer.write_record(ret).ok(); - String::from_utf8(disp_serializer.into_inner().unwrap_or_default()).unwrap_or_default() + String::from_utf8(disp_serializer.into_inner().unwrap_or_default()) + .unwrap_or_default() + .replace('|', "‖") + .replace('🦅', "|") } /// return str position in output file @@ -918,28 +927,28 @@ 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|RecordInformation\n"; + let expect_header = "Timestamp ‖ Computer ‖ Channel ‖ EventID ‖ Level ‖ RecordID ‖ RuleTitle ‖ Details ‖ RecordInformation\n"; let expect_tz = test_timestamp.with_timezone(&Local); let expect_no_header = expect_tz .clone() .format("%Y-%m-%d %H:%M:%S%.3f %:z") .to_string() - + " | " + + " ‖ " + test_computername - + " | " + + " ‖ " + test_channel - + " | " + + " ‖ " + test_eventid - + " | " + + " ‖ " + test_level - + " | " + + " ‖ " + test_recid - + " | " + + " ‖ " + test_title - + " | " + + " ‖ " + output - + " | " + + " ‖ " + test_recinfo + "\n"; let mut data: LinkedHashMap = LinkedHashMap::new(); diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 75e801de..f1b5af43 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -326,7 +326,7 @@ impl Detection { .filter(|x| TAGS_CONFIG.values().contains(x)) .map(|y| y.to_owned()) .collect(); - profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); + profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" ¦ ")); } "%MitreTags%" => { let techniques: &Vec = &tag_info @@ -342,7 +342,7 @@ impl Detection { make_ascii_titlecase(&mut replaced_tag) }) .collect(); - profile_converter.insert("%MitreTags%".to_string(), techniques.join(" : ")); + profile_converter.insert("%MitreTags%".to_string(), techniques.join(" ¦ ")); } "%OtherTags%" => { let tags: &Vec = &tag_info @@ -355,7 +355,7 @@ impl Detection { }) .map(|y| y.to_owned()) .collect(); - profile_converter.insert("%OtherTags%".to_string(), tags.join(" : ")); + profile_converter.insert("%OtherTags%".to_string(), tags.join(" ¦ ")); } _ => {} @@ -458,7 +458,7 @@ impl Detection { .filter(|x| TAGS_CONFIG.values().contains(x)) .map(|y| y.to_owned()) .collect(); - profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" : ")); + profile_converter.insert("%MitreTactics%".to_string(), tactics.join(" ¦ ")); } "%MitreTags%" => { let techniques: &Vec = &tag_info @@ -474,7 +474,7 @@ impl Detection { make_ascii_titlecase(&mut replaced_tag) }) .collect(); - profile_converter.insert("%MitreTags%".to_string(), techniques.join(" : ")); + profile_converter.insert("%MitreTags%".to_string(), techniques.join(" ¦ ")); } "%OtherTags%" => { let tags: &Vec = &tag_info @@ -487,7 +487,7 @@ impl Detection { }) .map(|y| y.to_owned()) .collect(); - profile_converter.insert("%OtherTags%".to_string(), tags.join(" : ")); + profile_converter.insert("%OtherTags%".to_string(), tags.join(" ¦ ")); } _ => {} } diff --git a/src/detections/utils.rs b/src/detections/utils.rs index f7ee3a14..837da55d 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -297,15 +297,10 @@ fn create_recordinfos(record: &Value) -> String { let summary: Vec = output .iter() - .map(|(key, value)| format!("{}:{}", key, value)) + .map(|(key, value)| format!("{}: {}", key, value)) .collect(); - // 標準出力する時はセルがハイプ区切りになるので、パイプ区切りにしない - if configs::CONFIG.read().unwrap().args.output.is_some() { - summary.join(" | ") - } else { - summary.join(" ") - } + summary.join(" ¦ ") } /** @@ -510,7 +505,7 @@ mod tests { Ok(record) => { let ret = utils::create_recordinfos(&record); // Systemは除外される/属性(_attributesも除外される)/key順に並ぶ - let expected = "AccessMask:%%1369 Process:lsass.exe User:u1".to_string(); + let expected = "AccessMask: %%1369 ¦ Process: lsass.exe ¦ User: u1".to_string(); assert_eq!(ret, expected); } Err(_) => { @@ -544,7 +539,7 @@ mod tests { Ok(record) => { let ret = utils::create_recordinfos(&record); // Systemは除外される/属性(_attributesも除外される)/key順に並ぶ - let expected = "Binary:hogehoge Data: Data:Data1 Data:DataData2 Data:DataDataData3" + let expected = "Binary: hogehoge ¦ Data: ¦ Data: Data1 ¦ Data: DataData2 ¦ Data: DataDataData3" .to_string(); assert_eq!(ret, expected); }