remove unneccesary pub

This commit is contained in:
Your Name
2020-10-05 08:55:03 +09:00
parent ca56063f12
commit 1057a72efc
3 changed files with 441 additions and 442 deletions

View File

@@ -38,7 +38,12 @@ impl Detection {
&common.detection(&event.system, &event_data); &common.detection(&event.system, &event_data);
//&common.detection(&event.system, &event_data); //&common.detection(&event.system, &event_data);
if channel == "Security" { if channel == "Security" {
&security.detection(event_id, &event.system, &event.user_data, event_data); &security.detection(
event_id,
&event.system,
&event.user_data.as_ref(),
event_data,
);
} else if channel == "System" { } else if channel == "System" {
&system.detection(event_id, &event.system, event_data); &system.detection(event_id, &event.system, event_data);
} else if channel == "Application" { } else if channel == "Application" {

View File

@@ -1,308 +1,302 @@
use crate::models::event; use crate::models::event;
use std::collections::HashMap; use std::collections::HashMap;
// eventlogが用意できていない // eventlogが用意できていない
// 4674 // 4674
// 4756 // 4756
#[derive(Debug)] #[derive(Debug)]
pub struct Security { pub struct Security {
max_total_sensitive_privuse: i32, max_total_sensitive_privuse: i32,
max_passspray_login: i32, max_passspray_login: i32,
max_passspray_uniquser: i32, max_passspray_uniquser: i32,
max_failed_logons: i32, max_failed_logons: i32,
alert_all_admin: i32, alert_all_admin: i32,
total_admin_logons: i32, total_admin_logons: i32,
total_failed_logons: i32, total_failed_logons: i32,
total_failed_account: i32, total_failed_account: i32,
total_sensitive_privuse: i32, total_sensitive_privuse: i32,
admin_logons: HashMap<String, HashMap<String, i32>>, admin_logons: HashMap<String, HashMap<String, i32>>,
multiple_admin_logons: HashMap<String, i32>, multiple_admin_logons: HashMap<String, i32>,
account_2_failedcnt: HashMap<String, i32>, account_2_failedcnt: HashMap<String, i32>,
passspray_2_user: HashMap<String, i32>, passspray_2_user: HashMap<String, i32>,
empty_str: String, empty_str: String,
} }
impl Security { impl Security {
pub fn new() -> Security { pub fn new() -> Security {
Security { Security {
max_total_sensitive_privuse: 4, max_total_sensitive_privuse: 4,
max_passspray_login: 6, max_passspray_login: 6,
max_passspray_uniquser: 6, max_passspray_uniquser: 6,
max_failed_logons: 5, max_failed_logons: 5,
alert_all_admin: 0, alert_all_admin: 0,
total_admin_logons: 0, total_admin_logons: 0,
total_failed_logons: 0, total_failed_logons: 0,
total_failed_account: 0, total_failed_account: 0,
total_sensitive_privuse: 0, total_sensitive_privuse: 0,
admin_logons: HashMap::new(), admin_logons: HashMap::new(),
multiple_admin_logons: HashMap::new(), multiple_admin_logons: HashMap::new(),
account_2_failedcnt: HashMap::new(), account_2_failedcnt: HashMap::new(),
passspray_2_user: HashMap::new(), passspray_2_user: HashMap::new(),
empty_str: String::default(), empty_str: String::default(),
} }
} }
pub fn disp(&self) { pub fn disp(&self) {
if self.total_admin_logons > 0 { if self.total_admin_logons > 0 {
println!("total_admin_logons:{}", self.total_admin_logons); println!("total_admin_logons:{}", self.total_admin_logons);
println!("admin_logons:{:?}", self.admin_logons); println!("admin_logons:{:?}", self.admin_logons);
println!("multiple_admin_logons:{:?}\n", self.multiple_admin_logons); println!("multiple_admin_logons:{:?}\n", self.multiple_admin_logons);
} }
let exceed_failed_logons = self.total_failed_logons > self.max_failed_logons; let exceed_failed_logons = self.total_failed_logons > self.max_failed_logons;
let exist_failed_account = self.account_2_failedcnt.keys().count() as i32 > 1; let exist_failed_account = self.account_2_failedcnt.keys().count() as i32 > 1;
if exceed_failed_logons && exist_failed_account { if exceed_failed_logons && exist_failed_account {
println!("High number of total logon failures for multiple accounts"); println!("High number of total logon failures for multiple accounts");
println!( println!(
"Total accounts: {}", "Total accounts: {}",
self.account_2_failedcnt.keys().count() self.account_2_failedcnt.keys().count()
); );
println!("Total logon failures: {}\n", self.total_failed_logons); println!("Total logon failures: {}\n", self.total_failed_logons);
} }
} }
pub fn detection( pub fn detection(
&mut self, &mut self,
event_id: String, event_id: String,
_system: &event::System, _system: &event::System,
user_data: &Option<event::UserData>, user_data: &Option<&event::UserData>,
event_data: HashMap<String, String>, event_data: HashMap<String, String>,
) { ) {
self.process_craeted(&event_id, &event_data); self.process_craeted(&event_id, &event_data);
self.se_debug_privilege(&event_id, &event_data); self.se_debug_privilege(&event_id, &event_data);
self.account_created(&event_id, &event_data); self.account_created(&event_id, &event_data);
self.add_member_security_group(&event_id, &event_data); self.add_member_security_group(&event_id, &event_data);
self.failed_logon(&event_id, &event_data); self.failed_logon(&event_id, &event_data);
self.sensitive_priviledge(&event_id, &event_data); self.sensitive_priviledge(&event_id, &event_data);
self.attempt_priviledge(&event_id, &event_data); self.attempt_priviledge(&event_id, &event_data);
self.pass_spray(&event_id, &event_data); self.pass_spray(&event_id, &event_data);
self.audit_log_cleared(&event_id, &user_data); self.audit_log_cleared(&event_id, &user_data);
} }
fn process_craeted(&mut self, event_id: &String, _event_data: &HashMap<String, String>) { fn process_craeted(&mut self, event_id: &String, _event_data: &HashMap<String, String>) {
if event_id != "4688" { if event_id != "4688" {
return; return;
} }
// TODO Check-Commnad // TODO Check-Commnad
return; return;
} }
// //
// Special privileges assigned to new logon (possible admin access) // Special privileges assigned to new logon (possible admin access)
// //
fn se_debug_privilege(&mut self, event_id: &String, event_data: &HashMap<String, String>) { fn se_debug_privilege(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
if event_id != "4672" { if event_id != "4672" {
return; return;
} }
if let Some(privileage_list) = event_data.get("PrivilegeList") { if let Some(privileage_list) = event_data.get("PrivilegeList") {
if let Some(_data) = privileage_list.find("SeDebugPrivilege") { if let Some(_data) = privileage_list.find("SeDebugPrivilege") {
// alert_all_adminが有効であれば、標準出力して知らせる // alert_all_adminが有効であれば、標準出力して知らせる
// DeepBlueCLIでは必ず0になっていて、基本的には表示されない。 // DeepBlueCLIでは必ず0になっていて、基本的には表示されない。
if self.alert_all_admin == 1 { if self.alert_all_admin == 1 {
println!("Logon with SeDebugPrivilege (admin access)"); println!("Logon with SeDebugPrivilege (admin access)");
println!("Username:{}", event_data["SubjectUserName"]); println!("Username:{}", event_data["SubjectUserName"]);
println!("Domain:{}", event_data["SubjectDomainName"]); println!("Domain:{}", event_data["SubjectDomainName"]);
println!("User SID:{}", event_data["SubjectUserSid"]); println!("User SID:{}", event_data["SubjectUserSid"]);
println!("Domain:{}", event_data["PrivilegeList"]); println!("Domain:{}", event_data["PrivilegeList"]);
} }
self.total_admin_logons += 1; self.total_admin_logons += 1;
// admin_logons配列にusernameが含まれているか確認 // admin_logons配列にusernameが含まれているか確認
match self.admin_logons.get(&event_data["SubjectUserName"]) { match self.admin_logons.get(&event_data["SubjectUserName"]) {
Some(sid) => { Some(sid) => {
// 含まれていれば、マルチユーザが管理者としてログインしているか確認 // 含まれていれば、マルチユーザが管理者としてログインしているか確認
// マルチログオンのデータをセット // マルチログオンのデータをセット
if event_data["SubjectUserName"] != event_data["SubjectUserSid"] { if event_data["SubjectUserName"] != event_data["SubjectUserSid"] {
// One username with multiple admin logon SIDs // One username with multiple admin logon SIDs
self.multiple_admin_logons self.multiple_admin_logons
.insert(event_data["SubjectUserName"].to_string(), 1); .insert(event_data["SubjectUserName"].to_string(), 1);
let mut count_hash: HashMap<String, i32> = HashMap::new(); let mut count_hash: HashMap<String, i32> = HashMap::new();
count_hash.insert( count_hash.insert(
event_data["SubjectUserSid"].to_string(), event_data["SubjectUserSid"].to_string(),
sid[&event_data["SubjectUserSid"]] + 1, sid[&event_data["SubjectUserSid"]] + 1,
); );
self.admin_logons self.admin_logons
.insert(event_data["SubjectUserName"].to_string(), count_hash); .insert(event_data["SubjectUserName"].to_string(), count_hash);
} }
} }
None => { None => {
// admin_logons配列にセットUserNameとSIDとカウンタをセット // admin_logons配列にセットUserNameとSIDとカウンタをセット
let mut count_hash: HashMap<String, i32> = HashMap::new(); let mut count_hash: HashMap<String, i32> = HashMap::new();
count_hash.insert(event_data["SubjectUserSid"].to_string(), 1); count_hash.insert(event_data["SubjectUserSid"].to_string(), 1);
self.admin_logons self.admin_logons
.insert(event_data["SubjectUserName"].to_string(), count_hash); .insert(event_data["SubjectUserName"].to_string(), count_hash);
} }
} }
} }
} }
} }
// account craeted:OK // account craeted:OK
fn account_created(&mut self, event_id: &String, event_data: &HashMap<String, String>) { fn account_created(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
if event_id != "4720" { if event_id != "4720" {
return; return;
} }
println!("New User Created"); println!("New User Created");
println!( println!(
"Username: {}", "Username: {}",
event_data.get("TargetUserName").unwrap_or(&"".to_string()) event_data.get("TargetUserName").unwrap_or(&"".to_string())
); );
println!( println!(
"User SID:: {}\n", "User SID:: {}\n",
event_data.get("TargetSid").unwrap_or(&"".to_string()) event_data.get("TargetSid").unwrap_or(&"".to_string())
); );
} }
// add member to security group // add member to security group
fn add_member_security_group( fn add_member_security_group(
&mut self, &mut self,
event_id: &String, event_id: &String,
event_data: &HashMap<String, String>, event_data: &HashMap<String, String>,
) { ) {
// check if group is Administrator, may later expand to all groups // check if group is Administrator, may later expand to all groups
if event_data.get("TargetUserName").unwrap_or(&self.empty_str) != "Administrators" { if event_data.get("TargetUserName").unwrap_or(&self.empty_str) != "Administrators" {
return; return;
} }
// A member was added to a security-enabled (global|local|universal) group. // A member was added to a security-enabled (global|local|universal) group.
if event_id == "4728" { if event_id == "4728" {
println!("User added to global Administrators group"); println!("User added to global Administrators group");
} else if event_id == "4732" { } else if event_id == "4732" {
println!("User added to local Administrators group"); println!("User added to local Administrators group");
} else if event_id == "4756" { } else if event_id == "4756" {
println!("User added to universal Administrators group"); println!("User added to universal Administrators group");
} else { } else {
return; return;
} }
println!( println!(
"Username: {}", "Username: {}",
event_data.get("TargetUserName").unwrap_or(&"".to_string()) event_data.get("TargetUserName").unwrap_or(&"".to_string())
); );
println!( println!(
"User SID:: {}\n", "User SID:: {}\n",
event_data.get("TargetSid").unwrap_or(&"".to_string()) event_data.get("TargetSid").unwrap_or(&"".to_string())
); );
} }
// An account failed to log on.:OK // An account failed to log on.:OK
// Requires auditing logon failures // Requires auditing logon failures
// https://technet.microsoft.com/en-us/library/cc976395.aspx // https://technet.microsoft.com/en-us/library/cc976395.aspx
fn failed_logon(&mut self, event_id: &String, event_data: &HashMap<String, String>) { fn failed_logon(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
if event_id != "4625" { if event_id != "4625" {
return; return;
} }
// see fn disp() // see fn disp()
self.total_failed_logons += 1; self.total_failed_logons += 1;
let username = event_data.get("TargetUserName").unwrap_or(&self.empty_str); let username = event_data.get("TargetUserName").unwrap_or(&self.empty_str);
let failed_cnt = self.account_2_failedcnt.get(username).unwrap_or(&0) + &1; let failed_cnt = self.account_2_failedcnt.get(username).unwrap_or(&0) + &1;
self.account_2_failedcnt self.account_2_failedcnt
.insert(username.to_string(), failed_cnt); .insert(username.to_string(), failed_cnt);
} }
// Sensitive Privilege Use (Mimikatz) // Sensitive Privilege Use (Mimikatz)
fn sensitive_priviledge(&mut self, event_id: &String, event_data: &HashMap<String, String>) { fn sensitive_priviledge(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
if event_id != "4673" { if event_id != "4673" {
return; return;
} }
self.total_sensitive_privuse += 1; self.total_sensitive_privuse += 1;
// use == operator here to avoid multiple log notices // use == operator here to avoid multiple log notices
if self.max_total_sensitive_privuse == self.total_sensitive_privuse { if self.max_total_sensitive_privuse == self.total_sensitive_privuse {
println!("Sensititive Privilege Use Exceeds Threshold"); println!("Sensititive Privilege Use Exceeds Threshold");
println!( println!(
"Username: {}", "Username: {}",
event_data.get("SubjectUserName").unwrap_or(&self.empty_str) event_data.get("SubjectUserName").unwrap_or(&self.empty_str)
); );
println!( println!(
"Domain Name: {}", "Domain Name: {}",
event_data event_data
.get("SubjectDomainName") .get("SubjectDomainName")
.unwrap_or(&self.empty_str) .unwrap_or(&self.empty_str)
); );
} }
} }
fn attempt_priviledge(&mut self, _event_id: &String, _event_data: &HashMap<String, String>) { fn attempt_priviledge(&mut self, _event_id: &String, _event_data: &HashMap<String, String>) {
// event log cannot get... // event log cannot get...
} }
// A logon was attempted using explicit credentials. // A logon was attempted using explicit credentials.
fn pass_spray(&mut self, event_id: &String, event_data: &HashMap<String, String>) { fn pass_spray(&mut self, event_id: &String, event_data: &HashMap<String, String>) {
if event_id != "4648" { if event_id != "4648" {
return; return;
} }
let targetusername = event_data.get("TargetUserName").unwrap_or(&self.empty_str); let targetusername = event_data.get("TargetUserName").unwrap_or(&self.empty_str);
let spray_cnt = self.passspray_2_user.get(targetusername).unwrap_or(&0) + 1; let spray_cnt = self.passspray_2_user.get(targetusername).unwrap_or(&0) + 1;
self.passspray_2_user self.passspray_2_user
.insert(targetusername.to_string(), spray_cnt); .insert(targetusername.to_string(), spray_cnt);
// check targetuser's attempt count. // check targetuser's attempt count.
if self.passspray_2_user.get(targetusername).unwrap_or(&0) <= &self.max_passspray_login { if self.passspray_2_user.get(targetusername).unwrap_or(&0) <= &self.max_passspray_login {
return; return;
} }
// check exceeded targetuser count. // check exceeded targetuser count.
let spray_uniq_user = self let spray_uniq_user = self
.passspray_2_user .passspray_2_user
.values() .values()
.filter(|value| value > &&self.max_passspray_login) .filter(|value| value > &&self.max_passspray_login)
.count() as i32; .count() as i32;
if spray_uniq_user <= self.max_passspray_uniquser { if spray_uniq_user <= self.max_passspray_uniquser {
return; return;
} }
let usernames: String = self.passspray_2_user.keys().fold( let usernames: String = self.passspray_2_user.keys().fold(
self.empty_str.to_string(), self.empty_str.to_string(),
|mut acc: String, cur| -> String { |mut acc: String, cur| -> String {
acc.push_str(cur); acc.push_str(cur);
acc.push_str(" "); acc.push_str(" ");
return acc; return acc;
}, },
); );
println!("Distributed Account Explicit Credential Use (Password Spray Attack)"); println!("Distributed Account Explicit Credential Use (Password Spray Attack)");
println!("The use of multiple user account access attempts with explicit credentials is "); println!("The use of multiple user account access attempts with explicit credentials is ");
println!("an indicator of a password spray attack."); println!("an indicator of a password spray attack.");
println!("Target Usernames: {}", usernames.trim()); println!("Target Usernames: {}", usernames.trim());
println!( println!(
"Accessing Username: {}", "Accessing Username: {}",
event_data.get("SubjectUserName").unwrap_or(&self.empty_str) event_data.get("SubjectUserName").unwrap_or(&self.empty_str)
); );
println!( println!(
"Accessing Host Name: {}\n\n", "Accessing Host Name: {}\n\n",
event_data event_data
.get("SubjectDomainName") .get("SubjectDomainName")
.unwrap_or(&self.empty_str) .unwrap_or(&self.empty_str)
); );
// reset // reset
self.passspray_2_user = HashMap::new(); self.passspray_2_user = HashMap::new();
} }
fn audit_log_cleared( fn audit_log_cleared(&mut self, event_id: &String, user_data: &Option<&event::UserData>) {
&mut self, if event_id != "1102" {
event_id: &String, return;
user_data: &Option<event::UserData> }
) {
if event_id != "1102" { println!("Audit Log Clear");
return; println!("The Audit log was cleared.");
} user_data.and_then(|u| u.log_file_cleared.as_ref());
println!("Audit Log Clear"); let username = user_data.and_then(|u| u.log_file_cleared.and_then(|l| l.subject_user_name));
println!("The Audit log was cleared."); println!("Security ID: {}", username.unwrap_or("".to_string()));
let username = user_data.as_ref().and_then(|u| { }
u.log_file_cleared }
.as_ref()
.and_then(|l| l.subject_user_name.as_ref())
});
println!("Security ID: {}", username.unwrap_or(&"".to_string()));
}
}

View File

@@ -1,133 +1,133 @@
extern crate serde; extern crate serde;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct Data { pub struct Data {
#[serde(rename = "Name")] #[serde(rename = "Name")]
pub name: Option<String>, pub name: Option<String>,
#[serde(rename = "$value")] #[serde(rename = "$value")]
pub text: Option<String>, pub text: Option<String>,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct TimeCreated { pub struct TimeCreated {
#[serde(rename = "SystemTime")] #[serde(rename = "SystemTime")]
pub system_time: String, pub system_time: String,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
struct Execution { struct Execution {
#[serde(rename = "ProcessID")] #[serde(rename = "ProcessID")]
process_id: i32, process_id: i32,
#[serde(rename = "ThreadID")] #[serde(rename = "ThreadID")]
thread_id: i32, thread_id: i32,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct Provider { pub struct Provider {
#[serde(rename = "Name")] #[serde(rename = "Name")]
pub name: Option<String>, pub name: Option<String>,
#[serde(rename = "Guid")] #[serde(rename = "Guid")]
guid: Option<String>, guid: Option<String>,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct System { pub struct System {
#[serde(rename = "Provider")] #[serde(rename = "Provider")]
pub provider: Provider, pub provider: Provider,
#[serde(rename = "EventID")] #[serde(rename = "EventID")]
pub event_id: String, pub event_id: String,
#[serde(rename = "Version")] #[serde(rename = "Version")]
pub version: Option<String>, version: Option<String>,
#[serde(rename = "Level")] #[serde(rename = "Level")]
level: String, level: String,
#[serde(rename = "Task")] #[serde(rename = "Task")]
task: String, task: String,
#[serde(rename = "Opcode")] #[serde(rename = "Opcode")]
opcode: Option<String>, opcode: Option<String>,
#[serde(rename = "Keywords")] #[serde(rename = "Keywords")]
keywords: String, keywords: String,
#[serde(rename = "TimeCreated")] #[serde(rename = "TimeCreated")]
pub time_created: TimeCreated, pub time_created: TimeCreated,
#[serde(rename = "EventRecordID")] #[serde(rename = "EventRecordID")]
pub event_record_id: String, pub event_record_id: String,
#[serde(rename = "Correlation")] #[serde(rename = "Correlation")]
correlation: Option<String>, correlation: Option<String>,
#[serde(rename = "Execution")] #[serde(rename = "Execution")]
execution: Option<Execution>, execution: Option<Execution>,
#[serde(rename = "Channel")] #[serde(rename = "Channel")]
pub channel: String, // Security, System, Application ...etc pub channel: String, // Security, System, Application ...etc
#[serde(rename = "Computer")] #[serde(rename = "Computer")]
computer: String, computer: String,
#[serde(rename = "Security")] #[serde(rename = "Security")]
security: String, security: String,
#[serde(rename = "Message")] #[serde(rename = "Message")]
pub message: Option<String>, pub message: Option<String>,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct EventData { pub struct EventData {
#[serde(rename = "Data")] #[serde(rename = "Data")]
pub data: Option<Vec<Data>>, pub data: Option<Vec<Data>>,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct UserData { pub struct UserData {
#[serde(rename = "LogFileCleared")] #[serde(rename = "LogFileCleared")]
pub log_file_cleared: Option<LogFileCleared>, pub log_file_cleared: Option<LogFileCleared>,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct LogFileCleared { pub struct LogFileCleared {
#[serde(rename = "SubjectUserSid")] #[serde(rename = "SubjectUserSid")]
pub subject_user_sid: Option<String>, pub subject_user_sid: Option<String>,
#[serde(rename = "SubjectUserName")] #[serde(rename = "SubjectUserName")]
pub subject_user_name: Option<String>, pub subject_user_name: Option<String>,
#[serde(rename = "SubjectDomainName")] #[serde(rename = "SubjectDomainName")]
pub subject_domain_name: Option<String>, pub subject_domain_name: Option<String>,
#[serde(rename = "SubjectLogonId")] #[serde(rename = "SubjectLogonId")]
pub subject_logon_id: Option<String>, pub subject_logon_id: Option<String>,
} }
#[derive(Debug, Deserialize, PartialEq)] #[derive(Debug, Deserialize, PartialEq)]
pub struct Evtx { pub struct Evtx {
#[serde(rename = "System")] #[serde(rename = "System")]
pub system: System, pub system: System,
#[serde(rename = "EventData")] #[serde(rename = "EventData")]
pub event_data: Option<EventData>, pub event_data: Option<EventData>,
#[serde(rename = "UserData")] #[serde(rename = "UserData")]
pub user_data: Option<UserData>, pub user_data: Option<UserData>,
} }
impl Evtx { impl Evtx {
// //
// 文字列データを取得する // 文字列データを取得する
// //
fn get_string(v: &Data) -> String { fn get_string(v: &Data) -> String {
let mut ret = "".to_string(); let mut ret = "".to_string();
if let Some(text) = &v.text { if let Some(text) = &v.text {
ret = text.to_string(); ret = text.to_string();
} }
return ret; return ret;
} }
// //
// EventDataをHashMapとして取得する // EventDataをHashMapとして取得する
// //
pub fn parse_event_data(&self) -> HashMap<String, String> { pub fn parse_event_data(&self) -> HashMap<String, String> {
let mut values = HashMap::new(); let mut values = HashMap::new();
if let Some(event_data) = &self.event_data { if let Some(event_data) = &self.event_data {
if let Some(data) = &event_data.data { if let Some(data) = &event_data.data {
for v in data.iter() { for v in data.iter() {
if let Some(name) = &v.name { if let Some(name) = &v.name {
values.insert(name.to_string(), Evtx::get_string(v)); values.insert(name.to_string(), Evtx::get_string(v));
} }
} }
} }
} }
values values
} }
} }