Skip to main content

Chapter 4.3 - Incident Response and Digital Forensics

Module 4: Defense Engineering and Hardening Prerequisites: Chapter 4.2 (SIEM, SOAR and Detection Engineering)


Table of Contents

  1. Incident Response Framework - PICERL and NIST SP 800-61
  2. Triage and Scoping - Initial Compromise Assessment
  3. Evidence Collection and Chain of Custody
  4. Memory Forensics - Volatility and Process Analysis
  5. Disk Forensics - Imaging, Artifact Recovery and Timeline
  6. Network Forensics During IR - PCAP and Flow Analysis
  7. Windows Artifact Analysis - Registry, Prefetch and Event Logs
  8. Linux Artifact Analysis - Bash History, Cron and Systemd
  9. Containment, Eradication and Recovery
  10. MITRE ATT&CK Mapping

1. Incident Response Framework - PICERL and NIST SP 800-61

PICERL Phases

The standard IR lifecycle (SANS PICERL):

PhaseGoalKey ActivitiesCommon Failures
PreparationBuild capability before incidents happenIR plan, playbooks, tooling, retainerNo plan until breach occurs
IdentificationDetect and confirm an incidentAlert triage, scope assessment, severity classificationSlow detection - long dwell time
ContainmentLimit damage without destroying evidenceNetwork isolation, credential resets, firewall blocksRebooting before memory capture
EradicationRemove attacker presence completelyMalware removal, backdoor hunting, account cleanupMissing persistence mechanisms
RecoveryRestore affected systems safelyClean rebuild, patch, monitoring increaseReturning to production too early
Lessons LearnedImprove posture for next timePost-incident review, detection gaps, playbook updatesSkipped entirely under pressure

Incident Severity Classification

#!/usr/bin/env python3
def classify_severity(indicators: dict) -> tuple:
score = 0
reasons = []

if indicators.get('domain_admin_compromised'):
score += 50; reasons.append("Domain Admin account confirmed compromised")
if indicators.get('data_exfiltration_confirmed'):
score += 40; reasons.append("Data exfiltration confirmed")
if indicators.get('ransomware_detected'):
score += 60; reasons.append("Ransomware/encryption activity detected")
if indicators.get('lateral_movement_confirmed'):
score += 30; reasons.append("Lateral movement to multiple hosts")
if indicators.get('persistence_confirmed'):
score += 20; reasons.append("Attacker persistence mechanism found")
if indicators.get('hosts_affected', 0) > 10:
score += 20; reasons.append(f"{indicators['hosts_affected']} hosts affected")
if indicators.get('critical_system_affected'):
score += 30; reasons.append("Critical business system affected")

if score >= 80:
return ("CRITICAL", "15 minutes", ["Immediate CISO notification", "Activate IR retainer"])
elif score >= 50:
return ("HIGH", "1 hour", ["IR team lead notification", "Begin containment immediately"])
elif score >= 25:
return ("MEDIUM", "4 hours", ["Assign senior analyst", "Begin investigation"])
else:
return ("LOW", "24 hours", ["Assign to standard queue"])


2. Triage and Scoping - Initial Compromise Assessment

The first 30 minutes of an IR are critical. The goal is not full forensic analysis - it is rapid scope determination: how many systems are affected, what is the attacker doing right now, and is the attack ongoing.

Live System Triage - Windows

# Run as Administrator - collect volatile system state quickly

# 1. Current timestamp (for timeline correlation)
Get-Date -Format "yyyy-MM-dd HH:mm:ss UTC" | Out-File C:\IR\triage.txt

# 2. Running processes with full paths and hashes
Get-Process | Select-Object Name, Id, Path, CPU, WorkingSet, StartTime |
Export-Csv C:\IR\processes.csv -NoTypeInformation

Get-Process | Where-Object {$_.Path} | ForEach-Object {
$hash = (Get-FileHash $_.Path -Algorithm SHA256 -ErrorAction SilentlyContinue).Hash
[PSCustomObject]@{ Name=$_.Name; PID=$_.Id; Path=$_.Path; SHA256=$hash }
} | Export-Csv C:\IR\process_hashes.csv -NoTypeInformation

# 3. Active network connections with owning process
Get-NetTCPConnection -State Established,Listen |
Select-Object LocalAddress,LocalPort,RemoteAddress,RemotePort,State,OwningProcess |
Export-Csv C:\IR\connections.csv -NoTypeInformation

