Forensics

Digital forensics patterns — evidence acquisition, disk imaging, and memory analysis.

Digital Forensics

Evidence Preservation — First Principles

Order of Volatility (collect in this order):
  1. CPU registers, cache          — gone in nanoseconds
  2. Memory (RAM)                  — gone on power loss
  3. Network connections           — ephemeral
  4. Running processes             — ephemeral
  5. Disk (filesystem)             — persistent but mutable
  6. Remote logging / SIEM         — persistent, append-only
  7. Backups / archives            — cold storage

Rule: Always collect the most volatile evidence first.
      Never run tools on the evidence drive.
      Work from forensic images, never the original.

Chain of Custody

Document for every evidence item:
  - What: Description (e.g., "500GB SSD from web-server-01")
  - When: Date/time acquired (UTC)
  - Who: Name of person who acquired it
  - How: Method (dd, FTK Imager, memory dump)
  - Hash: SHA-256 of image at acquisition time
  - Transfers: Every person who handled it, with timestamps
  - Storage: Where it's stored (locked cabinet, evidence room)

A break in chain of custody = evidence may be inadmissible.

Disk Imaging

Create a forensic disk image with dd — bit-for-bit copy
# Image an entire disk — use /dev/sdX, not /dev/sdX1
sudo dd if=/dev/sdb of=/evidence/case001/disk.img bs=4M status=progress conv=noerror,sync
Create a forensic image with dc3dd — adds hashing and logging
sudo dc3dd if=/dev/sdb of=/evidence/case001/disk.img \
  hash=sha256 \
  log=/evidence/case001/imaging.log \
  bs=4M
Verify image integrity — hash must match original
# Hash the original device
sudo sha256sum /dev/sdb | tee /evidence/case001/original.sha256

# Hash the image
sha256sum /evidence/case001/disk.img | tee /evidence/case001/image.sha256

# Compare — must be identical
diff <(awk '{print $1}' /evidence/case001/original.sha256) \
     <(awk '{print $1}' /evidence/case001/image.sha256)
Mount a forensic image read-only — never modify evidence
sudo mount -o ro,loop,noexec,noatime /evidence/case001/disk.img /mnt/evidence
Mount a specific partition from the image — use offset
# Find partition offsets
fdisk -l /evidence/case001/disk.img

# Mount partition starting at sector 2048 (sector size 512)
sudo mount -o ro,loop,offset=$((2048 * 512)),noexec /evidence/case001/disk.img /mnt/evidence

Memory Acquisition

Dump live memory with LiME (Linux Memory Extractor)
# Load LiME kernel module — outputs raw memory dump
sudo insmod lime-$(uname -r).ko "path=/evidence/case001/memory.lime format=lime"
Dump memory with avml (Microsoft’s acquisition tool for Linux)
sudo ./avml /evidence/case001/memory.raw
Capture volatile data before shutdown — the 60-second collection
# Run these on the live system, save output to external media
echo "=== Date ===" > /media/usb/volatile.txt
date -u >> /media/usb/volatile.txt

echo "=== Network Connections ===" >> /media/usb/volatile.txt
ss -tulnp >> /media/usb/volatile.txt

echo "=== Processes ===" >> /media/usb/volatile.txt
ps auxf >> /media/usb/volatile.txt

echo "=== Logged-in Users ===" >> /media/usb/volatile.txt
w >> /media/usb/volatile.txt

echo "=== ARP Cache ===" >> /media/usb/volatile.txt
ip neigh >> /media/usb/volatile.txt

echo "=== Routing Table ===" >> /media/usb/volatile.txt
ip route >> /media/usb/volatile.txt

echo "=== Loaded Kernel Modules ===" >> /media/usb/volatile.txt
lsmod >> /media/usb/volatile.txt

echo "=== Open Files ===" >> /media/usb/volatile.txt
lsof -nP >> /media/usb/volatile.txt

Memory Analysis with Volatility 3

Identify the OS profile — Volatility needs to know the kernel version
python3 vol.py -f memory.lime banners.Banners
List running processes
python3 vol.py -f memory.lime linux.pslist.PsList
List network connections from memory
python3 vol.py -f memory.lime linux.sockstat.Sockstat
Find hidden or injected processes — compare pslist vs psscan
# pslist walks the active process list (what the OS sees)
python3 vol.py -f memory.lime linux.pslist.PsList > /tmp/pslist.txt

# psscan scans all memory for process structures (finds hidden processes)
python3 vol.py -f memory.lime linux.psscan.PsScan > /tmp/psscan.txt

