Pular para o conteúdo

Prefetch Parser Cheat Sheet

Overview

Windows Prefetch is a performance optimization feature that monitors application loading behavior and creates .pf files in C:\Windows\Prefetch\ to speed up subsequent launches. For digital forensics, Prefetch files are goldmines of evidence because they record which executables ran on the system, how many times they ran, when they last ran (and up to 8 previous execution timestamps on Windows 8+), and which files and directories were accessed during the first 10 seconds of execution. Prefetch files persist even after the original executable is deleted, providing proof of execution that survives many anti-forensic techniques.

Prefetch files follow the naming convention EXECUTABLE_NAME-XXXXXXXX.pf where the hash is derived from the executable path and any command-line arguments (for hosting executables like svchost.exe and dllhost.exe). Windows 10/11 uses MAM (Memory Access Manager) compressed Prefetch format, while earlier versions use an uncompressed format. Each Prefetch file contains the executable name, run count, up to 8 last run timestamps, volume information (device path, serial number, creation time), and a list of files and directories referenced during loading. Tools like PECmd, WinPrefetchView, and python-prefetch parse these binary files for forensic analysis.

Installation

PECmd (Eric Zimmerman)

# Download PECmd
Invoke-WebRequest -Uri "https://f001.backblazeb2.com/file/EricZimmermanTools/net6/PECmd.zip" -OutFile PECmd.zip
Expand-Archive PECmd.zip -DestinationPath C:\Tools\PECmd

# Verify
C:\Tools\PECmd\PECmd.exe --help

WinPrefetchView (NirSoft)

# Download from NirSoft
# https://www.nirsoft.net/utils/win_prefetch_view.html
# GUI tool — no installation required

python-prefetch

# Install Python library
pip install prefetch

# Or install from source
git clone https://github.com/PoorBillionaire/Windows-Prefetch-Parser.git
cd Windows-Prefetch-Parser
pip install -e .

prefetchruncounts (Volatility Plugin)

# For memory forensics prefetch analysis
# Part of Volatility community plugins
pip install volatility3

Core Commands

PECmd

CommandDescription
PECmd.exe -f <file>Parse single Prefetch file
PECmd.exe -d <directory>Parse all Prefetch files in directory
PECmd.exe --csv <outdir>Output as CSV
PECmd.exe --json <outdir>Output as JSON
PECmd.exe -k <keyword>Filter by keyword in filename references
PECmd.exe -qQuiet mode
# Parse single Prefetch file
PECmd.exe -f "C:\Windows\Prefetch\CMD.EXE-4A81B364.pf"

# Parse entire Prefetch directory
PECmd.exe -d "C:\Windows\Prefetch" --csv C:\Analysis\

# Parse with keyword filtering
PECmd.exe -d "C:\Windows\Prefetch" -k "password" --csv C:\Analysis\

# Parse from mounted forensic image
PECmd.exe -d "E:\Windows\Prefetch" --csv C:\Evidence\

# JSON output
PECmd.exe -d "C:\Windows\Prefetch" --json C:\Analysis\

# Parse specific timeframe
PECmd.exe -d "C:\Windows\Prefetch" --csv C:\Analysis\ -q

Python Prefetch Parser

#!/usr/bin/env python3
import prefetch

# Parse a single Prefetch file
pf = prefetch.Prefetch("CMD.EXE-4A81B364.pf")

# Display basic information
print(f"Executable: {pf.executableName}")
print(f"Run Count: {pf.runCount}")
print(f"Last Run: {pf.lastRunTime}")

# Display all 8 timestamps (Windows 8+)
for i, ts in enumerate(pf.timestamps):
    print(f"Run {i+1}: {ts}")

# List files referenced during execution
print("\nFiles loaded:")
for filename in pf.filenames:
    print(f"  {filename}")

# Volume information
for volume in pf.volumeInformation:
    print(f"Volume: {volume['Name']}")
    print(f"Serial: {volume['Serial Number']}")
    print(f"Created: {volume['Creation Time']}")

# List directories
print("\nDirectories:")
for directory in pf.directoryStrings:
    print(f"  {directory}")

WinPrefetchView (CLI Mode)

# Export all Prefetch data to CSV
WinPrefetchView.exe /scomma prefetch_output.csv

# Export specific columns
WinPrefetchView.exe /scomma prefetch_output.csv /PrefetchFolder "C:\Windows\Prefetch"

# Export as HTML report
WinPrefetchView.exe /shtml prefetch_report.html

Prefetch File Format

File Structure

FieldDescription
SignatureMAM\x04 (compressed Win10+) or SCCA (legacy)
File SizeSize of the Prefetch file
Executable NameName of the executable (up to 29 chars)
HashPath hash in filename
Run CountNumber of times executed
Last Run Time(s)Up to 8 FILETIME timestamps
Volume InfoDevice path, serial number, creation time
File ReferencesMFT references to files accessed
Directory StringsDirectory paths accessed

Hash Calculation

# Prefetch filename hash is based on:
# - Full path to executable (case-insensitive)
# - For hosting executables (svchost, dllhost, rundll32):
#   - Includes command-line arguments

