Skip to content

Commit

Permalink
feat: added recoveredrecord column processing #1160
Browse files Browse the repository at this point in the history
  • Loading branch information
hitenkoku committed Aug 21, 2023
1 parent 600c010 commit b28edc2
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 21 deletions.
19 changes: 16 additions & 3 deletions src/detections/detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use crate::detections::utils::{
};
use crate::options::profile::Profile::{
self, AllFieldInfo, Channel, Computer, EventID, EvtxFile, Level, MitreTactics, MitreTags,
OtherTags, Provider, RecordID, RenderedMessage, RuleAuthor, RuleCreationDate, RuleFile, RuleID,
RuleModifiedDate, RuleTitle, SrcASN, SrcCity, SrcCountry, Status, TgtASN, TgtCity, TgtCountry,
Timestamp,
OtherTags, Provider, RecordID, RecoveredRecord, RenderedMessage, RuleAuthor, RuleCreationDate,
RuleFile, RuleID, RuleModifiedDate, RuleTitle, SrcASN, SrcCity, SrcCountry, Status, TgtASN,
TgtCity, TgtCountry, Timestamp,
};
use chrono::{TimeZone, Utc};
use compact_str::CompactString;
Expand Down Expand Up @@ -47,6 +47,7 @@ pub struct EvtxRecordInfo {
pub record: Value, // 1レコード分のデータをJSON形式にシリアライズしたもの
pub data_string: String, //1レコード内のデータを文字列にしたもの
pub key_2_value: HashMap<String, String>, // 階層化されたキーを.でつないだデータとその値のマップ
pub recovered_record: bool, // レコードが復元されたかどうか
}