# 4. Logged-on users
query session
query user

# 5. Scheduled tasks (persistence check)
Get-ScheduledTask | Where-Object {$_.State -ne 'Disabled'} |
Select-Object TaskName, TaskPath, State,
@{N='Execute';E={$_.Actions.Execute}},
@{N='Arguments';E={$_.Actions.Arguments}} |
Export-Csv C:\IR\scheduled_tasks.csv -NoTypeInformation

# 6. Autorun locations
$autorun_keys = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
"HKLM:\SYSTEM\CurrentControlSet\Services"
)
foreach ($key in $autorun_keys) {
Get-ItemProperty $key -ErrorAction SilentlyContinue | Out-File -Append C:\IR\autoruns.txt
}

# 7. Recently modified files (last 24 hours)
Get-ChildItem C:\Windows\Temp, C:\Users\*\AppData\Local\Temp, C:\ProgramData `
-Recurse -ErrorAction SilentlyContinue |
Where-Object {$_.LastWriteTime -gt (Get-Date).AddHours(-24)} |
Select-Object FullName, LastWriteTime, Length |
Export-Csv C:\IR\recent_files.csv -NoTypeInformation

Live System Triage - Linux

IR_DIR="/tmp/ir_$(date +%Y%m%d_%H%M%S)"
mkdir -p $IR_DIR

# 1. System information
date > $IR_DIR/timestamp.txt
uname -a >> $IR_DIR/sysinfo.txt

# 2. Running processes - detect deleted-but-running binaries
ps auxf > $IR_DIR/processes.txt
ls -la /proc/*/exe 2>/dev/null > $IR_DIR/proc_exe_links.txt
# KEY: "(deleted)" in exe link = binary ran then removed

# 3. Network connections
ss -tulnp > $IR_DIR/listening_ports.txt
ss -tnp state established > $IR_DIR/established.txt
arp -a > $IR_DIR/arp_cache.txt

# 4. Persistence locations
crontab -l 2>/dev/null > $IR_DIR/crontab_root.txt
for user in $(cut -f1 -d: /etc/passwd); do
crontab -l -u $user 2>/dev/null | awk -v u="$user" 'NF {print u": "$0}' \
>> $IR_DIR/crontabs_all.txt
done

# New systemd service units (modified after passwd = suspicious)
find /etc/systemd /usr/lib/systemd /lib/systemd \
-name "*.service" -newer /etc/passwd 2>/dev/null > $IR_DIR/new_systemd_units.txt

# 5. SUID/SGID files (persistence via SUID bit)
find / -not \( -path /proc -prune \) -perm -4000 -type f 2>/dev/null > $IR_DIR/suid_files.txt

# 6. Open network sockets
lsof -nP -i 2>/dev/null > $IR_DIR/open_network_files.txt

# 7. Loaded kernel modules (rootkit detection)
lsmod > $IR_DIR/kernel_modules.txt

# 8. Package integrity check
rpm -Va 2>/dev/null > $IR_DIR/rpm_verify.txt # RHEL
dpkg --verify 2>/dev/null > $IR_DIR/dpkg_verify.txt # Debian
# Lines with "5" in first column = hash changed = file modified

3. Evidence Collection and Chain of Custody

Every piece of evidence must be collected with documented chain of custody: who, when, what, how, where stored.

# Generate evidence hash immediately after collection
sha256sum /evidence/workstation01_memory.lime > /evidence/workstation01_memory.lime.sha256
md5sum /evidence/workstation01_memory.lime > /evidence/workstation01_memory.lime.md5

# Document the collection
cat > /evidence/COC_workstation01.txt << EOF
CHAIN OF CUSTODY
================
Case Number: IR-2024-042
Evidence Item: workstation01_memory.lime
Investigator: J. Smith (jsmith@corp.com)
Date Collected: $(date -u)
Hostname: WORKSTATION-01
IP Address: 192.168.1.105
Method: LiME kernel module loaded via SSH
SHA256: $(sha256sum /evidence/workstation01_memory.lime | cut -d' ' -f1)
MD5: $(md5sum /evidence/workstation01_memory.lime | cut -d' ' -f1)
Notes: System running; acquisition performed before containment
EOF

Remote Collection at Scale - Velociraptor

# Velociraptor: collect from all Windows endpoints simultaneously
velociraptor --config /etc/velociraptor/server.config.yaml \
artifacts collect Windows.System.Pslist \
--args Hunt=true --args ClientId="ALL"

# Artifacts to collect:
# - Windows.EventLogs.Evtx (Security, System, Application logs)
# - Windows.System.Pslist (running processes)
# - Windows.Network.Netstat (connections)
# - Windows.Persistence.PersistentItems (all persistence mechanisms)
# - Windows.System.Amcache (execution history)

4. Memory Forensics - Volatility and Process Analysis

Memory forensics recovers artifacts that exist only in RAM: running processes (including fileless malware), network connections at time of capture, decrypted strings, injected shellcode, and registry hives.

Acquiring Memory

# Linux memory acquisition with LiME
git clone https://github.com/504ensicsLabs/LiME
cd LiME/src && make

# Acquire over network (preferred - avoids writing to target disk)
# On collection workstation:
nc -l -p 4444 > /evidence/target_memory.lime

# On target:
sudo insmod lime-$(uname -r).ko "path=tcp:4444 format=lime"

# Windows memory acquisition
winpmem_mini_x64_rc2.exe -o C:\evidence\memory.raw
DumpIt.exe /O C:\evidence\memory.raw /Q

Volatility 3 - Memory Analysis

pip install volatility3

# List all processes
python3 vol.py -f memory.lime windows.pslist

# Process tree (shows parent-child relationships)
python3 vol.py -f memory.lime windows.pstree
# Look for: cmd.exe parent=Word, powershell parent=excel

# Scan for hidden processes (psscan scans pool tags, finds hidden/terminated)
python3 vol.py -f memory.lime windows.psscan
# Processes in psscan NOT in pslist = hidden by rootkit

# Find injected code (malfind - looks for RWX memory regions)
python3 vol.py -f memory.lime windows.malfind --pid 1234
# KEY INDICATOR: MZ header in injected region = PE file injected into process

# Dump suspicious process memory for YARA scanning
python3 vol.py -f memory.lime windows.memmap --pid 1234 --dump

# Active/recent network connections
python3 vol.py -f memory.lime windows.netstat
# Shows PID, process name, local/remote addr:port, state, creation time

# Credential extraction
python3 vol.py -f memory.lime windows.hashdump # NTLM hashes from SAM
python3 vol.py -f memory.lime windows.cachedump # Cached domain credentials
python3 vol.py -f memory.lime windows.lsadump # LSA secrets

# Command lines of all processes
python3 vol.py -f memory.lime windows.cmdline

# Detect DLL injection/sideloading
python3 vol.py -f memory.lime windows.dlllist --pid 1234

# Registry key from memory
python3 vol.py -f memory.lime windows.registry.printkey \
--key "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"

# YARA scan
python3 vol.py -f memory.lime windows.yarascan \
--yara-file /etc/yara/rules/cobalt_strike.yar

# Linux equivalents
python3 vol.py -f memory.lime linux.bash
python3 vol.py -f memory.lime linux.pslist
python3 vol.py -f memory.lime linux.netstat

5. Disk Forensics - Imaging, Artifact Recovery and Timeline

Forensic Disk Imaging

# dd - bit-for-bit image with error handling
dd if=/dev/sda \
of=/evidence/sda.img \
bs=512 \
conv=noerror,sync \
status=progress

# Verify image integrity
sha256sum /dev/sda > /evidence/sda.sha256_source
sha256sum /evidence/sda.img > /evidence/sda.sha256_image
diff <(cut -d' ' -f1 /evidence/sda.sha256_source) \
<(cut -d' ' -f1 /evidence/sda.sha256_image)
# Must match exactly

# ewfacquire - Expert Witness Format with compression and metadata
ewfacquire \
-t /evidence/workstation01 \
-c deflate \
-C "IR-2024-042" \
-e "J. Smith" \
/dev/sda

# Mount image read-only for analysis
mkdir /mnt/evidence_sda
mount -o ro,noexec,loop,offset=$((512*2048)) \
/evidence/sda.img /mnt/evidence_sda

File System Timeline - The Sleuth Kit and Plaso

# List partitions in image
mmls /evidence/sda.img

# Generate MAC times bodyfile
fls -r -m / -o 2048 /evidence/sda.img > /tmp/bodyfile.txt

# Human-readable timeline
mactime -b /tmp/bodyfile.txt -d -z UTC > /tmp/timeline.csv

# Filter to incident window
grep "2024-01-15" /tmp/timeline.csv | grep -E "NTFS|ADDED|CHANGED" | head -100

# Plaso - comprehensive timeline from ALL artifacts
pip install plaso

log2timeline.py \
--storage-file /tmp/evidence.plaso \
--parsers win7 \
/mnt/evidence_sda/

# Export to CSV with date filter
psort.py \
--output-time-zone UTC \
-o l2tcsv \
-w /tmp/supertimeline.csv \
/tmp/evidence.plaso \
"date > '2024-01-14' AND date < '2024-01-16'"

# Artifacts automatically processed by Plaso:
# $MFT (NTFS Master File Table), Windows Event Logs (.evtx),
# Prefetch files, Registry hives, LNK files, Browser history,
# Shellbags, Jump lists, Recycle Bin

6. Network Forensics During IR - PCAP and Flow Analysis

# Reconstruct TCP sessions from PCAP
tcpflow -r /evidence/incident.pcap -o /tmp/tcp_sessions/ -a -g

# Extract all files transferred over HTTP
tshark -r /evidence/incident.pcap \
--export-objects "http,/tmp/http_objects/"
tshark -r /evidence/incident.pcap \
--export-objects "smb,/tmp/smb_objects/"

# Reconstruct DNS queries (C2 domain, DGA, DNS tunneling)
tshark -r /evidence/incident.pcap \
-Y 'dns.flags.response == 1' \
-T fields -e frame.time -e ip.src -e dns.qry.name -e dns.a \
> /tmp/dns_resolutions.txt

# Find data exfiltration - large outbound transfers
tshark -r /evidence/incident.pcap -q -z "conv,tcp" | \
sort -t ' ' -k 10 -rn | head -20

# Identify C2 beaconing - low jitter periodic connections
python3 << 'PYEOF'
import dpkt, socket, collections, numpy as np

sessions = collections.defaultdict(list)
with open('/evidence/incident.pcap','rb') as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
if isinstance(ip.data, dpkt.tcp.TCP):
tcp = ip.data
if tcp.flags & dpkt.tcp.TH_SYN and not tcp.flags & dpkt.tcp.TH_ACK:
src = socket.inet_ntoa(ip.src)
dst = socket.inet_ntoa(ip.dst)
sessions[f"{src}->{dst}:{tcp.dport}"].append(ts)
except: pass

print(f"{'Connection':<50} {'Count':>6} {'Avg Interval':>14} {'Jitter':>8}")
for conn, timestamps in sorted(sessions.items(), key=lambda x: len(x[1]), reverse=True)[:20]:
if len(timestamps) < 5: continue
intervals = np.diff(sorted(timestamps))
avg = np.mean(intervals)
jitter = np.std(intervals) / avg if avg > 0 else 999
flag = " <- BEACON?" if jitter < 0.2 and avg < 300 else ""
print(f"{conn:<50} {len(timestamps):>6} {avg:>13.1f}s {jitter:>7.3f}{flag}")
PYEOF

7. Windows Artifact Analysis - Registry, Prefetch and Event Logs

Registry Forensics

from Registry import Registry
import datetime

# Parse SOFTWARE hive
reg = Registry.Registry("/mnt/evidence_sda/Windows/System32/config/SOFTWARE")

# Check Run key (autostart persistence)
key = reg.open("Microsoft\\Windows\\CurrentVersion\\Run")
print("=== HKLM Run Key ===")
for value in key.values():
print(f" {value.name()}: {value.value()}")
print(f" Last Modified: {key.timestamp()}")

# UserAssist - GUI program execution history (ROT-13 encoded)
import struct, codecs
user_reg = Registry.Registry("/mnt/evidence_sda/Users/victim/NTUSER.DAT")
key = user_reg.open(
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist\\"
"{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\\Count")
print("\n=== UserAssist (GUI Executions) ===")
for value in key.values():
name = codecs.decode(value.name(), 'rot_13')
data = value.value()
if len(data) >= 72:
run_count = struct.unpack('<I', data[4:8])[0]
ts_raw = struct.unpack('<Q', data[60:68])[0]
if ts_raw > 0:
ts = datetime.datetime(1601,1,1) + datetime.timedelta(microseconds=ts_raw//10)
print(f" [{run_count:>4}x] {ts} | {name}")

Prefetch Analysis

Prefetch files record program execution: name, run count, timestamps, and loaded files. Location: C:\Windows\Prefetch\

# Eric Zimmermann's PECmd (Windows)
PECmd.exe -d C:\Windows\Prefetch --csv C:\IR\prefetch.csv

# Key fields: executable name, run count, last 8 execution timestamps, loaded files
# High-value indicators:
# - psexec.exe, mimikatz.exe, cobalt_strike, meterpreter variants
# - Executables running from temp directories
# - Tools executed once and deleted (single run count, no disk artifact)

Windows Event Log Analysis

import Evtx.Evtx as evtx
import xml.etree.ElementTree as ET

logon_types = {
'2': 'Interactive', '3': 'Network', '4': 'Batch',
'5': 'Service', '7': 'Unlock', '8': 'NetworkCleartext',
'9': 'NewCredentials', '10': 'RemoteInteractive', '11': 'CachedInteractive'
}

# Key Event IDs for IR:
# 4624 - Logon success
# 4625 - Logon failure
# 4648 - Explicit credentials used
# 4698 - Scheduled task created
# 4720 - New account created
# 7045 - New service installed

suspicious_events = []
with evtx.Evtx("/evidence/Security.evtx") as log:
for record in log.records():
try:
root = ET.fromstring(record.xml())
ns = {'e': 'http://schemas.microsoft.com/win/2004/08/events/event'}
event_id = root.find('.//e:EventID', ns).text

if event_id in ['4624', '4625', '4648', '4698', '4720', '7045']:
time_created = root.find('.//e:TimeCreated', ns).get('SystemTime')
data = {d.get('Name'): d.text
for d in root.findall('.//e:Data', ns) if d.get('Name')}
entry = {
'time': time_created, 'event_id': event_id,
'user': data.get('TargetUserName', ''),
'src_ip': data.get('IpAddress', ''),
}
# Flag NTLM network logons (potential Pass-the-Hash)
if event_id == '4624' and data.get('LogonType') == '3' \
and data.get('AuthenticationPackageName') == 'NTLM':
entry['FLAG'] = 'POSSIBLE PtH - NTLM NETWORK LOGON'
suspicious_events.append(entry)
elif event_id in ['4698', '4720', '7045']:
entry['FLAG'] = 'PERSISTENCE/PRIVILEGE'
suspicious_events.append(entry)
except: pass

for e in sorted(suspicious_events, key=lambda x: x['time']):
print(f"{e['time'][:19]} | EID:{e['event_id']} | {e.get('FLAG','')} | "
f"User:{e['user']} | From:{e['src_ip']}")

8. Linux Artifact Analysis - Bash History, Cron and Systemd

# Bash history reconstruction
cat /home/*/.bash_history 2>/dev/null
cat /root/.bash_history 2>/dev/null
# Also check: ~/.zsh_history, ~/.fish_history

# /var/log/auth.log - authentication and sudo events
grep -E "sudo|su |Failed|Accepted|Invalid" /var/log/auth.log | tail -200

# Commands run via sudo (even if history cleared)
grep "COMMAND=" /var/log/auth.log | tail -50

# Systemd journal - comprehensive event log
journalctl \
--since "2024-01-14 00:00:00" \
--until "2024-01-15 23:59:59" \
--no-pager -o json > /tmp/journal_incident.json

# SSH service events specifically
journalctl -u sshd --since "2024-01-14" --no-pager

# Find new/modified systemd units (persistence)
find /etc/systemd /usr/lib/systemd /lib/systemd \
-name "*.service" -newer /etc/hostname 2>/dev/null -exec cat {} \;

# Detect LD_PRELOAD hijacking
cat /etc/ld.so.preload 2>/dev/null # Should be empty

# Root-equivalent accounts (UID 0)
awk -F: '$3 == 0 {print "ROOT ACCOUNT:", $1}' /etc/passwd

# SSH authorized_keys additions (persistence)
find /home /root -name "authorized_keys" -exec ls -la {} \; -exec cat {} \;

# Webshell detection
find /var/www /srv/www /opt/*/htdocs \
-name "*.php" -o -name "*.asp" -o -name "*.jsp" 2>/dev/null \
-newer /var/log/syslog -exec ls -la {} \;

grep -r --include="*.php" -l \
-E "eval\(base64_decode|system\(|passthru\(|exec\(|\$_POST\[|shell_exec" \
/var/www/ 2>/dev/null

9. Containment, Eradication and Recovery

Network Containment

# Full isolation (CRITICAL incidents) - allow only IR team
iptables -I INPUT 1 -s IR_TEAM_IP -j ACCEPT
iptables -I OUTPUT 1 -d IR_TEAM_IP -j ACCEPT
iptables -I INPUT 2 -j DROP
iptables -I OUTPUT 2 -j DROP
iptables -I FORWARD 1 -j DROP

# Targeted blocking (MEDIUM - preserve functionality)
iptables -I OUTPUT -d C2_IP -j DROP
iptables -I INPUT -s ATTACKER_IP -j DROP

Credential Containment

# If credentials were harvested - bulk password reset
$affected_users = @("jsmith", "admin", "svc-web", "helpdesk01")
foreach ($user in $affected_users) {
$newpass = ConvertTo-SecureString (New-Guid).ToString() -AsPlainText -Force
Set-ADAccountPassword -Identity $user -NewPassword $newpass -Reset
Set-ADUser $user -ChangePasswordAtLogon $true
Write-Host "Reset: $user"
}

# If DA credentials compromised: reset krbtgt TWICE (24 hours apart)
# First reset invalidates all existing tickets
# Second reset ensures no Golden Tickets remain valid

# Force Azure AD session revocation
Revoke-AzureADUserAllRefreshToken -ObjectId USER_OBJECT_ID

Eradication Checklist

# 1. Autoruns - all autostart locations
autorunsc.exe -accepteula -a * -c -h -vt > C:\IR\autoruns_scan.csv

# 2. Scheduled tasks
schtasks /query /fo csv /v > C:\IR\scheduled_tasks.csv

# 3. WMI subscriptions (stealthy persistence - often missed)
Get-WMIObject -Namespace root\subscription -Class __EventFilter
Get-WMIObject -Namespace root\subscription -Class __EventConsumer
Get-WMIObject -Namespace root\subscription -Class __FilterToConsumerBinding
# ANY results not from known software = WMI persistence

# Remove malicious WMI subscription
Get-WMIObject -Namespace root\subscription -Class __FilterToConsumerBinding |
Where-Object {$_.Consumer -like "*malicious*"} |
Remove-WMIObject

# 4. COM hijacking detection (HKCU registry override)
Get-ChildItem "HKCU:\Software\Classes\CLSID" |
Select-Object Name, @{N='Value';E={(Get-ItemProperty $_.PSPath).'(default)'}}

# 5. Validate eradication - second scan after manual removal
# Run AV/EDR full scan AFTER manual removal
# Verify no re-infection indicators in SIEM 24h post-recovery

Recovery

# NEVER restore from a backup taken after the compromise date
# Find last clean backup BEFORE attacker's initial access timestamp

# Clean rebuild is always preferred over patching compromised system:
# 1. Wipe and reimage from known-good golden image
# 2. Apply all patches before connecting to network
# 3. Restore data from pre-compromise backup only
# 4. Validate with EDR scan before production use

# 30-day enhanced monitoring post-recovery
nmap -sV -p- RECOVERED_HOST # Verify no unexpected services
cme smb RECOVERED_HOST -u admin -p pass --processes

10. MITRE ATT&CK Mapping

TechniqueIDIR Detection MethodEvidence Source
Process InjectionT1055malfind - RWX memory regionsMemory dump (Volatility)
Fileless MalwareT1059In-memory artifacts, no disk fileMemory forensics only
Scheduled Task PersistenceT1053.005Task XML in System32\TasksDisk image + Event 4698
Registry Run KeyT1547.001Registry hive analysisNTUSER.DAT, SOFTWARE hive
WMI SubscriptionT1546.003WMI repository queryWMI repository database
New ServiceT1543.003Service binary hash checkSYSTEM hive + Event 7045
Data ExfiltrationT1041Large outbound flows in PCAPNetFlow + PCAP analysis
Credential DumpingT1003LSASS memory access in EDRMemory dump + Event 4663
Lateral MovementT1021Cross-host logon correlationEvent 4624 type 3 chain
Defense Evasion: TimestompingT1070.006MFT STANDARD vs FILENAME mismatchNTFS MFT analysis
Account ManipulationT1098New accounts in AD, auth.logEvent 4720 + /etc/passwd
Boot/Logon InitializationT1037Startup scripts + systemd unitsDisk image + journalctl