Feature/output logo#206 (#222)

* add output logo #206

* added newline and orgnization name #206

* add output rule count #200

* Changed yml summarize the totals for each folder hierarchy. #157

* added analyzing evtx file count output #157

* added loaded rule count output #157

* added quiet option #206
This commit is contained in:
DustInDark
2021-11-21 15:16:44 +09:00
committed by GitHub
parent 86321a4502
commit b53342218c
5 changed files with 68 additions and 2 deletions

7
art/logo.txt Normal file
View File

@@ -0,0 +1,7 @@
██╗ ██╗ █████╗ ██╗ ██╗ █████╗ ██████╗ ██╗ ██╗███████╗ █████╗
██║ ██║██╔══██╗╚██╗ ██╔╝██╔══██╗██╔══██╗██║ ██║██╔════╝██╔══██╗
███████║███████║ ╚████╔╝ ███████║██████╔╝██║ ██║███████╗███████║
██╔══██║██╔══██║ ╚██╔╝ ██╔══██║██╔══██╗██║ ██║╚════██║██╔══██║
██║ ██║██║ ██║ ██║ ██║ ██║██████╔╝╚██████╔╝███████║██║ ██║
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
by Yamato Security

View File

@@ -52,6 +52,7 @@ fn build_app<'a>() -> ArgMatches<'a> {
--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'
--verbose 'Output check information to target event file path and rule file.'
-q 'Quiet Output Logo'
-r --rules=[RULEDIRECTORY] 'using target of rule file directory'
-L --level=[LEVEL] 'Specified execute rule level(default: LOW)'
-u --utc 'Output time in UTC format(default: local time)'

View File

@@ -2,6 +2,7 @@ extern crate csv;
use crate::detections::rule::AggResult;
use serde_json::Value;
use std::collections::HashMap;
use tokio::{runtime::Runtime, spawn, task::JoinHandle};
use crate::detections::print::AlertMessage;
@@ -51,6 +52,11 @@ impl Detection {
// ルールファイルのパースを実行
let mut rulefile_loader = ParseYaml::new();
let result_readdir = rulefile_loader.read_dir(rulespath.unwrap_or(DIRPATH_RULES), &level);
Detection::print_rule_load_info(
rulefile_loader.rulecounter,
rulefile_loader.parseerror_count,
rulefile_loader.ignore_count,
);
if result_readdir.is_err() {
AlertMessage::alert(
&mut std::io::stderr().lock(),
@@ -201,6 +207,21 @@ impl Detection {
));
return ret;
}
pub fn print_rule_load_info(
rc: HashMap<String, u128>,
parseerror_count: u128,
ignore_count: u128,
) {
let mut total = parseerror_count + ignore_count;
rc.into_iter().for_each(|(key, value)| {
println!("{} Rules: {}", key, value);
total += value;
});
println!("Ignored Rule Count: {}", ignore_count);
println!("Rule Parse Errors Count: {}", parseerror_count);
println!("Total Detection Rules: {}", total);
println!("");
}
}
#[test]

View File

@@ -20,6 +20,10 @@ use std::{
const MAX_DETECT_RECORDS: usize = 40000;
fn main() {
if !configs::CONFIG.read().unwrap().args.is_present("q") {
output_logo();
println!("");
}
if configs::CONFIG.read().unwrap().args.args.len() == 0 {
println!(
"{}",
@@ -114,6 +118,7 @@ fn analysis_files(evtx_files: Vec<PathBuf>) {
.value_of("level")
.unwrap_or("INFO")
.to_uppercase();
println!("Analyzing Event Files: {:?}", evtx_files.len());
let rule_files = detection::Detection::parse_rule_files(
level,
configs::CONFIG.read().unwrap().args.value_of("rules"),
@@ -212,6 +217,12 @@ fn _output_with_omikuji(omikuji: Omikuji) {
println!("{}", content);
}
fn output_logo() {
let fp = &format!("art/logo.txt");
let content = fs::read_to_string(fp).unwrap();
println!("{}", content);
}
#[cfg(test)]
mod tests {
use crate::collect_evtxfiles;

View File

@@ -3,6 +3,7 @@ extern crate yaml_rust;
use crate::detections::configs;
use crate::detections::print::AlertMessage;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io;
@@ -13,11 +14,19 @@ use yaml_rust::YamlLoader;
pub struct ParseYaml {
pub files: Vec<(String, yaml_rust::Yaml)>,
pub rulecounter: HashMap<String, u128>,
pub ignore_count: u128,
pub parseerror_count: u128,
}
impl ParseYaml {
pub fn new() -> ParseYaml {
ParseYaml { files: Vec::new() }
ParseYaml {
files: Vec::new(),
rulecounter: HashMap::new(),
ignore_count: 0,
parseerror_count: 0,
}
}
pub fn read_file(&self, path: PathBuf) -> Result<String, String> {
@@ -64,6 +73,7 @@ impl ParseYaml {
read_content.unwrap_err()
),
)?;
self.parseerror_count += 1;
return io::Result::Ok(ret);
}
@@ -78,6 +88,7 @@ impl ParseYaml {
yaml_contents.unwrap_err()
),
)?;
self.parseerror_count += 1;
return io::Result::Ok(ret);
}
@@ -94,8 +105,24 @@ impl ParseYaml {
.filter_map(|(filepath, yaml_doc)| {
// ignoreフラグがONになっているルールは無視する。
if yaml_doc["ignore"].as_bool().unwrap_or(false) {
self.ignore_count += 1;
return Option::None;
}
self.rulecounter.insert(
yaml_doc["rulesection"]
.as_str()
.unwrap_or("other")
.to_string(),
self.rulecounter
.get(
&yaml_doc["rulesection"]
.as_str()
.unwrap_or("other")
.to_string(),
)
.unwrap_or(&0)
+ 1,
);
if configs::CONFIG.read().unwrap().args.is_present("verbose") {
println!("Loaded yml FilePath: {}", filepath);
}
@@ -115,7 +142,6 @@ impl ParseYaml {
})
.collect();
self.files.extend(files);
return io::Result::Ok(String::default());
}
}