diff --git a/src/afterfact.rs b/src/afterfact.rs index f4387f4f0..2289753ad 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -1,42 +1,40 @@ -use crate::detections::configs::{ - Action, OutputOption, StoredStatic, CONTROL_CHAT_REPLACE_MAP, CURRENT_EXE_PATH, GEOIP_DB_PARSER, -}; -use crate::detections::message::{AlertMessage, DetectInfo, COMPUTER_MITRE_ATTCK_MAP, LEVEL_FULL}; -use crate::detections::utils::{ - self, format_time, get_writable_color, output_and_data_stack_for_html, write_color_buffer, -}; -use crate::options::htmlreport; -use crate::options::profile::Profile; -use crate::yaml::ParseYaml; +use std::cmp::{self, min, Ordering}; +use std::error::Error; +use std::fs::File; +use std::io::{self, BufWriter, Write}; +use std::path::Path; +use std::process; +use std::str::FromStr; + use aho_corasick::{AhoCorasick, AhoCorasickBuilder, MatchKind}; use chrono::{DateTime, Local, TimeZone, Utc}; use comfy_table::modifiers::UTF8_ROUND_CORNERS; use comfy_table::presets::UTF8_FULL; +use comfy_table::*; use compact_str::CompactString; -use hashbrown::hash_map::RawEntryMut; -use terminal_size::terminal_size; - use csv::{QuoteStyle, Writer, WriterBuilder}; +use hashbrown::hash_map::RawEntryMut; +use hashbrown::{HashMap, HashSet}; use itertools::Itertools; use krapslog::{build_sparkline, build_time_markers}; +use lazy_static::lazy_static; use nested::Nested; -use std::path::Path; -use std::str::FromStr; -use yaml_rust::YamlLoader; - -use comfy_table::*; -use hashbrown::{HashMap, HashSet}; use num_format::{Locale, ToFormattedString}; -use std::cmp::{self, min, Ordering}; -use std::error::Error; - -use std::io::{self, BufWriter, Write}; - -use lazy_static::lazy_static; -use std::fs::File; -use std::process; use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; +use terminal_size::terminal_size; use terminal_size::Width; +use yaml_rust::YamlLoader; + +use crate::detections::configs::{ + Action, OutputOption, StoredStatic, CONTROL_CHAT_REPLACE_MAP, CURRENT_EXE_PATH, GEOIP_DB_PARSER, +}; +use crate::detections::message::{AlertMessage, DetectInfo, COMPUTER_MITRE_ATTCK_MAP, LEVEL_FULL}; +use crate::detections::utils::{ + self, format_time, get_writable_color, output_and_data_stack_for_html, write_color_buffer, +}; +use crate::options::htmlreport; +use crate::options::profile::Profile; +use crate::yaml::ParseYaml; lazy_static! { // ここで字句解析するときに使う正規表現の一覧を定義する。 @@ -2204,7 +2202,15 @@ fn _output_html_computer_by_mitre_attck(html_output_stock: &mut Nested) #[cfg(test)] mod tests { - use super::create_output_color_map; + use std::fs::{read_to_string, remove_file}; + use std::path::Path; + + use chrono::NaiveDateTime; + use chrono::{Local, TimeZone, Utc}; + use compact_str::CompactString; + use hashbrown::HashMap; + use serde_json::Value; + use crate::afterfact::format_time; use crate::afterfact::init_writer; use crate::afterfact::output_afterfact_inner; @@ -2226,13 +2232,8 @@ 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; - use serde_json::Value; - use std::fs::{read_to_string, remove_file}; - use std::path::Path; + + use super::create_output_color_map; #[test] fn test_emit_csv_output() { @@ -3934,7 +3935,7 @@ mod tests { ), ( "RecordInformation", - CompactString::from("{\n \"CommandRLine\": \"hoge\",\n \"Data\": [\"xxx\", \"yyy\"]\n }"), + CompactString::from("{\n \"CommandRLine\": \"hoge\",\n \"Data[1]\": \"xxx\",\n \"Data[2]\": \"yyy\"\n }"), ), ( "RuleFile", diff --git a/src/detections/utils.rs b/src/detections/utils.rs index b74b3acef..d2800ab0d 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -2,42 +2,39 @@ extern crate base64; extern crate csv; extern crate regex; -use crate::detections::configs::CURRENT_EXE_PATH; -use crate::options::htmlreport; +use std::{fs, io}; +use std::cmp::Ordering; +use std::fs::{File, read_to_string}; +use std::io::{BufRead, BufReader}; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; +use std::str; +use std::string::String; +use std::thread::available_parallelism; +use std::vec; +use chrono::{DateTime, TimeZone, Utc}; +use chrono::Local; use compact_str::{CompactString, ToCompactString}; use hashbrown::{HashMap, HashSet}; use itertools::Itertools; +use memchr::memmem; use nested::Nested; -use std::path::{Path, PathBuf}; -use std::thread::available_parallelism; - -use chrono::Local; +use regex::Regex; +use serde_json::{Error, json, Map, Value}; +use termcolor::{BufferWriter, ColorSpec, WriteColor}; use termcolor::{Color, ColorChoice}; - use tokio::runtime::{Builder, Runtime}; -use chrono::{DateTime, TimeZone, Utc}; -use regex::Regex; -use serde_json::{json, Error, Map, Value}; -use std::cmp::Ordering; -use std::fs::{read_to_string, File}; -use std::io::prelude::*; -use std::io::{BufRead, BufReader}; -use std::str; -use std::string::String; -use std::vec; -use std::{fs, io}; -use termcolor::{BufferWriter, ColorSpec, WriteColor}; +use crate::detections::configs::CURRENT_EXE_PATH; +use crate::detections::field_data_map::{convert_field_data, FieldDataMap, FieldDataMapKey}; +use crate::detections::field_extract::extract_fields; +use crate::options::htmlreport; use super::configs::{EventKeyAliasConfig, OutputOption, STORED_EKEY_ALIAS}; use super::detection::EvtxRecordInfo; use super::message::AlertMessage; -use crate::detections::field_data_map::{convert_field_data, FieldDataMap, FieldDataMapKey}; -use crate::detections::field_extract::extract_fields; -use memchr::memmem; - pub fn concat_selection_key(key_list: &Nested) -> String { return key_list .iter() @@ -396,7 +393,7 @@ pub fn create_recordinfos( _collect_recordinfo( &mut vec![], "", - 0, + -1, record, record, &mut output, @@ -437,7 +434,7 @@ pub fn create_recordinfos( fn _collect_recordinfo<'a>( keys: &mut Vec<&'a str>, parent_key: &'a str, - arr_index: usize, + arr_index: i8, org_value: &'a Value, cur_value: &'a Value, output: &mut HashSet<(String, String)>, @@ -449,7 +446,7 @@ fn _collect_recordinfo<'a>( _collect_recordinfo( keys, parent_key, - i, + i as i8, org_value, sub_value, output, @@ -471,7 +468,15 @@ fn _collect_recordinfo<'a>( continue; } - _collect_recordinfo(keys, key, 0, org_value, value, output, filed_data_converter); + _collect_recordinfo( + keys, + key, + -1, + org_value, + value, + output, + filed_data_converter, + ); } if !parent_key.is_empty() { keys.pop(); @@ -492,10 +497,10 @@ fn _collect_recordinfo<'a>( }; acc }); - if arr_index > 0 { + let key = if arr_index >= 0 { let (field_data_map, field_data_map_key) = filed_data_converter; let i = arr_index + 1; - let field = format!("{parent_key}[{i}]",).to_lowercase(); + let field = format!("{parent_key}[{i}]").to_lowercase(); if let Some(map) = field_data_map { let converted_str = convert_field_data( map, @@ -508,8 +513,11 @@ fn _collect_recordinfo<'a>( strval = converted_str.to_string(); } } - } - output.insert((parent_key.to_string(), strval)); + format!("{parent_key}[{i}]") + } else { + parent_key.to_string() + }; + output.insert((key, strval)); } } } @@ -763,7 +771,13 @@ pub fn remove_sp_char(record_value: CompactString) -> CompactString { mod tests { use std::path::Path; - use crate::detections::field_data_map::FieldDataMapKey; + use chrono::NaiveDate; + use compact_str::CompactString; + use hashbrown::{HashMap, HashSet}; + use nested::Nested; + use regex::Regex; + use serde_json::Value; + use crate::{ detections::{ configs::{ @@ -774,12 +788,7 @@ mod tests { }, options::htmlreport::HTML_REPORTER, }; - use chrono::NaiveDate; - use compact_str::CompactString; - use hashbrown::{HashMap, HashSet}; - use nested::Nested; - use regex::Regex; - use serde_json::Value; + use crate::detections::field_data_map::FieldDataMapKey; use super::{output_duration, output_profile_name}; @@ -833,7 +842,7 @@ mod tests { Ok(record) => { let ret = utils::create_recordinfos(&record, &FieldDataMapKey::default(), &None); // Systemは除外される/属性(_attributesも除外される)/key順に並ぶ - let expected = "Binary: hogehoge ¦ Data: ¦ Data: Data1 ¦ Data: DataData2 ¦ Data: DataDataData3" + let expected = "Binary: hogehoge ¦ Data[1]: Data1 ¦ Data[2]: DataData2 ¦ Data[3]: ¦ Data[4]: DataDataData3" .to_string(); assert_eq!(ret.join(" ¦ "), expected); }