Merge branch 'main' into 592-config-flag-seems-to-be-ignored

This commit is contained in:
DustInDark
2022-06-25 21:57:01 +09:00
8 changed files with 126 additions and 55 deletions

View File

@@ -35,6 +35,8 @@ lazy_static! {
get_target_extensions(CONFIG.read().unwrap().args.evtx_file_ext.as_ref());
pub static ref CURRENT_EXE_PATH: PathBuf =
current_exe().unwrap().parent().unwrap().to_path_buf();
pub static ref EXCLUDE_STATUS: HashSet<String> =
convert_option_vecs_to_hs(CONFIG.read().unwrap().args.exclude_status.as_ref());
}
pub struct ConfigReader<'a> {
@@ -214,6 +216,10 @@ pub struct Config {
/// Specify additional target file extensions (ex: evtx_data) (ex: evtx1 evtx2)
#[clap(long = "target-file-ext", multiple_values = true)]
pub evtx_file_ext: Option<Vec<String>>,
/// Ignore rules according to status (ex: experimental) (ex: stable test)
#[clap(long = "exclude-status", multiple_values = true)]
pub exclude_status: Option<Vec<String>>,
}
impl ConfigReader<'_> {
@@ -474,12 +480,17 @@ pub fn load_pivot_keywords(path: &str) {
/// --target-file-extで追加された拡張子から、調査対象ファイルの拡張子セットを返す関数
pub fn get_target_extensions(arg: Option<&Vec<String>>) -> HashSet<String> {
let mut target_file_extensions: HashSet<String> =
arg.unwrap_or(&Vec::new()).iter().cloned().collect();
let mut target_file_extensions: HashSet<String> = convert_option_vecs_to_hs(arg);
target_file_extensions.insert(String::from("evtx"));
target_file_extensions
}
/// Option<Vec<String>>の内容をHashSetに変換する関数
pub fn convert_option_vecs_to_hs(arg: Option<&Vec<String>>) -> HashSet<String> {
let ret: HashSet<String> = arg.unwrap_or(&Vec::new()).iter().cloned().collect();
ret
}
#[derive(Debug, Clone)]
pub struct EventInfo {
pub evttitle: String,

View File

@@ -1,6 +1,9 @@
extern crate csv;
use crate::detections::configs;
use crate::detections::utils::write_color_buffer;
use termcolor::{BufferWriter, Color, ColorChoice};
use crate::detections::pivot::insert_pivot_keyword;
use crate::detections::print::AlertMessage;
use crate::detections::print::DetectInfo;
@@ -119,13 +122,11 @@ impl Detection {
.filter_map(return_if_success)
.collect();
if !*LOGONSUMMARY_FLAG {
let _ = &rulefile_loader
.rule_load_cnt
.insert(String::from("rule parsing error"), parseerror_count);
Detection::print_rule_load_info(
&rulefile_loader.rulecounter,
&rulefile_loader.rule_load_cnt,
&rulefile_loader.rule_status_cnt,
&parseerror_count,
);
}
ret
@@ -363,46 +364,80 @@ impl Detection {
rc: &HashMap<String, u128>,
ld_rc: &HashMap<String, u128>,
st_rc: &HashMap<String, u128>,
err_rc: &u128,
) {
if *STATISTICS_FLAG {
return;
}
let mut sorted_ld_rc: Vec<(&String, &u128)> = ld_rc.iter().collect();
sorted_ld_rc.sort_by(|a, b| a.0.cmp(b.0));
let args = &configs::CONFIG.read().unwrap().args;
sorted_ld_rc.into_iter().for_each(|(key, value)| {
//タイトルに利用するものはascii文字であることを前提として1文字目を大文字にするように変更する
println!(
"{} rules: {}",
make_ascii_titlecase(key.clone().as_mut()),
value,
);
if value != &0_u128 {
let disable_flag = if key == "noisy" && !args.enable_noisy_rules {
" (Disabled)"
} else {
""
};
//タイトルに利用するものはascii文字であることを前提として1文字目を大文字にするように変更する
println!(
"{} rules: {}{}",
make_ascii_titlecase(key.clone().as_mut()),
value,
disable_flag,
);
}
});
if err_rc != &0_u128 {
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
Some(Color::Red),
&format!("Rule parsing errors: {}", err_rc),
)
.ok();
}
println!();
let mut sorted_st_rc: Vec<(&String, &u128)> = st_rc.iter().collect();
let total_loaded_rule_cnt: u128 = sorted_st_rc.iter().map(|(_, v)| v.to_owned()).sum();
sorted_st_rc.sort_by(|a, b| a.0.cmp(b.0));
sorted_st_rc.into_iter().for_each(|(key, value)| {
let rate = if value == &0_u128 {
0 as f64
} else {
(*value as f64) / (total_loaded_rule_cnt as f64) * 100.0
};
//タイトルに利用するものはascii文字であることを前提として1文字目を大文字にするように変更する
println!(
"{} rules: {} ({:.2}%)",
make_ascii_titlecase(key.clone().as_mut()),
value,
rate
);
if value != &0_u128 {
let rate = (*value as f64) / (total_loaded_rule_cnt as f64) * 100.0;
let deprecated_flag = if key == "deprecated" && !args.enable_deprecated_rules {
" (Disabled)"
} else {
""
};
//タイトルに利用するものはascii文字であることを前提として1文字目を大文字にするように変更する
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
&format!(
"{} rules: {} ({:.2}%){}",
make_ascii_titlecase(key.clone().as_mut()),
value,
rate,
deprecated_flag
),
)
.ok();
}
});
println!();
let mut sorted_rc: Vec<(&String, &u128)> = rc.iter().collect();
sorted_rc.sort_by(|a, b| a.0.cmp(b.0));
sorted_rc.into_iter().for_each(|(key, value)| {
println!("{} rules: {}", key, value);
write_color_buffer(
&BufferWriter::stdout(ColorChoice::Always),
None,
&format!("{} rules: {}", key, value),
)
.ok();
});
println!("Total enabled detection rules: {}", total_loaded_rule_cnt);
println!();
}

View File

@@ -29,18 +29,16 @@ impl RuleExclude {
pub fn exclude_ids() -> RuleExclude {
let mut exclude_ids = RuleExclude::default();
if !configs::CONFIG.read().unwrap().args.enable_noisy_rules {
exclude_ids.insert_ids(&format!(
"{}/noisy_rules.txt",
configs::CONFIG
.read()
.unwrap()
.args
.config
.as_path()
.display()
));
};
exclude_ids.insert_ids(&format!(
"{}/noisy_rules.txt",
configs::CONFIG
.read()
.unwrap()
.args
.config
.as_path()
.display()
));
exclude_ids.insert_ids(&format!(
"{}/exclude_rules.txt",

View File

@@ -2,9 +2,9 @@ extern crate serde_derive;
extern crate yaml_rust;
use crate::detections::configs;
use crate::detections::configs::EXCLUDE_STATUS;
use crate::detections::print::AlertMessage;
use crate::detections::print::ERROR_LOG_STACK;
use crate::detections::print::QUIET_ERRORS_FLAG;
use crate::detections::print::{ERROR_LOG_STACK, QUIET_ERRORS_FLAG};
use crate::filter::RuleExclude;
use hashbrown::HashMap;
use std::ffi::OsStr;
@@ -165,6 +165,19 @@ impl ParseYaml {
return io::Result::Ok(ret);
}
// ignore if tool test yml file in hayabusa-rules.
if path
.to_str()
.unwrap()
.contains("rules/tools/sigmac/test_files")
|| path
.to_str()
.unwrap()
.contains("rules\\tools\\sigmac\\test_files")
{
return io::Result::Ok(ret);
}
// 個別のファイルの読み込みは即終了としない。
let read_content = self.read_file(path);
if read_content.is_err() {
@@ -231,7 +244,28 @@ impl ParseYaml {
} else {
"noisy"
};
let entry = self.rule_load_cnt.entry(entry_key.to_string()).or_insert(0);
// テスト用のルール(ID:000...0)の場合はexcluded ruleのカウントから除外するようにする
if v != "00000000-0000-0000-0000-000000000000" {
let entry =
self.rule_load_cnt.entry(entry_key.to_string()).or_insert(0);
*entry += 1;
}
if entry_key == "excluded"
|| (entry_key == "noisy"
&& !configs::CONFIG.read().unwrap().args.enable_noisy_rules)
{
return Option::None;
}
}
}
let status = &yaml_doc["status"].as_str();
if let Some(s) = status {
if EXCLUDE_STATUS.contains(&s.to_string()) {
let entry = self
.rule_load_cnt
.entry("excluded".to_string())
.or_insert(0);
*entry += 1;
return Option::None;
}
@@ -271,19 +305,6 @@ impl ParseYaml {
if doc_level_num < args_level_num {
return Option::None;
}
if !configs::CONFIG.read().unwrap().args.enable_deprecated_rules {
let rule_status = &yaml_doc["status"].as_str().unwrap_or_default();
if *rule_status == "deprecated" {
let entry = self
.rule_status_cnt
.entry(rule_status.to_string())
.or_insert(0);
*entry += 1;
return Option::None;
}
}
Option::Some((filepath, yaml_doc))
})
.collect();
@@ -439,7 +460,7 @@ mod tests {
yaml.read_dir(path, "", &exclude_ids).unwrap();
assert_eq!(
yaml.rule_status_cnt.get("deprecated").unwrap().to_owned(),
2
1
);
}
}