Skip to content

Commit

Permalink
Merge pull request #720 from Yamato-Security/707-analyze-metrics-of-e…
Browse files Browse the repository at this point in the history
…vent-ids-when-scanning-directory-together

Unified table of  analyze metrics and logon summary of event ids when scanning directory together
  • Loading branch information
YamatoSecurity authored Sep 28, 2022
2 parents de0dc8e + bac2d57 commit c600aa7
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 188 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG-Japanese.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
- EventID解析のオプションをmetricsオプションに変更した。(旧: `-s, --statistics` -> 新: `-M, --metrics`) (#706) (@hitenkoku)
- ルール更新オプション(`-u`)を利用したときにHayabusaの新バージョンがないかを確認し、表示するようにした。 (#710) (@hitenkoku)
- HTMLレポート内にロゴを追加した。 (#714) (@hitenkoku)
- メトリクスオプション(`-M --metrics`)もしくはログオン情報(`-L --logon-summary`)と`-d`オプションを利用した場合に1つのテーブルで表示されるように修正した。 (#707) (@hitenkoku)
- メトリクスオプションの結果出力にチャンネル列を追加した。 (#707) (@hitenkoku)
- メトリクスオプション(`-M --metrics`)もしくはログオン情報(`-L --logon-summary`)と`-d`オプションを利用した場合に「First Timestamp」と「Last Timestamp」の出力を行わないように修正した。 (#707) (@hitenkoku)
- メトリクスオプションとログオン情報オプションに対してcsv出力機能(`-o --output`)を追加した。 (#707) (@hitenkoku)
- メトリクスオプションの出力を検出回数と全体の割合が1つのセルで表示されていた箇所を2つの列に分けた。 (#707) (@hitenkoku)
- メトリクスオプションとログオン情報の画面出力に利用していたprettytable-rsクレートをcomfy_tableクレートに修正した. (#707) (@hitenkoku)

## v1.6.0 [2022/09/16]

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
(Note: `statistics_event_info.txt` was changed to `event_id_info.txt`.)
- Display new version of Hayabusa link when updating if there is a newer version. (#710) (@hitenkoku)
- Added logo in HTML summary output. (#714) (@hitenkoku)
- Unified output one table of -M or -L option with -d option. (#707) (@hitenkoku)
- Added Channel column to metrics output. (#707) (@hitenkoku)
- Removed First Timestamp and Last Timestamp of -M and -L option with -d option. (#707) (@hitenkoku)
- Added csv output option(`-o --output`) when -M and -L option is used. (#707) (@hitenkoku)
- Separated Count and Percent columns in metric output. (#707) (@hitenkoku)
- Changed output table format of metric option and logon information crate from prettytable-rs to comfy_table. (#707) (@hitenkoku)

## v1.6.0 [2022/09/16]

Expand Down
66 changes: 1 addition & 65 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ hashbrown = "0.12.*"
hex = "0.4.*"
git2 = "0.*"
termcolor = "*"
prettytable-rs = "0.*"
krapslog = "*"
terminal_size = "*"
bytesize = "1.*"
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,4 @@ pub mod options;
pub mod timeline;
pub mod yaml;
#[macro_use]
extern crate prettytable;
#[macro_use]
extern crate horrorshow;
21 changes: 13 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,15 +656,23 @@ impl App {
self.rule_keys = self.get_all_keys(&rule_files);
let mut detection = detection::Detection::new(rule_files);
let mut total_records: usize = 0;
let mut tl = Timeline::new();
for evtx_file in evtx_files {
if configs::CONFIG.read().unwrap().args.verbose {
println!("Checking target evtx FilePath: {:?}", &evtx_file);
}
let cnt_tmp: usize;
(detection, cnt_tmp) = self.analysis_file(evtx_file, detection, time_filter);
(detection, cnt_tmp, tl) =
self.analysis_file(evtx_file, detection, time_filter, tl.clone());
total_records += cnt_tmp;
pb.inc();
}
if *METRICS_FLAG {
tl.tm_stats_dsp_msg();
}
if *LOGONSUMMARY_FLAG {
tl.tm_logon_stats_dsp_msg();
}
if configs::CONFIG.read().unwrap().args.output.is_some() {
println!();
println!();
Expand All @@ -683,15 +691,15 @@ impl App {
evtx_filepath: PathBuf,
mut detection: detection::Detection,
time_filter: &TargetEventTime,
) -> (detection::Detection, usize) {
mut tl: Timeline,
) -> (detection::Detection, usize, Timeline) {
let path = evtx_filepath.display();
let parser = self.evtx_to_jsons(evtx_filepath.clone());
let mut record_cnt = 0;
if parser.is_none() {
return (detection, record_cnt);
return (detection, record_cnt, tl);
}

let mut tl = Timeline::new();
let mut parser = parser.unwrap();
let mut records = parser.records_json_value();

Expand Down Expand Up @@ -760,10 +768,7 @@ impl App {
}
}

tl.tm_stats_dsp_msg();
tl.tm_logon_stats_dsp_msg();

(detection, record_cnt)
(detection, record_cnt, tl)
}

async fn create_rec_infos(
Expand Down
110 changes: 51 additions & 59 deletions src/timeline/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use crate::detections::message::{LOGONSUMMARY_FLAG, METRICS_FLAG};
use crate::detections::{detection::EvtxRecordInfo, utils};
use hashbrown::HashMap;

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct EventMetrics {
pub total: usize,
pub filepath: String,
pub start_time: String,
pub end_time: String,
pub stats_list: HashMap<String, usize>,
pub stats_list: HashMap<(String, String), usize>,
pub stats_login_list: HashMap<String, [usize; 2]>,
}
/**
Expand All @@ -20,7 +20,7 @@ impl EventMetrics {
filepath: String,
start_time: String,
end_time: String,
stats_list: HashMap<String, usize>,
stats_list: HashMap<(String, String), usize>,
stats_login_list: HashMap<String, [usize; 2]>,
) -> EventMetrics {
EventMetrics {
Expand Down Expand Up @@ -66,79 +66,71 @@ impl EventMetrics {
self.filepath = records[0].evtx_filepath.as_str().to_owned();
// sortしなくてもイベントログのTimeframeを取得できるように修正しました。
// sortしないことにより計算量が改善されています。
// もうちょっと感じに書けるといえば書けます。
for record in records.iter() {
let evttime = utils::get_event_value(
if let Some(evttime) = utils::get_event_value(
"Event.System.TimeCreated_attributes.SystemTime",
&record.record,
)
.map(|evt_value| evt_value.to_string());
if evttime.is_none() {
continue;
}

let evttime = evttime.unwrap();
if self.start_time.is_empty() || evttime < self.start_time {
self.start_time = evttime.to_string();
}
if self.end_time.is_empty() || evttime > self.end_time {
self.end_time = evttime;
}
.map(|evt_value| evt_value.to_string())
{
if self.start_time.is_empty() || evttime < self.start_time {
self.start_time = evttime.to_string();
}
if self.end_time.is_empty() || evttime > self.end_time {
self.end_time = evttime;
}
};
}
self.total += records.len();
}

// EventIDで集計
/// EventID`で集計
fn stats_eventid(&mut self, records: &[EvtxRecordInfo]) {
// let mut evtstat_map = HashMap::new();
for record in records.iter() {
let evtid = utils::get_event_value("EventID", &record.record);
if evtid.is_none() {
continue;
}

let idnum = evtid.unwrap();
let count: &mut usize = self.stats_list.entry(idnum.to_string()).or_insert(0);
*count += 1;
let channel = if let Some(ch) = utils::get_event_value("Channel", &record.record) {
ch.to_string()
} else {
"-".to_string()
};
if let Some(idnum) = utils::get_event_value("EventID", &record.record) {
let count: &mut usize = self
.stats_list
.entry((idnum.to_string(), channel))
.or_insert(0);
*count += 1;
};
}
// return evtstat_map;
}
// Login event
fn stats_login_eventid(&mut self, records: &[EvtxRecordInfo]) {
for record in records.iter() {
let evtid = utils::get_event_value("EventID", &record.record);
if evtid.is_none() {
continue;
}
let idnum: i64 = if evtid.unwrap().is_number() {
evtid.unwrap().as_i64().unwrap()
} else {
evtid
.unwrap()
.as_str()
.unwrap()
.parse::<i64>()
.unwrap_or_default()
};
if !(idnum == 4624 || idnum == 4625) {
continue;
}
if let Some(evtid) = utils::get_event_value("EventID", &record.record) {
let idnum: i64 = if evtid.is_number() {
evtid.as_i64().unwrap()
} else {
evtid.as_str().unwrap().parse::<i64>().unwrap_or_default()
};
if !(idnum == 4624 || idnum == 4625) {
continue;
}

let username = utils::get_event_value("TargetUserName", &record.record);
let countlist: [usize; 2] = [0, 0];
if idnum == 4624 {
let count: &mut [usize; 2] = self
.stats_login_list
.entry(username.unwrap().to_string())
.or_insert(countlist);
count[0] += 1;
} else if idnum == 4625 {
let count: &mut [usize; 2] = self
.stats_login_list
.entry(username.unwrap().to_string())
.or_insert(countlist);
count[1] += 1;
}
let username = utils::get_event_value("TargetUserName", &record.record);
let countlist: [usize; 2] = [0, 0];
if idnum == 4624 {
let count: &mut [usize; 2] = self
.stats_login_list
.entry(username.unwrap().to_string())
.or_insert(countlist);
count[0] += 1;
} else if idnum == 4625 {
let count: &mut [usize; 2] = self
.stats_login_list
.entry(username.unwrap().to_string())
.or_insert(countlist);
count[1] += 1;
}
};
}
}
}
Loading

0 comments on commit c600aa7

Please sign in to comment.