# Processes in psscan but not pslist = potentially hidden
diff <(awk '{print $1}' /tmp/pslist.txt | sort) \
     <(awk '{print $1}' /tmp/psscan.txt | sort)
Extract bash history from memory — commands that may not be on disk
python3 vol.py -f memory.lime linux.bash.Bash
Dump a suspicious process for analysis
python3 vol.py -f memory.lime linux.proc.Maps --pid 1234 --dump

File Carving

Recover deleted files with foremost — carves by file header signatures
foremost -t jpg,png,pdf,doc,xls -i /evidence/case001/disk.img -o /evidence/case001/carved/
Recover deleted files with scalpel — configurable file signatures
# Edit /etc/scalpel/scalpel.conf to enable desired file types
sudo scalpel /evidence/case001/disk.img -o /evidence/case001/scalpel_output/
Search for specific strings in a disk image — find fragments
strings -a /evidence/case001/disk.img | grep -i "password\|credit.card\|ssn" > /evidence/case001/strings_hits.txt

Timeline Analysis

Create a filesystem timeline with fls (Sleuth Kit)
# Generate body file from image
fls -r -m "/" /evidence/case001/disk.img > /evidence/case001/bodyfile.txt

# Convert body file to timeline
mactime -b /evidence/case001/bodyfile.txt -d > /evidence/case001/timeline.csv
Create a super timeline with log2timeline (Plaso)
# Parse all artifacts into a Plaso storage file
log2timeline.py /evidence/case001/plaso.dump /evidence/case001/disk.img

# Convert to CSV timeline — filter by date range
psort.py -o l2tcsv /evidence/case001/plaso.dump \
  "date > '2026-04-01 00:00:00' AND date < '2026-04-10 23:59:59'" \
  > /evidence/case001/super_timeline.csv
Analyze timeline — find activity around the incident window
# Filter timeline to a 2-hour window around the suspected compromise
awk -F',' '$1 >= "2026-04-09T14:00" && $1 <= "2026-04-09T16:00"' \
  /evidence/case001/super_timeline.csv | head -100

Common Linux Artifacts

Artifacts to collect and where they live
Authentication:
  /var/log/auth.log          — SSH, sudo, su, PAM events
  /var/log/secure            — RHEL/CentOS equivalent
  /var/log/wtmp              — Login records (parse with 'last')
  /var/log/btmp              — Failed login records ('lastb')
  /var/log/lastlog           — Last login per user ('lastlog')

User activity:
  ~/.bash_history             — Command history (per user)
  ~/.zsh_history              — Zsh command history
  ~/.local/share/recently-used.xbel — Recently opened files (GNOME)

System:
  /var/log/syslog             — General system log
  /var/log/kern.log           — Kernel messages
  /var/log/cron.log           — Scheduled task execution
  /etc/passwd                 — User accounts (check for additions)
  /etc/shadow                 — Password hashes (check modification time)
  /etc/crontab                — System cron jobs
  /var/spool/cron/            — Per-user cron jobs

Persistence:
  /etc/systemd/system/        — Systemd service files (backdoor persistence)
  /etc/init.d/                — SysV init scripts
  ~/.bashrc, ~/.profile       — Shell startup scripts (command injection)
  /etc/ld.so.preload          — Shared library preloading (rootkit technique)

Network:
  /var/log/ufw.log            — UFW firewall log
  /etc/hosts                  — DNS overrides (check for hijacking)
  /etc/resolv.conf            — DNS server config
  ~/.ssh/authorized_keys      — SSH authorized keys (check for additions)
Quick artifact collection script — gather key files for analysis
DEST="/evidence/case001/artifacts"
mkdir -p "$DEST"

# Logs
cp -a /var/log/auth.log* "$DEST/"
cp -a /var/log/syslog* "$DEST/"

# Login records
last -aiF > "$DEST/last_output.txt"
lastb -aiF > "$DEST/lastb_output.txt" 2>/dev/null

# User histories
for home in /home/*/; do
  user=$(basename "$home")
  cp "$home/.bash_history" "$DEST/${user}_bash_history" 2>/dev/null
  cp "$home/.zsh_history" "$DEST/${user}_zsh_history" 2>/dev/null
done

# Persistence mechanisms
find /etc/systemd/system/ -name "*.service" -newer /etc/os-release > "$DEST/new_services.txt"
crontab -l > "$DEST/root_crontab.txt" 2>/dev/null

# Hash everything collected
find "$DEST" -type f -exec sha256sum {} \; > "$DEST/hashes.sha256"