From 8b58d6cc752875b2ae6b77589d67d8e0dc130cfb Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Fri, 22 Sep 2023 12:17:00 +0200 Subject: [PATCH 01/19] Add client to lnk2bodyfile --- Cargo.toml | 6 ++++++ src/bin/lnk2bodyfile/cli.rs | 22 ++++++++++++++++++++++ src/bin/lnk2bodyfile/main.rs | 11 +++++++++++ 3 files changed, 39 insertions(+) create mode 100644 src/bin/lnk2bodyfile/cli.rs create mode 100644 src/bin/lnk2bodyfile/main.rs diff --git a/Cargo.toml b/Cargo.toml index f218c7d..2b52c33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,11 @@ name = "ipgrep" path = "src/bin/ipgrep/main.rs" required-features = ["ipgrep"] +[[bin]] +name = "lnk2bodyfile" +path = "src/bin/lnk2bodyfile/main.rs" +required-features = ["lnk2bodyfile"] + # 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"] @@ -81,6 +86,7 @@ evtxls = ["evtx", "colored", "lazy-regex", "regex", "sigpipe", "dfirtk-eventdata evtxanalyze = ["evtx", "dfirtk-sessionevent-derive", "dfirtk-eventdata"] evtx2bodyfile = ["evtx", "getset", "ouroboros", "indicatif"] ipgrep = [] +lnk2bodyfile = [] regdump = ["nt_hive2"] hivescan = ["nt_hive2"] diff --git a/src/bin/lnk2bodyfile/cli.rs b/src/bin/lnk2bodyfile/cli.rs new file mode 100644 index 0000000..540baee --- /dev/null +++ b/src/bin/lnk2bodyfile/cli.rs @@ -0,0 +1,22 @@ +use clap::{Parser, ValueHint}; +use dfir_toolkit::common::HasVerboseFlag; +use log::LevelFilter; +use clio::{Input,Output}; + +/// Parse Windows LNK files and create bodyfile output +#[derive(Parser, Debug)] +#[clap(name=env!("CARGO_BIN_NAME"), author, version, long_about = None)] +pub (crate) struct Cli { + /// Name of the LNK files to read from + #[clap(value_parser, value_hint=ValueHint::FilePath, default_value="-", display_order(100))] + pub(crate) input_file: Input, + + #[clap(flatten)] + pub (crate) verbose: clap_verbosity_flag::Verbosity, +} + +impl HasVerboseFlag for Cli { + fn log_level_filter(&self) -> LevelFilter { + self.verbose.log_level_filter() + } +} \ No newline at end of file diff --git a/src/bin/lnk2bodyfile/main.rs b/src/bin/lnk2bodyfile/main.rs new file mode 100644 index 0000000..367c976 --- /dev/null +++ b/src/bin/lnk2bodyfile/main.rs @@ -0,0 +1,11 @@ +use dfir_toolkit::common::FancyParser; +use cli::Cli; +use anyhow::Result; + +mod cli; + +fn main() -> Result<()> { + let cli = Cli::parse_cli(); + + Ok(()) +} \ No newline at end of file From 40a4bb3171729edfe34bcd103d4ff3db8a46143a Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Sun, 24 Sep 2023 16:54:27 +0200 Subject: [PATCH 02/19] Add first try of lnk2bodyfile --- Cargo.lock | 98 +++++++++++++++++++++++++++++++++--- Cargo.toml | 5 +- src/bin/lnk2bodyfile/cli.rs | 2 +- src/bin/lnk2bodyfile/main.rs | 10 ++++ 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b918a32..e15059c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,6 +47,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "anstream" version = "0.3.2" @@ -224,6 +233,15 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +[[package]] +name = "bitreader" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd859c9d97f7c468252795b35aeccc412bdbb1e90ee6969c4fa6328272eaeff" +dependencies = [ + "cfg-if", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -338,6 +356,21 @@ dependencies = [ "phf_codegen", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap 0.11.0", + "unicode-width", + "vec_map", +] + [[package]] name = "clap" version = "3.2.25" @@ -348,9 +381,9 @@ dependencies = [ "bitflags 1.3.2", "clap_lex 0.2.4", "indexmap", - "strsim", + "strsim 0.10.0", "termcolor", - "textwrap", + "textwrap 0.16.0", ] [[package]] @@ -393,7 +426,7 @@ dependencies = [ "anstyle", "clap_lex 0.5.0", "once_cell", - "strsim", + "strsim 0.10.0", "terminal_size", ] @@ -628,7 +661,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] @@ -642,7 +675,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 2.0.23", ] @@ -681,7 +714,7 @@ dependencies = [ [[package]] name = "dfir-toolkit" -version = "0.7.5-dev" +version = "0.7.6-dev" dependencies = [ "anyhow", "assert-json-diff", @@ -710,6 +743,7 @@ dependencies = [ "getset", "indicatif", "lazy-regex", + "lnk_parser", "log", "matches", "more-asserts", @@ -1470,6 +1504,22 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +[[package]] +name = "lnk_parser" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578c47ca1d1a3bc6aa759696292a4c61407a41cf038ee07ed96113a9ac64e516" +dependencies = [ + "byteorder", + "chrono", + "clap 2.34.0", + "getset", + "glob", + "serde", + "serde_json", + "winparsingtools", +] + [[package]] name = "lock_api" version = "0.4.10" @@ -2383,6 +2433,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.10.0" @@ -2502,6 +2558,15 @@ dependencies = [ "winapi 0.2.8", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "textwrap" version = "0.16.0" @@ -2741,6 +2806,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.4" @@ -3059,6 +3130,21 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winparsingtools" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dd921a63230e1e38bc97c26beb5e0be6dc750415c26a179768b15943efcc6f4" +dependencies = [ + "bitreader", + "byteorder", + "chrono", + "encoding_rs", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "winreg" version = "0.10.1" diff --git a/Cargo.toml b/Cargo.toml index 2b52c33..21a40f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dfir-toolkit" -version = "0.7.5-dev" +version = "0.7.6-dev" edition = "2021" authors = ["Jan Starke ", "Deborah Mahn "] description = "CLI tools for digital forensics and incident response" @@ -156,6 +156,9 @@ strum_macros = {version="0", optional=true} # nt-hive2 nt_hive2 = {version="4.0.1", optional=true} +# lnk2bodyfile +lnk_parser = "0.4.0" + [dev-dependencies] # mactime2 diff --git a/src/bin/lnk2bodyfile/cli.rs b/src/bin/lnk2bodyfile/cli.rs index 540baee..b81034b 100644 --- a/src/bin/lnk2bodyfile/cli.rs +++ b/src/bin/lnk2bodyfile/cli.rs @@ -9,7 +9,7 @@ use clio::{Input,Output}; pub (crate) struct Cli { /// Name of the LNK files to read from #[clap(value_parser, value_hint=ValueHint::FilePath, default_value="-", display_order(100))] - pub(crate) input_file: Input, + pub(crate) lnk_files: Vec, #[clap(flatten)] pub (crate) verbose: clap_verbosity_flag::Verbosity, diff --git a/src/bin/lnk2bodyfile/main.rs b/src/bin/lnk2bodyfile/main.rs index 367c976..0bb70e7 100644 --- a/src/bin/lnk2bodyfile/main.rs +++ b/src/bin/lnk2bodyfile/main.rs @@ -1,11 +1,21 @@ use dfir_toolkit::common::FancyParser; use cli::Cli; use anyhow::Result; +use lnk_parser; mod cli; fn main() -> Result<()> { let cli = Cli::parse_cli(); + for filename in cli.lnk_files { + match LnkFile::try_from(&filename[..]) { + Ok(lnk_file) => lnk_file.print_bodyfile(), + Err(why) => log::error!("unable to open {filename}: {why}"), + } + } + + println!("test"); + Ok(()) } \ No newline at end of file From 4f46608f1612bf4d7926a7e5274db4766e18301b Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Mon, 25 Sep 2023 12:49:27 +0200 Subject: [PATCH 03/19] Edit Cargo.toml --- Cargo.toml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 21a40f8..cc6a17b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,11 +67,6 @@ name = "ipgrep" path = "src/bin/ipgrep/main.rs" required-features = ["ipgrep"] -[[bin]] -name = "lnk2bodyfile" -path = "src/bin/lnk2bodyfile/main.rs" -required-features = ["lnk2bodyfile"] - # 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"] @@ -86,7 +81,6 @@ evtxls = ["evtx", "colored", "lazy-regex", "regex", "sigpipe", "dfirtk-eventdata evtxanalyze = ["evtx", "dfirtk-sessionevent-derive", "dfirtk-eventdata"] evtx2bodyfile = ["evtx", "getset", "ouroboros", "indicatif"] ipgrep = [] -lnk2bodyfile = [] regdump = ["nt_hive2"] hivescan = ["nt_hive2"] From 6b790a88a6aeae46d350b7ffa573a8e7693e7061 Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Thu, 28 Sep 2023 12:34:01 +0200 Subject: [PATCH 04/19] Integrate lnk2bodyfile with crate lnk --- Cargo.lock | 113 ++++++++++++------------------- Cargo.toml | 12 +++- src/bin/lnk2bodyfile/cli.rs | 4 +- src/bin/lnk2bodyfile/lnk_file.rs | 52 ++++++++++++++ src/bin/lnk2bodyfile/main.rs | 21 +++--- 5 files changed, 121 insertions(+), 81 deletions(-) create mode 100644 src/bin/lnk2bodyfile/lnk_file.rs diff --git a/Cargo.lock b/Cargo.lock index d6f1bd7..5dd4833 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,15 +47,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "anstream" version = "0.5.0" @@ -374,21 +365,6 @@ dependencies = [ "phf_codegen", ] -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", - "strsim 0.8.0", - "textwrap 0.11.0", - "unicode-width", - "vec_map", -] - [[package]] name = "clap" version = "3.2.25" @@ -399,16 +375,16 @@ dependencies = [ "bitflags 1.3.2", "clap_lex 0.2.4", "indexmap", - "strsim 0.10.0", + "strsim", "termcolor", - "textwrap 0.16.0", + "textwrap", ] [[package]] name = "clap" -version = "4.4.4" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" +checksum = "824956d0dca8334758a5b7f7e50518d66ea319330cbceedcf76905c2f6ab30e3" dependencies = [ "clap_builder", "clap_derive", @@ -420,7 +396,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "325f50228f76921784b6d9f2d62de6778d834483248eefecd27279174797e579" dependencies = [ - "clap 4.4.4", + "clap 4.4.5", ] [[package]] @@ -429,31 +405,30 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1eef05769009513df2eb1c3b4613e7fad873a14c600ff025b08f250f59fee7de" dependencies = [ - "clap 4.4.4", + "clap 4.4.5", "log", ] [[package]] name = "clap_builder" -version = "4.4.4" +version = "4.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" +checksum = "122ec64120a49b4563ccaedcbea7818d069ed8e9aa6d829b82d8a4128936b2ab" dependencies = [ "anstream", "anstyle", - "clap_lex 0.5.0", - "once_cell", + "clap_lex 0.5.1", "strsim", "terminal_size", ] [[package]] name = "clap_complete" -version = "4.4.1" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4110a1e6af615a9e6d0a36f805d5c99099f8bab9b8042f5bc1fa220a4a89e36f" +checksum = "8baeccdb91cd69189985f87f3c7e453a3a451ab5746cf3be6acc92120bd16d24" dependencies = [ - "clap 4.4.4", + "clap 4.4.5", ] [[package]] @@ -490,7 +465,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "746ce4269bee03af43b3349f37f420cf5957f8431c531c08dea0441b298b10e0" dependencies = [ "cfg-if", - "clap 4.4.4", + "clap 4.4.5", "is-terminal", "libc", "tempfile", @@ -668,7 +643,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn 1.0.109", ] @@ -683,7 +658,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.23", + "syn 2.0.37", ] [[package]] @@ -727,7 +702,7 @@ dependencies = [ [[package]] name = "dfir-toolkit" -version = "0.7.5-dev" +version = "0.8.2" dependencies = [ "anyhow", "assert-json-diff", @@ -737,7 +712,7 @@ dependencies = [ "bitflags 2.4.0", "chrono", "chrono-tz", - "clap 4.4.4", + "clap 4.4.5", "clap-markdown", "clap-verbosity-flag", "clap_complete", @@ -757,7 +732,7 @@ dependencies = [ "getset", "indicatif", "lazy-regex", - "lnk_parser", + "lnk", "log", "matches", "more-asserts", @@ -1033,9 +1008,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "flate2" @@ -1495,13 +1470,21 @@ checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" name = "linux-raw-sys" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" [[package]] -name = "linux-raw-sys" -version = "0.4.3" +name = "lnk" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "e066ce29d4da51727b57c404c1270e3fa2a5ded0db1a4cb67c61f7a132421b2c" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "chrono", + "log", + "num-derive 0.3.3", + "num-traits", +] [[package]] name = "lock_api" @@ -2327,9 +2310,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -2433,12 +2416,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" @@ -2557,6 +2534,12 @@ dependencies = [ "winapi 0.2.8", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "textwrap" version = "0.16.0" @@ -2565,18 +2548,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", @@ -2785,12 +2768,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" @@ -3110,7 +3087,7 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winreg" diff --git a/Cargo.toml b/Cargo.toml index c731954..5cbcaf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dfir-toolkit" -version = "0.8.1" +version = "0.8.2" edition = "2021" authors = ["Jan Starke ", "Deborah Mahn "] description = "CLI tools for digital forensics and incident response" @@ -72,9 +72,14 @@ name = "ts2date" path = "src/bin/ts2date/main.rs" required-features = ["ts2date"] +[[bin]] +name = "lnk2bodyfile" +path = "src/bin/lnk2bodyfile/main.rs" +required-features = ["lnk2bodyfile"] + # 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"] +default = ["pol_export", "mactime2", "evtxtools", "regdump", "hivescan", "cleanhive", "ipgrep", "ts2date", "lnk2bodyfile"] 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"] @@ -87,6 +92,7 @@ evtxanalyze = ["evtx", "dfirtk-sessionevent-derive", "dfirtk-eventdata"] evtx2bodyfile = ["evtx", "getset", "ouroboros", "indicatif"] ipgrep = [] ts2date = ["regex"] +lnk2bodyfile = ["lnk"] regdump = ["nt_hive2"] hivescan = ["nt_hive2"] @@ -157,7 +163,7 @@ strum_macros = {version="0", optional=true} nt_hive2 = {version="4.0.1", optional=true} # lnk2bodyfile -lnk_parser = "0.4.0" +lnk = {version="0.5.1", optional=true} [dev-dependencies] diff --git a/src/bin/lnk2bodyfile/cli.rs b/src/bin/lnk2bodyfile/cli.rs index b81034b..b9405e9 100644 --- a/src/bin/lnk2bodyfile/cli.rs +++ b/src/bin/lnk2bodyfile/cli.rs @@ -1,13 +1,13 @@ use clap::{Parser, ValueHint}; use dfir_toolkit::common::HasVerboseFlag; use log::LevelFilter; -use clio::{Input,Output}; +use clio::Input; /// Parse Windows LNK files and create bodyfile output #[derive(Parser, Debug)] #[clap(name=env!("CARGO_BIN_NAME"), author, version, long_about = None)] pub (crate) struct Cli { - /// Name of the LNK files to read from + /// Names of the LNK files to read from #[clap(value_parser, value_hint=ValueHint::FilePath, default_value="-", display_order(100))] pub(crate) lnk_files: Vec, diff --git a/src/bin/lnk2bodyfile/lnk_file.rs b/src/bin/lnk2bodyfile/lnk_file.rs new file mode 100644 index 0000000..4e02c52 --- /dev/null +++ b/src/bin/lnk2bodyfile/lnk_file.rs @@ -0,0 +1,52 @@ +use chrono::{DateTime, Utc}; +use clio::Input; +use dfir_toolkit::common::bodyfile::Bodyfile3Line; +use lnk::{ShellLinkHeader, ShellLink, LinkInfo}; + + +pub struct LnkFile { + lnk_file: ShellLink, + file_name: String, +} + +impl LnkFile { + pub fn print_bodyfile(&self) { + self.print_bodyfile_for_me(); + } + + fn print_bodyfile_for_me(&self) { + let header = self.lnk_file.header(); + let linkinfo = self.lnk_file.link_info().clone().unwrap(); + let localpath = match LinkInfo::local_base_path(&linkinfo) { + Some(s) => s, + None => "-", + }; + let arguments = match self.lnk_file.arguments() { + Some(s) => s, + None => "-", + }; + let atime = ShellLinkHeader::access_time(header); + let mtime = ShellLinkHeader::write_time(header); + let ctime = ShellLinkHeader::creation_time(header); + + let bfline = Bodyfile3Line::new() + .with_name(&format!("{} {} (referred to by \"{}\")", localpath, arguments, self.file_name)) + .with_size(ShellLinkHeader::file_size(header).into()) + .with_ctime(DateTime::::from_naive_utc_and_offset(ctime.datetime(), Utc).timestamp()) + .with_mtime(DateTime::::from_naive_utc_and_offset(mtime.datetime(), Utc).timestamp()) + .with_atime(DateTime::::from_naive_utc_and_offset(atime.datetime(), Utc).timestamp()); + + println!("{bfline}"); + } +} + +impl From<&Input> for LnkFile { + fn from(input: &Input) -> Self { + let file_path = input.path().to_path_buf(); + let file_name = file_path.to_str().unwrap().to_string(); + let lnk_file = ShellLink::open(file_path).unwrap(); + + Self { lnk_file, file_name } + } +} + diff --git a/src/bin/lnk2bodyfile/main.rs b/src/bin/lnk2bodyfile/main.rs index 0bb70e7..5c16893 100644 --- a/src/bin/lnk2bodyfile/main.rs +++ b/src/bin/lnk2bodyfile/main.rs @@ -1,21 +1,26 @@ use dfir_toolkit::common::FancyParser; use cli::Cli; -use anyhow::Result; -use lnk_parser; +use anyhow::{Result, bail}; + +use crate::lnk_file::LnkFile; mod cli; +mod lnk_file; fn main() -> Result<()> { let cli = Cli::parse_cli(); - for filename in cli.lnk_files { - match LnkFile::try_from(&filename[..]) { - Ok(lnk_file) => lnk_file.print_bodyfile(), - Err(why) => log::error!("unable to open {filename}: {why}"), - } + if cli.lnk_files.iter().any(|f| !f.can_seek()) { + bail!( + "{} cannot read from a stream; you must specify a file", + env!("CARGO_BIN_NAME") + ); } - println!("test"); + for filename in cli.lnk_files.iter() { + let lnkfile = LnkFile::from(filename); + lnkfile.print_bodyfile(); + } Ok(()) } \ No newline at end of file From b37695d2519e162cba5e603b151f061b30de4f5f Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Thu, 28 Sep 2023 13:26:19 +0200 Subject: [PATCH 05/19] Add error handling for lnk2bodyfile parsing --- src/bin/lnk2bodyfile/lnk_file.rs | 14 +++++++++----- src/bin/lnk2bodyfile/main.rs | 5 ++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/bin/lnk2bodyfile/lnk_file.rs b/src/bin/lnk2bodyfile/lnk_file.rs index 4e02c52..fbec192 100644 --- a/src/bin/lnk2bodyfile/lnk_file.rs +++ b/src/bin/lnk2bodyfile/lnk_file.rs @@ -1,3 +1,4 @@ +use anyhow::bail; use chrono::{DateTime, Utc}; use clio::Input; use dfir_toolkit::common::bodyfile::Bodyfile3Line; @@ -40,13 +41,16 @@ impl LnkFile { } } -impl From<&Input> for LnkFile { - fn from(input: &Input) -> Self { +impl TryFrom<&Input> for LnkFile { + type Error = anyhow::Error; + + fn try_from(input: &Input) -> Result { let file_path = input.path().to_path_buf(); let file_name = file_path.to_str().unwrap().to_string(); - let lnk_file = ShellLink::open(file_path).unwrap(); - - Self { lnk_file, file_name } + match ShellLink::open(file_path) { + Ok(lnk_file) => Ok ( Self { lnk_file, file_name }), + Err(e) => bail!("{:?}: The file {} is not in a valid ShellLink format", e, file_name), + } } } diff --git a/src/bin/lnk2bodyfile/main.rs b/src/bin/lnk2bodyfile/main.rs index 5c16893..0f172d5 100644 --- a/src/bin/lnk2bodyfile/main.rs +++ b/src/bin/lnk2bodyfile/main.rs @@ -18,7 +18,10 @@ fn main() -> Result<()> { } for filename in cli.lnk_files.iter() { - let lnkfile = LnkFile::from(filename); + let lnkfile = match LnkFile::try_from(filename) { + Ok(file) => file, + Err(e) => {println!("{:#?}", e); continue;}, + }; lnkfile.print_bodyfile(); } From 6849514f50122768ce4bf3dcae3dd4c052cea845 Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Thu, 28 Sep 2023 14:00:14 +0200 Subject: [PATCH 06/19] modify error output --- src/bin/lnk2bodyfile/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/lnk2bodyfile/main.rs b/src/bin/lnk2bodyfile/main.rs index 0f172d5..816ab7b 100644 --- a/src/bin/lnk2bodyfile/main.rs +++ b/src/bin/lnk2bodyfile/main.rs @@ -20,7 +20,7 @@ fn main() -> Result<()> { for filename in cli.lnk_files.iter() { let lnkfile = match LnkFile::try_from(filename) { Ok(file) => file, - Err(e) => {println!("{:#?}", e); continue;}, + Err(why) => {log::error!("{why}"); continue;}, }; lnkfile.print_bodyfile(); } From e80db0a39cf8061d1098c8467740e38a74c5e2dd Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Thu, 28 Sep 2023 14:24:42 +0200 Subject: [PATCH 07/19] add more error handling --- src/bin/lnk2bodyfile/lnk_file.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/bin/lnk2bodyfile/lnk_file.rs b/src/bin/lnk2bodyfile/lnk_file.rs index fbec192..ca6f2bb 100644 --- a/src/bin/lnk2bodyfile/lnk_file.rs +++ b/src/bin/lnk2bodyfile/lnk_file.rs @@ -17,9 +17,11 @@ impl LnkFile { fn print_bodyfile_for_me(&self) { let header = self.lnk_file.header(); - let linkinfo = self.lnk_file.link_info().clone().unwrap(); - let localpath = match LinkInfo::local_base_path(&linkinfo) { - Some(s) => s, + let localpath = match self.lnk_file.link_info() { + Some(s1) => match LinkInfo::local_base_path(s1) { + Some(s2) => s2, + None => "-", + }, None => "-", }; let arguments = match self.lnk_file.arguments() { @@ -46,7 +48,7 @@ impl TryFrom<&Input> for LnkFile { fn try_from(input: &Input) -> Result { let file_path = input.path().to_path_buf(); - let file_name = file_path.to_str().unwrap().to_string(); + let file_name = file_path.file_name().unwrap().to_str().unwrap().to_string(); match ShellLink::open(file_path) { Ok(lnk_file) => Ok ( Self { lnk_file, file_name }), Err(e) => bail!("{:?}: The file {} is not in a valid ShellLink format", e, file_name), From 71a5f1b3dded219d61f3378dacbcf1af6d119fd6 Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Thu, 28 Sep 2023 14:53:00 +0200 Subject: [PATCH 08/19] Update md Script --- scripts/update-md.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update-md.sh b/scripts/update-md.sh index 5bfa3fa..e4be5a4 100755 --- a/scripts/update-md.sh +++ b/scripts/update-md.sh @@ -28,7 +28,7 @@ cat >README.md <<'EOF' - [x] [`es4forensics`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/es4forensics.md) - [x] [`hivescan`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/hivescan.md) - [x] [`ipgrep`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/ipgrep.md) - - [ ] [`lnk2bodyfile`](https://github.com/janstarke/lnk2bodyfile) + - [x] [`lnk2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/lnk2bodyfile.md) - [x] [`mactime2`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/mactime2.md) - [ ] [`mft2bodyfile`](https://github.com/janstarke/mft2bodyfile) - [ ] [`ntdsextract2`](https://github.com/janstarke/ntdsextract2) From 450bbba9e07a55db94e9899b6604b084e96642ba Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Mon, 30 Oct 2023 10:59:05 +0100 Subject: [PATCH 09/19] Update lnk2bodyfile files --- src/bin/lnk2bodyfile/lnk_file.rs | 32 +++++++++++++++++++++++--------- src/bin/lnk2bodyfile/main.rs | 11 +++++++---- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/bin/lnk2bodyfile/lnk_file.rs b/src/bin/lnk2bodyfile/lnk_file.rs index ca6f2bb..08449e5 100644 --- a/src/bin/lnk2bodyfile/lnk_file.rs +++ b/src/bin/lnk2bodyfile/lnk_file.rs @@ -2,8 +2,7 @@ use anyhow::bail; use chrono::{DateTime, Utc}; use clio::Input; use dfir_toolkit::common::bodyfile::Bodyfile3Line; -use lnk::{ShellLinkHeader, ShellLink, LinkInfo}; - +use lnk::{LinkInfo, ShellLink, ShellLinkHeader}; pub struct LnkFile { lnk_file: ShellLink, @@ -33,11 +32,20 @@ impl LnkFile { let ctime = ShellLinkHeader::creation_time(header); let bfline = Bodyfile3Line::new() - .with_name(&format!("{} {} (referred to by \"{}\")", localpath, arguments, self.file_name)) + .with_name(&format!( + "{} {} (referred to by \"{}\")", + localpath, arguments, self.file_name + )) .with_size(ShellLinkHeader::file_size(header).into()) - .with_ctime(DateTime::::from_naive_utc_and_offset(ctime.datetime(), Utc).timestamp()) - .with_mtime(DateTime::::from_naive_utc_and_offset(mtime.datetime(), Utc).timestamp()) - .with_atime(DateTime::::from_naive_utc_and_offset(atime.datetime(), Utc).timestamp()); + .with_ctime( + DateTime::::from_naive_utc_and_offset(ctime.datetime(), Utc).timestamp(), + ) + .with_mtime( + DateTime::::from_naive_utc_and_offset(mtime.datetime(), Utc).timestamp(), + ) + .with_atime( + DateTime::::from_naive_utc_and_offset(atime.datetime(), Utc).timestamp(), + ); println!("{bfline}"); } @@ -50,9 +58,15 @@ impl TryFrom<&Input> for LnkFile { let file_path = input.path().to_path_buf(); let file_name = file_path.file_name().unwrap().to_str().unwrap().to_string(); match ShellLink::open(file_path) { - Ok(lnk_file) => Ok ( Self { lnk_file, file_name }), - Err(e) => bail!("{:?}: The file {} is not in a valid ShellLink format", e, file_name), + Ok(lnk_file) => Ok(Self { + lnk_file, + file_name, + }), + Err(e) => bail!( + "{:?}: The file {} is not in a valid ShellLink format", + e, + file_name + ), } } } - diff --git a/src/bin/lnk2bodyfile/main.rs b/src/bin/lnk2bodyfile/main.rs index 816ab7b..e634af1 100644 --- a/src/bin/lnk2bodyfile/main.rs +++ b/src/bin/lnk2bodyfile/main.rs @@ -1,6 +1,6 @@ -use dfir_toolkit::common::FancyParser; +use anyhow::{bail, Result}; use cli::Cli; -use anyhow::{Result, bail}; +use dfir_toolkit::common::FancyParser; use crate::lnk_file::LnkFile; @@ -20,10 +20,13 @@ fn main() -> Result<()> { for filename in cli.lnk_files.iter() { let lnkfile = match LnkFile::try_from(filename) { Ok(file) => file, - Err(why) => {log::error!("{why}"); continue;}, + Err(why) => { + log::error!("{why}"); + continue; + } }; lnkfile.print_bodyfile(); } Ok(()) -} \ No newline at end of file +} From 121fa7a63b3f98b5135c226c28c51b61e850770c Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Thu, 2 Nov 2023 08:46:57 +0100 Subject: [PATCH 10/19] Add test files for lnk2bodyfile --- tests/data/lnk2bodyfile/Forensik - Chrome.lnk | Bin 0 -> 2435 bytes tests/data/lnk2bodyfile/Internet Explorer.lnk | Bin 0 -> 1323 bytes tests/data/lnk2bodyfile/Network Connections.lnk | Bin 0 -> 4017 bytes tests/data/lnk2bodyfile/Pentest.lnk | Bin 0 -> 730 bytes tests/data/lnk2bodyfile/Test_123.lnk | Bin 0 -> 1339 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/lnk2bodyfile/Forensik - Chrome.lnk create mode 100644 tests/data/lnk2bodyfile/Internet Explorer.lnk create mode 100644 tests/data/lnk2bodyfile/Network Connections.lnk create mode 100644 tests/data/lnk2bodyfile/Pentest.lnk create mode 100644 tests/data/lnk2bodyfile/Test_123.lnk diff --git a/tests/data/lnk2bodyfile/Forensik - Chrome.lnk b/tests/data/lnk2bodyfile/Forensik - Chrome.lnk new file mode 100644 index 0000000000000000000000000000000000000000..e6c9e7c7e2abb8dbcfce2bf2184dd9ba3ef480f4 GIT binary patch literal 2435 zcmdT_O>9(E6#j}BA(U7`C51rxM2ke7$IKMlX-Q4%bf$g7Xva5BWbu?vW?tK;GkxRC zs0D*DArWIho4BwGq+m44LK9p-h(u+L!HQxvEEIQ2NE1kOW1`==^V?<`H!keGIp>~x z?!D)H@0@e*ivnnBT}2Ljr8vTW_X8T`d#**EIn_7cR2d^LeSPV4V7_T$`hK;uN%0!H zZ&fSWW50~dX}|Y6E${!h1`m0??`_7eV6Ro%Rh5pyr{oi6^ZpHpnIl8yz^hahu@C~qX5F45?r;MS=No!BJ3CFgHQYL}PbvIc=;L|P zR+8jW#@!@o&ym_l64|z{^_N>XKJ84V-Iohs{lxO_cs`lc!cN96SfvD6rI=a+xm?Cc zC5w(bY1Ko%8wNkCNY{CeHl>4jQI(2=G4?$y2p!fUzI-`ZixO-tN{zKlNUer}c#vm% z>G!|&)y|^!Fs)K9W93WWVZl4p*u+t!K92+F!}hZ0$}Wvb7hMTef|o`jRv^MOr7TON z@_mDa0*oL+QpRNkkMJsFLF5qNGA|5jNUWAQk zs6(1h7)4y~-vos`Q;TXC%e3B(bC$yk{f;q^3_ zlMp)oC%Ia20bQYh<(a&bcVY*}^CWpv*KvL}_3ZSQ7oRXbJ8qxze|Keztc{X*g--6{ zC@r5(+g|Tjpfm%TLsvdM=)3Xw;q7nTd!g$$d%e|q_3hI)HoWm#?i=HeAGZD5dMDrX zwX}bX27U2Z{MR@4g)c+{!O#EN_|A@*?By4zUoFnsNxMjKK3G1|BP97B3-@x?$sXXJ z!OOYm{G4@heK+-@^-?R6bU%7Xor-(7&(HJSoL5?sf`CcvjLsgI?b-YB-1YB0*RS3V zQP04Yz-;DN|Etw`yGpNM<<-)cyh(mJs#*`ZI5@K@JNU`5-0(-k{rU%eQ%AQ^KOsAY bNrzrJe&*1+?#PF?e%kujx33=-eWm>aDH??7 literal 0 HcmV?d00001 diff --git a/tests/data/lnk2bodyfile/Internet Explorer.lnk b/tests/data/lnk2bodyfile/Internet Explorer.lnk new file mode 100644 index 0000000000000000000000000000000000000000..8f94714c36fc53f4f3e7a86c6ea391e66e42a295 GIT binary patch literal 1323 zcmb7DT}V@57=Bk4Nd-z8CWXV86t=maY?~A)>OAvj8=INYCW$-gp>1c*Nz;oiy67St z1VI!Pngm5)^oJou83ZAO*&lhAMs#5p2}O9}MbG=q`7?;>J3Q~-_nz;4&ij6+k%%;T z>mZ57g(Sxyv=;a_GiN>W>5V2+k6+v(GBrZ3h@>Wuiaay!DeYW^k~2KLiAs&eYdff{ zy28JbwQLQLN!Yzk?Uh{ec-?j0s?!L?DVwtB`_p+TY2-ZvvJQ&Om4fxce|2VxJQO39 zIw9LB4B8G-C`2;#Afpnp3w8*Ph0J82ps@Fm9-fJ;WD^_;5KVEJm-@SN$mwdX^}3i# z^D>u(0PiuEvl(23OB+XDlanG~FM~@2G7dJil%Ob1R}telQ30JmZEoSb6bxudkrUC7 z8j}rjLMEzTt`|hTV1VnrY~Tv1Z%?o(R{qune5t(Ve1q_D4DAHkmNdV~z8>He0CIu# zK-tK|a1JzKM4p)18EX$~9ZE><@jD}NITn%Q+S(Mqn13zP5_GqibaV1D%5aIr9AQ~!x9s{`7o8gakw4HzU+~vG~ReofC_qLGtjsxiX zP%AXApxkpZu159d4vW&=rP8m4!v5>J2d>MOiRl)rGFer5?6&sq*W5AX;hoYKi$DLi z--=;p<9xoOCZET5cu(VC-=MwW*3|5K{p^PyJa_C1f~@E$0P;jdz;2)kbLzk>RZLOE zUFCUY-s{X;Z9tD?t{F*2 frJGWv;l`oFz%InQI6(sTCcb=Ro5WO8R$BfBv3v@+ literal 0 HcmV?d00001 diff --git a/tests/data/lnk2bodyfile/Network Connections.lnk b/tests/data/lnk2bodyfile/Network Connections.lnk new file mode 100644 index 0000000000000000000000000000000000000000..0d47150e3ede8a8f025af5cf1540a134c2f70d0f GIT binary patch literal 4017 zcmd5ij;6n_aR7UW1N0zIU$fITpwM|x^8B{WG(X$wV=8W3y>)TW0`n9>2c96-t; zPDO?(2tz?cq$7@~U|~=h`QU^@1{57B9Rj*Fg54HQTk;DeX^IrzemvkKpl>J)-f>Ln)b6@%K95wu--zNK;0 zdrFnqSO?MZg$0EH=UwNw>B7|YTLNk93-_9S0`m~2$fSkjq)N)AQgQ$zngAFHsG@4D zSCO6)C=GoYB~yyPldwy)0wS9BJ%lT(C*V9YYyMBd2adF#2Xq++KDp7Rlr&GL`ziW=#r=}UD6}HM62N|dzsp!_R z+2+q%S>$&Ap#(?DT5P$Z#gh$JvH6*?eV*5*d5Ij zvMKEzQyTFd{z?f=!%8_u!qpSKbfW!l)};&(3Fv`w5}0a15djDTJihXA;PP(H(3!J8 zY&mDyFn@Sr^FPr?=7%{{i5L54ZMvG{(tQxv5ewpA7#4%Zo6j3(<$q9y!P#yEtOyyZ z{w_d}iq4x(#`}OFGC&FhL)-X~W1H>fl_{~V(03Xl&mvCXsl9jmtzg&;cpu;|vYvx1 zH4BvPE}aS}nSotUWAafR`=B5MXi=^U8csn+m?LK z*RnWp+UBoL?a$iUS#ds4>x0n6IQ^N*@M%86(cFlC7l@U1TPT#T6zWUDL45{JilCYIUIM66fF&T88WHXB7*ny92Fe8d-i9=ymjV45$@6$Kq0&pq+t--g{ai}G zf?akODW|aYyc!p0mMU^~??Oo8&cVP5?c+C#qcb-D9CYXc9nZfw;>@#Hf0{|S2(Ul0 zFLPz#`Vj;O0f_7dXwUHvS<%{kUg7SNY4JeI|d-=c$3}AH}7Fdw0QJv zyMx2ZCmz^PW!Y;n=yqo;TK^2zZA`&Pv$-Sei$go^@|=}q2H!^m8=GHJ!ZY|F3jw?+ zVuU}#sUsOFAPLDpk7U3JBNMZDf$@q7IIroET#|qpJ!vLIRGkE@CxT)kQil$yiR;9C z^crwf;QqPs2Zet|i1!A8%q#Ty%8aO&R-f0TwVVB{|9N4%A%oBF8_4|RM2JaWdmf|o zl;ILriE^zG1-b(2GVcA1W>Y=L09?fUnToA203ggE|JmWiLA+=H$p46VJ|4h2e)@YQ z<*yE({7Ku@sOrC_b@1(ow8dBS2Y?p_0z|5cLWD9t6TsZuDRFr`uG{i z<8DT0tlx1ZsQwxah)IsMK59P;GU0DK*>l<6zA1pCWdVRJfYjSJM>9@Tz~=AL{skvg B-WmV^ literal 0 HcmV?d00001 diff --git a/tests/data/lnk2bodyfile/Pentest.lnk b/tests/data/lnk2bodyfile/Pentest.lnk new file mode 100644 index 0000000000000000000000000000000000000000..890ab5079d82ee4725aee01a7bc8f88588479368 GIT binary patch literal 730 zcmeZaU|?VrVFHp23<0_7PY>fvN7 zg9w9szytpa3a_j(1s2`lV9+)&m@CPk?`#zVSA<}MF&Kh5L81Qc0t^AEc_pdEB@7M> zoD3`s@AvfwZ}bJp=mFI{WCbaFh-M!nn*~DvLn=caLkW;929gX6VnFNw#4Uec!!z?z^2>`EfG&hN0BFA+Lkyb92@rh?B7igq6s4r38W^Nm zKzIxcJg%44RT;kaZC2`2+++4KHKTEp@Ya|&f*pq$RA%Qpy(A>>4|FUi1H%GSpn-Z=X)^ezy8XSol)%!D zObI>nUawIEigSUKfHZLcF?wi;0>$`&7#w5_#ifm)*wzH{K{kMO@c?NThD2}(XENk7 z6aih42Mp~Zpg2f39}t6e!_o+d?+U~q_bkgw*07y=NpR~mh6DaLB`$zWmIEmOxrZBw zA)Y{Y6-WgGgC!7y4B04_>$0}Dz+<_GgWeL`iXK^@cm_y;2N2g*&)HbZZSJ-7(@hzt Li*3yyaTovqm@Aw) literal 0 HcmV?d00001 diff --git a/tests/data/lnk2bodyfile/Test_123.lnk b/tests/data/lnk2bodyfile/Test_123.lnk new file mode 100644 index 0000000000000000000000000000000000000000..b5ef3cadd3d87fb66257a64ad886165f73394cad GIT binary patch literal 1339 zcma)6TS(Jk6#r=^n%9v@O6CfTv^M|Sm`-sacuBnEz}t|K;w79pyllpZpqGL!NplLUgkXexH+7K$L zA0}n>ln)qmsPVS;c+rALgkj;iy=_$e+%}b$h6)P-PN$-D5p$1;GqK6#FCvT(H z!Jh?Y7@14tgD_At!A4jZmw;2jx=nQ^yAF=trVe*AaBQ{mOOJS@a>|$WmGe~P;(=#y zpchTd?gqF1SM4muC9;ZHqS=te zpP8^i zACPz4CK1w146*qb06XZ9BRHR=i$~R;S&V9)L|CCT3ae-2WiYLi(4&|W-oZ%|k`1vU z8DID(a zD!E^hZ@g>w_et(H2`C}b{h!~645;B&l5`>)%bl~I&W+TUj_Oa>7mf!$$OlM$SfoP< L|9giFSVO-7#{v63 literal 0 HcmV?d00001 From 03301153956920abe43a7969f6001a090ac88959 Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Thu, 2 Nov 2023 11:03:37 +0100 Subject: [PATCH 11/19] add lnk2bodyfile integration test --- tests/data/lnk2bodyfile/x64dbg.lnk | Bin 0 -> 1981 bytes tests/lnk2bodyfile/mod.rs | 1 + tests/lnk2bodyfile/x64dbg.rs | 39 +++++++++++++++++++++++++++++ tests/mod.rs | 3 ++- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100755 tests/data/lnk2bodyfile/x64dbg.lnk create mode 100644 tests/lnk2bodyfile/mod.rs create mode 100644 tests/lnk2bodyfile/x64dbg.rs diff --git a/tests/data/lnk2bodyfile/x64dbg.lnk b/tests/data/lnk2bodyfile/x64dbg.lnk new file mode 100755 index 0000000000000000000000000000000000000000..a9f589e7c196124c08e857282fa090b6150d5d76 GIT binary patch literal 1981 zcmds1OK1~O6g{bm=|XKK7F+y8B)HIwO^i_o)V673tV&}On+j8CLdGODA!U-*bR)P> zH+7-l&T45zS5m9sLb14V;X-t!MZ_v@)M8y&7lPn?WDs0#ooN9Y! z|0t)bMqXO6wZ49+7TbNYGRLiG4#K6Ia>RP98o~Cq1MQ8cd6h>cmSSe&eA}yo;+;gV zCf)N_z*ha-xZwwa(2zxfGKvgo`;kH#DsuE_piI(E^VtD6B*b-l8=O43unW6&4r>uE zadC&MQ1E)`QsWFkjg;Ube8_XP{106Ga>oQ>No1$g0Mgc#WXHRvc|HW5=((`q!Q zl9Q309C4R0r^{kqe)p7F3HB;;%TWr{))MNWaJ^v49EylLONeJ4lw;{jPQYLZtVTC$ zAX+I$ykWbUv!oUn#&05eB4hXD$TGbH*UBP}-o9fZ8hJ}(Si76_+2OB;Kz z92jgl3#q!l(6lGgW@d3UcQT*tb!HPi>8v*f>*G=FyYskjEbwr}lT$~CWq4Anb^Q{ZLft!H_>H6Nn;CkLCMeG1~YCL-6TkTcf-QHx!O8cz% Hjh5C=`??oQ literal 0 HcmV?d00001 diff --git a/tests/lnk2bodyfile/mod.rs b/tests/lnk2bodyfile/mod.rs new file mode 100644 index 0000000..59aa627 --- /dev/null +++ b/tests/lnk2bodyfile/mod.rs @@ -0,0 +1 @@ +mod x64dbg; \ No newline at end of file diff --git a/tests/lnk2bodyfile/x64dbg.rs b/tests/lnk2bodyfile/x64dbg.rs new file mode 100644 index 0000000..0af82e9 --- /dev/null +++ b/tests/lnk2bodyfile/x64dbg.rs @@ -0,0 +1,39 @@ +use std::{ + io::{BufRead, BufReader, Cursor}, + path::PathBuf, +}; + +use assert_cmd::Command; +use dfir_toolkit::common::bodyfile::Bodyfile3Line; + +#[test] +fn test_x64dbg() { + let mut cmd = Command::cargo_bin("lnk2bodyfile").unwrap(); + let mut data_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); + data_path.push("tests"); + data_path.push("data"); + data_path.push("lnk2bodyfile"); + data_path.push("x64dbg.lnk"); + + let result = cmd.arg(data_path).ok(); + if result.is_err() { + println!("{}", result.as_ref().err().unwrap()); + } + + assert!(result.is_ok()); + + // parse the result as bodyfile 😈 + let reader = BufReader::new(Cursor::new(result.unwrap().stdout)); + let mut lines_iterator = reader.lines(); + let first_line = lines_iterator.next().unwrap().unwrap(); + + let bfline = Bodyfile3Line::try_from(&first_line[..]).unwrap(); + assert_eq!(bfline.get_name(), r#"C:\Program Files\x64dbg\release\x64\x64dbg.exe - (referred to by "x64dbg.lnk")"#); + assert_eq!(*bfline.get_size(), 172768); + assert_eq!(*bfline.get_atime(), 1695724808); + assert_eq!(*bfline.get_mtime(), 1695250410); + assert_eq!(*bfline.get_ctime(), -1); + assert_eq!(*bfline.get_crtime(), 1695724422); + + assert!(lines_iterator.next().is_none()); +} diff --git a/tests/mod.rs b/tests/mod.rs index 9d99919..b6c5636 100644 --- a/tests/mod.rs +++ b/tests/mod.rs @@ -1,2 +1,3 @@ mod mactime2; -mod ts2date; \ No newline at end of file +mod ts2date; +mod lnk2bodyfile; \ No newline at end of file From 0af350a78bf1d6749061aca434706dc8aa06461b Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Thu, 2 Nov 2023 12:10:23 +0100 Subject: [PATCH 12/19] use semantic types for bodyfile times --- src/bin/evtx2bodyfile/bf_data.rs | 4 +- src/bin/hivescan/hivescanapplication.rs | 2 +- src/bin/lnk2bodyfile/lnk_file.rs | 13 +-- src/bin/mactime2/bodyfile/bodyfile_sorter.rs | 38 +++---- src/bin/mactime2/output/csv_output.rs | 4 +- src/bin/mactime2/output/txt_output.rs | 5 +- src/bin/regdump/main.rs | 2 +- src/common/bodyfile/bodyfile3.rs | 51 ++++----- src/common/bodyfile/mod.rs | 3 + src/common/bodyfile/times.rs | 107 +++++++++++++++++++ src/es4forensics/ecs/objects/posix_file.rs | 20 ++-- tests/lnk2bodyfile/x64dbg.rs | 10 +- 12 files changed, 175 insertions(+), 84 deletions(-) create mode 100644 src/common/bodyfile/times.rs diff --git a/src/bin/evtx2bodyfile/bf_data.rs b/src/bin/evtx2bodyfile/bf_data.rs index 842a602..e6d0762 100644 --- a/src/bin/evtx2bodyfile/bf_data.rs +++ b/src/bin/evtx2bodyfile/bf_data.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::{anyhow, bail, Result}; use chrono::{DateTime, Utc}; -use dfir_toolkit::common::bodyfile::Bodyfile3Line; +use dfir_toolkit::common::bodyfile::{Bodyfile3Line, Modified}; use dfir_toolkit::es4forensics::{objects::WindowsEvent, TimelineObject}; use evtx::SerializedEvtxRecord; use getset::{Getters, Setters}; @@ -32,7 +32,7 @@ pub(crate) struct BfData<'a> { impl<'a> BfData<'a> { pub(crate) fn try_into_mactime(&self) -> Result { let bf_line = Bodyfile3Line::new() - .with_mtime(self.timestamp.timestamp()) + .with_mtime(Modified::from(self.timestamp.timestamp())) .with_owned_name(json!(self).to_string()); Ok(bf_line.to_string()) } diff --git a/src/bin/hivescan/hivescanapplication.rs b/src/bin/hivescan/hivescanapplication.rs index a289337..9e2826d 100644 --- a/src/bin/hivescan/hivescanapplication.rs +++ b/src/bin/hivescan/hivescanapplication.rs @@ -68,7 +68,7 @@ impl HiveScanApplication { let bf_line = Bodyfile3Line::new() .with_owned_name(bf_name) .with_inode(&format!("{:x}", entry.offset().0)) - .with_ctime(entry.nk().timestamp().timestamp()); + .with_ctime(entry.nk().timestamp().into()); println!("{}", bf_line); } else if entry.is_deleted() || force_print { println!( diff --git a/src/bin/lnk2bodyfile/lnk_file.rs b/src/bin/lnk2bodyfile/lnk_file.rs index 08449e5..60e78de 100644 --- a/src/bin/lnk2bodyfile/lnk_file.rs +++ b/src/bin/lnk2bodyfile/lnk_file.rs @@ -1,5 +1,4 @@ use anyhow::bail; -use chrono::{DateTime, Utc}; use clio::Input; use dfir_toolkit::common::bodyfile::Bodyfile3Line; use lnk::{LinkInfo, ShellLink, ShellLinkHeader}; @@ -37,15 +36,9 @@ impl LnkFile { localpath, arguments, self.file_name )) .with_size(ShellLinkHeader::file_size(header).into()) - .with_ctime( - DateTime::::from_naive_utc_and_offset(ctime.datetime(), Utc).timestamp(), - ) - .with_mtime( - DateTime::::from_naive_utc_and_offset(mtime.datetime(), Utc).timestamp(), - ) - .with_atime( - DateTime::::from_naive_utc_and_offset(atime.datetime(), Utc).timestamp(), - ); + .with_ctime(ctime.datetime().into()) + .with_mtime(mtime.datetime().into()) + .with_atime(atime.datetime().into()); println!("{bfline}"); } diff --git a/src/bin/mactime2/bodyfile/bodyfile_sorter.rs b/src/bin/mactime2/bodyfile/bodyfile_sorter.rs index fcd9045..d2f7ea6 100644 --- a/src/bin/mactime2/bodyfile/bodyfile_sorter.rs +++ b/src/bin/mactime2/bodyfile/bodyfile_sorter.rs @@ -1,4 +1,4 @@ -use dfir_toolkit::common::bodyfile::Bodyfile3Line; +use dfir_toolkit::common::bodyfile::{Bodyfile3Line, BehavesLikeI64}; use std::borrow::Borrow; use std::cmp::Ordering; use std::collections::{BTreeMap, HashSet}; @@ -59,13 +59,13 @@ fn insert_timestamp( line: Arc, ) { let timestamp = if flag.contains(MACBFlags::M) { - *line.get_mtime() + *line.get_mtime().as_ref().unwrap() } else if flag.contains(MACBFlags::A) { - *line.get_atime() + *line.get_atime().as_ref().unwrap() } else if flag.contains(MACBFlags::C) { - *line.get_ctime() + *line.get_ctime().as_ref().unwrap() } else if flag.contains(MACBFlags::B) { - *line.get_crtime() + *line.get_crtime().as_ref().unwrap() } else { -1 }; @@ -139,10 +139,10 @@ impl BodyfileSorter { } // delete the borrow to line // we need *some* value in mactimes! - if *line.get_mtime() == -1 - && *line.get_atime() == -1 - && *line.get_ctime() == -1 - && *line.get_crtime() == -1 + if line.get_mtime().is_none() + && line.get_atime().is_none() + && line.get_ctime().is_none() + && line.get_crtime().is_none() { insert_timestamp(&mut entries, MACBFlags::NONE, Arc::clone(&line)); continue; @@ -150,31 +150,31 @@ impl BodyfileSorter { let mut flags: [MACBFlags; 4] = [MACBFlags::NONE; 4]; - if *line.get_mtime() != -1 { + if line.get_mtime().is_some() { flags[0] |= MACBFlags::M; } - if *line.get_atime() != -1 { - if line.get_mtime() == line.get_atime() { + if line.get_atime().is_some() { + if line.get_mtime().as_ref() == line.get_atime().as_ref() { flags[0] |= MACBFlags::A; } else { flags[1] |= MACBFlags::A; } } - if *line.get_ctime() != -1 { - if line.get_mtime() == line.get_ctime() { + if line.get_ctime().is_some() { + if line.get_mtime().as_ref() == line.get_ctime().as_ref() { flags[0] |= MACBFlags::C; - } else if line.get_atime() == line.get_ctime() { + } else if line.get_atime().as_ref() == line.get_ctime().as_ref() { flags[1] |= MACBFlags::C; } else { flags[2] |= MACBFlags::C; } } - if *line.get_crtime() != -1 { - if line.get_mtime() == line.get_crtime() { + if line.get_crtime().is_some() { + if line.get_mtime().as_ref() == line.get_crtime().as_ref() { flags[0] |= MACBFlags::B; - } else if line.get_atime() == line.get_crtime() { + } else if line.get_atime().as_ref() == line.get_crtime().as_ref() { flags[1] |= MACBFlags::B; - } else if line.get_ctime() == line.get_crtime() { + } else if line.get_ctime().as_ref() == line.get_crtime().as_ref() { flags[2] |= MACBFlags::B; } else { flags[3] |= MACBFlags::B; diff --git a/src/bin/mactime2/output/csv_output.rs b/src/bin/mactime2/output/csv_output.rs index 28cd50c..7bf74c7 100644 --- a/src/bin/mactime2/output/csv_output.rs +++ b/src/bin/mactime2/output/csv_output.rs @@ -55,7 +55,7 @@ mod tests { let output = CsvOutput::new(Tz::UTC, Tz::UTC); for _ in 1..10 { let unix_ts = rand::random::() as i64; - let bf_line = Bodyfile3Line::new().with_crtime(unix_ts); + let bf_line = Bodyfile3Line::new().with_crtime(unix_ts.into()); let entry = ListEntry { flags: MACBFlags::B, line: Arc::new(bf_line), @@ -82,7 +82,7 @@ mod tests { let tz = random_tz(); let output = CsvOutput::new(tz, tz); let unix_ts = rand::random::() as i64; - let bf_line = Bodyfile3Line::new().with_crtime(unix_ts); + let bf_line = Bodyfile3Line::new().with_crtime(unix_ts.into()); let entry = ListEntry { flags: MACBFlags::B, line: Arc::new(bf_line), diff --git a/src/bin/mactime2/output/txt_output.rs b/src/bin/mactime2/output/txt_output.rs index 4a29786..97330eb 100644 --- a/src/bin/mactime2/output/txt_output.rs +++ b/src/bin/mactime2/output/txt_output.rs @@ -54,6 +54,7 @@ mod tests { use chrono_tz::Tz; use chrono_tz::TZ_VARIANTS; use dfir_toolkit::common::bodyfile::Bodyfile3Line; + use dfir_toolkit::common::bodyfile::Created; use std::sync::Arc; fn random_tz() -> Tz { @@ -67,7 +68,7 @@ mod tests { let output = TxtOutput::new(Tz::UTC, Tz::UTC); for _ in 1..10 { let unix_ts = rand::random::() as i64; - let bf_line = Bodyfile3Line::new().with_crtime(unix_ts); + let bf_line = Bodyfile3Line::new().with_crtime(Created::from(unix_ts)); let entry = ListEntry { flags: MACBFlags::B, line: Arc::new(bf_line), @@ -97,7 +98,7 @@ mod tests { let tz = random_tz(); let output = TxtOutput::new(tz, tz); let unix_ts = rand::random::() as i64; - let bf_line = Bodyfile3Line::new().with_crtime(unix_ts); + let bf_line = Bodyfile3Line::new().with_crtime(Created::from(unix_ts)); let entry = ListEntry { flags: MACBFlags::B, line: Arc::new(bf_line), diff --git a/src/bin/regdump/main.rs b/src/bin/regdump/main.rs index eacea07..8c19f2d 100644 --- a/src/bin/regdump/main.rs +++ b/src/bin/regdump/main.rs @@ -74,7 +74,7 @@ where if cli.display_bodyfile { let bf_line = Bodyfile3Line::new() .with_name(¤t_path) - .with_ctime(keynode.timestamp().timestamp()); + .with_ctime(keynode.timestamp().into()); println!("{}", bf_line); } else { if cli.hide_timestamps { diff --git a/src/common/bodyfile/bodyfile3.rs b/src/common/bodyfile/bodyfile3.rs index 770b024..3836705 100644 --- a/src/common/bodyfile/bodyfile3.rs +++ b/src/common/bodyfile/bodyfile3.rs @@ -4,6 +4,8 @@ use std::convert::TryFrom; use std::error::Error; use std::fmt; +use super::{Accessed, Modified, Changed, Created}; + /// /// This struct implements the bodyfile format generated by TSK 3.x /// @@ -17,10 +19,10 @@ pub struct Bodyfile3Line { uid: u64, gid: u64, size: u64, - atime: i64, - mtime: i64, - ctime: i64, - crtime: i64, + atime: Accessed, + mtime: Modified, + ctime: Changed, + crtime: Created, } impl Default for Bodyfile3Line { @@ -58,10 +60,10 @@ impl Bodyfile3Line { uid: 0, gid: 0, size: 0, - atime: -1, - mtime: -1, - ctime: -1, - crtime: -1, + atime: Default::default(), + mtime: Default::default(), + ctime: Default::default(), + crtime: Default::default(), } } @@ -86,10 +88,10 @@ impl Bodyfile3Line { [with_uid] [uid] [u64]; [with_gid] [gid] [u64]; [with_size] [size] [u64]; - [with_atime] [atime] [i64]; - [with_mtime] [mtime] [i64]; - [with_ctime] [ctime] [i64]; - [with_crtime] [crtime] [i64]; + [with_atime] [atime] [Accessed]; + [with_mtime] [mtime] [Modified]; + [with_ctime] [ctime] [Changed]; + [with_crtime] [crtime] [Created]; )] pub fn method_name(mut self, attribute_name: attribute_type) -> Self { self.attribute_name = attribute_name; @@ -325,26 +327,11 @@ impl TryFrom<&str> for Bodyfile3Line { let size = str::parse::(parts[6 + name_chunks - 1]).or(Err(Self::Error::IllegalSize))?; - let atime = - str::parse::(parts[7 + name_chunks - 1]).or(Err(Self::Error::IllegalATime))?; - if atime < -1 { - return Err(Self::Error::IllegalATime); - } - let mtime = - str::parse::(parts[8 + name_chunks - 1]).or(Err(Self::Error::IllegalMTime))?; - if mtime < -1 { - return Err(Self::Error::IllegalMTime); - } - let ctime = - str::parse::(parts[9 + name_chunks - 1]).or(Err(Self::Error::IllegalCTime))?; - if ctime < -1 { - return Err(Self::Error::IllegalCTime); - } - let crtime = - str::parse::(parts[10 + name_chunks - 1]).or(Err(Self::Error::IllegalCRTime))?; - if crtime < -1 { - return Err(Self::Error::IllegalCRTime); - } + let atime = Accessed::try_from(parts[7 + name_chunks - 1])?; + let mtime = Modified::try_from(parts[8 + name_chunks - 1])?; + let ctime = Changed::try_from(parts[9 + name_chunks - 1])?; + let crtime = Created::try_from(parts[10 + name_chunks - 1])?; + Ok(Self { md5: md5.to_owned(), name: name.to_owned(), diff --git a/src/common/bodyfile/mod.rs b/src/common/bodyfile/mod.rs index 4f7853f..379cb4a 100644 --- a/src/common/bodyfile/mod.rs +++ b/src/common/bodyfile/mod.rs @@ -52,6 +52,9 @@ pub mod bodyfile3; pub use bodyfile3::*; +mod times; +pub use times::*; + #[cfg(test)] mod tests { use super::Bodyfile3Line; diff --git a/src/common/bodyfile/times.rs b/src/common/bodyfile/times.rs new file mode 100644 index 0000000..dc7f6a0 --- /dev/null +++ b/src/common/bodyfile/times.rs @@ -0,0 +1,107 @@ +use crate::common::bodyfile::Bodyfile3ParserError; +use std::fmt::Display; +use chrono::{DateTime, NaiveDateTime, Utc}; + +#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)] +pub struct Accessed(Option); +#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)] +pub struct Modified(Option); +#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)] +pub struct Changed(Option); +#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)] +pub struct Created(Option); + +pub trait BehavesLikeI64: From + From> { + fn as_ref(&self) -> Option<&i64>; + fn is_none(&self) -> bool; + fn is_some(&self) -> bool; +} + +macro_rules! behaves_like_i64 { + ($t: ty, $error: expr) => { + impl BehavesLikeI64 for $t { + fn as_ref(&self) -> Option<&i64> { + self.0.as_ref() + } + fn is_none(&self) -> bool { + self.0.is_none() + } + fn is_some(&self) -> bool { + self.0.is_some() + } + } + + impl From for $t { + fn from(v: i64) -> Self { + if v == -1 { + Self(None) + } else { + Self(Some(v)) + } + } + } + + impl From> for $t { + fn from(v: Option) -> Self { + Self(v) + } + } + + impl From for $t { + fn from(v: NaiveDateTime) -> Self { + Self(Some(DateTime::::from_naive_utc_and_offset(v, Utc).timestamp())) + } + } + + impl From<&NaiveDateTime> for $t { + fn from(v: &NaiveDateTime) -> Self { + Self(Some(DateTime::::from_naive_utc_and_offset(*v, Utc).timestamp())) + } + } + + impl From> for $t { + fn from(v: DateTime::) -> Self { + Self(Some(v.timestamp())) + } + } + + impl From<&DateTime::> for $t { + fn from(v: &DateTime::) -> Self { + Self(Some(v.timestamp())) + } + } + + impl TryFrom<&str> for $t { + type Error = Bodyfile3ParserError; + fn try_from( + val: &str, + ) -> std::result::Result>::Error> { + let my_time = str::parse::(val).or(Err($error))?; + if my_time < -1 { + Err($error) + } else if my_time == -1 { + Ok(Self::default()) + } else { + Ok(Self(Some(my_time))) + } + } + } + + impl Display for $t { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::result::Result<(), std::fmt::Error> { + match self.0 { + None => write!(f, "-1"), + Some(v) => write!(f, "{v}"), + } + } + } + }; +} + +behaves_like_i64!(Accessed, Bodyfile3ParserError::IllegalATime); +behaves_like_i64!(Modified, Bodyfile3ParserError::IllegalMTime); +behaves_like_i64!(Changed, Bodyfile3ParserError::IllegalCTime); +behaves_like_i64!(Created, Bodyfile3ParserError::IllegalCRTime); diff --git a/src/es4forensics/ecs/objects/posix_file.rs b/src/es4forensics/ecs/objects/posix_file.rs index 67cb09e..5b6d961 100644 --- a/src/es4forensics/ecs/objects/posix_file.rs +++ b/src/es4forensics/ecs/objects/posix_file.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use anyhow::Result; -use crate::common::bodyfile::Bodyfile3Line; +use crate::common::bodyfile::{Bodyfile3Line, BehavesLikeI64}; use chrono_tz::Tz; use serde::Serialize; @@ -22,11 +22,11 @@ pub struct PosixFile { } impl PosixFile { - fn load_timestamp(ts: i64, tz: &Tz) -> Result> { - match ts { - -1 => Ok(None), - _ => { - Ok(Some((ts, tz).try_into()?)) + fn load_timestamp(ts: &TS, tz: &Tz) -> Result> where TS: BehavesLikeI64 { + match ts.as_ref() { + None => Ok(None), + Some(ts) => { + Ok(Some((*ts, tz).try_into()?)) } } } @@ -118,10 +118,10 @@ impl TryFrom<(&Bodyfile3Line, &Tz)> for PosixFile { uid: *bfline.get_uid(), gid: *bfline.get_gid(), size: *bfline.get_size(), - atime: Self::load_timestamp(*bfline.get_atime(), src_tz)?, - mtime: Self::load_timestamp(*bfline.get_mtime(), src_tz)?, - ctime: Self::load_timestamp(*bfline.get_ctime(), src_tz)?, - crtime: Self::load_timestamp(*bfline.get_crtime(), src_tz)?, + atime: Self::load_timestamp(bfline.get_atime(), src_tz)?, + mtime: Self::load_timestamp(bfline.get_mtime(), src_tz)?, + ctime: Self::load_timestamp(bfline.get_ctime(), src_tz)?, + crtime: Self::load_timestamp(bfline.get_crtime(), src_tz)?, }) } } diff --git a/tests/lnk2bodyfile/x64dbg.rs b/tests/lnk2bodyfile/x64dbg.rs index 0af82e9..969c9aa 100644 --- a/tests/lnk2bodyfile/x64dbg.rs +++ b/tests/lnk2bodyfile/x64dbg.rs @@ -4,7 +4,7 @@ use std::{ }; use assert_cmd::Command; -use dfir_toolkit::common::bodyfile::Bodyfile3Line; +use dfir_toolkit::common::bodyfile::{Bodyfile3Line, Accessed, Modified, Changed, Created}; #[test] fn test_x64dbg() { @@ -30,10 +30,10 @@ fn test_x64dbg() { let bfline = Bodyfile3Line::try_from(&first_line[..]).unwrap(); assert_eq!(bfline.get_name(), r#"C:\Program Files\x64dbg\release\x64\x64dbg.exe - (referred to by "x64dbg.lnk")"#); assert_eq!(*bfline.get_size(), 172768); - assert_eq!(*bfline.get_atime(), 1695724808); - assert_eq!(*bfline.get_mtime(), 1695250410); - assert_eq!(*bfline.get_ctime(), -1); - assert_eq!(*bfline.get_crtime(), 1695724422); + assert_eq!(*bfline.get_atime(), Accessed::from(1695724808)); + assert_eq!(*bfline.get_mtime(), Modified::from(1695250410)); + assert_eq!(*bfline.get_ctime(), Changed::default()); + assert_eq!(*bfline.get_crtime(), Created::from(1695724422)); assert!(lines_iterator.next().is_none()); } From 8cc9f796da0c523c1a99da87d20d117264e0da62 Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Thu, 2 Nov 2023 12:13:42 +0100 Subject: [PATCH 13/19] fix clippy complaints --- src/bin/evtxanalyze/pstree/mod.rs | 2 +- src/bin/evtxanalyze/pstree/unique_pid.rs | 2 ++ src/bin/mactime2/output/json_sorter.rs | 2 +- src/bin/pol_export/policy_file_entry.rs | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bin/evtxanalyze/pstree/mod.rs b/src/bin/evtxanalyze/pstree/mod.rs index 24366bd..6ca0a7e 100644 --- a/src/bin/evtxanalyze/pstree/mod.rs +++ b/src/bin/evtxanalyze/pstree/mod.rs @@ -42,7 +42,7 @@ pub(crate) fn display_pstree(cli: &Cli) -> anyhow::Result<()> { .map(|r| r.expect("error reading event")) .map(Process::try_from) .filter_map(|r| r.expect("invalid event")) - .filter(|p| has_username(p)) + .filter(has_username) .map(|e| { let pid = UniquePid::from(&e); unique_pids diff --git a/src/bin/evtxanalyze/pstree/unique_pid.rs b/src/bin/evtxanalyze/pstree/unique_pid.rs index 2ff0df6..8d29d30 100644 --- a/src/bin/evtxanalyze/pstree/unique_pid.rs +++ b/src/bin/evtxanalyze/pstree/unique_pid.rs @@ -36,6 +36,8 @@ impl Ord for UniquePid { self.timestamp.cmp(&other.timestamp) } } + +#[allow(clippy::incorrect_partial_ord_impl_on_ord_type)] impl PartialOrd for UniquePid { fn partial_cmp(&self, other: &Self) -> Option { if self.pid != other.pid { diff --git a/src/bin/mactime2/output/json_sorter.rs b/src/bin/mactime2/output/json_sorter.rs index de9c528..a001a1b 100644 --- a/src/bin/mactime2/output/json_sorter.rs +++ b/src/bin/mactime2/output/json_sorter.rs @@ -78,7 +78,7 @@ impl JsonSorter { log::warn!("raw entry is {}", line.to_string()); } else { for (ts, line) in lines { - entries.entry(ts).or_insert(BTreeSet::new()).insert(line); + entries.entry(ts).or_default().insert(line); } } } diff --git a/src/bin/pol_export/policy_file_entry.rs b/src/bin/pol_export/policy_file_entry.rs index b69f192..c79e556 100644 --- a/src/bin/pol_export/policy_file_entry.rs +++ b/src/bin/pol_export/policy_file_entry.rs @@ -56,7 +56,7 @@ fn parse_wide_string(reader: &mut R, _ro: &ReadOptions, _args: ( fn read_char(reader: &mut R, _ro: &ReadOptions, _args: ()) -> BinResult { let b: [u16; 1] = reader.read_le()?; - Ok(char::decode_utf16(b.into_iter()) + Ok(char::decode_utf16(b) .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)) .next() .unwrap()) From 3a7cda157a50876989936b9266ad862dac8608e9 Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Thu, 2 Nov 2023 12:55:07 +0100 Subject: [PATCH 14/19] fix timestamp mapping --- src/bin/lnk2bodyfile/lnk_file.rs | 4 ++-- src/common/bodyfile/bodyfile3.rs | 36 ++++++++++++++++---------------- tests/lnk2bodyfile/x64dbg.rs | 4 ++-- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/bin/lnk2bodyfile/lnk_file.rs b/src/bin/lnk2bodyfile/lnk_file.rs index 60e78de..cccdcb7 100644 --- a/src/bin/lnk2bodyfile/lnk_file.rs +++ b/src/bin/lnk2bodyfile/lnk_file.rs @@ -28,7 +28,7 @@ impl LnkFile { }; let atime = ShellLinkHeader::access_time(header); let mtime = ShellLinkHeader::write_time(header); - let ctime = ShellLinkHeader::creation_time(header); + let crtime = ShellLinkHeader::creation_time(header); let bfline = Bodyfile3Line::new() .with_name(&format!( @@ -36,7 +36,7 @@ impl LnkFile { localpath, arguments, self.file_name )) .with_size(ShellLinkHeader::file_size(header).into()) - .with_ctime(ctime.datetime().into()) + .with_crtime(crtime.datetime().into()) .with_mtime(mtime.datetime().into()) .with_atime(atime.datetime().into()); diff --git a/src/common/bodyfile/bodyfile3.rs b/src/common/bodyfile/bodyfile3.rs index 3836705..009c810 100644 --- a/src/common/bodyfile/bodyfile3.rs +++ b/src/common/bodyfile/bodyfile3.rs @@ -36,7 +36,7 @@ impl Bodyfile3Line { /// /// # Example /// ``` - /// use dfir_toolkit::common::bodyfile::Bodyfile3Line; + /// use dfir_toolkit::common::bodyfile::{BehavesLikeI64, Bodyfile3Line}; /// /// let bf = Bodyfile3Line::new(); /// assert_eq!(bf.get_md5(), "0"); @@ -46,10 +46,10 @@ impl Bodyfile3Line { /// assert_eq!(*bf.get_uid(), 0); /// assert_eq!(*bf.get_gid(), 0); /// assert_eq!(*bf.get_size(), 0); - /// assert_eq!(*bf.get_atime(), -1); - /// assert_eq!(*bf.get_mtime(), -1); - /// assert_eq!(*bf.get_ctime(), -1); - /// assert_eq!(*bf.get_crtime(), -1); + /// assert!(bf.get_atime().is_none()); + /// assert!(bf.get_mtime().is_none()); + /// assert!(bf.get_ctime().is_none()); + /// assert!(bf.get_crtime().is_none()); /// ``` pub fn new() -> Self { Self { @@ -114,10 +114,10 @@ impl fmt::Display for Bodyfile3Line { /// .with_uid(1003) /// .with_gid(500) /// .with_size(126378) - /// .with_atime(12341) - /// .with_mtime(12342) - /// .with_ctime(12343) - /// .with_crtime(12344); + /// .with_atime(12341.into()) + /// .with_mtime(12342.into()) + /// .with_ctime(12343.into()) + /// .with_crtime(12344.into()); /// let line = bf.to_string(); /// assert_eq!(line, "4bad420da66571dac7f1ace995cc55c6|sample.txt|87915-128-1|r/rrwxrwxrwx|1003|500|126378|12341|12342|12343|12344") /// ``` @@ -218,7 +218,7 @@ pub enum Bodyfile3ParserError { /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|X|-1|-1|-1"), Err(Bodyfile3ParserError::IllegalATime)); /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|-5|-1|-1|-1"), Err(Bodyfile3ParserError::IllegalATime)); /// let valid_bf = Bodyfile3Line::try_from("0||0||1|0|0|5|-1|-1|-1").unwrap(); - /// assert_eq!(*valid_bf.get_atime(), 5); + /// assert_eq!(*valid_bf.get_atime(), 5.into()); /// ``` IllegalATime, @@ -234,7 +234,7 @@ pub enum Bodyfile3ParserError { /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|-1|X|-1|-1"), Err(Bodyfile3ParserError::IllegalMTime)); /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|-1|-5|-1|-1"), Err(Bodyfile3ParserError::IllegalMTime)); /// let valid_bf = Bodyfile3Line::try_from("0||0||1|0|0|-1|5|-1|-1").unwrap(); - /// assert_eq!(*valid_bf.get_mtime(), 5); + /// assert_eq!(*valid_bf.get_mtime(), 5.into()); /// ``` IllegalMTime, @@ -250,7 +250,7 @@ pub enum Bodyfile3ParserError { /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|-1|-1|X|-1"), Err(Bodyfile3ParserError::IllegalCTime)); /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|-1|-1|-5|-1"), Err(Bodyfile3ParserError::IllegalCTime)); /// let valid_bf = Bodyfile3Line::try_from("0||0||1|0|0|-1|-1|5|-1").unwrap(); - /// assert_eq!(*valid_bf.get_ctime(), 5); + /// assert_eq!(*valid_bf.get_ctime(), 5.into()); /// ``` IllegalCTime, @@ -266,7 +266,7 @@ pub enum Bodyfile3ParserError { /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|-1|-1|-1|X"), Err(Bodyfile3ParserError::IllegalCRTime)); /// assert_matches!(Bodyfile3Line::try_from("0||0||0|0|0|-1|-1|-1|-5"), Err(Bodyfile3ParserError::IllegalCRTime)); /// let valid_bf = Bodyfile3Line::try_from("0||0||1|0|0|-1|-1|-1|5").unwrap(); - /// assert_eq!(*valid_bf.get_crtime(), 5); + /// assert_eq!(*valid_bf.get_crtime(), 5.into()); /// ``` IllegalCRTime, } @@ -295,7 +295,7 @@ impl TryFrom<&str> for Bodyfile3Line { /// /// # Example /// ``` - /// use dfir_toolkit::common::bodyfile::{Bodyfile3Line, Bodyfile3ParserError}; + /// use dfir_toolkit::common::bodyfile::{Bodyfile3Line, Bodyfile3ParserError, Accessed, Modified, Changed, Created}; /// use std::convert::TryFrom; /// let bf_line = Bodyfile3Line::try_from("0|ls -l |wc|1|2|3|4|5|6|7|8|9").unwrap(); /// assert_eq!(bf_line.get_md5(), "0"); @@ -305,10 +305,10 @@ impl TryFrom<&str> for Bodyfile3Line { /// assert_eq!(*bf_line.get_uid(), 3); /// assert_eq!(*bf_line.get_gid(), 4); /// assert_eq!(*bf_line.get_size(), 5); - /// assert_eq!(*bf_line.get_atime(), 6); - /// assert_eq!(*bf_line.get_mtime(), 7); - /// assert_eq!(*bf_line.get_ctime(), 8); - /// assert_eq!(*bf_line.get_crtime(), 9); + /// assert_eq!(*bf_line.get_atime(), Accessed::from(6)); + /// assert_eq!(*bf_line.get_mtime(), Modified::from(7)); + /// assert_eq!(*bf_line.get_ctime(), Changed::from(8)); + /// assert_eq!(*bf_line.get_crtime(), Created::from(9)); /// ``` fn try_from(line: &str) -> Result { diff --git a/tests/lnk2bodyfile/x64dbg.rs b/tests/lnk2bodyfile/x64dbg.rs index 969c9aa..79d0d7e 100644 --- a/tests/lnk2bodyfile/x64dbg.rs +++ b/tests/lnk2bodyfile/x64dbg.rs @@ -31,9 +31,9 @@ fn test_x64dbg() { assert_eq!(bfline.get_name(), r#"C:\Program Files\x64dbg\release\x64\x64dbg.exe - (referred to by "x64dbg.lnk")"#); assert_eq!(*bfline.get_size(), 172768); assert_eq!(*bfline.get_atime(), Accessed::from(1695724808)); - assert_eq!(*bfline.get_mtime(), Modified::from(1695250410)); + assert_eq!(*bfline.get_mtime(), Modified::from(1695724422)); assert_eq!(*bfline.get_ctime(), Changed::default()); - assert_eq!(*bfline.get_crtime(), Created::from(1695724422)); + assert_eq!(*bfline.get_crtime(), Created::from(1695250410)); assert!(lines_iterator.next().is_none()); } From 548c6563fcd9f6ddf1ca60dc2b3114e007dcf69b Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Thu, 2 Nov 2023 13:37:21 +0100 Subject: [PATCH 15/19] add lnk2bodyfile test file --- tests/data/lnk2bodyfile/Obsidian.lnk | Bin 0 -> 2142 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/lnk2bodyfile/Obsidian.lnk diff --git a/tests/data/lnk2bodyfile/Obsidian.lnk b/tests/data/lnk2bodyfile/Obsidian.lnk new file mode 100644 index 0000000000000000000000000000000000000000..48808f867467d62c6f20a9c57ab1cb73a29cdab6 GIT binary patch literal 2142 zcmds2T}abW6hBL?NlKc-$|8lBX|dt9G?gIN+;lmay5>i%kIgL|x{tO|20Qh)Vb}eJK&r2YXR_3L%Xotf=UB{&TV>Qa<$Jxtx!C{`dawz31HjxdtK< zNwz=|jR=x-Getxhu-jd_-qyr-qOhhf4TeuYr$w_*hT?gsh(!dAijH}w{MVC5SG^{0bivqNdG&++ml@tP2pjv-^C#k*O zVr#$(Pav)C+@qPdrS}?ksfHJ_27_TMtD9E}?bB9MZVO{tg)PQLVGe)YLq@WZpPXa|TM5%?H(ewpaqP=$ zf;TfLj4XGwIEYTJqF1h>r<~#pZH+?bZZx`_9Ml3Pc+EyKNseZTN|Plb#FjO4 z)_TInk&%W9fo4W19pr;#WIMTVL^s%vOW+f(f(LqIs}}x8?DbD1LF~5?bxF-8ZB<2; zQKvU(rT-RePS&O(De`I}Emh$cuEMR*kskL%i(<2}Os*g8O%<+9dl)WJ+wo6a+cCZ* z(!W00S~@jZ7Q5K4g#Q8!-?S8dp#Z1D z;72pM^1>xh8zcj~zf-FlHsouDexy9eeC!%`!7scI48YHj3FTM;&IKz4OG)|Y9VHc7 zF6;s{9;1NHr#wg%Y}PVZd1$%l9|7l64jN;z4v`j$H)75*bYAT&D0? Date: Thu, 2 Nov 2023 13:45:06 +0100 Subject: [PATCH 16/19] delete testfiles from repo --- tests/data/lnk2bodyfile/Forensik - Chrome.lnk | Bin 2435 -> 0 bytes tests/data/lnk2bodyfile/Internet Explorer.lnk | Bin 1323 -> 0 bytes tests/data/lnk2bodyfile/Network Connections.lnk | Bin 4017 -> 0 bytes tests/data/lnk2bodyfile/Pentest.lnk | Bin 730 -> 0 bytes tests/data/lnk2bodyfile/Test_123.lnk | Bin 1339 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/data/lnk2bodyfile/Forensik - Chrome.lnk delete mode 100644 tests/data/lnk2bodyfile/Internet Explorer.lnk delete mode 100644 tests/data/lnk2bodyfile/Network Connections.lnk delete mode 100644 tests/data/lnk2bodyfile/Pentest.lnk delete mode 100644 tests/data/lnk2bodyfile/Test_123.lnk diff --git a/tests/data/lnk2bodyfile/Forensik - Chrome.lnk b/tests/data/lnk2bodyfile/Forensik - Chrome.lnk deleted file mode 100644 index e6c9e7c7e2abb8dbcfce2bf2184dd9ba3ef480f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2435 zcmdT_O>9(E6#j}BA(U7`C51rxM2ke7$IKMlX-Q4%bf$g7Xva5BWbu?vW?tK;GkxRC zs0D*DArWIho4BwGq+m44LK9p-h(u+L!HQxvEEIQ2NE1kOW1`==^V?<`H!keGIp>~x z?!D)H@0@e*ivnnBT}2Ljr8vTW_X8T`d#**EIn_7cR2d^LeSPV4V7_T$`hK;uN%0!H zZ&fSWW50~dX}|Y6E${!h1`m0??`_7eV6Ro%Rh5pyr{oi6^ZpHpnIl8yz^hahu@C~qX5F45?r;MS=No!BJ3CFgHQYL}PbvIc=;L|P zR+8jW#@!@o&ym_l64|z{^_N>XKJ84V-Iohs{lxO_cs`lc!cN96SfvD6rI=a+xm?Cc zC5w(bY1Ko%8wNkCNY{CeHl>4jQI(2=G4?$y2p!fUzI-`ZixO-tN{zKlNUer}c#vm% z>G!|&)y|^!Fs)K9W93WWVZl4p*u+t!K92+F!}hZ0$}Wvb7hMTef|o`jRv^MOr7TON z@_mDa0*oL+QpRNkkMJsFLF5qNGA|5jNUWAQk zs6(1h7)4y~-vos`Q;TXC%e3B(bC$yk{f;q^3_ zlMp)oC%Ia20bQYh<(a&bcVY*}^CWpv*KvL}_3ZSQ7oRXbJ8qxze|Keztc{X*g--6{ zC@r5(+g|Tjpfm%TLsvdM=)3Xw;q7nTd!g$$d%e|q_3hI)HoWm#?i=HeAGZD5dMDrX zwX}bX27U2Z{MR@4g)c+{!O#EN_|A@*?By4zUoFnsNxMjKK3G1|BP97B3-@x?$sXXJ z!OOYm{G4@heK+-@^-?R6bU%7Xor-(7&(HJSoL5?sf`CcvjLsgI?b-YB-1YB0*RS3V zQP04Yz-;DN|Etw`yGpNM<<-)cyh(mJs#*`ZI5@K@JNU`5-0(-k{rU%eQ%AQ^KOsAY bNrzrJe&*1+?#PF?e%kujx33=-eWm>aDH??7 diff --git a/tests/data/lnk2bodyfile/Internet Explorer.lnk b/tests/data/lnk2bodyfile/Internet Explorer.lnk deleted file mode 100644 index 8f94714c36fc53f4f3e7a86c6ea391e66e42a295..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1323 zcmb7DT}V@57=Bk4Nd-z8CWXV86t=maY?~A)>OAvj8=INYCW$-gp>1c*Nz;oiy67St z1VI!Pngm5)^oJou83ZAO*&lhAMs#5p2}O9}MbG=q`7?;>J3Q~-_nz;4&ij6+k%%;T z>mZ57g(Sxyv=;a_GiN>W>5V2+k6+v(GBrZ3h@>Wuiaay!DeYW^k~2KLiAs&eYdff{ zy28JbwQLQLN!Yzk?Uh{ec-?j0s?!L?DVwtB`_p+TY2-ZvvJQ&Om4fxce|2VxJQO39 zIw9LB4B8G-C`2;#Afpnp3w8*Ph0J82ps@Fm9-fJ;WD^_;5KVEJm-@SN$mwdX^}3i# z^D>u(0PiuEvl(23OB+XDlanG~FM~@2G7dJil%Ob1R}telQ30JmZEoSb6bxudkrUC7 z8j}rjLMEzTt`|hTV1VnrY~Tv1Z%?o(R{qune5t(Ve1q_D4DAHkmNdV~z8>He0CIu# zK-tK|a1JzKM4p)18EX$~9ZE><@jD}NITn%Q+S(Mqn13zP5_GqibaV1D%5aIr9AQ~!x9s{`7o8gakw4HzU+~vG~ReofC_qLGtjsxiX zP%AXApxkpZu159d4vW&=rP8m4!v5>J2d>MOiRl)rGFer5?6&sq*W5AX;hoYKi$DLi z--=;p<9xoOCZET5cu(VC-=MwW*3|5K{p^PyJa_C1f~@E$0P;jdz;2)kbLzk>RZLOE zUFCUY-s{X;Z9tD?t{F*2 frJGWv;l`oFz%InQI6(sTCcb=Ro5WO8R$BfBv3v@+ diff --git a/tests/data/lnk2bodyfile/Network Connections.lnk b/tests/data/lnk2bodyfile/Network Connections.lnk deleted file mode 100644 index 0d47150e3ede8a8f025af5cf1540a134c2f70d0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4017 zcmd5ij;6n_aR7UW1N0zIU$fITpwM|x^8B{WG(X$wV=8W3y>)TW0`n9>2c96-t; zPDO?(2tz?cq$7@~U|~=h`QU^@1{57B9Rj*Fg54HQTk;DeX^IrzemvkKpl>J)-f>Ln)b6@%K95wu--zNK;0 zdrFnqSO?MZg$0EH=UwNw>B7|YTLNk93-_9S0`m~2$fSkjq)N)AQgQ$zngAFHsG@4D zSCO6)C=GoYB~yyPldwy)0wS9BJ%lT(C*V9YYyMBd2adF#2Xq++KDp7Rlr&GL`ziW=#r=}UD6}HM62N|dzsp!_R z+2+q%S>$&Ap#(?DT5P$Z#gh$JvH6*?eV*5*d5Ij zvMKEzQyTFd{z?f=!%8_u!qpSKbfW!l)};&(3Fv`w5}0a15djDTJihXA;PP(H(3!J8 zY&mDyFn@Sr^FPr?=7%{{i5L54ZMvG{(tQxv5ewpA7#4%Zo6j3(<$q9y!P#yEtOyyZ z{w_d}iq4x(#`}OFGC&FhL)-X~W1H>fl_{~V(03Xl&mvCXsl9jmtzg&;cpu;|vYvx1 zH4BvPE}aS}nSotUWAafR`=B5MXi=^U8csn+m?LK z*RnWp+UBoL?a$iUS#ds4>x0n6IQ^N*@M%86(cFlC7l@U1TPT#T6zWUDL45{JilCYIUIM66fF&T88WHXB7*ny92Fe8d-i9=ymjV45$@6$Kq0&pq+t--g{ai}G zf?akODW|aYyc!p0mMU^~??Oo8&cVP5?c+C#qcb-D9CYXc9nZfw;>@#Hf0{|S2(Ul0 zFLPz#`Vj;O0f_7dXwUHvS<%{kUg7SNY4JeI|d-=c$3}AH}7Fdw0QJv zyMx2ZCmz^PW!Y;n=yqo;TK^2zZA`&Pv$-Sei$go^@|=}q2H!^m8=GHJ!ZY|F3jw?+ zVuU}#sUsOFAPLDpk7U3JBNMZDf$@q7IIroET#|qpJ!vLIRGkE@CxT)kQil$yiR;9C z^crwf;QqPs2Zet|i1!A8%q#Ty%8aO&R-f0TwVVB{|9N4%A%oBF8_4|RM2JaWdmf|o zl;ILriE^zG1-b(2GVcA1W>Y=L09?fUnToA203ggE|JmWiLA+=H$p46VJ|4h2e)@YQ z<*yE({7Ku@sOrC_b@1(ow8dBS2Y?p_0z|5cLWD9t6TsZuDRFr`uG{i z<8DT0tlx1ZsQwxah)IsMK59P;GU0DK*>l<6zA1pCWdVRJfYjSJM>9@Tz~=AL{skvg B-WmV^ diff --git a/tests/data/lnk2bodyfile/Pentest.lnk b/tests/data/lnk2bodyfile/Pentest.lnk deleted file mode 100644 index 890ab5079d82ee4725aee01a7bc8f88588479368..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 730 zcmeZaU|?VrVFHp23<0_7PY>fvN7 zg9w9szytpa3a_j(1s2`lV9+)&m@CPk?`#zVSA<}MF&Kh5L81Qc0t^AEc_pdEB@7M> zoD3`s@AvfwZ}bJp=mFI{WCbaFh-M!nn*~DvLn=caLkW;929gX6VnFNw#4Uec!!z?z^2>`EfG&hN0BFA+Lkyb92@rh?B7igq6s4r38W^Nm zKzIxcJg%44RT;kaZC2`2+++4KHKTEp@Ya|&f*pq$RA%Qpy(A>>4|FUi1H%GSpn-Z=X)^ezy8XSol)%!D zObI>nUawIEigSUKfHZLcF?wi;0>$`&7#w5_#ifm)*wzH{K{kMO@c?NThD2}(XENk7 z6aih42Mp~Zpg2f39}t6e!_o+d?+U~q_bkgw*07y=NpR~mh6DaLB`$zWmIEmOxrZBw zA)Y{Y6-WgGgC!7y4B04_>$0}Dz+<_GgWeL`iXK^@cm_y;2N2g*&)HbZZSJ-7(@hzt Li*3yyaTovqm@Aw) diff --git a/tests/data/lnk2bodyfile/Test_123.lnk b/tests/data/lnk2bodyfile/Test_123.lnk deleted file mode 100644 index b5ef3cadd3d87fb66257a64ad886165f73394cad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1339 zcma)6TS(Jk6#r=^n%9v@O6CfTv^M|Sm`-sacuBnEz}t|K;w79pyllpZpqGL!NplLUgkXexH+7K$L zA0}n>ln)qmsPVS;c+rALgkj;iy=_$e+%}b$h6)P-PN$-D5p$1;GqK6#FCvT(H z!Jh?Y7@14tgD_At!A4jZmw;2jx=nQ^yAF=trVe*AaBQ{mOOJS@a>|$WmGe~P;(=#y zpchTd?gqF1SM4muC9;ZHqS=te zpP8^i zACPz4CK1w146*qb06XZ9BRHR=i$~R;S&V9)L|CCT3ae-2WiYLi(4&|W-oZ%|k`1vU z8DID(a zD!E^hZ@g>w_et(H2`C}b{h!~645;B&l5`>)%bl~I&W+TUj_Oa>7mf!$$OlM$SfoP< L|9giFSVO-7#{v63 From 1c752f478d2200d4698ea03ae8fb7ff7831fee3b Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Fri, 3 Nov 2023 08:40:45 +0100 Subject: [PATCH 17/19] add obsidian test case --- tests/lnk2bodyfile/mod.rs | 3 ++- tests/lnk2bodyfile/obsidian.rs | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/lnk2bodyfile/obsidian.rs diff --git a/tests/lnk2bodyfile/mod.rs b/tests/lnk2bodyfile/mod.rs index 59aa627..15d2d19 100644 --- a/tests/lnk2bodyfile/mod.rs +++ b/tests/lnk2bodyfile/mod.rs @@ -1 +1,2 @@ -mod x64dbg; \ No newline at end of file +mod x64dbg; +mod obsidian; \ No newline at end of file diff --git a/tests/lnk2bodyfile/obsidian.rs b/tests/lnk2bodyfile/obsidian.rs new file mode 100644 index 0000000..9009250 --- /dev/null +++ b/tests/lnk2bodyfile/obsidian.rs @@ -0,0 +1,39 @@ +use std::{ + io::{BufRead, BufReader, Cursor}, + path::PathBuf, +}; + +use assert_cmd::Command; +use dfir_toolkit::common::bodyfile::Bodyfile3Line; + +#[test] +fn test_x64dbg() { + let mut cmd = Command::cargo_bin("lnk2bodyfile").unwrap(); + let mut data_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); + data_path.push("tests"); + data_path.push("data"); + data_path.push("lnk2bodyfile"); + data_path.push("Obsidian.lnk"); + + let result = cmd.arg(data_path).ok(); + if result.is_err() { + println!("{}", result.as_ref().err().unwrap()); + } + + assert!(result.is_ok()); + + // parse the result as bodyfile 😈 + let reader = BufReader::new(Cursor::new(result.unwrap().stdout)); + let mut lines_iterator = reader.lines(); + let first_line = lines_iterator.next().unwrap().unwrap(); + + let bfline = Bodyfile3Line::try_from(&first_line[..]).unwrap(); + assert_eq!(bfline.get_name(), r#"C:\Users\Administrator\AppData\Local\Obsidian\Obsidian.exe - (referred to by "Obsidian.lnk")"#); + assert_eq!(*bfline.get_size(), 163290848); + assert_eq!(*bfline.get_atime(), 1698927512.into()); + assert_eq!(*bfline.get_mtime(), 1697213650.into()); + assert_eq!(*bfline.get_ctime(), Default::default()); + assert_eq!(*bfline.get_crtime(), 1698927512.into()); + + assert!(lines_iterator.next().is_none()); +} From 20890a104ba7417c813b222f4a15c66c99dc9b63 Mon Sep 17 00:00:00 2001 From: Jan Starke Date: Fri, 3 Nov 2023 08:42:53 +0100 Subject: [PATCH 18/19] update documentation --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 2 +- 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/pol_export.md | 32 ++++++++++++++++ doc/regdump.md | 36 ++++++++++++++++++ doc/ts2date.md | 43 ++++++++++++++++++++++ 17 files changed, 659 insertions(+), 3 deletions(-) create mode 100644 doc/lnk2bodyfile.md diff --git a/Cargo.lock b/Cargo.lock index 5dd4833..17cfb28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -702,7 +702,7 @@ dependencies = [ [[package]] name = "dfir-toolkit" -version = "0.8.2" +version = "0.9.0" dependencies = [ "anyhow", "assert-json-diff", diff --git a/Cargo.toml b/Cargo.toml index 5cbcaf6..aca050e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dfir-toolkit" -version = "0.8.2" +version = "0.9.0" edition = "2021" authors = ["Jan Starke ", "Deborah Mahn "] description = "CLI tools for digital forensics and incident response" diff --git a/README.md b/README.md index 157d62a..b4c7d3b 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ - [x] [`es4forensics`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/es4forensics.md) - [x] [`hivescan`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/hivescan.md) - [x] [`ipgrep`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/ipgrep.md) - - [ ] [`lnk2bodyfile`](https://github.com/janstarke/lnk2bodyfile) + - [x] [`lnk2bodyfile`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/lnk2bodyfile.md) - [x] [`mactime2`](https://github.com/dfir-dd/dfir-toolkit/blob/main/doc/mactime2.md) - [ ] [`mft2bodyfile`](https://github.com/janstarke/mft2bodyfile) - [ ] [`ntdsextract2`](https://github.com/janstarke/ntdsextract2) diff --git a/doc/cleanhive.md b/doc/cleanhive.md index 4548d2e..291166f 100644 --- a/doc/cleanhive.md +++ b/doc/cleanhive.md @@ -27,6 +27,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 ee1f07b..ba37dde 100644 --- a/doc/es4forensics.md +++ b/doc/es4forensics.md @@ -53,6 +53,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 3021022..c5e50e7 100644 --- a/doc/evtx2bodyfile.md +++ b/doc/evtx2bodyfile.md @@ -30,6 +30,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 ebb1dae..47dd0c9 100644 --- a/doc/evtxanalyze.md +++ b/doc/evtxanalyze.md @@ -50,6 +50,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 5e30f51..3ebc824 100644 --- a/doc/evtxcat.md +++ b/doc/evtxcat.md @@ -33,6 +33,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 2cb1abe..e571dc9 100644 --- a/doc/evtxls.md +++ b/doc/evtxls.md @@ -61,6 +61,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 b612996..696e7c9 100644 --- a/doc/evtxscan.md +++ b/doc/evtxscan.md @@ -27,6 +27,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 0edfb85..3040695 100644 --- a/doc/hivescan.md +++ b/doc/hivescan.md @@ -25,6 +25,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 c947391..2f1dae8 100644 --- a/doc/ipgrep.md +++ b/doc/ipgrep.md @@ -33,6 +33,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 new file mode 100644 index 0000000..3d528de --- /dev/null +++ b/doc/lnk2bodyfile.md @@ -0,0 +1,34 @@ +# 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 + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/doc/mactime2.md b/doc/mactime2.md index e038dc3..a309f31 100644 --- a/doc/mactime2.md +++ b/doc/mactime2.md @@ -35,6 +35,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/pol_export.md b/doc/pol_export.md index 3d0f28d..a0f5dd1 100644 --- a/doc/pol_export.md +++ b/doc/pol_export.md @@ -23,6 +23,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 4c9edd0..77d91d8 100644 --- a/doc/regdump.md +++ b/doc/regdump.md @@ -27,6 +27,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 94bc467..cf7a032 100644 --- a/doc/ts2date.md +++ b/doc/ts2date.md @@ -34,6 +34,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` + + +
From 5871a1b1f7f110084c58502219567cbd1a8ec871 Mon Sep 17 00:00:00 2001 From: Deborah Mahn Date: Fri, 3 Nov 2023 10:49:34 +0100 Subject: [PATCH 19/19] rename obsidian test function --- tests/lnk2bodyfile/obsidian.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lnk2bodyfile/obsidian.rs b/tests/lnk2bodyfile/obsidian.rs index 9009250..b81ebad 100644 --- a/tests/lnk2bodyfile/obsidian.rs +++ b/tests/lnk2bodyfile/obsidian.rs @@ -7,7 +7,7 @@ use assert_cmd::Command; use dfir_toolkit::common::bodyfile::Bodyfile3Line; #[test] -fn test_x64dbg() { +fn test_obsidian() { let mut cmd = Command::cargo_bin("lnk2bodyfile").unwrap(); let mut data_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); data_path.push("tests");