meta data for this page
  •  

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
soc:irt:playbooks:windows_disk [2026/06/17 07:54] titannetsoc:irt:playbooks:windows_disk [2026/06/18 16:51] (current) – [Prefetch on Linux] titannet
Line 30: Line 30:
 <code bash> <code bash>
 mmls -r $E mmls -r $E
-sudo -E ~/.local/bin/imount -p -o ## $E+sudo -E ~/.local/bin/imount -p -o ## -md /mnt/imount $E
 # -p has 'pretty' & predictable folder name, fails if in use # -p has 'pretty' & predictable folder name, fails if in use
 # new tab or crtl-z # new tab or crtl-z
Line 40: Line 40:
 <code bash> <code bash>
 target-fs "$E" cp 'c:/Windows/System32/winevt/Logs' --output ./logs target-fs "$E" cp 'c:/Windows/System32/winevt/Logs' --output ./logs
-docker run --rm -v "$PWD":/work --entrypoint /opt/hayabusa/hayabusa tabledevil/hayabusa:3.8.1 csv-timeline -d /work/logs -o /wok/output/hayabusa.csv -p super-verbose +docker run -it --rm -v "$PWD":/work --entrypoint /opt/hayabusa/hayabusa tabledevil/hayabusa:3.8.1 csv-timeline -d /work/logs -o /work/output/hayabusa.csv -p super-verbose 
-docker run --rm -v "$PWD":/work --entrypoint /opt/hayabusa/hayabusa tabledevil/hayabusa:3.8.1 json-timeline -d /work/logs -o /work/output/hayabusa.jsonl -p super-verbose+docker run -it --rm -v "$PWD":/work --entrypoint /opt/hayabusa/hayabusa tabledevil/hayabusa:3.8.1 json-timeline -d /work/logs -o /work/output/hayabusa.jsonl -p super-verbose
 </code> </code>
  
