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"