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:
@@ -17,7 +17,7 @@
|
||||
|
||||
**バグ修正:**
|
||||
|
||||
- xxx
|
||||
- `--start-timeline`、`--end-timeline`オプションが動かなかったのを修正した。 (#546) (@hitenkoku)
|
||||
|
||||
## v1.2.2 [2022/05/20]
|
||||
|
||||
|
||||
+2
-1
@@ -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
@@ -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形式で日付と時刻を出力する。(デフォルト: 現地時間)'
|
||||
|
||||
@@ -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
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user