Skip to content

Commit

Permalink
Support ESE parsing without NTFS access (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
puffyCid committed Mar 11, 2024
1 parent b6bff3e commit 5f71e81
Show file tree
Hide file tree
Showing 38 changed files with 513 additions and 222 deletions.
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/applications/chromium/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum ChromiumHistoryError {
pub(crate) enum ChromiumHistoryError {
PathError,
SQLITEParseError,
BadSQL,
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/applications/chromium/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub(crate) mod downloads;
pub mod error;
mod error;
pub(crate) mod history;
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/applications/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum ApplicationError {
pub(crate) enum ApplicationError {
#[cfg(target_family = "unix")]
SafariHistory,
#[cfg(target_family = "unix")]
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/applications/firefox/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum FirefoxHistoryError {
pub(crate) enum FirefoxHistoryError {
PathError,
SqliteParse,
BadSQL,
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/applications/safari/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum SafariError {
pub(crate) enum SafariError {
SqliteParse,
BadSQL,
Plist,
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/os/macos/execpolicy/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum ExecPolicyError {
pub(crate) enum ExecPolicyError {
PathError,
SQLITEParseError,
BadSQL,
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/os/macos/macho/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use nom::bytes::complete::take;
use serde::Serialize;

#[derive(Debug, Serialize)]
pub struct MachoHeader {
pub(crate) struct MachoHeader {
signature: u32,
pub cpu_type: String,
pub cpu_subtype: String,
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/os/processes/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum ProcessError {
pub(crate) enum ProcessError {
Empty,
ParseProcFile,
}
Expand Down
15 changes: 0 additions & 15 deletions artemis-core/src/artifacts/os/systeminfo/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@ pub(crate) fn get_platform() -> String {
sysinfo::System::name().unwrap_or_else(|| String::from("Unknown system name"))
}

#[cfg(target_os = "windows")]
/// Get the OS version number
pub(crate) fn get_os_version() -> String {
sysinfo::System::os_version().unwrap_or_else(|| String::from("Unknown OS Version"))
}

#[cfg(target_os = "windows")]
/// Get the kernel version number
pub(crate) fn get_win_kernel_version() -> f64 {
Expand Down Expand Up @@ -130,15 +124,6 @@ mod tests {
assert!(system_info.cpu.len() > 1);
}

#[test]
#[cfg(target_os = "windows")]
fn test_get_os() {
use crate::artifacts::os::systeminfo::info::get_os_version;

let system_info = get_os_version();
assert_eq!(system_info.contains("Unknown"), false);
}

#[test]
#[cfg(target_os = "windows")]
fn test_get_kernel_version() {
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/os/unix/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum UnixArtifactError {
pub(crate) enum UnixArtifactError {
Zsh,
Bash,
Python,
Expand Down
5 changes: 4 additions & 1 deletion artemis-core/src/artifacts/os/windows/artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,10 @@ mod tests {
#[test]
#[ignore = "Takes a long time"]
fn test_usnjrnl() {
let options = UsnJrnlOptions { alt_drive: None };
let options = UsnJrnlOptions {
alt_drive: None,
alt_path: None,
};
let mut output = output_options("usn_temp", "json", "./tmp", false);

let status = usnjrnl(&options, &mut output, &false).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion artemis-core/src/artifacts/os/windows/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

#[derive(Debug)]
pub enum WinArtifactError {
pub(crate) enum WinArtifactError {
Prefetch,
EventLogs,
Ntfs,
Expand Down
28 changes: 14 additions & 14 deletions artemis-core/src/artifacts/os/windows/ese/catalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
page::PageFlags,
pages::{branch::BranchPage, leaf::PageLeaf, root::parse_root_page},
},
filesystem::ntfs::{reader::read_bytes, sector_reader::SectorReader},
filesystem::ntfs::reader::read_bytes,
utils::{
nom_helper::{
nom_signed_four_bytes, nom_signed_two_bytes, nom_unsigned_one_byte,
Expand All @@ -21,7 +21,7 @@ use crate::{
use log::{error, warn};
use nom::{bytes::complete::take, error::ErrorKind};
use ntfs::NtfsFile;
use std::{collections::HashMap, fs::File, io::BufReader};
use std::{collections::HashMap, io::BufReader};

#[derive(Debug)]
pub(crate) struct Catalog {
Expand Down Expand Up @@ -128,9 +128,9 @@ impl Catalog {
* Before any significant parsing of the ESE db can start, we must parse the Catalog
* Once parsed, we return an array of `Catalog` rows
*/
pub(crate) fn grab_catalog(
ntfs_file: &NtfsFile<'_>,
fs: &mut BufReader<SectorReader<File>>,
pub(crate) fn grab_catalog<T: std::io::Seek + std::io::Read>(
ntfs_file: Option<&NtfsFile<'_>>,
fs: &mut BufReader<T>,
page_size: u32,
) -> Result<Vec<Catalog>, EseError> {
// Some documention states Catalog is acutally page four (4), but the first page of the ESE is a shadow copy of the header
Expand Down Expand Up @@ -160,11 +160,11 @@ impl Catalog {
}

/// Parse the components of the Catalog
fn parse_catalog<'a>(
fn parse_catalog<'a, T: std::io::Seek + std::io::Read>(
catalog_data: &'a [u8],
page_size: u32,
ntfs_file: &NtfsFile<'_>,
fs: &mut BufReader<SectorReader<File>>,
ntfs_file: Option<&NtfsFile<'_>>,
fs: &mut BufReader<T>,
) -> nom::IResult<&'a [u8], Vec<Catalog>> {
let (page_data, catalog_page_data) = PageHeader::parse_header(catalog_data)?;

Expand Down Expand Up @@ -741,11 +741,11 @@ mod tests {
setup_ntfs_parser(&test_location.to_str().unwrap().chars().next().unwrap()).unwrap();

let reader = raw_reader(&binding, &ntfs_parser.ntfs, &mut ntfs_parser.fs).unwrap();
let header_bytes = read_bytes(&0, 668, &reader, &mut ntfs_parser.fs).unwrap();
let header_bytes = read_bytes(&0, 668, Some(&reader), &mut ntfs_parser.fs).unwrap();

let (_, header) = EseHeader::parse_header(&header_bytes).unwrap();
let results =
Catalog::grab_catalog(&reader, &mut ntfs_parser.fs, header.page_size).unwrap();
Catalog::grab_catalog(Some(&reader), &mut ntfs_parser.fs, header.page_size).unwrap();

assert_eq!(results[0].name, "MSysObjects");
assert_eq!(results[0].obj_id_table, 2);
Expand Down Expand Up @@ -925,11 +925,11 @@ mod tests {
&mut ntfs_parser.fs,
)
.unwrap();
let header_bytes = read_bytes(&0, 668, &reader, &mut ntfs_parser.fs).unwrap();
let header_bytes = read_bytes(&0, 668, Some(&reader), &mut ntfs_parser.fs).unwrap();

let (_, header) = EseHeader::parse_header(&header_bytes).unwrap();
let results =
Catalog::grab_catalog(&reader, &mut ntfs_parser.fs, header.page_size).unwrap();
Catalog::grab_catalog(Some(&reader), &mut ntfs_parser.fs, header.page_size).unwrap();
assert!(results.len() > 100);
}

Expand All @@ -943,13 +943,13 @@ mod tests {
&mut ntfs_parser.fs,
)
.unwrap();
let header_bytes = read_bytes(&0, 668, &reader, &mut ntfs_parser.fs).unwrap();
let header_bytes = read_bytes(&0, 668, Some(&reader), &mut ntfs_parser.fs).unwrap();
if header_bytes.is_empty() {
return;
}
let (_, header) = EseHeader::parse_header(&header_bytes).unwrap();
let results =
Catalog::grab_catalog(&reader, &mut ntfs_parser.fs, header.page_size).unwrap();
Catalog::grab_catalog(Some(&reader), &mut ntfs_parser.fs, header.page_size).unwrap();

assert!(results.len() > 10);
}
Expand Down
20 changes: 10 additions & 10 deletions artemis-core/src/artifacts/os/windows/ese/pages/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use crate::{
tables::{clear_column_data, parse_row, ColumnInfo},
tags::TagFlags,
},
filesystem::ntfs::{reader::read_bytes, sector_reader::SectorReader},
filesystem::ntfs::reader::read_bytes,
utils::nom_helper::{nom_unsigned_four_bytes, nom_unsigned_two_bytes, Endian},
};
use log::{error, warn};
use nom::{bytes::complete::take, error::ErrorKind};
use ntfs::NtfsFile;
use std::collections::HashMap;
use std::{fs::File, io::BufReader};
use std::io::BufReader;

#[derive(Debug)]
pub(crate) struct BranchPage {
Expand Down Expand Up @@ -56,11 +56,11 @@ impl BranchPage {
}

/// Parse child branch pages related to catalog. Only care about tags that have data definition type
pub(crate) fn parse_branch_child_catalog<'a>(
pub(crate) fn parse_branch_child_catalog<'a, T: std::io::Seek + std::io::Read>(
data: &'a [u8],
page_tracker: &mut HashMap<u32, bool>,
ntfs_file: &NtfsFile<'_>,
fs: &mut BufReader<SectorReader<File>>,
ntfs_file: Option<&NtfsFile<'_>>,
fs: &mut BufReader<T>,
) -> nom::IResult<&'a [u8], Vec<Catalog>> {
let (page_data, branch_page_data) = PageHeader::parse_header(data)?;

Expand Down Expand Up @@ -159,13 +159,13 @@ impl BranchPage {
}

/// Parse child branch pages related to tables. Only care about tags that have data definition type
pub(crate) fn parse_branch_child_table<'a>(
pub(crate) fn parse_branch_child_table<'a, T: std::io::Seek + std::io::Read>(
page_branch_data: &'a [u8],
column_info: &mut [ColumnInfo],
column_rows: &mut Vec<Vec<ColumnInfo>>,
page_tracker: &mut HashMap<u32, bool>,
ntfs_file: &NtfsFile<'_>,
fs: &mut BufReader<SectorReader<File>>,
ntfs_file: Option<&NtfsFile<'_>>,
fs: &mut BufReader<T>,
) -> nom::IResult<&'a [u8], u32> {
let (page_data, branch_page_data) = PageHeader::parse_header(page_branch_data)?;
// Empty pages are not part of table data
Expand Down Expand Up @@ -312,7 +312,7 @@ mod tests {
let (_, results) = BranchPage::parse_branch_child_catalog(
&test_data,
&mut tracker,
&ntfs_file,
Some(&ntfs_file),
&mut ntfs_parser.fs,
)
.unwrap();
Expand Down Expand Up @@ -354,7 +354,7 @@ mod tests {
&mut info,
&mut rows,
&mut tracker,
&reader,
Some(&reader),
&mut ntfs_parser.fs,
)
.unwrap();
Expand Down
12 changes: 6 additions & 6 deletions artemis-core/src/artifacts/os/windows/ese/pages/longvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ use crate::{
},
tags::TagFlags,
},
filesystem::ntfs::{reader::read_bytes, sector_reader::SectorReader},
filesystem::ntfs::reader::read_bytes,
};
use log::{error, warn};
use nom::{bytes::complete::take, error::ErrorKind};
use ntfs::NtfsFile;
use std::collections::HashMap;
use std::{fs::File, io::BufReader};
use std::io::BufReader;

/**
* Parse long value page into a `HashMap`
* long value is data too large to fit in a cell
* Columns that have long value data can use this `HashMap` to lookup the column actual data
*/
pub(crate) fn parse_long_value<'a>(
pub(crate) fn parse_long_value<'a, T: std::io::Seek + std::io::Read>(
page_lv_data: &'a [u8],
ntfs_file: &NtfsFile<'_>,
fs: &mut BufReader<SectorReader<File>>,
ntfs_file: Option<&NtfsFile<'_>>,
fs: &mut BufReader<T>,
) -> nom::IResult<&'a [u8], HashMap<Vec<u8>, Vec<u8>>> {
let (page_data, table_page_data) = PageHeader::parse_header(page_lv_data)?;
let mut has_root = false;
Expand Down Expand Up @@ -238,7 +238,7 @@ mod tests {
let mut ntfs_parser = setup_ntfs_parser(&binding.chars().next().unwrap()).unwrap();

let reader = raw_reader(&binding, &ntfs_parser.ntfs, &mut ntfs_parser.fs).unwrap();
let (_, results) = parse_long_value(&lv, &reader, &mut ntfs_parser.fs).unwrap();
let (_, results) = parse_long_value(&lv, Some(&reader), &mut ntfs_parser.fs).unwrap();
assert_eq!(results.len(), 94);
}

Expand Down
Loading

0 comments on commit 5f71e81

Please sign in to comment.