diff --git a/Cargo.lock b/Cargo.lock index ab932e6f..551ac12e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -531,6 +531,12 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +[[package]] +name = "linked-hash-map" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" + [[package]] name = "log" version = "0.4.11" @@ -1071,15 +1077,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "toml" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" -dependencies = [ - "serde", -] - [[package]] name = "unicode-width" version = "0.1.8" @@ -1196,5 +1193,14 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "toml", + "yaml-rust", +] + +[[package]] +name = "yaml-rust" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" +dependencies = [ + "linked-hash-map", ] diff --git a/Cargo.toml b/Cargo.toml index b28772bf..d4de1c60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,4 +17,4 @@ regex = "1" csv = "1.1" base64 = "*" flate2 = "1.0" -toml = "0.5" +yaml-rust = "0.4" diff --git a/rules/test.toml b/rules/test.toml deleted file mode 100644 index 08260f64..00000000 --- a/rules/test.toml +++ /dev/null @@ -1,2 +0,0 @@ -[rule] -severity = "high" diff --git a/src/lib.rs b/src/lib.rs index b1dd090e..d9abfe41 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ pub mod detections; pub mod models; pub mod omikuji; -pub mod toml; +pub mod yaml; diff --git a/src/main.rs b/src/main.rs index fe8ffba4..ce910bf5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use quick_xml::de::DeError; use std::{fs, path::PathBuf, process}; use yamato_event_analyzer::detections::detection; use yamato_event_analyzer::omikuji::Omikuji; -use yamato_event_analyzer::toml; +use yamato_event_analyzer::yaml; fn build_app() -> clap::App<'static, 'static> { let program = std::env::args() diff --git a/src/models/mod.rs b/src/models/mod.rs index ee089cbc..53f11265 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,2 +1 @@ pub mod event; -pub mod rule; diff --git a/src/models/rule.rs b/src/models/rule.rs deleted file mode 100644 index 550bdc65..00000000 --- a/src/models/rule.rs +++ /dev/null @@ -1,13 +0,0 @@ -extern crate serde; -use serde::Deserialize; - -#[derive(Debug, Deserialize)] -pub struct Rule { - pub severity: Option, - pub name: Option, -} - -#[derive(Debug, Deserialize)] -pub struct Toml { - pub rule: Rule, -} diff --git a/src/toml.rs b/src/toml.rs deleted file mode 100644 index 08482f88..00000000 --- a/src/toml.rs +++ /dev/null @@ -1,89 +0,0 @@ -extern crate serde_derive; -extern crate toml; - -use crate::models::rule; -use std::fs; -use std::io; -use std::io::{BufReader, Read}; -use std::path::{Path, PathBuf}; - -pub struct ParseToml { - pub rules: Vec>, -} - -impl ParseToml { - pub fn new() -> ParseToml { - ParseToml { rules: Vec::new() } - } - - pub fn read_file(&self, path: PathBuf) -> Result { - let mut file_content = String::new(); - - let mut fr = fs::File::open(path) - .map(|f| BufReader::new(f)) - .map_err(|e| e.to_string())?; - - fr.read_to_string(&mut file_content) - .map_err(|e| e.to_string())?; - - Ok(file_content) - } - - pub fn read_dir>(&mut self, path: P) -> io::Result { - Ok(fs::read_dir(path)? - .filter_map(|entry| { - let entry = entry.ok()?; - if entry.file_type().ok()?.is_file() { - match self.read_file(entry.path()) { - Ok(s) => &self.rules.push(toml::from_str(&s)), - Err(e) => panic!("fail to read file: {}", e), - }; - } - if entry.file_type().ok()?.is_dir() { - self.read_dir(entry.path()); - } - Some("") - }) - .collect()) - } -} - -#[cfg(test)] -mod tests { - - use crate::toml; - - #[test] - fn test_read_toml() { - let mut toml = toml::ParseToml::new(); - &toml.read_dir("test_files/rules".to_string()); - - for rule in toml.rules { - match rule { - Ok(_rule) => { - if let Some(severity) = _rule.rule.severity { - assert_eq!("high", severity); - } - } - Err(_) => (), - } - } - } - - #[test] - fn test_read_multiple_dir() { - let mut toml = toml::ParseToml::new(); - &toml.read_dir("test_files".to_string()); - - for rule in toml.rules { - match rule { - Ok(_rule) => { - if let Some(severity) = _rule.rule.severity { - assert_eq!("high", severity); - } - } - Err(_) => (), - } - } - } -} diff --git a/src/yaml.rs b/src/yaml.rs new file mode 100644 index 00000000..cbe05bba --- /dev/null +++ b/src/yaml.rs @@ -0,0 +1,80 @@ +extern crate serde_derive; +extern crate yaml_rust; + +use std::fs; +use std::io; +use std::io::{BufReader, Read}; +use std::path::{Path, PathBuf}; +use yaml_rust::YamlLoader; + +pub struct ParseYaml { + pub rules: Vec, +} + +impl ParseYaml { + pub fn new() -> ParseYaml { + ParseYaml { rules: Vec::new() } + } + + pub fn read_file(&self, path: PathBuf) -> Result { + let mut file_content = String::new(); + + let mut fr = fs::File::open(path) + .map(|f| BufReader::new(f)) + .map_err(|e| e.to_string())?; + + fr.read_to_string(&mut file_content) + .map_err(|e| e.to_string())?; + + Ok(file_content) + } + + pub fn read_dir>(&mut self, path: P) -> io::Result { + Ok(fs::read_dir(path)? + .filter_map(|entry| { + let entry = entry.ok()?; + if entry.file_type().ok()?.is_file() { + match self.read_file(entry.path()) { + Ok(s) => { + let docs = YamlLoader::load_from_str(&s).unwrap(); + for i in docs { + &self.rules.push(i); + } + } + Err(e) => panic!("fail to read file: {}", e), + }; + } + if entry.file_type().ok()?.is_dir() { + self.read_dir(entry.path()); + } + Some("") + }) + .collect()) + } +} + +#[cfg(test)] +mod tests { + + use crate::yaml; + + #[test] + fn test_read_yaml() { + let mut yaml = yaml::ParseYaml::new(); + &yaml.read_dir("test_files/rules/yaml/".to_string()); + for rule in yaml.rules { + if rule["title"].as_str().unwrap() == "Sysmon Check command lines" { + assert_eq!( + "*", + rule["detection"]["selection"]["CommandLine"] + .as_str() + .unwrap() + ); + assert_eq!( + 1, + rule["detection"]["selection"]["EventID"].as_i64().unwrap() + ); + } + } + } +} diff --git a/test_files/rules/test.toml b/test_files/rules/test.toml deleted file mode 100644 index 08260f64..00000000 --- a/test_files/rules/test.toml +++ /dev/null @@ -1,2 +0,0 @@ -[rule] -severity = "high" diff --git a/test_files/rules/test2.toml b/test_files/rules/test2.toml deleted file mode 100644 index 9cebf717..00000000 --- a/test_files/rules/test2.toml +++ /dev/null @@ -1,3 +0,0 @@ -[rule] -severity = "high" -name = "test2" diff --git a/test_files/rules/yaml/1.yml b/test_files/rules/yaml/1.yml new file mode 100644 index 00000000..26e06dbb --- /dev/null +++ b/test_files/rules/yaml/1.yml @@ -0,0 +1,19 @@ +title: Sysmon Check command lines +description: hogehoge +enabled: true +author: Yea +logsource: + product: windows +detection: + selection: + EventLog: Sysmon + EventID: 1 + CommandLine: '*' + condition: selection +falsepositives: + - unknown +level: medium +output: 'CommandLine=%CommandLine%¥nParentImage=%ParentImage%' +creation_date: 2020/11/8 +uodated_date: 2020/11/8 +