digital forensics

Analyzing Windows Registry for Artifacts

Extract and analyze Windows Registry hives to uncover user activity, installed software, autostart entries, and evidence of system compromise.

artifact-analysisevidence-collectionforensicsregistry-explorerregripperwindows-registry
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

  • When investigating user activity on a Windows system during an incident
  • For identifying autorun/persistence mechanisms used by malware
  • When tracing installed software, USB devices, and network connections
  • During insider threat investigations to reconstruct user actions
  • For correlating registry timestamps with other forensic artifacts

Prerequisites

  • Forensic image or extracted registry hive files
  • RegRipper, Registry Explorer (Eric Zimmerman), or python-registry
  • Access to registry hive locations (SAM, SYSTEM, SOFTWARE, NTUSER.DAT, UsrClass.dat)
  • Understanding of Windows Registry structure (hives, keys, values)
  • SIFT Workstation or forensic analysis environment

Workflow

Step 1: Extract Registry Hives from the Forensic Image

# Mount the forensic image read-only
mkdir /mnt/evidence
mount -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/evidence.dd /mnt/evidence
 
# Copy system registry hives
cp /mnt/evidence/Windows/System32/config/SAM /cases/case-2024-001/registry/
cp /mnt/evidence/Windows/System32/config/SYSTEM /cases/case-2024-001/registry/
cp /mnt/evidence/Windows/System32/config/SOFTWARE /cases/case-2024-001/registry/
cp /mnt/evidence/Windows/System32/config/SECURITY /cases/case-2024-001/registry/
cp /mnt/evidence/Windows/System32/config/DEFAULT /cases/case-2024-001/registry/
 
# Copy user-specific hives
cp /mnt/evidence/Users/*/NTUSER.DAT /cases/case-2024-001/registry/
cp /mnt/evidence/Users/*/AppData/Local/Microsoft/Windows/UsrClass.dat /cases/case-2024-001/registry/
 
