From 180e8cada2e7a51bae6c71b232b800ba2fa97123 Mon Sep 17 00:00:00 2001 From: DustInDark Date: Mon, 13 Jun 2022 01:58:40 +0900 Subject: [PATCH] adjusted usage to clap v3 derive struct #413 --- src/detections/configs.rs | 173 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 166 insertions(+), 7 deletions(-) diff --git a/src/detections/configs.rs b/src/detections/configs.rs index ed5c49e3..11516a18 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -3,14 +3,15 @@ use crate::detections::pivot::PIVOT_KEYWORD; use crate::detections::print::AlertMessage; use crate::detections::utils; use chrono::{DateTime, Utc}; -use clap::{App, AppSettings, Arg, ArgMatches}; +use clap::{Command, ArgMatches, CommandFactory, Parser}; use hashbrown::HashMap; use hashbrown::HashSet; +use std::path::PathBuf; use lazy_static::lazy_static; use regex::Regex; use std::sync::RwLock; lazy_static! { - pub static ref CONFIG: RwLock = RwLock::new(ConfigReader::new()); + pub static ref CONFIG: RwLock> = RwLock::new(ConfigReader::new()); pub static ref LEVELMAP: HashMap = { let mut levelmap = HashMap::new(); levelmap.insert("INFORMATIONAL".to_owned(), 1); @@ -29,24 +30,182 @@ lazy_static! { } #[derive(Clone)] -pub struct ConfigReader { - pub args: ArgMatches<'static>, +pub struct ConfigReader<'a> { + pub cmd: Command<'a>, + pub args: ArgMatches, pub folder_path: String, pub event_timeline_config: EventInfoConfig, pub target_eventids: TargetEventIds, } -impl Default for ConfigReader { +impl Default for ConfigReader<'_> { fn default() -> Self { Self::new() } } -impl ConfigReader { +/// Hayabusa: Aiming to be the world's greatest Windows event log analysis tool! +#[derive(Parser)] +#[clap( + author = "Yamato Security (https://github.com/Yamato-Security/hayabusa) @SecurityYamato)", + version +)] +struct Config { + /// Directory of multiple .evtx files. + #[clap(short = 'd', long, value_name = "DIRECTORY")] + directory: Option, + + /// File path to one .evtx file. + #[clap(short = 'f', long, value_name = "FILE_PATH")] + filepath: Option, + + /// Print all field information. + #[clap(short = 'F', long = "full-data")] + full_data: bool, + + /// Rule directory or file (Default: .\\rules) + #[clap( + short = 'r', + long, + default_value = "./rules", + value_name = "RULE_DIRECTORY/RULE_FILE" + )] + rules: PathBuf, + + /// Rule config folder. (Default: .\\rules\\config) + #[clap( + short = 'C', + long, + default_value = "./rules/config", + value_name = "RULE_CONFIG_DIRECTORY" + )] + config: PathBuf, + + /// Save the timeline in CSV format. (Ex: results.csv) + #[clap(short = 'o', long, value_name = "CSV_TIMELINE")] + output: Option, + + /// Output all tags when saving to a CSV file. + #[clap(long = "all-tags")] + all_tags: bool, + + /// Do not display EventRecordID number. + #[clap(short = 'R', long = "hide-record-id")] + hide_record_id: bool, + + /// Output verbose information. + #[clap(short = 'v', long)] + verbose: bool, + + /// Output event frequency timeline. + #[clap(short = 'V', long = "visualize-timeline")] + visualize_timeline: bool, + + /// Enable rules marked as deprecated. + #[clap(short = 'D', long = "enable-deprecated-rules")] + enable_deprecated_rules: bool, + + /// Enable rules marked as noisy. + #[clap(short = 'n', long = "enable-noisy-rules")] + enable_noisy_rules: bool, + + /// Update to the latest rules in the hayabusa-rules github repository. + #[clap(short = 'u', long = "update-rules")] + update: bool, + + /// Minimum level for rules. (Default: informational) + #[clap( + short = 'm', + long = "min-level", + default_value = "informational", + value_name = "LEVEL" + )] + min_level: String, + + /// Analyze the local C:\\Windows\\System32\\winevt\\Logs folder (Windows Only. Administrator privileges required.) + #[clap(short = 'l', long = "live-analysis")] + live_analysis: bool, + + /// Start time of the event logs to load. (Ex: \"2020-02-22 00:00:00 +09:00\") + #[clap(long = "start-timeline", value_name = "START_TIMELINE")] + start_timeline: Option, + + /// End time of the event logs to load. (Ex: \"2022-02-22 23:59:59 +09:00\") + #[clap(long = "end-timeline", value_name = "END_TIMELINE")] + end_timeline: Option, + + /// Output timestamp in RFC 2822 format. (Ex: Fri, 22 Feb 2022 22:00:00 -0600) + #[clap(long = "rfc-2822")] + rfc_2822: bool, + + /// Output timestamp in RFC 3339 format. (Ex: 2022-02-22 22:00:00.123456-06:00) + #[clap(long = "rfc-3339")] + rfc_3339: bool, + + /// Output timestamp in US time format. (Ex: 02-22-2022 10:00:00.123 PM -06:00) + #[clap(long = "US-time")] + us_time: bool, + + /// Output timestamp in US military time format. (Ex: 02-22-2022 22:00:00.123 -06:00) + #[clap(long = "US-military-time")] + us_military_time: bool, + + /// Output timestamp in European time format. (Ex: 22-02-2022 22:00:00.123 +02:00) + #[clap(long = "European-time")] + european_time: bool, + + /// Output time in UTC format. (Default: local time) + #[clap(short = 'U', long = "utc")] + utc: bool, + + /// Disable color output. + #[clap(long = "no_color")] + no_color: bool, + + /// Thread number. (Default: Optimal number for performance.) + #[clap(short, long = "thread-number", value_name = "NUMBER")] + thread_number: Option, + + /// Prints statistics of event IDs. + #[clap(short, long)] + statistics: bool, + + /// Successful and failed logons summary. + #[clap(short = 'L', long = "logon-summary")] + logon_summary: bool, + + /// Tune alert levels. (Default: .\\rules\\config\\level_tuning.txt) + #[clap( + long = "level-tuning", + default_value = "./rules/config/level_tuning.txt", + value_name = "LEVEL_TUNING_FILE" + )] + level_tuning: PathBuf, + + /// Quiet mode. Do not display the launch banner. + #[clap(short, long)] + quiet: bool, + + /// Quiet errors mode. Do not save error logs. + #[clap(short = 'Q', long = "quiet-errors")] + quiet_errors: bool, + + /// Create a list of pivot keywords. + #[clap(short = 'p', long = "pivot-keywords-list")] + pivot_keywords_list: bool, + + /// Prints the list of contributors. + #[clap(long)] + contributors: bool, +} + +impl ConfigReader<'_> { pub fn new() -> Self { - let arg = build_app(); + let build_cmd = Config::command(); + let arg = build_cmd.clone().get_matches(); let folder_path_str = arg.value_of("config").unwrap_or("rules/config").to_string(); ConfigReader { + cmd: build_cmd, args: arg, folder_path: folder_path_str, event_timeline_config: load_eventcode_info("config/statistics_event_info.txt"),