# Examples:
# CMD.EXE-4A81B364.pf        -> C:\Windows\System32\cmd.exe
# POWERSHELL.EXE-022A1004.pf -> C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
# SVCHOST.EXE-D78CA325.pf    -> svchost.exe with specific -k parameter

Analysis Techniques

Execution Timeline

# Build execution timeline from PECmd CSV output
Import-Csv "C:\Analysis\PECmd_Output_Timeline.csv" |
    Sort-Object RunTime -Descending |
    Select-Object ExecutableName, RunTime, RunCount |
    Format-Table

# Find recently executed programs (last 24 hours)
$yesterday = (Get-Date).AddDays(-1)
Import-Csv "C:\Analysis\PECmd_Output.csv" |
    Where-Object { [DateTime]$_.LastRun -gt $yesterday } |
    Sort-Object LastRun -Descending |
    Select-Object ExecutableName, LastRun, RunCount |
    Format-Table

Suspicious Execution Detection

# Find executables that ran from suspicious locations
Import-Csv "C:\Analysis\PECmd_Output.csv" |
    Where-Object {
        $_.SourceFilename -match '(TEMP|APPDATA|USERS.*DOWNLOADS|PUBLIC|RECYCLER)' -or
        $_.SourceFilename -match '(PROGRAMDATA|RECYCLE\.BIN)'
    } |
    Select-Object ExecutableName, SourceFilename, LastRun, RunCount |
    Format-Table

# Find executables with low run counts (potentially first-time malware)
Import-Csv "C:\Analysis\PECmd_Output.csv" |
    Where-Object { [int]$_.RunCount -le 3 } |
    Sort-Object LastRun -Descending |
    Select-Object ExecutableName, LastRun, RunCount |
    Format-Table

# Find renamed system tools (LOLBAS-style)
$systemTools = @("cmd.exe","powershell.exe","certutil.exe","bitsadmin.exe",
                  "mshta.exe","wscript.exe","cscript.exe","rundll32.exe")
Import-Csv "C:\Analysis\PECmd_Output.csv" |
    Where-Object {
        $name = $_.ExecutableName
        $systemTools | Where-Object { $name -eq $_ } |
        ForEach-Object { $_.SourceFilename -notmatch "Windows\\System32" }
    }

DLL and File Reference Analysis

# Search for specific DLL references across all Prefetch files
Import-Csv "C:\Analysis\PECmd_Output_Timeline.csv" |
    Where-Object { $_.FilesLoaded -match "suspicious.dll" } |
    Select-Object ExecutableName, RunTime |
    Format-Table

# Find executables that loaded files from USB drives
# (Look for volume paths that don't match C:\)
Import-Csv "C:\Analysis\PECmd_Output.csv" |
    Where-Object { $_.VolumeInfo -notmatch "\\Device\\HarddiskVolume[12]" } |
    Select-Object ExecutableName, VolumeInfo, LastRun |
    Format-Table

Batch Processing for Incident Response

#!/usr/bin/env python3
"""Batch process Prefetch files for IR."""
import os
import json
import prefetch
from datetime import datetime

def process_prefetch_dir(pf_dir):
    results = []
    for filename in os.listdir(pf_dir):
        if not filename.upper().endswith('.PF'):
            continue
        filepath = os.path.join(pf_dir, filename)
        try:
            pf = prefetch.Prefetch(filepath)
            entry = {
                'filename': filename,
                'executable': pf.executableName,
                'run_count': pf.runCount,
                'last_run': str(pf.lastRunTime),
                'timestamps': [str(ts) for ts in pf.timestamps],
                'file_count': len(pf.filenames),
                'directory_count': len(pf.directoryStrings),
            }
            # Flag suspicious patterns
            if any(s in str(pf.filenames).lower() for s in ['temp', 'appdata', 'downloads']):
                entry['suspicious'] = True
            results.append(entry)
        except Exception as e:
            results.append({'filename': filename, 'error': str(e)})

    return sorted(results, key=lambda x: x.get('last_run', ''), reverse=True)

results = process_prefetch_dir('/evidence/Windows/Prefetch/')
print(json.dumps(results, indent=2))

Configuration

Enabling/Disabling Prefetch

# Check Prefetch status
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" -Name EnablePrefetcher

# Values:
# 0 = Disabled
# 1 = Application launch prefetching
# 2 = Boot prefetching
# 3 = Both application and boot (default)

# Note: Windows Server editions have Prefetch disabled by default
# To enable on server:
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters" -Name EnablePrefetcher -Value 3

# Superfetch/SysMain service must also be running
Get-Service SysMain

Troubleshooting

IssueSolution
No Prefetch files foundPrefetch may be disabled (common on servers); check registry EnablePrefetcher value
Cannot decompress Win10 .pfUse PECmd or updated parser; Win10+ uses MAM compression
Timestamps show as epoch 0File may be corrupted or from an incompatible Windows version
Missing file referencesFile references use MFT numbers; full paths may not always resolve
Only 128 Prefetch filesWindows limits Prefetch to 1024 files (Win8+) or 128 (Win7); oldest are recycled
Hash doesn’t match pathDifferent paths or command-line arguments produce different hashes
Permission deniedPrefetch directory requires Admin access; copy files to writable location
Python parser failsEnsure correct parser version for Windows version (Win10 format differs)