From c20c39865c25e395191b2de70fa17a420d19b699 Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Mon, 5 Feb 2024 21:46:56 +0100 Subject: [PATCH 1/4] add pf2bodyfile --- Cargo.lock | 71 ++++++- Cargo.toml | 13 +- src/bin/pf2bodyfile/cli.rs | 25 +++ src/bin/pf2bodyfile/main.rs | 38 ++++ src/lib.rs | 1 + src/scca/access_flags.rs | 5 + src/scca/check_file_signature.rs | 101 ++++++++++ src/scca/error.rs | 79 ++++++++ src/scca/file.rs | 242 +++++++++++++++++++++++ src/scca/get_version.rs | 23 +++ src/scca/mod.rs | 14 ++ src/scca/read_string.rs | 109 ++++++++++ tests/data/scca/DLLHOST.EXE-766398D2.pf | Bin 0 -> 29700 bytes tests/data/scca/RUNDLL32.EXE-411A328D.pf | Bin 0 -> 64266 bytes tests/data/scca/WMIADAP.EXE-F8DFDFA2.pf | Bin 0 -> 18810 bytes tests/data/scca/WMIPRVSE.EXE-1628051C.pf | Bin 0 -> 35022 bytes tests/data/scca/WUAUCLT.EXE-70318591.pf | Bin 0 -> 50736 bytes 17 files changed, 719 insertions(+), 2 deletions(-) create mode 100644 src/bin/pf2bodyfile/cli.rs create mode 100644 src/bin/pf2bodyfile/main.rs create mode 100644 src/scca/access_flags.rs create mode 100644 src/scca/check_file_signature.rs create mode 100644 src/scca/error.rs create mode 100644 src/scca/file.rs create mode 100644 src/scca/get_version.rs create mode 100644 src/scca/mod.rs create mode 100644 src/scca/read_string.rs create mode 100755 tests/data/scca/DLLHOST.EXE-766398D2.pf create mode 100755 tests/data/scca/RUNDLL32.EXE-411A328D.pf create mode 100755 tests/data/scca/WMIADAP.EXE-F8DFDFA2.pf create mode 100755 tests/data/scca/WMIPRVSE.EXE-1628051C.pf create mode 100755 tests/data/scca/WUAUCLT.EXE-70318591.pf diff --git a/Cargo.lock b/Cargo.lock index 75ebced..0b4bdca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -732,12 +732,14 @@ dependencies = [ "getset", "indicatif", "lazy-regex", + "libc", "lnk", "log", "matches", "more-asserts", "nt_hive2", - "num-derive 0.3.3", + "num", + "num-derive 0.4.0", "num-traits", "ouroboros", "phf", @@ -1636,6 +1638,40 @@ dependencies = [ "winstructs", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +dependencies = [ + "num-traits", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -1658,6 +1694,39 @@ dependencies = [ "syn 2.0.37", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.16" diff --git a/Cargo.toml b/Cargo.toml index 32f34b7..67bb835 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,9 +77,15 @@ name = "lnk2bodyfile" path = "src/bin/lnk2bodyfile/main.rs" required-features = ["lnk2bodyfile"] + +[[bin]] +name = "pf2bodyfile" +path = "src/bin/pf2bodyfile/main.rs" +required-features = ["pf2bodyfile"] + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["pol_export", "mactime2", "evtxtools", "regdump", "hivescan", "cleanhive", "ipgrep", "ts2date", "lnk2bodyfile"] +default = ["pol_export", "mactime2", "evtxtools", "regdump", "hivescan", "cleanhive", "ipgrep", "ts2date", "lnk2bodyfile", "pf2bodyfile"] mactime2 = ["gzip", "elastic", "chrono-tz", "thiserror", "bitflags", "encoding_rs_io"] gzip = ["flate2"] elastic = ["elasticsearch", "tokio", "futures", "serde_json", "sha2", "base64", "num-traits", "num-derive", "strum", "strum_macros", "tokio-async-drop"] @@ -93,6 +99,7 @@ evtx2bodyfile = ["evtx", "getset", "ouroboros", "indicatif"] ipgrep = [] ts2date = ["regex"] lnk2bodyfile = ["lnk"] +pf2bodyfile = ["num", "libc"] regdump = ["nt_hive2"] hivescan = ["nt_hive2"] @@ -165,6 +172,10 @@ nt_hive2 = {version="4.0.1", optional=true} # lnk2bodyfile lnk = {version="0.5.1", optional=true} +# pf2bodyfile +libc = {version="0.2", optional=true} +num = {version="0", optional=true} + [dev-dependencies] # mactime2 diff --git a/src/bin/pf2bodyfile/cli.rs b/src/bin/pf2bodyfile/cli.rs new file mode 100644 index 0000000..269177d --- /dev/null +++ b/src/bin/pf2bodyfile/cli.rs @@ -0,0 +1,25 @@ +use clap::Parser; +use clap::ValueHint; +use clio::Input; +use dfir_toolkit::common::HasVerboseFlag; +use getset::Getters; +use log::LevelFilter; + +/// creates bodyfile from Windows Prefetch files +#[derive(Parser, Getters)] +#[clap(name=env!("CARGO_BIN_NAME"), author, version)] +#[getset(get = "pub (crate)")] +pub(crate) struct Cli { + /// names of the prefetch files (commonly files with 'pf' extension in 'C:\Windows\Prefetch') + #[clap(value_hint=ValueHint::FilePath)] + prefetch_files: Vec, + + #[clap(flatten)] + verbose: clap_verbosity_flag::Verbosity, +} + +impl HasVerboseFlag for Cli { + fn log_level_filter(&self) -> LevelFilter { + self.verbose.log_level_filter() + } +} diff --git a/src/bin/pf2bodyfile/main.rs b/src/bin/pf2bodyfile/main.rs new file mode 100644 index 0000000..93f9877 --- /dev/null +++ b/src/bin/pf2bodyfile/main.rs @@ -0,0 +1,38 @@ +mod cli; +use cli::Cli; +use dfir_toolkit::common::bodyfile::Bodyfile3Line; +use dfir_toolkit::common::FancyParser; +use dfir_toolkit::scca::File; + +fn main() -> anyhow::Result<()> { + let cli = Cli::parse_cli(); + + if cli.prefetch_files().iter().any(|f| !f.can_seek()) { + anyhow::bail!( + "{} cannot read from a stream; you must specify a file", + env!("CARGO_BIN_NAME") + ); + } + + if cli.prefetch_files().iter().any(|f| ! f.path().is_file()) { + anyhow::bail!( + "{} you must specify a file", + env!("CARGO_BIN_NAME") + ); + } + + for input in cli.prefetch_files().iter() { + let path = input.path().as_os_str().to_string_lossy(); + let pf_file = input.path().file_name().unwrap().to_string_lossy(); + let file = File::open(&path)?; + let executable = file.utf8_executable_filename()?; + let run_count = file.run_count()?; + for time in file.last_run_times()? { + let bf_line = Bodyfile3Line::new() + .with_owned_name(format!("Prefetch: '{executable}' (run {run_count} times, read from '{pf_file}')")) + .with_atime(time.into()); + println!("{bf_line}"); + } + } + Ok(()) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 7576a65..d13cb0a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ pub mod registry; pub mod common; pub mod evtx; +pub mod scca; #[cfg(feature="elastic")] pub mod es4forensics; \ No newline at end of file diff --git a/src/scca/access_flags.rs b/src/scca/access_flags.rs new file mode 100644 index 0000000..e1f78ca --- /dev/null +++ b/src/scca/access_flags.rs @@ -0,0 +1,5 @@ + +pub enum AccessFlags { + AccessRead = 0x01, + AccessWrite = 0x02, +} \ No newline at end of file diff --git a/src/scca/check_file_signature.rs b/src/scca/check_file_signature.rs new file mode 100644 index 0000000..837a013 --- /dev/null +++ b/src/scca/check_file_signature.rs @@ -0,0 +1,101 @@ +use std::{ + ffi::{c_char, CString}, + os::raw::c_int, + ptr, +}; + +//use libc::wchar_t; + +use crate::scca::{libscca_error_t, Error}; + +#[link(name = "scca")] +extern "C" { + fn libscca_check_file_signature( + filename: *const c_char, + error: *mut *const libscca_error_t, + ) -> c_int; + + /* + fn libscca_check_file_signature_wide( + filename: *const wchar_t, + error: *mut *const libscca_error_t, + ) -> c_int; + */ +} + +/// Determines if a file contains a SCCA file signature +/// +pub fn has_file_signature(filename: &str) -> Result { + if filename.is_ascii() { + let c_filename = CString::new(filename).expect("unable to create CString"); + unsafe { + let mut error = ptr::null(); + match libscca_check_file_signature(c_filename.as_ptr(), &mut error) { + 1 => Ok(true), + 0 => Ok(false), + -1 => Err(Error::from(error)), + _ => unimplemented!(), + } + } + } else { + /* + let mut encoded: Vec<_> = filename.encode_utf16().map(i32::from).collect(); + encoded.push(0); + unsafe { + let mut error = ptr::null(); + match libscca_check_file_signature_wide(encoded.as_ptr(), &mut error) { + 1 => Ok(true), + 0 => Ok(false), + -1 => Err(Error::from(error)), + _ => unimplemented!(), + } + } + */ + unimplemented!() + } +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use crate::scca::has_file_signature; + + #[test] + fn test_missing_file() { + let res = has_file_signature("invalid_file_name"); + assert!(res.is_err()); + let error = res.unwrap_err(); + assert_eq!("libscca_check_file_signature: unable to check file signature using a file handle.", error.to_string()); + } + + #[test] + fn test_rundll32() { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("tests"); + d.push("data"); + d.push("scca"); + d.push("RUNDLL32.EXE-411A328D.pf"); + assert!(d.exists()); + let filename = d.to_string_lossy().to_string(); + + let res = has_file_signature(&filename).unwrap(); + assert!(res); + } + + /* + #[test] + fn test_rundll32_äöü() { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("tests"); + d.push("data"); + d.push("2020JimmyWilson"); + d.push("RUNDLL32-ÄÖÜ.EXE-411A328D.pf"); + assert!(d.exists()); + let filename = d.to_string_lossy().to_string(); + + let res = has_file_signature(&filename).unwrap(); + assert!(res); + } + */ +} diff --git a/src/scca/error.rs b/src/scca/error.rs new file mode 100644 index 0000000..55ded81 --- /dev/null +++ b/src/scca/error.rs @@ -0,0 +1,79 @@ +#![allow(non_camel_case_types)] +use std::{ + ffi::{c_char, CStr}, + fmt::Display, + marker::PhantomData, + os::raw::c_int, +}; + +use libc::size_t; + +#[link(name = "scca")] +extern "C" { + /// Frees an error + fn libscca_error_free(error: *const *const libscca_error_t); + + /// Prints a descriptive string of the error to the string + /// The end-of-string character is not included in the return value + /// Returns the number of printed characters if successful or -1 on error + fn libscca_error_sprint( + error: *const libscca_error_t, + string: *mut c_char, + size: size_t, + ) -> c_int; +} + +pub type libscca_error_t = *const c_int; + +pub struct Error<'a> { + error: *const libscca_error_t, + phantom: PhantomData<&'a ()>, +} + +impl<'a> From<*const libscca_error_t> for Error<'a> { + fn from(error: *const libscca_error_t) -> Self { + Self { + error, + phantom: PhantomData, + } + } +} + +impl<'a> Drop for Error<'a> { + fn drop(&mut self) { + unsafe { libscca_error_free(&self.error) } + } +} + +impl<'a> Display for Error<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + const BUFFER_SIZE: usize = 1024; + let mut buffer = vec![0; BUFFER_SIZE]; + + unsafe { + libscca_error_sprint(self.error, buffer.as_mut_ptr(), BUFFER_SIZE); + buffer[BUFFER_SIZE - 1] = 0; + CStr::from_ptr(buffer.as_ptr()).to_string_lossy().fmt(f) + } + } +} + + +impl<'a> std::fmt::Debug for Error<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + const BUFFER_SIZE: usize = 1024; + let mut buffer = vec![0; BUFFER_SIZE]; + + unsafe { + libscca_error_sprint(self.error, buffer.as_mut_ptr(), BUFFER_SIZE); + buffer[BUFFER_SIZE - 1] = 0; + std::fmt::Display::fmt(&CStr::from_ptr(buffer.as_ptr()).to_string_lossy(), f) + } + } +} + +impl<'a> From> for anyhow::Error { + fn from(value: Error<'a>) -> Self { + anyhow::anyhow!("{value}") + } +} \ No newline at end of file diff --git a/src/scca/file.rs b/src/scca/file.rs new file mode 100644 index 0000000..baa0909 --- /dev/null +++ b/src/scca/file.rs @@ -0,0 +1,242 @@ +use std::{ + ffi::{c_int, CString}, + marker::PhantomData, + ptr, +}; + +use chrono::{DateTime, Utc}; +use libc::{c_char, size_t}; +use winstructs::timestamp::WinTimestamp; + +use crate::scca::read_string::ReadString; +use crate::scca::{libscca_error_t, AccessFlags}; + +#[allow(non_camel_case_types)] +pub type libscca_file_t = *const c_int; + +#[link(name = "scca")] +extern "C" { + /// Creates a file + fn libscca_file_initialize( + file: *mut *const libscca_file_t, + error: *mut *const libscca_error_t, + ) -> c_int; + + /// Frees a file + fn libscca_file_free( + file: *mut *const libscca_file_t, + error: *mut *const libscca_error_t, + ) -> c_int; + + /// Opens a file + fn libscca_file_open( + file: *mut libscca_file_t, + filename: *const c_char, + access_flags: c_int, + error: *mut *const libscca_error_t, + ) -> c_int; + + /// Closes a file + fn libscca_file_close(file: *mut libscca_file_t, error: *mut *const libscca_error_t) -> c_int; + + fn libscca_file_get_format_version( + file: *const libscca_file_t, + format_version: *mut u32, + error: *mut *const libscca_error_t, + ) -> c_int; + + fn libscca_file_get_utf8_executable_filename_size( + file: *const libscca_file_t, + utf8_string_size: *mut size_t, + error: *mut *const libscca_error_t, + ) -> c_int; + + fn libscca_file_get_utf8_executable_filename( + file: *const libscca_file_t, + utf8_string: *mut u8, + utf8_string_size: size_t, + error: *mut *const libscca_error_t, + ) -> c_int; + + fn libscca_file_get_utf16_executable_filename_size( + file: *const libscca_file_t, + utf16_string_size: *mut size_t, + error: *mut *const libscca_error_t, + ) -> c_int; + + fn libscca_file_get_utf16_executable_filename( + file: *const libscca_file_t, + utf16_string: *mut u16, + utf16_string_size: size_t, + error: *mut *const libscca_error_t, + ) -> c_int; + + fn libscca_file_get_last_run_time( + file: *const libscca_file_t, + last_run_time_index: c_int, + filetime: *mut u64, + error: *mut *const libscca_error_t, + ) -> c_int; + + fn libscca_file_get_run_count( + file: *const libscca_file_t, + run_count: *mut u32, + error: *mut *const libscca_error_t, + ) -> c_int; +} + +pub struct File<'f> { + file: *const libscca_file_t, + phantom: PhantomData<&'f ()>, +} + +impl<'f> File<'f> { + /// Opens a prefetch file + pub fn open(filename: &str) -> Result { + let mut file = ptr::null(); + let mut error = ptr::null(); + unsafe { + if 1 != libscca_file_initialize(&mut file, &mut error) { + return Err(error.into()); + } + + let c_filename = CString::new(filename).expect("unable to create CString"); + + error = ptr::null(); + if 1 != libscca_file_open( + file.cast_mut(), + c_filename.as_ptr(), + AccessFlags::AccessRead as c_int, + &mut error, + ) { + return Err(error.into()); + } + } + + Ok(Self { + file, + phantom: PhantomData, + }) + } + + pub(crate) fn file(&self) -> *const libscca_file_t { + self.file + } + + /// Retrieves the format version + pub fn format_version(&self) -> Result { + unsafe { + let mut error = ptr::null(); + let mut version = 0; + if 1 != libscca_file_get_format_version(self.file, &mut version, &mut error) { + return Err(error.into()); + } + Ok(version) + } + } + + /// Retrieves the run count + pub fn run_count(&self) -> Result { + unsafe { + let mut error = ptr::null(); + let mut count = 0; + if 1 != libscca_file_get_run_count(self.file, &mut count, &mut error) { + return Err(error.into()); + } + Ok(count) + } + } + + /// Retrieves a specific last run time + /// + /// The timestamp is a 64-bit FILETIME date and time value + /// + /// Files of format version 23 and earlier contain a single last run time + /// + /// Files of format version 26 and later contain up to 8 last run time + pub fn last_run_times(&self) -> Result>, crate::scca::Error> { + let max_run_counts = if self.format_version()? < 26 { 1 } else { 8 }; + + let mut times = Vec::new(); + for index in 0..max_run_counts { + let time = unsafe { + let mut error = ptr::null(); + let mut filetime = 0; + if 1 != libscca_file_get_last_run_time(self.file, index, &mut filetime, &mut error) + { + //return Err(error.into()); + break; + } + filetime + }; + if time != 0 { + times.push( + WinTimestamp::new(&time.to_le_bytes()) + .unwrap() + .to_datetime(), + ); + } + } + Ok(times) + } + + /// Retrieves a specific UTF-8 encoded executable filename + pub fn utf8_executable_filename(&self) -> Result { + self.read_string( + libscca_file_get_utf8_executable_filename_size, + libscca_file_get_utf8_executable_filename, + ) + } + + /// Retrieves a specific UTF-16 encoded executable filename + pub fn utf16_executable_filename(&self) -> Result { + self.read_string( + libscca_file_get_utf16_executable_filename_size, + libscca_file_get_utf16_executable_filename, + ) + } +} + +impl<'f> Drop for File<'f> { + fn drop(&mut self) { + unsafe { + let mut error = ptr::null(); + if 1 != libscca_file_close(self.file.cast_mut(), &mut error) { + log::info!("{}", crate::scca::Error::from(error)); + } + + error = ptr::null(); + if 1 != libscca_file_free(&mut self.file, &mut error) { + panic!("{}", crate::scca::Error::from(error)); + } + } + } +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use chrono::{DateTime, Utc}; + + use crate::scca::File; + + #[test] + fn test_open_file() { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("tests"); + d.push("data"); + d.push("scca"); + d.push("RUNDLL32.EXE-411A328D.pf"); + assert!(d.exists()); + let filename = d.to_string_lossy().to_string(); + + let file = File::open(&filename).unwrap(); + assert_eq!(file.format_version().unwrap(), 23); + assert_eq!(file.utf8_executable_filename().unwrap(), "RUNDLL32.EXE"); + assert_eq!(file.utf16_executable_filename().unwrap(), "RUNDLL32.EXE"); + for time in file.last_run_times().unwrap() { + assert_ne!(time, DateTime::::default()); + } + } +} diff --git a/src/scca/get_version.rs b/src/scca/get_version.rs new file mode 100644 index 0000000..7d9616a --- /dev/null +++ b/src/scca/get_version.rs @@ -0,0 +1,23 @@ +use std::ffi::{c_char, CStr}; + +#[link(name = "scca")] +extern "C" { + fn libscca_get_version() -> *const c_char; +} + +pub fn get_version() -> String { + unsafe { + let slice = CStr::from_ptr(libscca_get_version()); + slice.to_str().unwrap().to_string() + } +} + +#[cfg(test)] +mod tests { + use crate::scca::get_version; + + #[test] + fn test_get_version() { + assert!(get_version().starts_with("20")); + } +} diff --git a/src/scca/mod.rs b/src/scca/mod.rs new file mode 100644 index 0000000..b7001f2 --- /dev/null +++ b/src/scca/mod.rs @@ -0,0 +1,14 @@ +mod error; +mod access_flags; +mod read_string; +pub use error::*; +pub use access_flags::*; + +mod get_version; +pub use get_version::*; + +mod check_file_signature; +pub use check_file_signature::*; + +mod file; +pub use file::*; \ No newline at end of file diff --git a/src/scca/read_string.rs b/src/scca/read_string.rs new file mode 100644 index 0000000..f774076 --- /dev/null +++ b/src/scca/read_string.rs @@ -0,0 +1,109 @@ +use std::{ffi::c_int, ptr}; + +use libc::size_t; +use num::Zero; + +use crate::scca::{libscca_error_t, libscca_file_t, File}; + + +pub (crate) trait CharacterType: Zero + Clone + Eq + PartialEq {} +impl CharacterType for u8 {} +impl CharacterType for u16 {} +pub (crate) trait ReadString { + fn read_string_with_conversion( + &self, + read_size: unsafe extern "C" fn( + file: *const libscca_file_t, + string_size: *mut size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + read_value: unsafe extern "C" fn( + file: *const libscca_file_t, + value: *mut T, + string_size: size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + file: *const libscca_file_t, + conversion: fn(&[T]) -> String, + ) -> Result { + let string_size = unsafe { + let mut error = ptr::null(); + let mut string_size = 0; + if 1 != read_size(file, &mut string_size, &mut error) { + return Err(error.into()); + } + string_size + }; + + let mut buffer = unsafe { + let mut buffer: Vec = vec![T::zero(); string_size]; + let mut error = ptr::null(); + if 1 != read_value(file, buffer.as_mut_ptr(), string_size, &mut error) { + return Err(error.into()); + } + buffer + }; + + assert!(buffer.last().unwrap().is_zero()); + buffer.pop().unwrap(); + + Ok(conversion(&buffer[..])) + } + + fn read_string( + &self, + read_size: unsafe extern "C" fn( + file: *const libscca_file_t, + string_size: *mut size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + read_value: unsafe extern "C" fn( + file: *const libscca_file_t, + value: *mut T, + string_size: size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + ) -> Result; +} + +impl<'f> ReadString for File<'f> { + fn read_string( + &self, + read_size: unsafe extern "C" fn( + file: *const libscca_file_t, + string_size: *mut size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + read_value: unsafe extern "C" fn( + file: *const libscca_file_t, + value: *mut u8, + string_size: size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + ) -> Result { + self.read_string_with_conversion(read_size, read_value, self.file(), |s| { + String::from_utf8_lossy(s).to_string() + }) + } +} + +impl<'f> ReadString for File<'f> { + fn read_string( + &self, + read_size: unsafe extern "C" fn( + file: *const libscca_file_t, + string_size: *mut size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + read_value: unsafe extern "C" fn( + file: *const libscca_file_t, + value: *mut u16, + string_size: size_t, + error: *mut *const libscca_error_t, + ) -> c_int, + ) -> Result { + self.read_string_with_conversion(read_size, read_value, self.file(), |s| { + String::from_utf16(s).expect("unable to convert from UTF-16") + }) + } +} diff --git a/tests/data/scca/DLLHOST.EXE-766398D2.pf b/tests/data/scca/DLLHOST.EXE-766398D2.pf new file mode 100755 index 0000000000000000000000000000000000000000..a2a50b66dac7ccb8838e322c396b314873e53b65 GIT binary patch literal 29700 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 rbB_Ogw6ph}TBl>< literal 0 HcmV?d00001 diff --git a/tests/data/scca/WMIPRVSE.EXE-1628051C.pf b/tests/data/scca/WMIPRVSE.EXE-1628051C.pf new file mode 100755 index 0000000000000000000000000000000000000000..be882a22fd9c4ff5facda90466c200c5046d0706 GIT binary patch literal 35022 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 R|FO=UPx^Q6H_86<{{a0gyR85K literal 0 HcmV?d00001 diff --git a/tests/data/scca/WUAUCLT.EXE-70318591.pf b/tests/data/scca/WUAUCLT.EXE-70318591.pf new file mode 100755 index 0000000000000000000000000000000000000000..28cb4d1a853ebcd3ba518268860a267a20977d7f GIT binary patch literal 50736 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 aqAWvfa#!_WVnN4F;m>*TpPz~PJpUhSHgBZ> literal 0 HcmV?d00001 From 3ae607e1ee9847a0af8b5ceb4e12025f1fc44147 Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Mon, 5 Feb 2024 21:51:20 +0100 Subject: [PATCH 2/4] update documentation --- README.md | 4 +- doc/cleanhive.md | 36 ++++++++++++++++++ doc/es4forensics.md | 80 ++++++++++++++++++++++++++++++++++++++++ doc/evtx2bodyfile.md | 39 ++++++++++++++++++++ doc/evtxanalyze.md | 88 ++++++++++++++++++++++++++++++++++++++++++++ doc/evtxcat.md | 42 +++++++++++++++++++++ doc/evtxls.md | 70 +++++++++++++++++++++++++++++++++++ doc/evtxscan.md | 36 ++++++++++++++++++ doc/hivescan.md | 34 +++++++++++++++++ doc/ipgrep.md | 42 +++++++++++++++++++++ doc/lnk2bodyfile.md | 34 +++++++++++++++++ doc/mactime2.md | 44 ++++++++++++++++++++++ doc/pf2bodyfile.md | 32 ++++++++++++++++ doc/pol_export.md | 32 ++++++++++++++++ doc/regdump.md | 36 ++++++++++++++++++ doc/ts2date.md | 43 ++++++++++++++++++++++ scripts/update-md.sh | 2 + 17 files changed, 693 insertions(+), 1 deletion(-) create mode 100644 doc/pf2bodyfile.md diff --git a/README.md b/README.md index d142116..4135f5d 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,9 @@ - [Overview of timelining tools](#overview-of-timelining-tools) - [Tools](#tools) - [x] [`cleanhive`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/cleanhive.md) + - [x] [`pf2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/pf2bodyfile.md) - [x] [`evtx2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtx2bodyfile.md) - - [x] [`evtxanalyze`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxanalyze.md) + - [x] [`evtxanalyze`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/avtxanalyze.md) - [x] [`evtxscan`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxscan.md) - [x] [`evtxcat`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxcat.md) - [x] [`evtxls`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxls.md) @@ -42,6 +43,7 @@ # Installation ```bash +sudo apt install libscca-dev cargo install dfir-toolkit ``` diff --git a/doc/cleanhive.md b/doc/cleanhive.md index 291166f..84b7f46 100644 --- a/doc/cleanhive.md +++ b/doc/cleanhive.md @@ -63,6 +63,42 @@ merges logfiles into a hive file +
+ + + This document was generated automatically by +
clap-markdown. + + +# Command-Line Help for `cleanhive` + +This document contains the help content for the `cleanhive` command-line program. + +**Command Overview:** + +* [`cleanhive`↴](#cleanhive) + +## `cleanhive` + +merges logfiles into a hive file + +**Usage:** `cleanhive [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the file to dump + +###### **Options:** + +* `-L`, `--log ` — transaction LOG file(s). This argument can be specified one or two times +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence +* `-O`, `--output ` — name of the file to which the cleaned hive will be written + + Default value: `-` + + +
diff --git a/doc/es4forensics.md b/doc/es4forensics.md index ba37dde..03f5212 100644 --- a/doc/es4forensics.md +++ b/doc/es4forensics.md @@ -133,6 +133,86 @@ This crates provides structs and functions to insert timeline data into an elast +## `es4forensics import` + +**Usage:** `es4forensics import [OPTIONS] [INPUT_FILE]` + +###### **Arguments:** + +* `` — path to input file or '-' for stdin (files ending with .gz will be treated as being gzipped) + + Default value: `-` + +###### **Options:** + +* `--bulk-size ` — number of timeline entries to combine in one bulk operation + + Default value: `1000` + + + +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `es4forensics` + +This document contains the help content for the `es4forensics` command-line program. + +**Command Overview:** + +* [`es4forensics`↴](#es4forensics) +* [`es4forensics create-index`↴](#es4forensics-create-index) +* [`es4forensics import`↴](#es4forensics-import) + +## `es4forensics` + +This crates provides structs and functions to insert timeline data into an elasticsearch index + +**Usage:** `es4forensics [OPTIONS] --index --password ` + +###### **Subcommands:** + +* `create-index` — +* `import` — + +###### **Options:** + +* `--strict` — strict mode: do not only warn, but abort if an error occurs +* `-I`, `--index ` — name of the elasticsearch index +* `-H`, `--host ` — server name or IP address of elasticsearch server + + Default value: `localhost` +* `-P`, `--port ` — API port number of elasticsearch server + + Default value: `9200` +* `--proto ` — protocol to be used to connect to elasticsearch + + Default value: `https` + + Possible values: `http`, `https` + +* `-k`, `--insecure` — omit certificate validation + + Default value: `false` +* `-U`, `--username ` — username for elasticsearch server + + Default value: `elastic` +* `-W`, `--password ` — password for authenticating at elasticsearch +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + + +## `es4forensics create-index` + +**Usage:** `es4forensics create-index` + + + ## `es4forensics import` **Usage:** `es4forensics import [OPTIONS] [INPUT_FILE]` diff --git a/doc/evtx2bodyfile.md b/doc/evtx2bodyfile.md index c5e50e7..b6b08b1 100644 --- a/doc/evtx2bodyfile.md +++ b/doc/evtx2bodyfile.md @@ -69,6 +69,45 @@ creates bodyfile from Windows evtx files +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtx2bodyfile` + +This document contains the help content for the `evtx2bodyfile` command-line program. + +**Command Overview:** + +* [`evtx2bodyfile`↴](#evtx2bodyfile) + +## `evtx2bodyfile` + +creates bodyfile from Windows evtx files + +**Usage:** `evtx2bodyfile [OPTIONS] [EVTX_FILES]...` + +###### **Arguments:** + +* `` — names of the evtx files + +###### **Options:** + +* `-F`, `--format ` — select output format + + Default value: `bodyfile` + + Possible values: `json`, `bodyfile` + +* `-S`, `--strict` — fail upon read error +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/evtxanalyze.md b/doc/evtxanalyze.md index 47dd0c9..ecca1e1 100644 --- a/doc/evtxanalyze.md +++ b/doc/evtxanalyze.md @@ -138,6 +138,94 @@ generate a process tree +## `evtxanalyze sessions` + +display sessions + +**Usage:** `evtxanalyze sessions [OPTIONS] ` + +###### **Arguments:** + +* `` — Names of the evtx files to parse + +###### **Options:** + +* `--include-anonymous` — include anonymous sessions + + + +## `evtxanalyze session` + +display one single session + +**Usage:** `evtxanalyze session ` + +###### **Arguments:** + +* `` — Names of the evtx files to parse +* `` — Session ID + + + +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxanalyze` + +This document contains the help content for the `evtxanalyze` command-line program. + +**Command Overview:** + +* [`evtxanalyze`↴](#evtxanalyze) +* [`evtxanalyze pstree`↴](#evtxanalyze-pstree) +* [`evtxanalyze sessions`↴](#evtxanalyze-sessions) +* [`evtxanalyze session`↴](#evtxanalyze-session) + +## `evtxanalyze` + +crate provide functions to analyze evtx files + +**Usage:** `evtxanalyze [OPTIONS] ` + +###### **Subcommands:** + +* `pstree` — generate a process tree +* `sessions` — display sessions +* `session` — display one single session + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + + +## `evtxanalyze pstree` + +generate a process tree + +**Usage:** `evtxanalyze pstree [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of the evtx file to parse + +###### **Options:** + +* `-U`, `--username ` — display only processes of this user (case insensitive regex search) +* `-F`, `--format ` — output format + + Default value: `csv` + + Possible values: `json`, `markdown`, `csv`, `latex`, `dot` + + + + ## `evtxanalyze sessions` display sessions diff --git a/doc/evtxcat.md b/doc/evtxcat.md index 3ebc824..d953c2b 100644 --- a/doc/evtxcat.md +++ b/doc/evtxcat.md @@ -75,6 +75,48 @@ Display one or more events from an evtx file +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxcat` + +This document contains the help content for the `evtxcat` command-line program. + +**Command Overview:** + +* [`evtxcat`↴](#evtxcat) + +## `evtxcat` + +Display one or more events from an evtx file + +**Usage:** `evtxcat [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of the evtx file to read from + +###### **Options:** + +* `--min ` — filter: minimal event record identifier +* `--max ` — filter: maximal event record identifier +* `-i`, `--id ` — show only the one event with this record identifier +* `-T`, `--display-table` — don't display the records in a table format +* `-F`, `--format ` — output format + + Default value: `xml` + + Possible values: `json`, `xml` + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/evtxls.md b/doc/evtxls.md index e571dc9..ee566f7 100644 --- a/doc/evtxls.md +++ b/doc/evtxls.md @@ -131,6 +131,76 @@ Display one or more events from an evtx file +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxls` + +This document contains the help content for the `evtxls` command-line program. + +**Command Overview:** + +* [`evtxls`↴](#evtxls) + +## `evtxls` + +Display one or more events from an evtx file + +**Usage:** `evtxls [OPTIONS] [EVTX_FILES]...` + +###### **Arguments:** + +* `` — Name of the evtx files to read from + +###### **Options:** + +* `-d`, `--delimiter ` — use this delimiter instead of generating fixed space columns +* `-i`, `--include ` — List events with only the specified event ids, separated by ',' +* `-x`, `--exclude ` — Exclude events with the specified event ids, separated by ',' +* `-c`, `--colors` — highlight interesting content using colors +* `-f`, `--from ` — hide events older than the specified date (hint: use RFC 3339 syntax) +* `-t`, `--to ` — hide events newer than the specified date (hint: use RFC 3339 syntax) +* `-r`, `--regex ` — highlight event data based on this regular expression +* `-s`, `--sort ` — sort order + + Default value: `storage` + + Possible values: + - `storage`: + don't change order, output records as they are stored + - `record-id`: + sort by event record id + - `time`: + sort by date and time + +* `-b`, `--base-fields ` — display fields common to all events. multiple values must be separated by ',' + + Default values: `event-id`, `event-record-id` + + Possible values: + - `event-id`: + The identifier that the provider used to identify the event + - `event-record-id`: + The record number assigned to the event when it was logged + - `activity-id`: + A globally unique identifier that identifies the current activity. The events that are published with this identifier are part of the same activity + - `related-activity-id`: + A globally unique identifier that identifies the activity to which control was transferred to. The related events would then have this identifier as their ActivityID identifier + - `process-id`: + The ID of the process that created the event + +* `-B`, `--hide-base-fields` — don't display any common event fields at all. This corresponds to specifying '--base-fields' without any values (which is not allowed, that's why there is this flag) + + Default value: `false` +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/evtxscan.md b/doc/evtxscan.md index 696e7c9..5a8c718 100644 --- a/doc/evtxscan.md +++ b/doc/evtxscan.md @@ -63,6 +63,42 @@ Find time skews in an evtx file +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxscan` + +This document contains the help content for the `evtxscan` command-line program. + +**Command Overview:** + +* [`evtxscan`↴](#evtxscan) + +## `evtxscan` + +Find time skews in an evtx file + +**Usage:** `evtxscan [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the evtx file to scan + +###### **Options:** + +* `-S`, `--show-records` — display also the contents of the records befor and after a time skew +* `-N`, `--negative-tolerance ` — negative tolerance limit (in seconds): time skews to the past below this limit will be ignored + + Default value: `5` +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/hivescan.md b/doc/hivescan.md index 3040695..30ff4be 100644 --- a/doc/hivescan.md +++ b/doc/hivescan.md @@ -59,6 +59,40 @@ scans a registry hive file for deleted entries +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `hivescan` + +This document contains the help content for the `hivescan` command-line program. + +**Command Overview:** + +* [`hivescan`↴](#hivescan) + +## `hivescan` + +scans a registry hive file for deleted entries + +**Usage:** `hivescan [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the file to scan + +###### **Options:** + +* `-L`, `--log ` — transaction LOG file(s). This argument can be specified one or two times +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence +* `-b` — output as bodyfile format + + +
diff --git a/doc/ipgrep.md b/doc/ipgrep.md index 2f1dae8..0b70d63 100644 --- a/doc/ipgrep.md +++ b/doc/ipgrep.md @@ -75,6 +75,48 @@ search for IP addresses in text files +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `ipgrep` + +This document contains the help content for the `ipgrep` command-line program. + +**Command Overview:** + +* [`ipgrep`↴](#ipgrep) + +## `ipgrep` + +search for IP addresses in text files + +**Usage:** `ipgrep [OPTIONS] [FILE]...` + +###### **Arguments:** + +* `` + +###### **Options:** + +* `-i`, `--include ` — display only lines who match ALL of the specified criteria. Values are delimited with comma + + Possible values: `ipv4`, `ipv6`, `public`, `private`, `loopback` + +* `-x`, `--exclude ` — hide lines who match ANY of the specified criteria. Values are delimited with comma + + Possible values: `ipv4`, `ipv6`, `public`, `private`, `loopback` + +* `-I`, `--ignore-ips ` — ignore any of the specified IP addresses. Values are delimited with comma +* `-c`, `--colors` — highlight interesting content using colors +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/lnk2bodyfile.md b/doc/lnk2bodyfile.md index 3d528de..b5dbcdb 100644 --- a/doc/lnk2bodyfile.md +++ b/doc/lnk2bodyfile.md @@ -25,6 +25,40 @@ Parse Windows LNK files and create bodyfile output +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `lnk2bodyfile` + +This document contains the help content for the `lnk2bodyfile` command-line program. + +**Command Overview:** + +* [`lnk2bodyfile`↴](#lnk2bodyfile) + +## `lnk2bodyfile` + +Parse Windows LNK files and create bodyfile output + +**Usage:** `lnk2bodyfile [OPTIONS] [LNK_FILES]...` + +###### **Arguments:** + +* `` — Names of the LNK files to read from + + Default value: `-` + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/mactime2.md b/doc/mactime2.md index a309f31..51cd312 100644 --- a/doc/mactime2.md +++ b/doc/mactime2.md @@ -79,6 +79,50 @@ replacement for `mactime` +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `mactime2` + +This document contains the help content for the `mactime2` command-line program. + +**Command Overview:** + +* [`mactime2`↴](#mactime2) + +## `mactime2` + +replacement for `mactime` + +**Usage:** `mactime2 [OPTIONS]` + +###### **Options:** + +* `-b ` — path to input file or '-' for stdin (files ending with .gz will be treated as being gzipped) + + Default value: `-` +* `-F`, `--format ` — output format, if not specified, default value is 'txt' + + Possible values: `csv`, `txt`, `json`, `elastic` + +* `-d` — output as CSV instead of TXT. This is a conveniance option, which is identical to `--format=csv` and will be removed in a future release. If you specified `--format` and `-d`, the latter will be ignored +* `-j` — output as JSON instead of TXT. This is a conveniance option, which is identical to `--format=json` and will be removed in a future release. If you specified `--format` and `-j`, the latter will be ignored +* `-f`, `--from-timezone ` — name of offset of source timezone (or 'list' to display all possible values + + Default value: `UTC` +* `-t`, `--to-timezone ` — name of offset of destination timezone (or 'list' to display all possible values + + Default value: `UTC` +* `--strict` — strict mode: do not only warn, but abort if an error occurs +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/pf2bodyfile.md b/doc/pf2bodyfile.md new file mode 100644 index 0000000..1e5e039 --- /dev/null +++ b/doc/pf2bodyfile.md @@ -0,0 +1,32 @@ +# Command-Line Help for `pf2bodyfile` + +This document contains the help content for the `pf2bodyfile` command-line program. + +**Command Overview:** + +* [`pf2bodyfile`↴](#pf2bodyfile) + +## `pf2bodyfile` + +creates bodyfile from Windows Prefetch files + +**Usage:** `pf2bodyfile [OPTIONS] [PREFETCH_FILES]...` + +###### **Arguments:** + +* `` — names of the prefetch files (commonly files with 'pf' extension in 'C:\Windows\Prefetch') + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/doc/pol_export.md b/doc/pol_export.md index a0f5dd1..880b833 100644 --- a/doc/pol_export.md +++ b/doc/pol_export.md @@ -55,6 +55,38 @@ Exporter for Windows Registry Policy Files +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `pol_export` + +This document contains the help content for the `pol_export` command-line program. + +**Command Overview:** + +* [`pol_export`↴](#pol_export) + +## `pol_export` + +Exporter for Windows Registry Policy Files + +**Usage:** `pol_export [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of the file to read + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/regdump.md b/doc/regdump.md index 77d91d8..5ee419e 100644 --- a/doc/regdump.md +++ b/doc/regdump.md @@ -63,6 +63,42 @@ parses registry hive files and prints a bodyfile +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `regdump` + +This document contains the help content for the `regdump` command-line program. + +**Command Overview:** + +* [`regdump`↴](#regdump) + +## `regdump` + +parses registry hive files and prints a bodyfile + +**Usage:** `regdump [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the file to dump + +###### **Options:** + +* `-L`, `--log ` — transaction LOG file(s). This argument can be specified one or two times +* `-b`, `--bodyfile` — print as bodyfile format +* `-I`, `--ignore-base-block` — ignore the base block (e.g. if it was encrypted by some ransomware) +* `-T`, `--hide-timestamps` — hide timestamps, if output is in reg format +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/ts2date.md b/doc/ts2date.md index cf7a032..ef63264 100644 --- a/doc/ts2date.md +++ b/doc/ts2date.md @@ -77,6 +77,49 @@ replaces UNIX timestamps in a stream by a formatted date +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `ts2date` + +This document contains the help content for the `ts2date` command-line program. + +**Command Overview:** + +* [`ts2date`↴](#ts2date) + +## `ts2date` + +replaces UNIX timestamps in a stream by a formatted date + +**Usage:** `ts2date [OPTIONS] [INPUT_FILE] [OUTPUT_FILE]` + +###### **Arguments:** + +* `` — name of the file to read (default from stdin) + + Default value: `-` +* `` — name of the file to write (default to stdout) + + Default value: `-` + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence +* `-f`, `--from-timezone ` — name of offset of source timezone (or 'list' to display all possible values + + Default value: `UTC` +* `-t`, `--to-timezone ` — name of offset of destination timezone (or 'list' to display all possible values + + Default value: `UTC` + + +
diff --git a/scripts/update-md.sh b/scripts/update-md.sh index e4be5a4..54228eb 100755 --- a/scripts/update-md.sh +++ b/scripts/update-md.sh @@ -20,6 +20,7 @@ cat >README.md <<'EOF' - [Overview of timelining tools](#overview-of-timelining-tools) - [Tools](#tools) - [x] [`cleanhive`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/cleanhive.md) + - [x] [`pf2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/pf2bodyfile.md) - [x] [`evtx2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtx2bodyfile.md) - [x] [`evtxanalyze`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/avtxanalyze.md) - [x] [`evtxscan`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxscan.md) @@ -47,6 +48,7 @@ cat >README.md <<'EOF' # Installation ```bash +sudo apt install libscca-dev cargo install dfir-toolkit ``` From e4a8bc21fe5e70c39255f3ef640f7ad3de0a2018 Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Tue, 6 Feb 2024 15:18:28 +0100 Subject: [PATCH 3/4] add libscca-dev to workflows --- .github/workflows/cargo_publish.yml | 4 ++++ .github/workflows/cargo_test.yml | 4 ++++ .github/workflows/coverage.yml | 3 +++ .github/workflows/rust-clippy.yml | 3 +++ 4 files changed, 14 insertions(+) diff --git a/.github/workflows/cargo_publish.yml b/.github/workflows/cargo_publish.yml index 763bf6c..e9115dd 100644 --- a/.github/workflows/cargo_publish.yml +++ b/.github/workflows/cargo_publish.yml @@ -8,6 +8,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + + - name: Install required libscca-dev + run: sudo apt install -y libscca-dev + - uses: actions-rs/toolchain@v1 with: toolchain: stable diff --git a/.github/workflows/cargo_test.yml b/.github/workflows/cargo_test.yml index b1b08ed..5cf83f0 100644 --- a/.github/workflows/cargo_test.yml +++ b/.github/workflows/cargo_test.yml @@ -8,6 +8,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + + - name: Install required libscca-dev + run: sudo apt install -y libscca-dev + - uses: actions-rs/toolchain@v1 with: toolchain: stable diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 34d1248..71ac140 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -8,6 +8,9 @@ jobs: steps: - uses: actions/checkout@v1 + + - name: Install required libscca-dev + run: sudo apt install -y libscca-dev - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/rust-clippy.yml b/.github/workflows/rust-clippy.yml index 5008eb0..4185417 100644 --- a/.github/workflows/rust-clippy.yml +++ b/.github/workflows/rust-clippy.yml @@ -38,6 +38,9 @@ jobs: components: clippy override: true + - name: Install required libscca-dev + run: sudo apt install -y libscca-dev + - name: Install required cargo run: cargo install clippy-sarif sarif-fmt From 4233859162961374f18d0ab56dbfdf2cd6776d89 Mon Sep 17 00:00:00 2001 From: Bitbee0 <92975980+Bitbee0@users.noreply.github.com> Date: Tue, 6 Feb 2024 18:17:42 +0100 Subject: [PATCH 4/4] update README.md --- Cargo.lock | 2 +- README.md | 6 ++- doc/cleanhive.md | 36 ++++++++++++++++++ doc/es4forensics.md | 80 ++++++++++++++++++++++++++++++++++++++++ doc/evtx2bodyfile.md | 39 ++++++++++++++++++++ doc/evtxanalyze.md | 88 ++++++++++++++++++++++++++++++++++++++++++++ doc/evtxcat.md | 42 +++++++++++++++++++++ doc/evtxls.md | 70 +++++++++++++++++++++++++++++++++++ doc/evtxscan.md | 36 ++++++++++++++++++ doc/hivescan.md | 34 +++++++++++++++++ doc/ipgrep.md | 42 +++++++++++++++++++++ doc/lnk2bodyfile.md | 34 +++++++++++++++++ doc/mactime2.md | 44 ++++++++++++++++++++++ doc/pf2bodyfile.md | 32 ++++++++++++++++ doc/pol_export.md | 32 ++++++++++++++++ doc/regdump.md | 36 ++++++++++++++++++ doc/ts2date.md | 43 ++++++++++++++++++++++ 17 files changed, 693 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a87da7..dd5f737 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -732,8 +732,8 @@ dependencies = [ "getset", "indicatif", "lazy-regex", - "libc", "lazy_static", + "libc", "lnk", "log", "matches", diff --git a/README.md b/README.md index 90ef22d..e831147 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ - [x] [`cleanhive`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/cleanhive.md) - [x] [`pf2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/pf2bodyfile.md) - [x] [`evtx2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtx2bodyfile.md) - - [x] [`evtxanalyze`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/avtxanalyze.md) + - [x] [`evtxanalyze`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxanalyze.md) - [x] [`evtxscan`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxscan.md) - [x] [`evtxcat`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxcat.md) - [x] [`evtxls`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/evtxls.md) @@ -90,4 +90,6 @@ $ DFIR_DATE="%F %T (%Z)" mac2time2 -b tests/data/mactime2/sample.bodyfile -d | h 2022-04-21 00:57:51 (UTC),4096,m...,d/drwxr-xr-x,0,0,38010881,"/srv" ``` -The value of `DFIR_DATE` can be any format string which can also be used in `DateTime::strftime` () \ No newline at end of file +The value of `DFIR_DATE` can be any format string which can also be used in `DateTime::strftime` () + + diff --git a/doc/cleanhive.md b/doc/cleanhive.md index 84b7f46..85e72ba 100644 --- a/doc/cleanhive.md +++ b/doc/cleanhive.md @@ -99,6 +99,42 @@ merges logfiles into a hive file +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `cleanhive` + +This document contains the help content for the `cleanhive` command-line program. + +**Command Overview:** + +* [`cleanhive`↴](#cleanhive) + +## `cleanhive` + +merges logfiles into a hive file + +**Usage:** `cleanhive [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the file to dump + +###### **Options:** + +* `-L`, `--log ` — transaction LOG file(s). This argument can be specified one or two times +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence +* `-O`, `--output ` — name of the file to which the cleaned hive will be written + + Default value: `-` + + +
diff --git a/doc/es4forensics.md b/doc/es4forensics.md index 03f5212..25eacc6 100644 --- a/doc/es4forensics.md +++ b/doc/es4forensics.md @@ -213,6 +213,86 @@ This crates provides structs and functions to insert timeline data into an elast +## `es4forensics import` + +**Usage:** `es4forensics import [OPTIONS] [INPUT_FILE]` + +###### **Arguments:** + +* `` — path to input file or '-' for stdin (files ending with .gz will be treated as being gzipped) + + Default value: `-` + +###### **Options:** + +* `--bulk-size ` — number of timeline entries to combine in one bulk operation + + Default value: `1000` + + + +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `es4forensics` + +This document contains the help content for the `es4forensics` command-line program. + +**Command Overview:** + +* [`es4forensics`↴](#es4forensics) +* [`es4forensics create-index`↴](#es4forensics-create-index) +* [`es4forensics import`↴](#es4forensics-import) + +## `es4forensics` + +This crates provides structs and functions to insert timeline data into an elasticsearch index + +**Usage:** `es4forensics [OPTIONS] --index --password ` + +###### **Subcommands:** + +* `create-index` — +* `import` — + +###### **Options:** + +* `--strict` — strict mode: do not only warn, but abort if an error occurs +* `-I`, `--index ` — name of the elasticsearch index +* `-H`, `--host ` — server name or IP address of elasticsearch server + + Default value: `localhost` +* `-P`, `--port ` — API port number of elasticsearch server + + Default value: `9200` +* `--proto ` — protocol to be used to connect to elasticsearch + + Default value: `https` + + Possible values: `http`, `https` + +* `-k`, `--insecure` — omit certificate validation + + Default value: `false` +* `-U`, `--username ` — username for elasticsearch server + + Default value: `elastic` +* `-W`, `--password ` — password for authenticating at elasticsearch +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + + +## `es4forensics create-index` + +**Usage:** `es4forensics create-index` + + + ## `es4forensics import` **Usage:** `es4forensics import [OPTIONS] [INPUT_FILE]` diff --git a/doc/evtx2bodyfile.md b/doc/evtx2bodyfile.md index b6b08b1..558a606 100644 --- a/doc/evtx2bodyfile.md +++ b/doc/evtx2bodyfile.md @@ -108,6 +108,45 @@ creates bodyfile from Windows evtx files +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtx2bodyfile` + +This document contains the help content for the `evtx2bodyfile` command-line program. + +**Command Overview:** + +* [`evtx2bodyfile`↴](#evtx2bodyfile) + +## `evtx2bodyfile` + +creates bodyfile from Windows evtx files + +**Usage:** `evtx2bodyfile [OPTIONS] [EVTX_FILES]...` + +###### **Arguments:** + +* `` — names of the evtx files + +###### **Options:** + +* `-F`, `--format ` — select output format + + Default value: `bodyfile` + + Possible values: `json`, `bodyfile` + +* `-S`, `--strict` — fail upon read error +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/evtxanalyze.md b/doc/evtxanalyze.md index ecca1e1..f430cd4 100644 --- a/doc/evtxanalyze.md +++ b/doc/evtxanalyze.md @@ -226,6 +226,94 @@ generate a process tree +## `evtxanalyze sessions` + +display sessions + +**Usage:** `evtxanalyze sessions [OPTIONS] ` + +###### **Arguments:** + +* `` — Names of the evtx files to parse + +###### **Options:** + +* `--include-anonymous` — include anonymous sessions + + + +## `evtxanalyze session` + +display one single session + +**Usage:** `evtxanalyze session ` + +###### **Arguments:** + +* `` — Names of the evtx files to parse +* `` — Session ID + + + +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxanalyze` + +This document contains the help content for the `evtxanalyze` command-line program. + +**Command Overview:** + +* [`evtxanalyze`↴](#evtxanalyze) +* [`evtxanalyze pstree`↴](#evtxanalyze-pstree) +* [`evtxanalyze sessions`↴](#evtxanalyze-sessions) +* [`evtxanalyze session`↴](#evtxanalyze-session) + +## `evtxanalyze` + +crate provide functions to analyze evtx files + +**Usage:** `evtxanalyze [OPTIONS] ` + +###### **Subcommands:** + +* `pstree` — generate a process tree +* `sessions` — display sessions +* `session` — display one single session + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + + +## `evtxanalyze pstree` + +generate a process tree + +**Usage:** `evtxanalyze pstree [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of the evtx file to parse + +###### **Options:** + +* `-U`, `--username ` — display only processes of this user (case insensitive regex search) +* `-F`, `--format ` — output format + + Default value: `csv` + + Possible values: `json`, `markdown`, `csv`, `latex`, `dot` + + + + ## `evtxanalyze sessions` display sessions diff --git a/doc/evtxcat.md b/doc/evtxcat.md index d953c2b..cad5888 100644 --- a/doc/evtxcat.md +++ b/doc/evtxcat.md @@ -117,6 +117,48 @@ Display one or more events from an evtx file +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxcat` + +This document contains the help content for the `evtxcat` command-line program. + +**Command Overview:** + +* [`evtxcat`↴](#evtxcat) + +## `evtxcat` + +Display one or more events from an evtx file + +**Usage:** `evtxcat [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of the evtx file to read from + +###### **Options:** + +* `--min ` — filter: minimal event record identifier +* `--max ` — filter: maximal event record identifier +* `-i`, `--id ` — show only the one event with this record identifier +* `-T`, `--display-table` — don't display the records in a table format +* `-F`, `--format ` — output format + + Default value: `xml` + + Possible values: `json`, `xml` + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/evtxls.md b/doc/evtxls.md index ee566f7..71a1aca 100644 --- a/doc/evtxls.md +++ b/doc/evtxls.md @@ -201,6 +201,76 @@ Display one or more events from an evtx file +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxls` + +This document contains the help content for the `evtxls` command-line program. + +**Command Overview:** + +* [`evtxls`↴](#evtxls) + +## `evtxls` + +Display one or more events from an evtx file + +**Usage:** `evtxls [OPTIONS] [EVTX_FILES]...` + +###### **Arguments:** + +* `` — Name of the evtx files to read from + +###### **Options:** + +* `-d`, `--delimiter ` — use this delimiter instead of generating fixed space columns +* `-i`, `--include ` — List events with only the specified event ids, separated by ',' +* `-x`, `--exclude ` — Exclude events with the specified event ids, separated by ',' +* `-c`, `--colors` — highlight interesting content using colors +* `-f`, `--from ` — hide events older than the specified date (hint: use RFC 3339 syntax) +* `-t`, `--to ` — hide events newer than the specified date (hint: use RFC 3339 syntax) +* `-r`, `--regex ` — highlight event data based on this regular expression +* `-s`, `--sort ` — sort order + + Default value: `storage` + + Possible values: + - `storage`: + don't change order, output records as they are stored + - `record-id`: + sort by event record id + - `time`: + sort by date and time + +* `-b`, `--base-fields ` — display fields common to all events. multiple values must be separated by ',' + + Default values: `event-id`, `event-record-id` + + Possible values: + - `event-id`: + The identifier that the provider used to identify the event + - `event-record-id`: + The record number assigned to the event when it was logged + - `activity-id`: + A globally unique identifier that identifies the current activity. The events that are published with this identifier are part of the same activity + - `related-activity-id`: + A globally unique identifier that identifies the activity to which control was transferred to. The related events would then have this identifier as their ActivityID identifier + - `process-id`: + The ID of the process that created the event + +* `-B`, `--hide-base-fields` — don't display any common event fields at all. This corresponds to specifying '--base-fields' without any values (which is not allowed, that's why there is this flag) + + Default value: `false` +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/evtxscan.md b/doc/evtxscan.md index 5a8c718..4fa1cbd 100644 --- a/doc/evtxscan.md +++ b/doc/evtxscan.md @@ -99,6 +99,42 @@ Find time skews in an evtx file +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `evtxscan` + +This document contains the help content for the `evtxscan` command-line program. + +**Command Overview:** + +* [`evtxscan`↴](#evtxscan) + +## `evtxscan` + +Find time skews in an evtx file + +**Usage:** `evtxscan [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the evtx file to scan + +###### **Options:** + +* `-S`, `--show-records` — display also the contents of the records befor and after a time skew +* `-N`, `--negative-tolerance ` — negative tolerance limit (in seconds): time skews to the past below this limit will be ignored + + Default value: `5` +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/hivescan.md b/doc/hivescan.md index 30ff4be..412f28c 100644 --- a/doc/hivescan.md +++ b/doc/hivescan.md @@ -93,6 +93,40 @@ scans a registry hive file for deleted entries +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `hivescan` + +This document contains the help content for the `hivescan` command-line program. + +**Command Overview:** + +* [`hivescan`↴](#hivescan) + +## `hivescan` + +scans a registry hive file for deleted entries + +**Usage:** `hivescan [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the file to scan + +###### **Options:** + +* `-L`, `--log ` — transaction LOG file(s). This argument can be specified one or two times +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence +* `-b` — output as bodyfile format + + +
diff --git a/doc/ipgrep.md b/doc/ipgrep.md index 0b70d63..43841d8 100644 --- a/doc/ipgrep.md +++ b/doc/ipgrep.md @@ -117,6 +117,48 @@ search for IP addresses in text files +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `ipgrep` + +This document contains the help content for the `ipgrep` command-line program. + +**Command Overview:** + +* [`ipgrep`↴](#ipgrep) + +## `ipgrep` + +search for IP addresses in text files + +**Usage:** `ipgrep [OPTIONS] [FILE]...` + +###### **Arguments:** + +* `` + +###### **Options:** + +* `-i`, `--include ` — display only lines who match ALL of the specified criteria. Values are delimited with comma + + Possible values: `ipv4`, `ipv6`, `public`, `private`, `loopback` + +* `-x`, `--exclude ` — hide lines who match ANY of the specified criteria. Values are delimited with comma + + Possible values: `ipv4`, `ipv6`, `public`, `private`, `loopback` + +* `-I`, `--ignore-ips ` — ignore any of the specified IP addresses. Values are delimited with comma +* `-c`, `--colors` — highlight interesting content using colors +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/lnk2bodyfile.md b/doc/lnk2bodyfile.md index b5dbcdb..28066ae 100644 --- a/doc/lnk2bodyfile.md +++ b/doc/lnk2bodyfile.md @@ -59,6 +59,40 @@ Parse Windows LNK files and create bodyfile output +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `lnk2bodyfile` + +This document contains the help content for the `lnk2bodyfile` command-line program. + +**Command Overview:** + +* [`lnk2bodyfile`↴](#lnk2bodyfile) + +## `lnk2bodyfile` + +Parse Windows LNK files and create bodyfile output + +**Usage:** `lnk2bodyfile [OPTIONS] [LNK_FILES]...` + +###### **Arguments:** + +* `` — Names of the LNK files to read from + + Default value: `-` + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/mactime2.md b/doc/mactime2.md index 51cd312..b24ce55 100644 --- a/doc/mactime2.md +++ b/doc/mactime2.md @@ -123,6 +123,50 @@ replacement for `mactime` +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `mactime2` + +This document contains the help content for the `mactime2` command-line program. + +**Command Overview:** + +* [`mactime2`↴](#mactime2) + +## `mactime2` + +replacement for `mactime` + +**Usage:** `mactime2 [OPTIONS]` + +###### **Options:** + +* `-b ` — path to input file or '-' for stdin (files ending with .gz will be treated as being gzipped) + + Default value: `-` +* `-F`, `--format ` — output format, if not specified, default value is 'txt' + + Possible values: `csv`, `txt`, `json`, `elastic` + +* `-d` — output as CSV instead of TXT. This is a conveniance option, which is identical to `--format=csv` and will be removed in a future release. If you specified `--format` and `-d`, the latter will be ignored +* `-j` — output as JSON instead of TXT. This is a conveniance option, which is identical to `--format=json` and will be removed in a future release. If you specified `--format` and `-j`, the latter will be ignored +* `-f`, `--from-timezone ` — name of offset of source timezone (or 'list' to display all possible values + + Default value: `UTC` +* `-t`, `--to-timezone ` — name of offset of destination timezone (or 'list' to display all possible values + + Default value: `UTC` +* `--strict` — strict mode: do not only warn, but abort if an error occurs +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/pf2bodyfile.md b/doc/pf2bodyfile.md index 1e5e039..f5ffc60 100644 --- a/doc/pf2bodyfile.md +++ b/doc/pf2bodyfile.md @@ -23,6 +23,38 @@ creates bodyfile from Windows Prefetch files +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `pf2bodyfile` + +This document contains the help content for the `pf2bodyfile` command-line program. + +**Command Overview:** + +* [`pf2bodyfile`↴](#pf2bodyfile) + +## `pf2bodyfile` + +creates bodyfile from Windows Prefetch files + +**Usage:** `pf2bodyfile [OPTIONS] [PREFETCH_FILES]...` + +###### **Arguments:** + +* `` — names of the prefetch files (commonly files with 'pf' extension in 'C:\Windows\Prefetch') + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/pol_export.md b/doc/pol_export.md index 880b833..1803abb 100644 --- a/doc/pol_export.md +++ b/doc/pol_export.md @@ -87,6 +87,38 @@ Exporter for Windows Registry Policy Files +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `pol_export` + +This document contains the help content for the `pol_export` command-line program. + +**Command Overview:** + +* [`pol_export`↴](#pol_export) + +## `pol_export` + +Exporter for Windows Registry Policy Files + +**Usage:** `pol_export [OPTIONS] ` + +###### **Arguments:** + +* `` — Name of the file to read + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/regdump.md b/doc/regdump.md index 5ee419e..6744afa 100644 --- a/doc/regdump.md +++ b/doc/regdump.md @@ -99,6 +99,42 @@ parses registry hive files and prints a bodyfile +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `regdump` + +This document contains the help content for the `regdump` command-line program. + +**Command Overview:** + +* [`regdump`↴](#regdump) + +## `regdump` + +parses registry hive files and prints a bodyfile + +**Usage:** `regdump [OPTIONS] ` + +###### **Arguments:** + +* `` — name of the file to dump + +###### **Options:** + +* `-L`, `--log ` — transaction LOG file(s). This argument can be specified one or two times +* `-b`, `--bodyfile` — print as bodyfile format +* `-I`, `--ignore-base-block` — ignore the base block (e.g. if it was encrypted by some ransomware) +* `-T`, `--hide-timestamps` — hide timestamps, if output is in reg format +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence + + +
diff --git a/doc/ts2date.md b/doc/ts2date.md index ef63264..c2ebada 100644 --- a/doc/ts2date.md +++ b/doc/ts2date.md @@ -120,6 +120,49 @@ replaces UNIX timestamps in a stream by a formatted date +
+ + + This document was generated automatically by + clap-markdown. + + +# Command-Line Help for `ts2date` + +This document contains the help content for the `ts2date` command-line program. + +**Command Overview:** + +* [`ts2date`↴](#ts2date) + +## `ts2date` + +replaces UNIX timestamps in a stream by a formatted date + +**Usage:** `ts2date [OPTIONS] [INPUT_FILE] [OUTPUT_FILE]` + +###### **Arguments:** + +* `` — name of the file to read (default from stdin) + + Default value: `-` +* `` — name of the file to write (default to stdout) + + Default value: `-` + +###### **Options:** + +* `-v`, `--verbose` — More output per occurrence +* `-q`, `--quiet` — Less output per occurrence +* `-f`, `--from-timezone ` — name of offset of source timezone (or 'list' to display all possible values + + Default value: `UTC` +* `-t`, `--to-timezone ` — name of offset of destination timezone (or 'list' to display all possible values + + Default value: `UTC` + + +