Line 68: Line 68:
  
  
 +==== Splunk ====
  
 +<code bash>
 +mkdir -p etc/system/local/
 +vim props.conf
 +cp props.conf etc/system/local
 +
 +</code>
 +
 +
 +==== Browser ====
 +
 +
 +<code bash>
 +Users\...\AppData\Local\Google\Chrome\User Data\Default\History
 +Users\...\AppData\Local\Microsoft\Edge\User Data\Default\History
 +Users\...\AppData\Roaming\Mozilla\Firefox\Profiles\<ProfileName>.default\places.sqlite
 +
 +
 +C_DR=
 +EUSER=
 +mkdir -p evidence/chrome
 +mkdir evidence/edge
 +mkdir evidence/firefox
 +cp -r $C_DR/Users/$EUSER/AppData/Local/Google/Chrome/User\ Data/Default/History evidence/chrome
 +cp -r $C_DR/Users/$EUSER/AppData/Local/Microsoft/Edge/User\ Data/Default/History evidence/edge
 +cp -r $C_DR/Users/$EUSER/AppData/Roaming/Mozilla/Firefox/Profiles/*-release/places.sqlite evidence/firefox/
 +
 +sqlitebrowser evidence/firefox/places.sqlite
 +sqlitebrowser evidence/chrome/History
 +
 +</code>
 +
 +
 +==== PE ====
 +
 +<code bash>
 +https://github.com/sethenoka/Install_EZTools.git
 +
 +
 +
 +
 +</code>
 +
 +==== Prefetch on Linux ====
 +
 +<code bash>
 +
 +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
 +source ~/.cargo/env
 +rustup toolchain install 1.85.0
 +rustup default 1.85.0
 +</code>
 +
 +<code rust>
 +use chrono::{DateTime, Utc};
 +use std::{env, fs};
 +
 +fn filetime_to_datetime(ft: i64) -> DateTime<Utc> {
 +    // FILETIME epoch (1601-01-01) -> Unix epoch (1970-01-01)
 +    const EPOCH_DIFF_100NS: i64 = 116_444_736_000_000_000;
 +
 +    let unix_100ns = ft - EPOCH_DIFF_100NS;
 +    let secs = unix_100ns / 10_000_000;
 +    let nanos = ((unix_100ns % 10_000_000) * 100) as u32;
 +
 +    DateTime::from_timestamp(secs, nanos)
 +        .expect("invalid timestamp")
 +}
 +
 +fn main() {
 +    let path = env::args()
 +        .nth(1)
 +        .expect("usage: pf_info <file.pf>");
 +
 +    let raw = fs::read(&path).expect("read failed");
 +
 +    let info = prefetch_core::parse(&raw)
 +        .unwrap_or_else(|e| panic!("parse error: {:?}", e));
 +
 +    println!("Executable : {}", info.executable);
 +    println!("Run count  : {}", info.run_count);
 +
 +    println!("\nLast run times:");
 +    for ft in &info.last_run_times {
 +        println!(
 +            "  {}  ({})",
 +            filetime_to_datetime(*ft).to_rfc3339(),
 +            ft
 +        );
 +    }
 +
 +    println!("\nVolumes:");
 +    for v in &info.volumes {
 +        println!("  Device: {}", v.device_path);
 +
 +        let created = filetime_to_datetime(v.creation_time);
 +        println!("  Created: {}", created.to_rfc3339());
 +
 +        println!("  Serial : {:08X}", v.serial);
 +        println!();
 +    }
 +}
 +
 +</code>
 +
 +
 +<code rust>
 +#![allow(clippy::unwrap_used, clippy::expect_used)]
 +use std::path::PathBuf;
 +use std::fs;
 +use std::path::Path;
 +use chrono::{DateTime, Utc};
 +
 +/// based on  https://docs.rs/crate/prefetch-core/0.1.0/source/examples/pf_dump.rs
 +
 +
 +fn filetime_to_datetime(ft: i64) -> DateTime<Utc> {
 +    // FILETIME epoch (1601-01-01) -> Unix epoch (1970-01-01)
 +    const EPOCH_DIFF_100NS: i64 = 116_444_736_000_000_000;
 + 
 +    let unix_100ns = ft - EPOCH_DIFF_100NS;
 +    let secs = unix_100ns / 10_000_000;
 +    let nanos = ((unix_100ns % 10_000_000) * 100) as u32;
 + 
 +    DateTime::from_timestamp(secs, nanos)
 +        .expect("invalid timestamp")
 +}
 +
 +fn csv_escape(s: &str) -> String {
 +    let mut out = String::new();
 +    out.push('"');
 +    for c in s.chars() {
 +        match c {
 +            '"' => out.push_str("\"\""),
 +            _ => out.push(c),
 +        }
 +    }
 +    out.push('"');
 +    out
 +}
 +
 +fn main() {
 +    let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
 +    root.pop();
 +    let out_dir = std::env::args()
 +        .nth(1)
 +        .unwrap_or_else(|| "/tmp/pf_scca".to_string());
 +    std::fs::create_dir_all(&out_dir).expect("mkdir out_dir");
 +
 +    let dir = Path::new("/media/data/IR/case260618/prefetch");
 +    
 +     let files: Vec<String> = fs::read_dir(dir)
 +        .unwrap()
 +        .filter_map(Result::ok)
 +        .map(|e| e.path())
 +        .filter(|p| {
 +            p.extension()
 +                .and_then(|ext| ext.to_str())
 +                .map(|ext| ext == "pf")
 +                .unwrap_or(false)
 +        })
 +        .map(|p| p.to_string_lossy().to_string())
 +        .collect();
 +
 +//.filter(|p| p.extension().and_then(|s| s.to_str()) == Some("pf"))
 +    println!(
 +        "file,scca_len,version,executable,run_count,last_run_times,filenames_count,filenames,volumes"
 +    );
 +    for name in files {
 +        let p = PathBuf::from(&name);
 +
 +        let raw = std::fs::read(&p).expect("read fixture");
 +        let scca = prefetch_core::decompress(&raw).expect("decompress");
 +
 +        std::fs::write(PathBuf::from(&out_dir).join(format!("{name}.scca")), &scca)
 +            .expect("write scca");
 +
 +        let info = prefetch_core::parse(&raw).expect("parse");
 +
 +        let filenames = info
 +            .filenames
 +            .iter()
 +            .map(|f| escape(f))
 +            .collect::<Vec<_>>()
 +            .join(";");
 +
 +        let volumes = info
 +            .volumes
 +            .iter()
 +            .map(|v| {
 +                format!(
 +                    "{{serial:{},device_path:{},creation_time:{}}}",
 +                    v.serial,
 +                    escape(&v.device_path),
 +                    filetime_to_datetime(v.creation_time)
 +                )
 +            })
 +            .collect::<Vec<_>>()
 +            .join(";");
 +
 +        let last_runs = info
 +            .last_run_times
 +            .iter()
 +            .map(|t| filetime_to_datetime(*t).to_string())
 +            .collect::<Vec<_>>()
 +            .join(";");
 +
 +        println!(
 +            "{},{},{},{},{},{},{},{},{}",
 +            csv_escape(&name),
 +            scca.len(),
 +            info.version,
 +            csv_escape(&info.executable),
 +            info.run_count,
 +            csv_escape(&last_runs),
 +            info.filenames.len(),
 +            csv_escape(&filenames),
 +            csv_escape(&volumes)
 +        );
 +    }
 +}
 +
 +fn escape(s: &str) -> String {
 +    s.replace('\\', "\\\\")
 +}
 +
 +</code>
  
 === Extended disk image anaylsis === === Extended disk image anaylsis ===