impl EvtxRecordInfo {
Expand Down Expand Up @@ -260,6 +261,11 @@ impl Detection {
let eid =
get_serde_number_to_string(&record_info.record["Event"]["System"]["EventID"], false)
.unwrap_or_else(|| "-".into());
let recovered_record = if record_info.recovered_record {
"y"
} else {
""
};

let default_time = Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap();
let time = message::get_event_time(&record_info.record, stored_static.json_input_flag)
Expand Down Expand Up @@ -478,6 +484,10 @@ impl Detection {
),
);
}
RecoveredRecord(_) => {
profile_converter
.insert(key.as_str(), RecoveredRecord(recovered_record.into()));
}
RenderedMessage(_) => {
let convert_value = if let Some(message) =
record_info.record["Event"]["RenderingInfo"]["Message"].as_str()
Expand Down Expand Up @@ -860,6 +870,9 @@ impl Detection {
Provider(_) => {
profile_converter.insert(key.as_str(), Provider("-".into()));
}
RecoveredRecord(_) => {
profile_converter.insert(key.as_str(), RenderedMessage("".into()));
}
RenderedMessage(_) => {
profile_converter.insert(key.as_str(), RenderedMessage("-".into()));
}
Expand Down
8 changes: 7 additions & 1 deletion src/detections/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,12 @@ pub fn create_tokio_runtime(thread_number: Option<usize>) -> Runtime {
}

// EvtxRecordInfoを作成します。
pub fn create_rec_info(data: Value, path: String, keys: &Nested<String>) -> EvtxRecordInfo {
pub fn create_rec_info(
data: Value,
path: String,
keys: &Nested<String>,
recovered_record: &bool,
) -> EvtxRecordInfo {
// 高速化のための処理

// 例えば、Value型から"Event.System.EventID"の値を取得しようとすると、value["Event"]["System"]["EventID"]のように3回アクセスする必要がある。
Expand Down Expand Up @@ -331,6 +336,7 @@ pub fn create_rec_info(data: Value, path: String, keys: &Nested<String>) -> Evtx
record: data,
data_string: data_str,
key_2_value: key_2_values,
recovered_record: *recovered_record,
}
}

Expand Down
33 changes: 20 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ impl App {
self.rule_keys = self.get_all_keys(&rule_files);
let mut detection = detection::Detection::new(rule_files);
let mut total_records: usize = 0;
let mut recover_recordss: usize = 0;
let mut recover_records: usize = 0;
let mut tl = Timeline::new();

*STORED_EKEY_ALIAS.write().unwrap() = Some(stored_static.eventkey_alias.clone());
Expand Down Expand Up @@ -1084,7 +1084,7 @@ impl App {
)
};
total_records += cnt_tmp;
recover_recordss += recover_cnt_tmp;
recover_records += recover_cnt_tmp;
pb.inc(1);
}
pb.finish_with_message(
Expand Down Expand Up @@ -1118,7 +1118,7 @@ impl App {
stored_static.common_options.no_color,
stored_static,
tl,
recover_recordss,
recover_records,
);
}
CHECKPOINT
Expand All @@ -1143,7 +1143,7 @@ impl App {
let mut record_cnt = 0;
let mut recover_records_cnt = 0;
if parser.is_none() {
return (detection, record_cnt, tl, recover_records_cnt);
return (detection, record_cnt, tl, 0);
}

let mut parser = parser.unwrap();
Expand All @@ -1166,7 +1166,7 @@ impl App {
&& record_result.as_ref().unwrap().allocation == RecordAllocation::EmptyPage
{
recover_records_cnt += 1;
};
}

if record_result.is_err() {
let evtx_filepath = &path;
Expand Down Expand Up @@ -1238,7 +1238,9 @@ impl App {
}
}

records_per_detect.push(data.to_owned());
let recover_record_flag = record_result.is_ok()
&& record_result.as_ref().unwrap().allocation == RecordAllocation::EmptyPage;
records_per_detect.push((data.to_owned(), recover_record_flag));
}
if records_per_detect.is_empty() {
break;
Expand Down Expand Up @@ -1409,7 +1411,7 @@ impl App {
continue;
}

records_per_detect.push(data.to_owned());
records_per_detect.push((data.to_owned(), false));
}
if records_per_detect.is_empty() {
break;
Expand Down Expand Up @@ -1438,22 +1440,27 @@ impl App {
}

async fn create_rec_infos(
records_per_detect: Vec<Value>,
records_per_detect: Vec<(Value, bool)>,
path: &dyn Display,
rule_keys: Nested<String>,
) -> Vec<EvtxRecordInfo> {
let path = Arc::new(path.to_string());
let rule_keys = Arc::new(rule_keys);
let threads: Vec<JoinHandle<EvtxRecordInfo>> = {
let this = records_per_detect
.into_iter()
.map(|rec| -> JoinHandle<EvtxRecordInfo> {
let this = records_per_detect.into_iter().map(
|(rec, recovered_record_flag)| -> JoinHandle<EvtxRecordInfo> {
let arc_rule_keys = Arc::clone(&rule_keys);
let arc_path = Arc::clone(&path);
spawn(async move {
utils::create_rec_info(rec, arc_path.to_string(), &arc_rule_keys)
utils::create_rec_info(
rec,
arc_path.to_string(),
&arc_rule_keys,
&recovered_record_flag,
)
})
});
},
);
FromIterator::from_iter(this)
};

Expand Down
13 changes: 9 additions & 4 deletions src/options/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use crate::detections::message::AlertMessage;
use crate::detections::utils::check_setting_path;
use crate::options::profile::Profile::{
AllFieldInfo, Channel, Computer, Details, EventID, EvtxFile, ExtraFieldInfo, Level, Literal,
MitreTactics, MitreTags, OtherTags, Provider, RecordID, RenderedMessage, RuleAuthor,
RuleCreationDate, RuleFile, RuleID, RuleModifiedDate, RuleTitle, SrcASN, SrcCity, SrcCountry,
Status, TgtASN, TgtCity, TgtCountry, Timestamp,
MitreTactics, MitreTags, OtherTags, Provider, RecordID, RecoveredRecord, RenderedMessage,
RuleAuthor, RuleCreationDate, RuleFile, RuleID, RuleModifiedDate, RuleTitle, SrcASN, SrcCity,
SrcCountry, Status, TgtASN, TgtCity, TgtCountry, Timestamp,
};
use crate::yaml;
use compact_str::CompactString;
Expand Down Expand Up @@ -47,6 +47,7 @@ pub enum Profile {
TgtCountry(Cow<'static, str>),
TgtCity(Cow<'static, str>),
ExtraFieldInfo(Cow<'static, str>),
RecoveredRecord(Cow<'static, str>),
Literal(Cow<'static, str>), // profiles.yamlの固定文字列を変換なしでそのまま出力する場合
}

Expand All @@ -58,7 +59,9 @@ impl Profile {
| MitreTags(v) | OtherTags(v) | RuleAuthor(v) | RuleCreationDate(v)
| RuleModifiedDate(v) | Status(v) | RuleID(v) | Provider(v) | Details(v)
| RenderedMessage(v) | SrcASN(v) | SrcCountry(v) | SrcCity(v) | TgtASN(v)
| TgtCountry(v) | TgtCity(v) | ExtraFieldInfo(v) | Literal(v) => v.to_string(),
| TgtCountry(v) | TgtCity(v) | RecoveredRecord(v) | ExtraFieldInfo(v) | Literal(v) => {
v.to_string()
}
}
}

Expand Down Expand Up @@ -90,6 +93,7 @@ impl Profile {
TgtCountry(_) => TgtCountry(converted_string.to_owned().into()),
TgtCity(_) => TgtCity(converted_string.to_owned().into()),
ExtraFieldInfo(_) => ExtraFieldInfo(converted_string.to_owned().into()),
RecoveredRecord(_) => RecoveredRecord(converted_string.to_owned().into()),
Details(_) => Details(converted_string.to_owned().into()),
AllFieldInfo(_) => AllFieldInfo(converted_string.to_owned().into()),
p => p.to_owned(),
Expand Down Expand Up @@ -122,6 +126,7 @@ impl From<&str> for Profile {
"%Details%" => Details(Default::default()),
"%RenderedMessage%" => RenderedMessage(Default::default()),
"%ExtraFieldInfo%" => ExtraFieldInfo(Default::default()),
"%RecoveredRecord%" => RecoveredRecord(Default::default()),
s => Literal(s.to_string().into()), // profiles.yamlの固定文字列を変換なしでそのまま出力する場合
}
}
Expand Down

0 comments on commit b28edc2

Please sign in to comment.