Skip to content

Commit

Permalink
Merge pull request #59 from dfir-dd/58-feature-request-case-insensiti…
Browse files Browse the repository at this point in the history
…vity-for-evtxanalyze-sessions

evtxanalyze session feature also find case insensitive filenames
  • Loading branch information
Bitbee0 authored Jul 31, 2024
2 parents 3a0deff + 6d63fb8 commit 319b885
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 54 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pol_export = []
evtxscan = ["evtx"]
evtxcat = ["evtx", "colored_json", "term-table", "termsize"]
evtxls = ["evtx", "colored", "lazy-regex", "regex", "sigpipe", "dfirtk-eventdata"]
evtxanalyze = ["evtx", "dfirtk-sessionevent-derive", "dfirtk-eventdata", "exitcode"]
evtxanalyze = ["evtx", "dfirtk-sessionevent-derive", "dfirtk-eventdata", "exitcode", "walkdir"]
evtx2bodyfile = ["evtx", "getset", "ouroboros", "indicatif"]
ipgrep = []
ts2date = ["regex"]
Expand Down Expand Up @@ -162,6 +162,7 @@ lazy-regex = {version = "3.0.0", optional=true}
sigpipe = {version = "0", optional=true}
phf = {version = "0.11", optional=true}
exitcode = {version="1.1.2", optional=true}
walkdir = {version="2.5.0", optional=true}

# evtx2bodyfile
indicatif = {version="0.17", optional=true}
Expand Down
29 changes: 0 additions & 29 deletions src/bin/evtxanalyze/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{io::stdout, path::PathBuf};

use anyhow::bail;
use clap::{Parser, Subcommand, ValueEnum, ValueHint};
use dfir_toolkit::common::HasVerboseFlag;
use log::LevelFilter;
Expand Down Expand Up @@ -83,20 +82,6 @@ impl Cli {
evtx_files_dir,
session_id,
} => {
if !evtx_files_dir.exists() {
bail!(
"directory '{}' does not exist. Aborting now.",
evtx_files_dir.to_string_lossy()
)
}

if !evtx_files_dir.is_dir() {
bail!(
"'{}' is no directory. Aborting now.",
evtx_files_dir.to_string_lossy()
);
}

let sessions = SessionStore::import(evtx_files_dir, true)?;
match sessions.find_session(session_id) {
None => log::error!("no value found for session id {session_id}"),
Expand All @@ -120,20 +105,6 @@ impl Cli {
evtx_files_dir,
include_anonymous,
} => {
if !evtx_files_dir.exists() {
bail!(
"directory '{}' does not exist. Aborting now.",
evtx_files_dir.to_string_lossy()
)
}

if !evtx_files_dir.is_dir() {
bail!(
"'{}' is no directory. Aborting now.",
evtx_files_dir.to_string_lossy()
);
}

let sessions = SessionStore::import(evtx_files_dir, *include_anonymous)?;

let mut csv_writer = csv::Writer::from_writer(stdout());
Expand Down
85 changes: 61 additions & 24 deletions src/bin/evtxanalyze/sessions/session_store.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use std::{collections::HashMap, path::Path};

use anyhow::bail;
use dfirtk_eventdata::SessionId;
use evtx::EvtxParser;
use walkdir::WalkDir;

use super::{Session, SessionEvent};

static KNOWN_FILES: & [&str] = &[
static KNOWN_FILES: &[&str] = &[
"Security.evtx",
"Microsoft-Windows-TerminalServices-RDPClient%4Operational.evtx",
"Microsoft-Windows-TerminalServices-RemoteConnectionManager%4Operational.evtx",
"Microsoft-Windows-TerminalServices-LocalSessionManager%4Operational.evtx"
"Microsoft-Windows-TerminalServices-LocalSessionManager%4Operational.evtx",
];

pub struct SessionStore {
Expand All @@ -18,21 +20,59 @@ pub struct SessionStore {

impl SessionStore {
pub fn import(evtx_files_dir: &Path, include_anonymous: bool) -> Result<Self, anyhow::Error> {
if !evtx_files_dir.exists() {
bail!(
"directory '{}' does not exist. Aborting now.",
evtx_files_dir.to_string_lossy()
)
}

if !evtx_files_dir.is_dir() {
bail!(
"'{}' is no directory. Aborting now.",
evtx_files_dir.to_string_lossy()
);
}

let mut sessions = Self {
sessions: HashMap::<SessionId, Session>::new(),
};


for filename in KNOWN_FILES {
let path = evtx_files_dir.join(filename);

if ! path.exists() {
log::error!("expected file '{}', but it does not exist. Omitting it...", path.display());
continue;
let mut path = evtx_files_dir.join(filename);

// maybe we have troubles with case sensitivity
// Let's try this:
if !path.exists() {
let mut files = WalkDir::new(evtx_files_dir)
.max_depth(1)
.into_iter()
.filter_map(Result::ok)
.filter(|f| f.file_name().to_string_lossy().to_lowercase() == filename.to_lowercase());

if let Some(first_entry) = files.next() {
path = first_entry.into_path();

// there should be no more entry, otherwise
// the filename is unambigious
if let Some(next_entry) = files.next() {
log::error!(
"expected file '{filename}', but there exist \
multiple variants of this name. I found at least \
'{}' and '{}'. Omitting those files...",
path.file_name().unwrap().to_string_lossy(),
next_entry.file_name().to_string_lossy()
);
continue;
}
}
}

if ! path.is_file() {
log::error!("tried to read '{}', but it is not a file. Omiting it...", path.display());
if !path.is_file() {
log::error!(
"tried to read '{}', but it is not a file. Omiting it...",
path.display()
);
continue;
}

Expand Down Expand Up @@ -76,19 +116,16 @@ impl SessionStore {
}

pub fn find_session(&self, index: &str) -> Option<&Session> {
self.sessions.iter().find(|(k, _)| {
match k {
SessionId::ActivityId(id)|
SessionId::SessionName(id)|
SessionId::LogonId(id) |
SessionId::SessionId(id) => {
index == id
}
SessionId::None(id) => {
index == id.to_string()
},
}
}).map(|(_, v)| v)
self.sessions
.iter()
.find(|(k, _)| match k {
SessionId::ActivityId(id)
| SessionId::SessionName(id)
| SessionId::LogonId(id)
| SessionId::SessionId(id) => index == id,
SessionId::None(id) => index == id.to_string(),
})
.map(|(_, v)| v)
}
}

Expand All @@ -102,4 +139,4 @@ impl IntoIterator for SessionStore {
v.sort();
v.into_iter()
}
}
}

0 comments on commit 319b885

Please sign in to comment.