diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 62b94e62..88408164 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -17,7 +17,7 @@ **バグ修正:** -- xxx +- `--start-timeline`、`--end-timeline`オプションが動かなかったのを修正した。 (#546) (@hitenkoku) ## v1.2.2 [2022/05/20] diff --git a/CHANGELOG.md b/CHANGELOG.md index 2134532f..4d68dc7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ **Bug Fixes:** -- xxx +- Fixed the `--start-timeline` and `--end-timeline` options as they were not working. (#546) @hitenkoku) + ## v1.2.2 [2022/05/20] diff --git a/README-Japanese.md b/README-Japanese.md index 947c1ec0..6a24768a 100644 --- a/README-Japanese.md +++ b/README-Japanese.md @@ -334,8 +334,8 @@ USAGE: -u --update-rules 'rulesフォルダをhayabusa-rulesのgithubリポジトリの最新版に更新する。' -m --min-level=[LEVEL] '結果出力をするルールの最低レベル。(デフォルト: informational)' -l --live-analysis 'ローカル端末のC:\Windows\System32\winevt\Logsフォルダを解析する。(Windowsのみ。管理者権限が必要。)' - --start-timeline=[STARTTIMELINE] '解析対象とするイベントログの開始時刻。(例: '2018/11/28 12:00:00 +09:00')' - --end-timeline=[ENDTIMELINE] '解析対象とするイベントログの終了時刻。(例: '2018/11/28 12:00:00 +09:00')' + --start-timeline=[STARTTIMELINE] '解析対象とするイベントログの開始時刻。(例: "2018-11-28 12:00:00 +09:00")' + --end-timeline=[ENDTIMELINE] '解析対象とするイベントログの終了時刻。(例: "2021-11-28 12:00:00 +09:00")' --rfc-2822 'RFC 2822形式で日付と時刻を出力する。(例: Mon, 07 Aug 2006 12:34:56 -0600)' --rfc-3339 'RFC 3339形式で日付と時刻を出力する。 (例: 2006-08-07T12:34:56.485214 -06:00)' -U --utc 'UTC形式で日付と時刻を出力する。(デフォルト: 現地時間)' diff --git a/README.md b/README.md index a1724a10..197dd8b1 100644 --- a/README.md +++ b/README.md @@ -332,8 +332,8 @@ USAGE: -u --update-rules 'Update to the latest rules in the hayabusa-rules github repository.' -m --min-level=[LEVEL] 'Minimum level for rules. (Default: informational)' -l --live-analysis 'Analyze the local C:\Windows\System32\winevt\Logs folder (Windows Only. Administrator privileges required.)' - --start-timeline=[STARTTIMELINE] 'Start time of the event logs to load. (Example: '2018/11/28 12:00:00 +09:00')' - --end-timeline=[ENDTIMELINE] 'End time of the event logs to load. (Example: '2018/11/28 12:00:00 +09:00')' + --start-timeline=[STARTTIMELINE] 'Start time of the event logs to load. (Example: "2018-11-28 12:00:00 +09:00")' + --end-timeline=[ENDTIMELINE] 'End time of the event logs to load. (Example: "2021-11-28 12:00:00 +09:00")' --rfc-2822 'Output date and time in RFC 2822 format. (Example: Mon, 07 Aug 2006 12:34:56 -0600)' --rfc-3339 'Output date and time in RFC 3339 format. (Example: 2006-08-07T12:34:56.485214 -06:00)' -U --utc 'Output time in UTC format. (Default: local time)' diff --git a/src/afterfact.rs b/src/afterfact.rs index 977d033b..1dce6f30 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -424,7 +424,8 @@ fn _get_timestamp(time: &DateTime) -> i64 { if configs::CONFIG.read().unwrap().args.is_present("utc") { time.timestamp() } else { - time.with_timezone(&Local).timestamp() + let offset_sec = Local.timestamp(0, 0).offset().local_minus_utc(); + offset_sec as i64 + time.with_timezone(&Local).timestamp() } } diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 6fc74ba0..ab4287c7 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -84,8 +84,8 @@ fn build_app<'a>() -> ArgMatches<'a> { -u --update-rules 'Update to the latest rules in the hayabusa-rules github repository.' -m --min-level=[LEVEL] 'Minimum level for rules. (Default: informational)' -l --live-analysis 'Analyze the local C:\\Windows\\System32\\winevt\\Logs folder (Windows Only. Administrator privileges required.)' - --start-timeline=[STARTTIMELINE] 'Start time of the event logs to load. (Example: '2018/11/28 12:00:00 +09:00')' - --end-timeline=[ENDTIMELINE] 'End time of the event logs to load. (Example: '2018/11/28 12:00:00 +09:00')' + --start-timeline=[STARTTIMELINE] 'Start time of the event logs to load. (Example: \"2018-11-28 12:00:00 +09:00\")' + --end-timeline=[ENDTIMELINE] 'End time of the event logs to load. (Example: \"2021-11-28 12:00:00 +09:00\")' --rfc-2822 'Output date and time in RFC 2822 format. (Example: Mon, 07 Aug 2006 12:34:56 -0600)' --rfc-3339 'Output date and time in RFC 3339 format. (Example: 2006-08-07T12:34:56.485214 -06:00)' -U --utc 'Output time in UTC format. (Default: local time)' @@ -173,6 +173,7 @@ fn load_target_ids(path: &str) -> TargetEventIds { #[derive(Debug, Clone)] pub struct TargetEventTime { + parse_success_flag: bool, start_time: Option>, end_time: Option>, } @@ -185,18 +186,20 @@ impl Default for TargetEventTime { impl TargetEventTime { pub fn new() -> Self { + let mut parse_success_flag = true; let start_time = if let Some(s_time) = CONFIG.read().unwrap().args.value_of("start-timeline") { match DateTime::parse_from_str(s_time, "%Y-%m-%d %H:%M:%S %z") // 2014-11-28 21:00:09 +09:00 .or_else(|_| DateTime::parse_from_str(s_time, "%Y/%m/%d %H:%M:%S %z")) // 2014/11/28 21:00:09 +09:00 { Ok(dt) => Some(dt.with_timezone(&Utc)), - Err(err) => { + Err(_) => { AlertMessage::alert( &mut BufWriter::new(std::io::stderr().lock()), - &format!("start-timeline field: {}", err), + "start-timeline field: the timestamp format is not correct.", ) .ok(); + parse_success_flag = false; None } } @@ -208,31 +211,38 @@ impl TargetEventTime { .or_else(|_| DateTime::parse_from_str(e_time, "%Y/%m/%d %H:%M:%S %z")) // 2014/11/28 21:00:09 +09:00 { Ok(dt) => Some(dt.with_timezone(&Utc)), - Err(err) => { + Err(_) => { AlertMessage::alert( &mut BufWriter::new(std::io::stderr().lock()), - &format!("end-timeline field: {}", err), + "end-timeline field: the timestamp format is not correct.", ) .ok(); + parse_success_flag = false; None } } } else { None }; - Self::set(start_time, end_time) + Self::set(parse_success_flag, start_time, end_time) } pub fn set( + input_parse_success_flag: bool, input_start_time: Option>, input_end_time: Option>, ) -> Self { Self { + parse_success_flag: input_parse_success_flag, start_time: input_start_time, end_time: input_end_time, } } + pub fn is_parse_success(&self) -> bool { + self.parse_success_flag + } + pub fn is_target(&self, eventtime: &Option>) -> bool { if eventtime.is_none() { return true; @@ -450,7 +460,7 @@ mod tests { fn target_event_time_filter() { let start_time = Some("2018-02-20T12:00:09Z".parse::>().unwrap()); let end_time = Some("2020-03-30T12:00:09Z".parse::>().unwrap()); - let time_filter = configs::TargetEventTime::set(start_time, end_time); + let time_filter = configs::TargetEventTime::set(true, start_time, end_time); let out_of_range1 = Some("1999-01-01T12:00:09Z".parse::>().unwrap()); let within_range = Some("2019-02-27T01:05:01Z".parse::>().unwrap()); @@ -465,7 +475,7 @@ mod tests { fn target_event_time_filter_containes_on_time() { let start_time = Some("2018-02-20T12:00:09Z".parse::>().unwrap()); let end_time = Some("2020-03-30T12:00:09Z".parse::>().unwrap()); - let time_filter = configs::TargetEventTime::set(start_time, end_time); + let time_filter = configs::TargetEventTime::set(true, start_time, end_time); assert!(time_filter.is_target(&start_time)); assert!(time_filter.is_target(&end_time)); diff --git a/src/main.rs b/src/main.rs index 4d6e2db6..9d9d9492 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use chrono::{DateTime, Datelike, Local, TimeZone}; use evtx::{EvtxParser, ParserSettings}; use git2::Repository; use hashbrown::{HashMap, HashSet}; -use hayabusa::detections::configs::load_pivot_keywords; +use hayabusa::detections::configs::{load_pivot_keywords, TargetEventTime}; use hayabusa::detections::detection::{self, EvtxRecordInfo}; use hayabusa::detections::pivot::PIVOT_KEYWORD; use hayabusa::detections::print::{ @@ -174,6 +174,11 @@ impl App { } } + let time_filter = TargetEventTime::default(); + if !time_filter.is_parse_success() { + return; + } + if *STATISTICS_FLAG { println!("Generating Event ID Statistics"); println!(); @@ -192,7 +197,7 @@ impl App { if live_analysis_list.is_none() { return; } - self.analysis_files(live_analysis_list.unwrap()); + self.analysis_files(live_analysis_list.unwrap(), &time_filter); } else if let Some(filepath) = configs::CONFIG.read().unwrap().args.value_of("filepath") { if !filepath.ends_with(".evtx") || Path::new(filepath) @@ -210,7 +215,7 @@ impl App { .ok(); return; } - self.analysis_files(vec![PathBuf::from(filepath)]); + self.analysis_files(vec![PathBuf::from(filepath)], &time_filter); } else if let Some(directory) = configs::CONFIG.read().unwrap().args.value_of("directory") { let evtx_files = self.collect_evtxfiles(directory); if evtx_files.is_empty() { @@ -221,7 +226,7 @@ impl App { .ok(); return; } - self.analysis_files(evtx_files); + self.analysis_files(evtx_files, &time_filter); } else if configs::CONFIG .read() .unwrap() @@ -430,7 +435,7 @@ impl App { } } - fn analysis_files(&mut self, evtx_files: Vec) { + fn analysis_files(&mut self, evtx_files: Vec, time_filter: &TargetEventTime) { let level = configs::CONFIG .read() .unwrap() @@ -473,7 +478,7 @@ impl App { println!("Checking target evtx FilePath: {:?}", &evtx_file); } let cnt_tmp: usize; - (detection, cnt_tmp) = self.analysis_file(evtx_file, detection); + (detection, cnt_tmp) = self.analysis_file(evtx_file, detection, time_filter); total_records += cnt_tmp; pb.inc(); } @@ -489,6 +494,7 @@ impl App { &self, evtx_filepath: PathBuf, mut detection: detection::Detection, + time_filter: &TargetEventTime, ) -> (detection::Detection, usize) { let path = evtx_filepath.display(); let parser = self.evtx_to_jsons(evtx_filepath.clone()); @@ -500,7 +506,6 @@ impl App { let mut tl = Timeline::new(); let mut parser = parser.unwrap(); let mut records = parser.records_json_value(); - loop { let mut records_per_detect = vec![]; while records_per_detect.len() < MAX_DETECT_RECORDS { @@ -532,12 +537,13 @@ impl App { } // target_eventids.txtでフィルタする。 - let data = record_result.unwrap().data; - if !self._is_target_event_id(&data) { + let data = record_result.as_ref().unwrap().data.clone(); + let timestamp = record_result.unwrap().timestamp; + + if !self._is_target_event_id(&data) || !time_filter.is_target(&Some(timestamp)) { continue; } - // EvtxRecordInfo構造体に変更 records_per_detect.push(data); } if records_per_detect.is_empty() {