Seized | HTB Forensics (Medium)

19 September 2023 | justruss.tech

Seized is a Medium-rated HackTheBox Forensics challenge. You receive a raw disk image of a Windows workstation. The scenario is corporate data exfiltration. The challenge tests MFT analysis, file carving, and the ability to not get distracted by
deliberate decoys.

Image mounting and initial triage

# Check image structure
mmls seized.img
# DOS Partition Table
# Slot  Start       End         Length      Description
# 000:  Meta        0000000000  0000000000  Primary Table (#0)
# 001:  -------     0000000000  0000002047  Unallocated
# 002:  000:000     0000002048  0125827071  NTFS (0x07)

# Mount the NTFS partition
sudo mkdir /mnt/seized
sudo mount -o ro,loop,offset=$((512*2048)) seized.img /mnt/seized

# Quick inventory of recently modified files
find /mnt/seized/Users -newer /mnt/seized/Windows/System32/ntoskrnl.exe \
  -not -path "*/AppData/Local/Temp/Low/*" \
  -not -name "*.log" \
  2>/dev/null | sort

Browser history analysis

# Chrome history is a SQLite database
cp "/mnt/seized/Users/jsmith/AppData/Local/Google/Chrome/User Data/Default/History" /tmp/

sqlite3 /tmp/History "
  SELECT datetime(last_visit_time/1000000-11644473600, 'unixepoch') as visit_time,
         url, title
  FROM urls
  WHERE last_visit_time > 0
  ORDER BY last_visit_time DESC
  LIMIT 50;
"

# Relevant output:
# 2023-09-18 23:41:22 | https://www.dropbox.com/upload | Upload files - Dropbox
# 2023-09-18 23:38:15 | https://pastebin.com/api/api_post | Pastebin
# 2023-09-18 23:22:07 | https://file.io/ | file.io - Super simple file sharing

Windows event log analysis

# Extract and parse relevant events
python3 -c "
import subprocess, json

# Get network connection events around the time of interest
result = subprocess.run([
    'python3', '-m', 'evtx',
    '/mnt/seized/Windows/System32/winevt/Logs/Microsoft-Windows-Sysmon%4Operational.evtx',
    '--json'
], capture_output=True, text=True)

for line in result.stdout.split(chr(10)):
    if not line: continue
    try:
        evt = json.loads(line)
        if evt.get(chr(69)+chr(118)+chr(101)+chr(110)+chr(116)+chr(73)+chr(68)) == 3:
            # EventID 3 = Network connection
            print(evt)
    except: pass
"

# Shows outbound connections to 185.220.x.x on port 443 at 23:38

MFT analysis — finding deleted files

# Extract the MFT
sudo cp /mnt/seized/\$MFT /tmp/mft_raw

# Parse with MFTECmd (Wine or native Windows)
# On Linux, use analyzeMFT:
pip install analyzeMFT
analyzeMFT.py -f /tmp/mft_raw -o /tmp/mft_parsed.csv

# Search for .zip files created around the incident time
grep "2023-09-18 23:[2-4]" /tmp/mft_parsed.csv | grep "\.zip" | grep -i "deleted\|$Recycle"

# Output includes:
# filename: staging_package_final.zip
# created:  2023-09-18 23:35:41
# parent:   C:\Users\jsmith\AppData\Local\Temp
# status:   deleted

File carving from unallocated space

# Use foremost to carve zip files from unallocated clusters
sudo foremost -t zip -i seized.img -o /tmp/carved/

# Check recovered files
ls -lh /tmp/carved/zip/
# 00000000.zip  2.3M
# 00001234.zip  847K  <-- this is the one

# The smaller file is the exfil package
unzip -l /tmp/carved/zip/00001234.zip
# Archive:  00001234.zip
#   Length      Date    Time    Name
#  ---------  ---------- -----   ----
#   1048576  09-18-2023 23:35   Q3_financials.xlsx
#    524288  09-18-2023 23:35   customer_database_export.csv
#       128  09-18-2023 23:35   flag.txt

The decoy archives in the obvious staging directory were both created at the same timestamp — a tell that they were placed deliberately rather than created through normal activity. Real staged files have slightly different creation times as each
file is added.

Forensic timeline reconstruction

# Build a super-timeline using plaso/log2timeline
log2timeline.py /tmp/seized_timeline.plaso seized.img

# Filter to the incident window
psort.py -o l2tcsv /tmp/seized_timeline.plaso \
  "date > '2023-09-18 23:00:00' AND date  /tmp/timeline_filtered.csv