# Copy transaction logs (for dirty hive recovery)
cp /mnt/evidence/Windows/System32/config/*.LOG* /cases/case-2024-001/registry/logs/
 
# Hash all extracted hives
sha256sum /cases/case-2024-001/registry/* > /cases/case-2024-001/registry/hive_hashes.txt

Step 2: Analyze with RegRipper for Automated Artifact Extraction

# Install RegRipper
git clone https://github.com/keydet89/RegRipper3.0.git /opt/regripper
 
# Run RegRipper against NTUSER.DAT (user profile)
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/NTUSER.DAT \
   -f ntuser > /cases/case-2024-001/analysis/ntuser_report.txt
 
# Run against SYSTEM hive
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SYSTEM \
   -f system > /cases/case-2024-001/analysis/system_report.txt
 
# Run against SOFTWARE hive
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SOFTWARE \
   -f software > /cases/case-2024-001/analysis/software_report.txt
 
# Run against SAM hive (user accounts)
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SAM \
   -f sam > /cases/case-2024-001/analysis/sam_report.txt
 
# Run specific plugins
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/NTUSER.DAT \
   -p userassist > /cases/case-2024-001/analysis/userassist.txt
 
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SYSTEM \
   -p usbstor > /cases/case-2024-001/analysis/usbstor.txt

Step 3: Extract Persistence and Autorun Entries

# Using python-registry for targeted extraction
pip install python-registry
 
python3 << 'PYEOF'
from Registry import Registry
 
# Open SOFTWARE hive
reg = Registry.Registry("/cases/case-2024-001/registry/SOFTWARE")
 
# Check Run keys (autostart)
autorun_paths = [
    "Microsoft\\Windows\\CurrentVersion\\Run",
    "Microsoft\\Windows\\CurrentVersion\\RunOnce",
    "Microsoft\\Windows\\CurrentVersion\\RunServices",
    "Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\Run",
    "Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"
]
 
for path in autorun_paths:
    try:
        key = reg.open(path)
        print(f"\n=== {path} (Last Modified: {key.timestamp()}) ===")
        for value in key.values():
            print(f"  {value.name()}: {value.value()}")
    except Registry.RegistryKeyNotFoundException:
        pass
 
# Check installed services
key = reg.open("Microsoft\\Windows NT\\CurrentVersion\\Svchost")
print(f"\n=== Svchost Groups ===")
for value in key.values():
    print(f"  {value.name()}: {value.value()}")
PYEOF
 
# Check NTUSER.DAT for user-specific autorun
python3 << 'PYEOF'
from Registry import Registry
 
reg = Registry.Registry("/cases/case-2024-001/registry/NTUSER.DAT")
 
user_autorun = [
    "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
    "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\Run"
]
 
for path in user_autorun:
    try:
        key = reg.open(path)
        print(f"\n=== {path} (Last Modified: {key.timestamp()}) ===")
        for value in key.values():
            print(f"  {value.name()}: {value.value()}")
    except Registry.RegistryKeyNotFoundException:
        pass
PYEOF

Step 4: Analyze User Activity Artifacts

# Extract UserAssist data (program execution history with ROT13 encoding)
python3 << 'PYEOF'
from Registry import Registry
import codecs, struct, datetime
 
reg = Registry.Registry("/cases/case-2024-001/registry/NTUSER.DAT")
 
ua_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist"
key = reg.open(ua_path)
 
for guid_key in key.subkeys():
    count_key = guid_key.subkey("Count")
    print(f"\n=== {guid_key.name()} ===")
    for value in count_key.values():
        decoded_name = codecs.decode(value.name(), 'rot_13')
        data = value.value()
        if len(data) >= 16:
            run_count = struct.unpack('<I', data[4:8])[0]
            focus_count = struct.unpack('<I', data[8:12])[0]
            timestamp = struct.unpack('<Q', data[60:68])[0] if len(data) >= 68 else 0
            if timestamp > 0:
                ts = datetime.datetime(1601,1,1) + datetime.timedelta(microseconds=timestamp//10)
                print(f"  {decoded_name}: Runs={run_count}, Focus={focus_count}, Last={ts}")
            else:
                print(f"  {decoded_name}: Runs={run_count}, Focus={focus_count}")
PYEOF
 
# Extract Recent Documents (MRU lists)
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/NTUSER.DAT \
   -p recentdocs > /cases/case-2024-001/analysis/recentdocs.txt
 
# Extract typed URLs (browser)
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/NTUSER.DAT \
   -p typedurls > /cases/case-2024-001/analysis/typedurls.txt
 
# Extract typed paths in Explorer
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/NTUSER.DAT \
   -p typedpaths > /cases/case-2024-001/analysis/typedpaths.txt

Step 5: Extract System and Network Information

# Computer name and OS version from SYSTEM hive
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SYSTEM \
   -p compname > /cases/case-2024-001/analysis/system_info.txt
 
# Network interfaces and configuration
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SYSTEM \
   -p nic2 >> /cases/case-2024-001/analysis/system_info.txt
 
# Wireless network history
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SOFTWARE \
   -p networklist > /cases/case-2024-001/analysis/network_history.txt
 
# Timezone configuration
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SYSTEM \
   -p timezone > /cases/case-2024-001/analysis/timezone.txt
 
# Shutdown time
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SYSTEM \
   -p shutdown > /cases/case-2024-001/analysis/shutdown.txt
 
# Installed software from Uninstall keys
perl /opt/regripper/rip.pl -r /cases/case-2024-001/registry/SOFTWARE \
   -p uninstall > /cases/case-2024-001/analysis/installed_software.txt

Key Concepts

Concept Description
Registry hive Binary file storing a section of the registry (SAM, SYSTEM, SOFTWARE, NTUSER.DAT)
MRU (Most Recently Used) Lists tracking recently accessed files, commands, and search terms
UserAssist ROT13-encoded registry entries tracking program execution with timestamps
ShimCache Application compatibility cache recording executed programs
AmCache Detailed execution history including SHA-1 hashes of executables
BAM/DAM Background/Desktop Activity Moderator tracking program execution in Win10+
Last Write Time Timestamp on registry keys indicating when they were last modified
Transaction logs Journal files allowing recovery of registry state after improper shutdown

Tools & Systems

Tool Purpose
RegRipper Automated registry artifact extraction with plugin architecture
Registry Explorer Eric Zimmerman GUI tool for interactive registry analysis
python-registry Python library for programmatic registry hive parsing
RECmd Eric Zimmerman command-line registry analysis tool
yarp Yet Another Registry Parser for Python-based analysis
AppCompatCacheParser Dedicated ShimCache/AppCompatCache parser
AmcacheParser Dedicated AmCache.hve analysis tool
ShellBags Explorer Specialized tool for analyzing ShellBag artifacts

Common Scenarios

Scenario 1: Malware Persistence Investigation Extract SOFTWARE and NTUSER.DAT hives, check all Run/RunOnce keys for unauthorized entries, examine services for suspicious additions, check scheduled tasks registry keys, correlate autorun timestamps with malware execution timeline.

Scenario 2: User Activity Reconstruction Analyze UserAssist for program execution history, examine RecentDocs for accessed files, check TypedPaths for Explorer navigation, extract ShellBags for folder access patterns, build a timeline of user activity around the incident window.

Scenario 3: Unauthorized Software Detection Parse Uninstall keys for all installed applications, compare against approved software baseline, check BAM/DAM for recently executed programs not in approved list, examine AppCompatCache for execution evidence even after uninstallation.

Scenario 4: USB Data Exfiltration Investigation Extract USBSTOR entries from SYSTEM hive for connected devices, correlate device serial numbers with MountedDevices, check NTUSER.DAT MountPoints2 for user access to removable media, examine SetupAPI logs for first-connection timestamps.

Output Format

Registry Analysis Summary:
  System: DESKTOP-ABC123 (Windows 10 Pro Build 19041)
  Timezone: Eastern Standard Time (UTC-5)
  Last Shutdown: 2024-01-18 23:45:12 UTC
 
  Autorun Entries:
    HKLM Run:     5 entries (1 suspicious: "updater.exe" -> C:\ProgramData\svc\updater.exe)
    HKCU Run:     3 entries (all legitimate)
    Services:     142 entries (2 unknown: "WinDefSvc", "SysMonAgent")
 
  User Activity (NTUSER.DAT):
    UserAssist Programs:  234 entries
    Recent Documents:     89 entries
    Typed URLs:           45 entries
    Typed Paths:          12 entries
 
  USB Devices Connected:
    - Kingston DataTraveler (Serial: 0019E06B4521) - First: 2024-01-10, Last: 2024-01-18
    - WD My Passport (Serial: 575834314131) - First: 2024-01-15, Last: 2024-01-15
 
  Installed Software:     127 applications
  Suspicious Findings:    3 items flagged for review
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md2.1 KB

API Reference: Analyzing Windows Registry for Artifacts

regipy

Open Registry Hive

from regipy.registry import RegistryHive
 
reg = RegistryHive("/path/to/NTUSER.DAT")
key = reg.get_key("Software\\Microsoft\\Windows\\CurrentVersion\\Run")
print(key.header.last_modified)
for val in key.iter_values():
    print(val.name, val.value)

Iterate Subkeys

key = reg.get_key("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall")
for subkey in key.iter_subkeys():
    print(subkey.name, subkey.header.last_modified)

Key Forensic Registry Paths

Path Hive Artifact
Microsoft\Windows\CurrentVersion\Run SOFTWARE / NTUSER Autostart entries
Microsoft\Windows\CurrentVersion\RunOnce SOFTWARE / NTUSER One-time autostart
CurrentVersion\Explorer\UserAssist NTUSER Program execution (ROT13)
CurrentVersion\Explorer\RecentDocs NTUSER Recently opened documents
CurrentVersion\Explorer\TypedPaths NTUSER Explorer address bar history
ControlSet00X\Enum\USBSTOR SYSTEM USB device history
MountedDevices SYSTEM Drive letter assignments
CurrentVersion\Uninstall SOFTWARE Installed software
ControlSet00X\Control\ComputerName SYSTEM Computer name
ControlSet00X\Control\TimeZoneInformation SYSTEM System timezone

UserAssist Decoding

import codecs, struct
from datetime import datetime, timedelta
 
decoded_name = codecs.decode(rot13_name, "rot_13")
run_count = struct.unpack_from("<I", data, 4)[0]
timestamp = struct.unpack_from("<Q", data, 60)[0]
ts = datetime(1601, 1, 1) + timedelta(microseconds=timestamp // 10)

RegRipper Plugins

# NTUSER.DAT analysis
rip.pl -r NTUSER.DAT -p userassist
rip.pl -r NTUSER.DAT -p recentdocs
rip.pl -r NTUSER.DAT -p typedurls
 
# SYSTEM hive
rip.pl -r SYSTEM -p compname
rip.pl -r SYSTEM -p usbstor
rip.pl -r SYSTEM -p shutdown

References

Scripts 1

agent.py8.0 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for analyzing Windows Registry hives for forensic artifacts."""

import os
import json
import codecs
import struct
import argparse
from datetime import datetime, timedelta

from regipy.registry import RegistryHive


def extract_autorun_entries(software_hive_path):
    """Extract Run/RunOnce autostart entries from SOFTWARE hive."""
    reg = RegistryHive(software_hive_path)
    autorun_paths = [
        "Microsoft\\Windows\\CurrentVersion\\Run",
        "Microsoft\\Windows\\CurrentVersion\\RunOnce",
        "Microsoft\\Windows\\CurrentVersion\\RunServices",
        "Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\Run",
        "Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run",
    ]
    entries = []
    for path in autorun_paths:
        try:
            key = reg.get_key(path)
            for val in key.iter_values():
                entries.append({
                    "path": path,
                    "name": val.name,
                    "value": str(val.value),
                    "last_modified": str(key.header.last_modified),
                })
        except Exception:
            pass
    return entries


def extract_user_autorun(ntuser_path):
    """Extract per-user autorun entries from NTUSER.DAT."""
    reg = RegistryHive(ntuser_path)
    paths = [
        "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
        "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
    ]
    entries = []
    for path in paths:
        try:
            key = reg.get_key(path)
            for val in key.iter_values():
                entries.append({
                    "path": path,
                    "name": val.name,
                    "value": str(val.value),
                    "last_modified": str(key.header.last_modified),
                })
        except Exception:
            pass
    return entries


def extract_userassist(ntuser_path):
    """Extract UserAssist program execution history (ROT13 decoded)."""
    reg = RegistryHive(ntuser_path)
    ua_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist"
    programs = []
    try:
        ua_key = reg.get_key(ua_path)
    except Exception:
        return programs
    for guid_key in ua_key.iter_subkeys():
        try:
            count_key = guid_key.get_subkey("Count")
        except Exception:
            continue
        for val in count_key.iter_values():
            decoded_name = codecs.decode(val.name, "rot_13")
            data = val.value
            if isinstance(data, bytes) and len(data) >= 16:
                run_count = struct.unpack_from("<I", data, 4)[0]
                timestamp = 0
                if len(data) >= 68:
                    timestamp = struct.unpack_from("<Q", data, 60)[0]
                last_run = ""
                if timestamp > 0:
                    ts = datetime(1601, 1, 1) + timedelta(microseconds=timestamp // 10)
                    last_run = ts.strftime("%Y-%m-%d %H:%M:%S")
                programs.append({
                    "program": decoded_name,
                    "run_count": run_count,
                    "last_run": last_run,
                })
    return programs


def extract_recent_docs(ntuser_path):
    """Extract RecentDocs MRU from NTUSER.DAT."""
    reg = RegistryHive(ntuser_path)
    path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs"
    docs = []
    try:
        key = reg.get_key(path)
        for val in key.iter_values():
            if val.name != "MRUListEx" and isinstance(val.value, bytes):
                try:
                    name = val.value.split(b"\x00\x00")[0].decode("utf-16-le", errors="ignore")
                    docs.append({"index": val.name, "filename": name})
                except Exception:
                    pass
    except Exception:
        pass
    return docs


def extract_system_info(system_hive_path):
    """Extract computer name, timezone, and shutdown time from SYSTEM hive."""
    reg = RegistryHive(system_hive_path)
    info = {}
    select_key = reg.get_key("Select")
    current = select_key.get_value("Current")
    cs = f"ControlSet{current:03d}"
    try:
        cn_key = reg.get_key(f"{cs}\\Control\\ComputerName\\ComputerName")
        info["computer_name"] = cn_key.get_value("ComputerName")
    except Exception:
        pass
    try:
        tz_key = reg.get_key(f"{cs}\\Control\\TimeZoneInformation")
        info["timezone"] = tz_key.get_value("TimeZoneKeyName")
    except Exception:
        pass
    return info


def extract_installed_software(software_hive_path):
    """Extract installed software from Uninstall registry key."""
    reg = RegistryHive(software_hive_path)
    path = "Microsoft\\Windows\\CurrentVersion\\Uninstall"
    software = []
    try:
        key = reg.get_key(path)
        for subkey in key.iter_subkeys():
            entry = {"key": subkey.name}
            for val in subkey.iter_values():
                if val.name in ("DisplayName", "DisplayVersion", "Publisher", "InstallDate"):
                    entry[val.name] = str(val.value)
            if "DisplayName" in entry:
                software.append(entry)
    except Exception:
        pass
    return software


def flag_suspicious_autorun(entries):
    """Flag autorun entries with suspicious characteristics."""
    suspicious = []
    suspect_paths = ["\\temp\\", "\\appdata\\", "\\programdata\\", "\\public\\", "powershell", "cmd"]
    for entry in entries:
        val_lower = entry.get("value", "").lower()
        if any(s in val_lower for s in suspect_paths):
            entry["suspicious"] = True
            entry["reason"] = "Path contains suspicious directory"
            suspicious.append(entry)
    return suspicious


def main():
    parser = argparse.ArgumentParser(description="Windows Registry Forensic Analysis Agent")
    parser.add_argument("--system-hive", help="Path to SYSTEM hive")
    parser.add_argument("--software-hive", help="Path to SOFTWARE hive")
    parser.add_argument("--ntuser", help="Path to NTUSER.DAT hive")
    parser.add_argument("--output-dir", default="./registry_analysis")
    parser.add_argument("--action", choices=[
        "autorun", "userassist", "recent_docs", "system_info",
        "installed_software", "full_analysis"
    ], default="full_analysis")
    args = parser.parse_args()

    os.makedirs(args.output_dir, exist_ok=True)
    report = {"generated_at": datetime.utcnow().isoformat()}

    if args.system_hive and args.action in ("system_info", "full_analysis"):
        report["system_info"] = extract_system_info(args.system_hive)
        print(f"[+] System: {report['system_info']}")

    if args.software_hive and args.action in ("autorun", "full_analysis"):
        autorun = extract_autorun_entries(args.software_hive)
        suspicious = flag_suspicious_autorun(autorun)
        report["autorun_software"] = autorun
        report["suspicious_autorun"] = suspicious
        print(f"[+] Autorun entries (SOFTWARE): {len(autorun)}, suspicious: {len(suspicious)}")

    if args.ntuser and args.action in ("autorun", "full_analysis"):
        user_autorun = extract_user_autorun(args.ntuser)
        report["autorun_user"] = user_autorun
        print(f"[+] Autorun entries (NTUSER): {len(user_autorun)}")

    if args.ntuser and args.action in ("userassist", "full_analysis"):
        ua = extract_userassist(args.ntuser)
        report["userassist"] = ua
        print(f"[+] UserAssist programs: {len(ua)}")

    if args.ntuser and args.action in ("recent_docs", "full_analysis"):
        docs = extract_recent_docs(args.ntuser)
        report["recent_docs"] = docs
        print(f"[+] Recent documents: {len(docs)}")

    if args.software_hive and args.action in ("installed_software", "full_analysis"):
        sw = extract_installed_software(args.software_hive)
        report["installed_software"] = sw
        print(f"[+] Installed software: {len(sw)}")

    output_path = os.path.join(args.output_dir, "registry_report.json")
    with open(output_path, "w") as f:
        json.dump(report, f, indent=2, default=str)
    print(f"[+] Report saved to {output_path}")


if __name__ == "__main__":
    main()
Keep exploring