start timeline and end timeline do not work (#547)

* fixed dont work start-timeline and end-timeline #546

* fixed condition

* added changelog #546

* changelog update

* changed stop analysis when start-timeline and end-timeline happend parse error #546

* cargo fmt

* fixed alert message

* fixed lack of timestamp convert

* cargo fmt

* readme/usage update

Co-authored-by: Tanaka Zakku <71482215+YamatoSecurity@users.noreply.github.com>
This commit is contained in:
DustInDark
2022-05-28 10:07:39 +09:00
committed by GitHub
parent a17d0d4e37
commit 2653e87588
7 changed files with 44 additions and 26 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
**バグ修正:**
- xxx
- `--start-timeline``--end-timeline`オプションが動かなかったのを修正した。 (#546) (@hitenkoku)
## v1.2.2 [2022/05/20]
+2 -1
View File
@@ -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]
+2 -2
View File
@@ -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形式で日付と時刻を出力する。(デフォルト: 現地時間)'
+2 -2
View File
@@ -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)'
+2 -1
View File
@@ -424,7 +424,8 @@ fn _get_timestamp(time: &DateTime<Utc>) -> 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()
}
}
+19 -9
View File
@@ -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<DateTime<Utc>>,
end_time: Option<DateTime<Utc>>,
}
@@ -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<chrono::DateTime<chrono::Utc>>,
input_end_time: Option<chrono::DateTime<chrono::Utc>>,
) -> 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<DateTime<Utc>>) -> 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::<DateTime<Utc>>().unwrap());
let end_time = Some("2020-03-30T12:00:09Z".parse::<DateTime<Utc>>().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::<DateTime<Utc>>().unwrap());
let within_range = Some("2019-02-27T01:05:01Z".parse::<DateTime<Utc>>().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::<DateTime<Utc>>().unwrap());
let end_time = Some("2020-03-30T12:00:09Z".parse::<DateTime<Utc>>().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));
+16 -10
View File
@@ -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<PathBuf>) {
fn analysis_files(&mut self, evtx_files: Vec<PathBuf>, 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() {