diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index b819e9053..53bf82b43 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -1,5 +1,25 @@ # 変更点 +## 2.9.0 [2023/XX/XX] "xxx Release" + +**新機能:** + +- XXX + +**改善:** + +- ディレクトリパスの指定にバックスラッシュを使用すべきではないことを示すエラーメッセージを追加した。 (#1166) (@hitenkoku, 提案者: @joswr1ght) +- 一度に読み込むレコード数の最適化。(#1175) (@yamatosecurity) +- プログレスバー内にあるバックスラッシュの表示をスラッシュに変更した。 (#1172) (@hitenkoku) + +**バグ修正:** + +- XXX + +**その他:** + +- XXX + ## 2.8.0 [2023/09/01] "Double X Release" **新機能:** diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f3ca2863..55886e735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changes +## 2.9.0 [2023/XX/XX] "xxx Release" + +**New Features:** + +- XXX + +**New Features:** + +- XXX + +**Enhancements:** + +- Added an error message to indicate that when you can't load evtx files in Windows due to specifying a directory path with spaces in it, you need to remove the trailing backslash. (#1166) (@hitenkoku, thanks for the suggestion from @joswr1ght) +- Optimized the number of records to load at a time. (#1175) (@yamatosecurity) +- Replaced double backslashes in paths in under the progress bar on Windows systems with single forward slashes. (#1172) (@hitenkoku) + +**Bug Fixes:** + +- XXX + +**Other:** + +- XXX + ## 2.8.0 [2023/09/01] "Double X Release" **New Features:** diff --git a/Cargo.lock b/Cargo.lock index b4f8ae18f..ed7ef2e17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -194,9 +194,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "bytesize" @@ -262,25 +262,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.28" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" +checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", - "time 0.1.45", "wasm-bindgen", "windows-targets 0.48.5", ] [[package]] name = "cidr-utils" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdfa36f04861d39453affe1cf084ce2d6554021a84eb6f31ebdeafb6fb92a01c" +checksum = "2315f7119b7146d6a883de6acd63ddf96071b5f79d9d98d2adaa84d749f6abf1" dependencies = [ "debug-helper", "num-bigint", @@ -335,7 +334,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -788,7 +787,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -836,7 +835,7 @@ dependencies = [ [[package]] name = "hayabusa" -version = "2.8.0" +version = "2.9.0-dev" dependencies = [ "aho-corasick", "base64", @@ -1232,9 +1231,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.2" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "memmap2" @@ -1289,7 +1288,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -1456,9 +1455,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -1492,7 +1491,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -1503,18 +1502,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.27.0+1.1.1v" +version = "300.1.3+3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e8f197c82d7511c5b014030c9b1efeda40d7d5f99d23b4ceed3524a5e63f02" +checksum = "cd2c101a165fff9935e34def4669595ab1c7847943c42be86e21503e482be107" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.92" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ "cc", "libc", @@ -1720,9 +1719,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" dependencies = [ "aho-corasick", "memchr", @@ -1732,9 +1731,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", @@ -1934,7 +1933,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -2149,9 +2148,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" dependencies = [ "proc-macro2", "quote", @@ -2204,33 +2203,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "syn 2.0.31", ] [[package]] @@ -2343,7 +2331,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", ] [[package]] @@ -2435,20 +2423,14 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2476,7 +2458,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", "wasm-bindgen-shared", ] @@ -2498,7 +2480,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.31", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 3b889ce89..38296ef9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hayabusa" -version = "2.8.0" +version = "2.9.0-dev" repository = "https://github.com/Yamato-Security/hayabusa" authors = ["Yamato Security @SecurityYamato"] edition = "2021" diff --git a/src/afterfact.rs b/src/afterfact.rs index 44074e79d..c5c5c1e64 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -1813,6 +1813,7 @@ mod tests { use crate::detections::message::DetectInfo; use crate::detections::utils; use crate::options::profile::{load_profile, Profile}; + use chrono::NaiveDateTime; use chrono::{Local, TimeZone, Utc}; use compact_str::CompactString; use hashbrown::HashMap; @@ -1843,9 +1844,9 @@ mod tests { let test_attack = "execution/txxxx.yyy"; let test_recinfo = "CommandRLine: hoge"; let test_record_id = "11111"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let expect_tz = expect_time.with_timezone(&Utc); let dummy_action = Action::CsvTimeline(CsvOutputOption { output_options: OutputOption { @@ -2169,9 +2170,9 @@ mod tests { let test_attack = "execution/txxxx.yyy"; let test_recinfo = "CommandRLine: hoge ¦ Test1: hogetest1 ¦ Test2: hogetest2"; let test_record_id = "11111"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let expect_tz = expect_time.with_timezone(&Utc); let dummy_action = Action::CsvTimeline(CsvOutputOption { output_options: OutputOption { @@ -2483,9 +2484,9 @@ mod tests { let test_attack = "execution/txxxx.yyy"; let test_recinfo = "CommandRLine: hoge"; let test_record_id = "11111"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let expect_tz = expect_time.with_timezone(&Utc); let dummy_action = Action::CsvTimeline(CsvOutputOption { output_options: OutputOption { @@ -2806,9 +2807,9 @@ mod tests { let test_attack = "execution/txxxx.yyy"; let test_recinfo = "CommandRLine: hoge"; let test_record_id = "11111"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let expect_tz = expect_time.with_timezone(&Utc); let dummy_action = Action::JsonTimeline(JSONOutputOption { output_options: OutputOption { @@ -3195,10 +3196,9 @@ mod tests { let output = "displaytest"; let test_recinfo = "testinfo"; let test_recid = "22222"; - - let test_timestamp = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let test_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let test_timestamp = Utc.from_local_datetime(&test_naivetime).unwrap(); let expect_header = "Timestamp ‖ Computer ‖ Channel ‖ EventID ‖ Level ‖ RecordID ‖ RuleTitle ‖ Details ‖ RecordInformation\n"; let expect_tz = test_timestamp.with_timezone(&Local); @@ -3353,9 +3353,9 @@ mod tests { let test_attack = "execution/txxxx.yyy"; let test_recinfo = "CommandRLine: hoge"; let test_record_id = "11111"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let expect_tz = expect_time.with_timezone(&Utc); let json_dummy_action = Action::JsonTimeline(JSONOutputOption { output_options: OutputOption { @@ -3616,9 +3616,9 @@ mod tests { let test_attack = "execution/txxxx.yyy"; let test_recinfo = "CommandRLine: hoge"; let test_record_id = "11111"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let expect_tz = expect_time.with_timezone(&Utc); let json_dummy_action = Action::JsonTimeline(JSONOutputOption { output_options: OutputOption { diff --git a/src/detections/detection.rs b/src/detections/detection.rs index 745fdc66a..d9040e98a 100644 --- a/src/detections/detection.rs +++ b/src/detections/detection.rs @@ -1186,6 +1186,7 @@ mod tests { use crate::detections::utils; use crate::filter; use crate::options::profile::Profile; + use chrono::NaiveDateTime; use chrono::TimeZone; use chrono::Utc; use compact_str::CompactString; @@ -1453,9 +1454,9 @@ mod tests { fn test_insert_message_with_geoip() { let test_filepath: &str = "test.evtx"; let test_rulepath: &str = "test-rule.yml"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let dummy_action = Action::CsvTimeline(CsvOutputOption { output_options: OutputOption { input_args: InputOption { @@ -1587,9 +1588,9 @@ mod tests { fn test_filtered_insert_message_with_geoip() { let test_filepath: &str = "test.evtx"; let test_rulepath: &str = "test-rule.yml"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let dummy_action = Action::CsvTimeline(CsvOutputOption { output_options: OutputOption { input_args: InputOption { @@ -1717,9 +1718,9 @@ mod tests { #[test] fn test_insert_message_extra_field_info() { let test_filepath: &str = "test.evtx"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let dummy_action = Action::CsvTimeline(CsvOutputOption { output_options: OutputOption { input_args: InputOption { @@ -1860,9 +1861,9 @@ mod tests { #[test] fn test_insert_message_multiline_ruleauthor() { let test_filepath: &str = "test.evtx"; - let expect_time = Utc - .datetime_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ") - .unwrap(); + let expect_naivetime = + NaiveDateTime::parse_from_str("1996-02-27T01:05:01Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); + let expect_time = Utc.from_local_datetime(&expect_naivetime).unwrap(); let dummy_action = Action::CsvTimeline(CsvOutputOption { output_options: OutputOption { input_args: InputOption { diff --git a/src/detections/field_data_map.rs b/src/detections/field_data_map.rs index 21c4c4fe0..3b6ee9041 100644 --- a/src/detections/field_data_map.rs +++ b/src/detections/field_data_map.rs @@ -133,7 +133,10 @@ fn load_yaml_files(dir_path: &Path) -> Result, String> { .flatten() .collect()), Err(e) => { - let msg = format!("Failed to open field mapping dir[{path}]."); + let mut msg = format!("Failed to open field mapping dir[{path}]. ",); + if e.to_string().ends_with("123)") { + msg = format!("{msg}. You may not be able to load evtx files when there are spaces in the directory path. Please enclose the path with double quotes and remove any trailing slash at the end of the path."); + } AlertMessage::warn(&msg).ok(); Err(e.to_string()) } diff --git a/src/detections/message.rs b/src/detections/message.rs index 8728305b0..d61389420 100644 --- a/src/detections/message.rs +++ b/src/detections/message.rs @@ -16,7 +16,6 @@ use lazy_static::lazy_static; use nested::Nested; use regex::Regex; use serde_json::Value; - use std::env; use std::fs::{create_dir, File}; use std::io::{self, BufWriter, Write}; diff --git a/src/main.rs b/src/main.rs index ab071c7a4..03606facd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,8 +64,9 @@ use is_elevated::is_elevated; #[global_allocator] static GLOBAL: MiMalloc = MiMalloc; -// 一度にtimelineやdetectionを実行する行数 -const MAX_DETECT_RECORDS: usize = 5000; +// 一度に読み込んで、スキャンするレコード数 +// The number of records to load and scan at a time. 1000 gave the fastest results and lowest memory usage in test benchmarks. +const MAX_DETECT_RECORDS: usize = 1000; fn main() { let mut config_reader = ConfigReader::new(); @@ -880,7 +881,10 @@ impl App { } let entries = fs::read_dir(dirpath); if entries.is_err() { - let errmsg = format!("{}", entries.unwrap_err()); + let mut errmsg = format!("{}", entries.unwrap_err()); + if errmsg.ends_with("123)") { + errmsg = format!("{errmsg}. You may not be able to load evtx files when there are spaces in the directory path. Please enclose the path with double quotes and remove any trailing slash at the end of the path."); + } if stored_static.verbose_flag { AlertMessage::alert(&errmsg).ok(); } @@ -1058,7 +1062,10 @@ impl App { *STORED_EKEY_ALIAS.write().unwrap() = Some(stored_static.eventkey_alias.clone()); *STORED_STATIC.write().unwrap() = Some(stored_static.clone()); for evtx_file in evtx_files { - let pb_msg = format!("{:?}", &evtx_file); + let pb_msg = format!( + "{:?}", + &evtx_file.to_str().unwrap_or_default().replace('\\', "/") + ); pb.set_message(pb_msg); let cnt_tmp: usize; diff --git a/src/yaml.rs b/src/yaml.rs index 0fcb97e1e..367688971 100644 --- a/src/yaml.rs +++ b/src/yaml.rs @@ -77,10 +77,19 @@ impl ParseYaml { ) -> io::Result { let metadata = fs::metadata(path.as_ref()); if metadata.is_err() { - let errmsg = format!( - "fail to read metadata of file: {}", + let err_contents = if let Err(e) = metadata { + e.to_string() + } else { + String::default() + }; + let mut errmsg = format!( + "fail to read metadata of file: {} {}", path.as_ref().to_path_buf().display(), + err_contents ); + if err_contents.ends_with("123)") { + errmsg = format!("{errmsg}. You may not be able to load evtx files when there are spaces in the directory path. Please enclose the path with double quotes and remove any trailing slash at the end of the path."); + } if stored_static.verbose_flag { AlertMessage::alert(&errmsg)?; }