From df86958850e9a981ab5a013ccb1cef0ef690cb74 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Tue, 15 Feb 2022 02:12:45 +0900 Subject: [PATCH] added live analysys feature (#398) * added windows live analysis option #125 * added live analysis option #125 * fixed live analysys condition #125 * changed live analysis option #125 * added live-analysis option in readme #125 * fixed live-analysis check condition #125 * is_elevated crate is only windows #125 * fixed is_elevated build error #125 * fixed is_elevated library crate load * fixed call way os dependencies crate #125 * fix build error on linux and removed unnecessary create #125 * fixed lack of load crate when build at windows #125 * Update error message Co-authored-by: Tanaka Zakku <71482215+YamatoSecurity@users.noreply.github.com> --- Cargo.lock | 10 ++++++++ Cargo.toml | 3 +++ README-English.md | 3 +++ README-Japanese.md | 3 +++ src/detections/configs.rs | 1 + src/main.rs | 51 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 70 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index fe2b81a4..26f573d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -818,6 +818,7 @@ dependencies = [ "hashbrown 0.12.0", "hex 0.4.3", "hhmmss", + "is_elevated", "lazy_static", "linked-hash-map", "mopa", @@ -1004,6 +1005,15 @@ dependencies = [ "libc", ] +[[package]] +name = "is_elevated" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5299060ff5db63e788015dcb9525ad9b84f4fd9717ed2cbdeba5018cbf42f9b5" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "itoa" version = "0.4.8" diff --git a/Cargo.toml b/Cargo.toml index 643b81fa..89206c58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,5 +32,8 @@ hashbrown = "0.12.*" colored = "2.*" hex = "0.4.*" +[target.'cfg(windows)'.dependencies] +is_elevated = "0.1.2" + [profile.release] lto = true \ No newline at end of file diff --git a/README-English.md b/README-English.md index a287a8de..ea314ce9 100644 --- a/README-English.md +++ b/README-English.md @@ -151,6 +151,7 @@ USAGE: -D --enable-deprecated-rules 'Enable sigma rules marked as deprecated.' -n --enable-noisy-rules 'Enable rules marked as noisy.' -m --min-level=[LEVEL] 'Minimum level for rules. (default: informational)' + -l --live-analysis 'Analyze to WINDIR\System32\winevt\Logs (Windows Only. Need Administrator privileges.)' --start-timeline=[STARTTIMELINE] 'Start time of the event to load from event file. (example: '2018/11/28 12:00:00 +09:00')' --end-timeline=[ENDTIMELINE] 'End time of the event to load from event file. (example: '2018/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)' @@ -168,6 +169,8 @@ FLAGS: -D, --enable-deprecated-rules Enable sigma rules marked as deprecated. -n, --enable-noisy-rules Enable rules marked as noisy. -h, --help Prints help information + -l, --live-analysis Analyze to WINDIR\System32\winevt\Logs (Windows Only. Need Administrator + privileges.) -q, --quiet Quiet mode. Do not display the launch banner. -Q, --quiet-errors Quiet errors mode. Do not save error logs. --rfc-2822 Output date and time in RFC 2822 format. (example: Mon, 07 Aug 2006 12:34:56 -0600) diff --git a/README-Japanese.md b/README-Japanese.md index 1b78800d..df71b3e2 100644 --- a/README-Japanese.md +++ b/README-Japanese.md @@ -152,6 +152,7 @@ USAGE: -D --enable-deprecated-rules 'Enable sigma rules marked as deprecated.' -n --enable-noisy-rules 'Enable rules marked as noisy.' -m --min-level=[LEVEL] 'Minimum level for rules. (default: informational)' + -l --live-analysis 'Analyze to WINDIR\System32\winevt\Logs (Windows Only. Need Administrator privileges.)' --start-timeline=[STARTTIMELINE] 'Start time of the event to load from event file. (example: '2018/11/28 12:00:00 +09:00')' --end-timeline=[ENDTIMELINE] 'End time of the event to load from event file. (example: '2018/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)' @@ -169,6 +170,8 @@ FLAGS: -D, --enable-deprecated-rules Enable sigma rules marked as deprecated. -n, --enable-noisy-rules Enable rules marked as noisy. -h, --help Prints help information + -l, --live-analysis Analyze to WINDIR\System32\winevt\Logs (Windows Only. Need Administrator + privileges.) -q, --quiet Quiet mode. Do not display the launch banner. -Q, --quiet-errors Quiet errors mode. Do not save error logs. --rfc-2822 Output date and time in RFC 2822 format. (example: Mon, 07 Aug 2006 12:34:56 -0600) diff --git a/src/detections/configs.rs b/src/detections/configs.rs index 3daa00d5..da849d41 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -62,6 +62,7 @@ fn build_app<'a>() -> ArgMatches<'a> { -D --enable-deprecated-rules 'Enable sigma rules marked as deprecated.' -n --enable-noisy-rules 'Enable rules marked as noisy.' -m --min-level=[LEVEL] 'Minimum level for rules. (default: informational)' + -l --live-analysis 'Analyze to WINDIR\\System32\\winevt\\Logs (Windows Only. Need Administrator privileges.)' --start-timeline=[STARTTIMELINE] 'Start time of the event to load from event file. (example: '2018/11/28 12:00:00 +09:00')' --end-timeline=[ENDTIMELINE] 'End time of the event to load from event file. (example: '2018/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)' diff --git a/src/main.rs b/src/main.rs index dccca891..801d5333 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,9 @@ use tokio::runtime::Runtime; use tokio::spawn; use tokio::task::JoinHandle; +#[cfg(target_os = "windows")] +use {is_elevated::is_elevated, std::env}; + // 一度にtimelineやdetectionを実行する行数 const MAX_DETECT_RECORDS: usize = 5000; @@ -99,7 +102,18 @@ impl App { println!("Generating Event ID Statistics"); println!(""); } - if let Some(filepath) = configs::CONFIG.read().unwrap().args.value_of("filepath") { + if configs::CONFIG + .read() + .unwrap() + .args + .is_present("live-analysis") + { + let live_analysis_list = self.collect_liveanalysis_files(); + if live_analysis_list.is_none() { + return; + } + self.analysis_files(live_analysis_list.unwrap()); + } else if let Some(filepath) = configs::CONFIG.read().unwrap().args.value_of("filepath") { if !filepath.ends_with(".evtx") || Path::new(filepath) .file_stem() @@ -149,6 +163,41 @@ impl App { } } + #[cfg(not(target_os = "windows"))] + fn collect_liveanalysis_files(&self) -> Option> { + AlertMessage::alert( + &mut BufWriter::new(std::io::stderr().lock()), + &"-l / --liveanalysis needs to be run as Administrator on Windows.\r\n".to_string(), + ) + .ok(); + return None; + } + + #[cfg(target_os = "windows")] + fn collect_liveanalysis_files(&self) -> Option> { + if is_elevated() { + let log_dir = env::var("windir").expect("windir is not found"); + let evtx_files = + self.collect_evtxfiles(&[log_dir, "System32\\winevt\\Logs".to_string()].join("/")); + if evtx_files.len() == 0 { + AlertMessage::alert( + &mut BufWriter::new(std::io::stderr().lock()), + &"No .evtx files were found.".to_string(), + ) + .ok(); + return None; + } + return Some(evtx_files); + } else { + AlertMessage::alert( + &mut BufWriter::new(std::io::stderr().lock()), + &"-l / --liveanalysis needs to be run as Administrator on Windows.\r\n".to_string(), + ) + .ok(); + return None; + } + } + fn collect_evtxfiles(&self, dirpath: &str) -> Vec { let entries = fs::read_dir(dirpath); if entries.is_err() {