Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: output field information in green and messages in orange #1498

Merged
merged 22 commits into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9bfe55b
feat: output field information in green and messages in orange
fukusuket Nov 15, 2024
8100cd8
test: add -C option
fukusuket Nov 15, 2024
bdd77b6
fix: --no-color case
fukusuket Nov 15, 2024
c66945d
fix: --no-color case
fukusuket Nov 15, 2024
5381b7b
fix: --no-color case
fukusuket Nov 15, 2024
33e521d
update changelog
YamatoSecurity Nov 15, 2024
2b266e8
feat: output field information in green and messages in orange(pivot-…
fukusuket Nov 15, 2024
e298d0a
feat: output field information in green and messages in orange(comput…
fukusuket Nov 15, 2024
bf1d2df
feat: output field information in green and messages in orange(logon-…
fukusuket Nov 15, 2024
6d75d16
feat: output field information in green and messages in orange(search)
fukusuket Nov 15, 2024
8a22b07
feat: output field information in green and messages in orange(list-p…
fukusuket Nov 15, 2024
a853d79
make scanning finished orange
YamatoSecurity Nov 15, 2024
7703228
cargo fmt
YamatoSecurity Nov 15, 2024
b4a98f7
feat: output field information in green and messages in orange(eid-me…
fukusuket Nov 15, 2024
964beb8
feat: add no-color short option(-K)
fukusuket Nov 15, 2024
ba1da35
feat: add no-color short option(-k)
fukusuket Nov 15, 2024
81dfe1c
feat: output field information in green and messages in orange(progre…
fukusuket Nov 15, 2024
dd29c10
fix: add space
fukusuket Nov 15, 2024
2f7ef48
chg: do not display start time when list-contributors
fukusuket Nov 15, 2024
f2f6945
chg: no-color short option
fukusuket Nov 15, 2024
8d3e8bf
contributor typo
YamatoSecurity Nov 15, 2024
b4c56cd
chg: add space
fukusuket Nov 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
run: cd main && cargo run --release -- computer-metrics -d ../hayabusa-sample-evtx -q -o out.csv -C

- name: csv-timeline
run: cd main && cargo run --release -- csv-timeline -d ../hayabusa-sample-evtx -o out.csv -q -w -D -n -u
run: cd main && cargo run --release -- csv-timeline -d ../hayabusa-sample-evtx -o out.csv -q -w -D -n -u -C

- name: csv-timeline(-p super-verbose)
run: cd main && cargo run --release -- csv-timeline -d ../hayabusa-sample-evtx -o out-s.csv -p super-verbose -q -w -D -n -u
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG-Japanese.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@

- `gt`、`gte`、`lt`、`lte`のフィールドモディファイアに対応した。(#1433) (@fukusuket)
- 新しい`log-metrics`コマンドで`.evtx`ファイルの情報を取得できるようになった。(コンピュータ名、イベント数、最初のタイムスタンプ、最後のタイムスタンプ、チャネル、プロバイダ) (#1474) (@fukusuket)
- 新しい`-b, --disable-abbreviations`コマンドは、`Channel`と`Provider`の略称を無効にする。元の値を確認したい時に便利。 (#1485) (@fukusuket)
- 以下のコマンドに`Channel`と`Provider`の略称を無効にする`-b, --disable-abbreviations`オプションを追加した。元の値を確認したい時に便利。 (#1485) (@fukusuket)
* csv-timeline
* json-timeline
* eid-metrics
* log-metrics
* search

**改善:**

Expand All @@ -15,6 +20,7 @@
- `logon-summary`コマンドがRDPイベントからのログオン情報を表示するようになった。注意: ファイルに保存する場合、Hayabusaはより詳細な情報を出力する。(#1468) (@fukusuket)
- 見やすくなるように色を更新した。 (#1480) (@yamatosecurity)
- 実行開始と終了のメッセージを出力するようにした。 (#1492) (@fukusuket)
- 出力に新しい配色を追加した。 (#1491) (@fukusuket)

**バグ修正:**

Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@

- Support for the `gt`, `gte`, `lt`, `lte` field modifiers. (#1433) (@fukusuket)
- New `log-metrics` command to get information about `.evtx` files. (computer names, event count, first timestamp, last timestamp, channels, providers) (#1474) (@fukusuket)
- New `-b, --disable-abbreviations` command to disable `Channel` and `Provider` abbreviations for when you want to check the original values. (#1485) (@fukusuket)
- New `-b, --disable-abbreviations` options for the following commands to disable `Channel` and `Provider` abbreviations for when you want to check the original values. (#1485) (@fukusuket)
* csv-timeline
* json-timeline
* eid-metrics
* log-metrics
* search

**Enhancements:**

Expand All @@ -15,6 +20,7 @@
- `logon-summary` command now displays logon information from RDP events. Note: Hayabusa will output more detailed information when saving to a file. (#1468) (@fukusuket)
- The colors were updated to make it easier to read. (#1480) (@yamatosecurity)
- Added start and finish messages of the day. (#1492) (@fukusuket)
- New color scheme added to output. (#1491) (@fukusuket)

**Bug Fixes:**

Expand Down
2 changes: 1 addition & 1 deletion contributors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Garigariganzy (@garigariganzy31): Developer (Event ID metrics implementation, et
ItiB (@itiB_S144): Core developer (sigmac hayabusa backend, search command, etc...)
James Takai / hachiyone(@hach1yon): Second lead developer (Tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, sigma count implementation etc…)
Kazuminn (@k47_um1n): Core Developer (Many features.)
Matthew Seyer: adding the ability to carve out records
Matthew Seyer: Adding the ability to carve out records
Tsubokku (@ytsuboi0322): Translations
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…
Expand Down
2 changes: 1 addition & 1 deletion src/detections/configs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1630,7 +1630,7 @@ pub struct OutputOption {
#[derive(Copy, Args, Clone, Debug)]
pub struct CommonOptions {
/// Disable color output
#[arg(help_heading = Some("Display Settings"), long = "no-color", global = true, display_order = 400)]
#[arg(help_heading = Some("Display Settings"), short = 'K', long = "no-color", global = true, display_order = 400)]
pub no_color: bool,

/// Quiet mode: do not display the launch banner
Expand Down
142 changes: 112 additions & 30 deletions src/detections/detection.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
extern crate csv;

use std::collections::HashSet;
use std::default::Default;
use std::fmt::Write;
use std::path::Path;
use std::sync::Arc;

use chrono::{TimeZone, Utc};
use compact_str::CompactString;
use hashbrown::HashMap;
use itertools::Itertools;
use nested::Nested;
use num_format::{Locale, ToFormattedString};
use serde_json::Value;
use std::collections::HashSet;
use std::default::Default;
use std::fmt::Write;
use std::path::Path;
use std::sync::Arc;
use termcolor::{BufferWriter, Color, ColorChoice};
use tokio::{runtime::Runtime, spawn, task::JoinHandle};
use yaml_rust2::Yaml;
Expand All @@ -24,7 +23,9 @@ use crate::detections::message::{AlertMessage, DetectInfo, ERROR_LOG_STACK, TAGS
use crate::detections::rule::correlation_parser::parse_correlation_rules;
use crate::detections::rule::count::AggRecordTimeInfo;
use crate::detections::rule::{self, AggResult, RuleNode};
use crate::detections::utils::{create_recordinfos, format_time, write_color_buffer};
use crate::detections::utils::{
create_recordinfos, format_time, get_writable_color, write_color_buffer,
};
use crate::detections::utils::{get_serde_number_to_string, make_ascii_titlecase};
use crate::filter;
use crate::options::htmlreport;
Expand Down Expand Up @@ -1142,14 +1143,27 @@ impl Detection {
""
};
//タイトルに利用するものはascii文字であることを前提として1文字目を大文字にするように変更する
let output_str = format!(
"{} rules: {}{}",
make_ascii_titlecase(key),
value.to_formatted_string(&Locale::en),
disable_flag
);
println!("{output_str}");
let key = format!("{} rules: ", make_ascii_titlecase(key));
let val = format!("{}{}", value.to_formatted_string(&Locale::en), disable_flag);
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(
Some(Color::Rgb(0, 255, 0)),
stored_static.common_options.no_color,
),
key.as_str(),
false,
)
.ok();
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
val.as_str(),
true,
)
.ok();
if stored_static.html_report_flag {
let output_str = format!("{}{}", key, val);
html_report_stock.push(format!("- {output_str}"));
}
}
Expand Down Expand Up @@ -1188,22 +1202,32 @@ impl Detection {
} else {
""
};
let output_str = format!(
"{} rules: {} ({:.2}%){}",
make_ascii_titlecase(key),
let key = format!("{} rules: ", make_ascii_titlecase(key));
let val = format!(
"{} ({:.2}%){}",
value.to_formatted_string(&Locale::en),
rate,
disabled_flag
);
//タイトルに利用するものはascii文字であることを前提として1文字目を大文字にするように変更する
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(
Some(Color::Rgb(0, 255, 0)),
stored_static.common_options.no_color,
),
key.as_str(),
false,
)
.ok();
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
&output_str,
val.as_str(),
true,
)
.ok();
if stored_static.html_report_flag {
let output_str = format!("{}{}", key, val);
html_report_stock.push(format!("- {output_str}"));
}
}
Expand All @@ -1213,24 +1237,54 @@ impl Detection {
let cor_total: u128 = cor_rc.values().sum();
let cor_ref_total: u128 = cor_ref_rc.values().sum();
if cor_total != 0 {
let col = format!(
"Correlation rules: {} ({:.2}%)",
let key = "Correlation rules: ";
let val = format!(
"{} ({:.2}%)",
cor_total.to_formatted_string(&Locale::en),
(cor_total as f64) / (total_loaded_rule_cnt as f64) * 100.0
);
write_color_buffer(&BufferWriter::stdout(ColorChoice::Always), None, &col, true).ok();
let col_ref = format!(
"Correlation referenced rules: {} ({:.2}%)",
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(
Some(Color::Rgb(0, 255, 0)),
stored_static.common_options.no_color,
),
key,
false,
)
.ok();
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(None, stored_static.common_options.no_color),
val.as_str(),
true,
)
.ok();
let col = format!("{}{}", key, val);
let key = "Correlation referenced rules: ";
let val = format!(
"{} ({:.2}%)",
cor_ref_total.to_formatted_string(&Locale::en),
(cor_ref_total as f64) / (total_loaded_rule_cnt as f64) * 100.0
);
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(
Some(Color::Rgb(0, 255, 0)),
stored_static.common_options.no_color,
),
key,
false,
)
.ok();
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
&col_ref,
val.as_str(),
true,
)
.ok();
let col_ref = format!("{}{}", key, val);
if stored_static.html_report_flag {
html_report_stock.push(format!("- {col}"));
html_report_stock.push(format!("- {col_ref}"));
Expand All @@ -1241,24 +1295,52 @@ impl Detection {
let mut sorted_rc: Vec<(&CompactString, &u128)> = rc.iter().collect();
sorted_rc.sort_by(|a, b| a.0.cmp(b.0));
sorted_rc.into_iter().for_each(|(key, value)| {
let output_str = format!("{key} rules: {}", value.to_formatted_string(&Locale::en));
let key = format!("{key} rules: ");
let val = value.to_formatted_string(&Locale::en);
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(
Some(Color::Rgb(0, 255, 0)),
stored_static.common_options.no_color,
),
key.as_str(),
false,
)
.ok();
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
&output_str,
val.as_str(),
true,
)
.ok();
if stored_static.html_report_flag {
html_report_stock.push(format!("- {output_str}"));
html_report_stock.push(format!("- {key}{val}"));
}
});

let key = "Total detection rules: ";
let val = total_loaded_rule_cnt.to_formatted_string(&Locale::en);
let tmp_total_detect_output = format!(
"Total detection rules: {}",
total_loaded_rule_cnt.to_formatted_string(&Locale::en)
);
println!("{tmp_total_detect_output}");
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(
Some(Color::Rgb(0, 255, 0)),
stored_static.common_options.no_color,
),
key,
false,
)
.ok();
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
val.as_str(),
true,
)
.ok();
println!();
if stored_static.html_report_flag {
html_report_stock.push(format!("- {tmp_total_detect_output}"));
Expand Down
35 changes: 20 additions & 15 deletions src/detections/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,17 +704,9 @@ pub fn output_and_data_stack_for_html(
section_name: &str,
html_report_flag: &bool,
) {
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
output_str,
true,
)
.ok();

if *html_report_flag {
let mut output_data = Nested::<String>::new();
output_data.extend(vec![format!("- {output_str}")]);
output_data.extend(vec![format!("- Elapsed time: {output_str}")]);
htmlreport::add_md_data(section_name, output_data);
}
}
Expand All @@ -723,7 +715,7 @@ pub fn contains_str(input: &str, check: &str) -> bool {
memmem::find(input.as_bytes(), check.as_bytes()).is_some()
}

pub fn output_profile_name(output_option: &Option<OutputOption>, stdout: bool) {
pub fn output_profile_name(output_option: &Option<OutputOption>, stdout: bool, no_color: bool) {
// output profile name
if let Some(profile_opt) = output_option {
// default profile name check
Expand All @@ -740,7 +732,7 @@ pub fn output_profile_name(output_option: &Option<OutputOption>, stdout: bool) {
name.trim().to_string()
} else {
let default_profile_name = DefaultProfileName::get("default_profile_name.txt").unwrap();
std::str::from_utf8(default_profile_name.data.as_ref())
str::from_utf8(default_profile_name.data.as_ref())
.unwrap_or("n/a")
.to_string()
};
Expand All @@ -750,10 +742,23 @@ pub fn output_profile_name(output_option: &Option<OutputOption>, stdout: bool) {
.profile
.as_ref()
.unwrap_or(&default_profile_name);
let output_saved_str = format!("Output profile: {profile_name}");
if stdout {
println!("{output_saved_str}");
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
get_writable_color(Some(Color::Rgb(0, 255, 0)), no_color),
"Output profile: ",
false,
)
.ok();
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
profile_name,
true,
)
.ok();
}
let output_saved_str = format!("Output profile: {profile_name}");
// profileの表示位置とHTMLの出力順が異なるため引数で管理をした
if !stdout && profile_opt.html_report.is_some() {
htmlreport::add_md_data(
Expand Down Expand Up @@ -1175,8 +1180,8 @@ mod tests {
})),
debug: false,
}));
output_profile_name(&stored_static.output_option, true);
output_profile_name(&stored_static.output_option, false);
output_profile_name(&stored_static.output_option, true, false);
output_profile_name(&stored_static.output_option, false, false);
let expect: HashMap<&str, Nested<String>> = HashMap::from_iter(vec![
("Results Summary {#results_summary}", Nested::new()),
(
Expand Down
Loading
Loading