Digital Forensics and Evidence Collection
Digital Forensics and Evidence Collection
Digital forensics provides the foundation for understanding incident scope, identifying root causes, and gathering evidence for potential legal proceedings. Proper forensic procedures ensure evidence integrity while enabling thorough investigation. Understanding forensic principles and tools for both Windows and Linux systems enables effective incident investigation.
Windows forensic data collection requires careful procedures to preserve evidence:
# Windows Forensic Evidence Collection Script
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$IncidentID,
[Parameter(Mandatory=$true)]
[string]$TargetComputer,
[Parameter(Mandatory=$true)]
[string]$EvidencePath
)
# Create evidence directory structure
$EvidenceRoot = Join-Path $EvidencePath $IncidentID
$Directories = @(
"memory",
"logs",
"registry",
"network",
"processes",
"artifacts",
"timeline"
)
foreach ($dir in $Directories) {
New-Item -Path (Join-Path $EvidenceRoot $dir) -ItemType Directory -Force
}
# Function to create forensic hash
function Get-ForensicHash {
param($FilePath)
$md5 = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
$sha256 = New-Object System.Security.Cryptography.SHA256CryptoServiceProvider
$file = [System.IO.File]::OpenRead($FilePath)
$md5Hash = [System.BitConverter]::ToString($md5.ComputeHash($file)).Replace("-","")
$sha256Hash = [System.BitConverter]::ToString($sha256.ComputeHash($file)).Replace("-","")
$file.Close()
return @{
MD5 = $md5Hash
SHA256 = $sha256Hash
File = $FilePath
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
# Collect volatile data first
Write-Host "Collecting volatile evidence from $TargetComputer..." -ForegroundColor Yellow
# Memory dump (requires administrative privileges)
$MemoryDump = Join-Path $EvidenceRoot "memory\memory.dmp"
if (Test-Path "C:\Tools\DumpIt.exe") {
Start-Process -FilePath "C:\Tools\DumpIt.exe" -ArgumentList "/quiet", "/output:$MemoryDump" -Wait
Get-ForensicHash $MemoryDump | Export-Csv -Path "$MemoryDump.hash" -NoTypeInformation
}
# Collect process information
Invoke-Command -ComputerName $TargetComputer -ScriptBlock {
Get-Process | Select-Object Id, ProcessName, Path, StartTime, CPU, WorkingSet, Company, Description
} | Export-Csv -Path (Join-Path $EvidenceRoot "processes\running_processes.csv") -NoTypeInformation
# Collect network connections
Invoke-Command -ComputerName $TargetComputer -ScriptBlock {
Get-NetTCPConnection | Select-Object LocalAddress, LocalPort, RemoteAddress, RemotePort, State, OwningProcess, CreationTime
} | Export-Csv -Path (Join-Path $EvidenceRoot "network\tcp_connections.csv") -NoTypeInformation
# Collect system information
$SystemInfo = Invoke-Command -ComputerName $TargetComputer -ScriptBlock {
@{
ComputerName = $env:COMPUTERNAME
OSVersion = (Get-CimInstance Win32_OperatingSystem).Version
LastBootTime = (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
TimeZone = (Get-TimeZone).DisplayName
Domain = (Get-CimInstance Win32_ComputerSystem).Domain
LoggedOnUsers = (Get-CimInstance Win32_LoggedOnUser | Select-Object -ExpandProperty Antecedent).Name
}
}
$SystemInfo | ConvertTo-Json | Out-File (Join-Path $EvidenceRoot "artifacts\system_info.json")
# Collect event logs
$EventLogs = @("System", "Security", "Application", "Microsoft-Windows-PowerShell/Operational")
foreach ($LogName in $EventLogs) {
Write-Host "Exporting $LogName log..."
$LogFile = Join-Path $EvidenceRoot "logs\$($LogName.Replace('/', '-')).evtx"
wevtutil export-log $LogName $LogFile /remote:$TargetComputer
Get-ForensicHash $LogFile | Export-Csv -Path "$LogFile.hash" -NoTypeInformation
}
# Collect registry hives
Write-Host "Collecting registry hives..."
$RegistryHives = @{
"HKLM_SYSTEM" = "HKLM:\SYSTEM"
"HKLM_SOFTWARE" = "HKLM:\SOFTWARE"
"HKLM_SECURITY" = "HKLM:\SECURITY"
}
foreach ($hive in $RegistryHives.GetEnumerator()) {
$ExportPath = Join-Path $EvidenceRoot "registry\$($hive.Key).reg"
reg export $hive.Value $ExportPath /y
}
# Create timeline
Write-Host "Creating forensic timeline..."
$TimelineEvents = @()
# File system timeline
$TimelineEvents += Get-ChildItem -Path C:\ -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } |
Select-Object FullName, CreationTime, LastWriteTime, LastAccessTime, Length
# Security event timeline
$TimelineEvents += Get-WinEvent -LogName Security -MaxEvents 10000 |
Select-Object TimeCreated, Id, Message |
Where-Object { $_.TimeCreated -gt (Get-Date).AddDays(-7) }
$TimelineEvents | Sort-Object { $_.TimeCreated, $_.LastWriteTime } |
Export-Csv -Path (Join-Path $EvidenceRoot "timeline\forensic_timeline.csv") -NoTypeInformation
# Create evidence inventory
$Inventory = Get-ChildItem -Path $EvidenceRoot -Recurse -File |
Select-Object FullName, Length, CreationTime |
ForEach-Object {
$hash = Get-ForensicHash $_.FullName
[PSCustomObject]@{
File = $_.FullName.Replace($EvidenceRoot, "")
Size = $_.Length
Created = $_.CreationTime
MD5 = $hash.MD5
SHA256 = $hash.SHA256
}
}
$Inventory | Export-Csv -Path (Join-Path $EvidenceRoot "evidence_inventory.csv") -NoTypeInformation
Write-Host "Forensic evidence collection completed: $EvidenceRoot" -ForegroundColor Green
Linux forensic collection requires different tools and approaches:
#!/bin/bash
# Linux Forensic Evidence Collection Script
set -euo pipefail
# Configuration
INCIDENT_ID="$1"
TARGET_HOST="${2:-localhost}"
EVIDENCE_BASE="/forensics/$INCIDENT_ID"
# Create evidence directory structure
mkdir -p "$EVIDENCE_BASE"/{memory,logs,network,processes,filesystem,artifacts}
# Logging function
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" | tee -a "$EVIDENCE_BASE/collection.log"
}
# Hash function for evidence integrity
create_hash() {
local file="$1"
md5sum "$file" > "$file.md5"
sha256sum "$file" > "$file.sha256"
log "Created hash for: $file"
}
# Collect volatile data first
log "Starting volatile data collection from $TARGET_HOST"
# Memory dump (if local)
if [[ "$TARGET_HOST" == "localhost" ]]; then
if command -v LiME >/dev/null 2>&1; then
log "Creating memory dump with LiME"
insmod /path/to/lime.ko "path=$EVIDENCE_BASE/memory/memory.lime format=lime"
create_hash "$EVIDENCE_BASE/memory/memory.lime"
else
log "WARNING: LiME not available, attempting /proc/kcore copy"
if [[ -r /proc/kcore ]]; then
dd if=/proc/kcore of="$EVIDENCE_BASE/memory/kcore.dump" bs=1M
create_hash "$EVIDENCE_BASE/memory/kcore.dump"
fi
fi
fi
# Process information
log "Collecting process information"
ps auxww > "$EVIDENCE_BASE/processes/ps_auxww.txt"
ps -ef > "$EVIDENCE_BASE/processes/ps_ef.txt"
lsof -n > "$EVIDENCE_BASE/processes/lsof.txt" 2>/dev/null || true
pstree -p > "$EVIDENCE_BASE/processes/pstree.txt"
# Process memory maps
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
if [[ -r "/proc/$pid/maps" ]]; then
cat "/proc/$pid/maps" > "$EVIDENCE_BASE/processes/maps_$pid.txt" 2>/dev/null || true
fi
done
# Network connections
log "Collecting network information"
netstat -an > "$EVIDENCE_BASE/network/netstat_an.txt"
netstat -rn > "$EVIDENCE_BASE/network/netstat_rn.txt"
ss -anp > "$EVIDENCE_BASE/network/ss_anp.txt" 2>/dev/null || true
iptables -L -n -v > "$EVIDENCE_BASE/network/iptables.txt"
ip addr show > "$EVIDENCE_BASE/network/ip_addr.txt"
ip route show > "$EVIDENCE_BASE/network/ip_route.txt"
arp -a > "$EVIDENCE_BASE/network/arp.txt"
# System information
log "Collecting system information"
{
echo "=== System Information ==="
uname -a
echo
echo "=== Hostname ==="
hostname -f
echo
echo "=== Date/Time ==="
date
echo
echo "=== Timezone ==="
timedatectl status 2>/dev/null || cat /etc/timezone
echo
echo "=== Uptime ==="
uptime
echo
echo "=== Logged in users ==="
who
echo
echo "=== Last logins ==="
last -20
} > "$EVIDENCE_BASE/artifacts/system_info.txt"
# Collect logs
log "Collecting system logs"
if [[ -d /var/log ]]; then
# Copy important logs
for logfile in auth.log secure messages syslog kern.log; do
if [[ -f "/var/log/$logfile" ]]; then
cp "/var/log/$logfile"* "$EVIDENCE_BASE/logs/" 2>/dev/null || true
fi
done
# Journal logs if systemd
if command -v journalctl >/dev/null 2>&1; then
journalctl --since="7 days ago" > "$EVIDENCE_BASE/logs/journalctl_7days.log"
journalctl -p err --since="30 days ago" > "$EVIDENCE_BASE/logs/journalctl_errors.log"
fi
fi
# Audit logs
if [[ -f /var/log/audit/audit.log ]]; then
cp /var/log/audit/audit.log* "$EVIDENCE_BASE/logs/"
ausearch -ts recent > "$EVIDENCE_BASE/logs/audit_recent.txt"
fi
# File system timeline
log "Creating filesystem timeline"
find / -type f -mtime -7 -ls 2>/dev/null | head -10000 > "$EVIDENCE_BASE/filesystem/modified_files_7days.txt"
find /home -type f -name ".*" -ls 2>/dev/null > "$EVIDENCE_BASE/filesystem/hidden_files_home.txt"
find / -type f -perm -4000 -ls 2>/dev/null > "$EVIDENCE_BASE/filesystem/suid_files.txt"
find / -type f -perm -2000 -ls 2>/dev/null > "$EVIDENCE_BASE/filesystem/sgid_files.txt"
# Persistence mechanisms
log "Checking persistence mechanisms"
{
echo "=== Crontabs ==="
for user in $(cut -f1 -d: /etc/passwd); do
echo "User: $user"
crontab -u "$user" -l 2>/dev/null || echo "No crontab"
echo
done
echo "=== System cron ==="
ls -la /etc/cron.*
echo "=== Systemd timers ==="
systemctl list-timers --all
echo "=== RC scripts ==="
ls -la /etc/rc*.d/
} > "$EVIDENCE_BASE/artifacts/persistence.txt"
# Create evidence package
log "Creating evidence package"
cd "$(dirname "$EVIDENCE_BASE")"
tar czf "$INCIDENT_ID.tar.gz" "$INCIDENT_ID/"
create_hash "$INCIDENT_ID.tar.gz"
# Generate collection report
{
echo "Forensic Evidence Collection Report"
echo "=================================="
echo "Incident ID: $INCIDENT_ID"
echo "Collection Date: $(date)"
echo "Target Host: $TARGET_HOST"
echo "Collector: $(whoami)@$(hostname)"
echo
echo "Evidence Summary:"
find "$EVIDENCE_BASE" -type f -name "*.txt" -o -name "*.log" | while read -r file; do
echo "- $file ($(stat -c%s "$file") bytes)"
done
echo
echo "Total Evidence Size: $(du -sh "$EVIDENCE_BASE" | cut -f1)"
} > "$EVIDENCE_BASE/collection_report.txt"
log "Forensic evidence collection completed: $EVIDENCE_BASE"