Parses Windows Prefetch files to extract program execution history, run counts, timestamps, and referenced files for digital forensics investigations.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 确定 Windows 系统上执行了哪些程序及执行时间
Extracts and parses Windows Prefetch files to uncover program execution history, run counts, timestamps, and referenced files for digital forensics, malware analysis, and incident timelines.
Parses Windows Prefetch files to extract program execution history, run counts, timestamps, and referenced files for digital forensics and malware investigations.
Parses Windows Prefetch files with windowsprefetch Python library to reconstruct execution history, detect renamed or disguised binaries, and identify suspicious execution patterns for digital forensics.
Share bugs, ideas, or general feedback.
# 挂载取证镜像
mount -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/evidence.dd /mnt/evidence
# 复制所有 Prefetch 文件
mkdir -p /cases/case-2024-001/prefetch/
cp /mnt/evidence/Windows/Prefetch/*.pf /cases/case-2024-001/prefetch/
# 统计并列出 Prefetch 文件
ls -la /cases/case-2024-001/prefetch/ | wc -l
ls -la /cases/case-2024-001/prefetch/ | head -30
# 对所有 Prefetch 文件进行哈希以验证完整性
sha256sum /cases/case-2024-001/prefetch/*.pf > /cases/case-2024-001/prefetch/pf_hashes.txt
# 注意:Prefetch 文件名格式为 EXECUTABLE_NAME-XXXXXXXX.pf
# 哈希值(XXXXXXXX)基于可执行文件路径
# 来自不同路径的相同可执行文件会创建不同的 Prefetch 文件
# 使用 Eric Zimmerman 的 PECmd(Windows 或通过 Linux 上的 Mono/Wine)
# 从 https://ericzimmerman.github.io/ 下载
# 解析单个 Prefetch 文件
PECmd.exe -f "C:\cases\prefetch\POWERSHELL.EXE-A]B2C3D4.pf"
# 解析所有 Prefetch 文件并输出到 CSV
PECmd.exe -d "C:\cases\prefetch\" --csv "C:\cases\analysis\" --csvf prefetch_results.csv
# 以 JSON 格式输出
PECmd.exe -d "C:\cases\prefetch\" --json "C:\cases\analysis\" --jsonf prefetch_results.json
# 每个文件的输出包含:
# - 可执行文件名和路径
# - 运行次数
# - 最后运行时间(Windows 10 中最多 8 个时间戳)
# - 执行期间引用的文件和目录
# - 卷信息(序列号、创建日期)
# - Prefetch 文件创建时间
pip install prefetch
python3 << 'PYEOF'
import os
import json
from datetime import datetime
# 使用 python 解析 Prefetch 文件
import struct
def parse_prefetch(filepath):
"""解析 Windows Prefetch 文件。"""
with open(filepath, 'rb') as f:
data = f.read()
# 检查 MAM 压缩格式(Windows 10)
if data[:4] == b'MAM\x04':
import lznt1 # 或使用 DecompressBuffer
# Windows 10 Prefetch 文件已压缩
print(f" [压缩的 Win10 格式 - 使用 PECmd 进行完整解析]")
return None
# 版本 17(XP)、23(Vista/7)、26(8.1)、30(10)
version = struct.unpack('<I', data[0:4])[0]
signature = data[4:8]
if signature != b'SCCA':
print(f" 无效的 Prefetch 签名")
return None
file_size = struct.unpack('<I', data[8:12])[0]
exec_name = data[16:76].decode('utf-16-le').strip('\x00')
run_count = struct.unpack('<I', data[208:212])[0] if version >= 23 else struct.unpack('<I', data[144:148])[0]
result = {
'version': version,
'executable': exec_name,
'file_size': file_size,
'run_count': run_count,
}
# 提取最后执行时间戳
if version == 23: # Vista/7 - 1 个时间戳
ts = struct.unpack('<Q', data[128:136])[0]
result['last_run'] = filetime_to_datetime(ts)
elif version >= 26: # Win8+ - 最多 8 个时间戳
timestamps = []
for i in range(8):
ts = struct.unpack('<Q', data[128+i*8:136+i*8])[0]
if ts > 0:
timestamps.append(filetime_to_datetime(ts))
result['last_run_times'] = timestamps
return result
def filetime_to_datetime(ft):
"""将 Windows FILETIME 转换为 datetime 字符串。"""
if ft == 0:
return None
timestamp = (ft - 116444736000000000) / 10000000
try:
return datetime.utcfromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S UTC')
except (OSError, ValueError):
return None
# 处理所有 Prefetch 文件
prefetch_dir = '/cases/case-2024-001/prefetch/'
results = []
for filename in sorted(os.listdir(prefetch_dir)):
if filename.lower().endswith('.pf'):
filepath = os.path.join(prefetch_dir, filename)
print(f"\n=== {filename} ===")
result = parse_prefetch(filepath)
if result:
print(f" 可执行文件: {result['executable']}")
print(f" 运行次数: {result['run_count']}")
if 'last_run' in result:
print(f" 最后运行: {result['last_run']}")
elif 'last_run_times' in result:
for i, ts in enumerate(result['last_run_times']):
print(f" 运行时间 {i+1}: {ts}")
results.append(result)
# 保存结果
with open('/cases/case-2024-001/analysis/prefetch_analysis.json', 'w') as f:
json.dump(results, f, indent=2)
PYEOF
# 在 Prefetch 中搜索已知恶意工具名称
ls /cases/case-2024-001/prefetch/ | grep -iE \
'(MIMIKATZ|PSEXEC|WMIC|COBALT|BEACON|PWDUMP|PROCDUMP|LAZAGNE|RUBEUS|BLOODHOUND|SHARPHOUND|CERTUTIL|BITSADMIN)'
# 搜索脚本解释器(潜在的恶意执行)
ls /cases/case-2024-001/prefetch/ | grep -iE \
'(POWERSHELL|CMD\.EXE|WSCRIPT|CSCRIPT|MSHTA|REGSVR32|RUNDLL32|MSIEXEC)'
# 搜索远程访问工具
ls /cases/case-2024-001/prefetch/ | grep -iE \
'(TEAMVIEWER|ANYDESK|LOGMEIN|VNC|SPLASHTOP|SCREENCONNECT|AMMYY)'
# 搜索数据外泄工具
ls /cases/case-2024-001/prefetch/ | grep -iE \
'(RAR|7Z|ZIP|RCLONE|MEGA|DROPBOX|ONEDRIVE|GDRIVE|FTP|CURL|WGET)'
# 查找最近创建的 Prefetch 文件(最近执行的可执行文件)
ls -lt /cases/case-2024-001/prefetch/ | head -20
# 与 Shimcache 和 Amcache 交叉验证以确认
# Prefetch 存在 = 程序至少执行过一次
# 从 Prefetch 数据创建时间线
python3 << 'PYEOF'
import json
import csv
with open('/cases/case-2024-001/analysis/prefetch_analysis.json') as f:
data = json.load(f)
timeline = []
for entry in data:
if 'last_run_times' in entry:
for ts in entry['last_run_times']:
if ts:
timeline.append({
'timestamp': ts,
'executable': entry['executable'],
'run_count': entry['run_count'],
'source': 'Prefetch'
})
elif 'last_run' in entry and entry['last_run']:
timeline.append({
'timestamp': entry['last_run'],
'executable': entry['executable'],
'run_count': entry['run_count'],
'source': 'Prefetch'
})
# 按时间排序
timeline.sort(key=lambda x: x['timestamp'])
# 写入时间线 CSV
with open('/cases/case-2024-001/analysis/execution_timeline.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['timestamp', 'executable', 'run_count', 'source'])
writer.writeheader()
writer.writerows(timeline)
# 打印可疑时间窗口
for entry in timeline:
if '2024-01-15' in entry['timestamp'] or '2024-01-16' in entry['timestamp']:
print(f" {entry['timestamp']} | {entry['executable']} (x{entry['run_count']})")
PYEOF
| 概念 | 描述 |
|---|---|
| Prefetch | Windows 性能优化功能,预加载应用程序数据并跟踪执行情况 |
| SCCA 签名 | 标识有效 Prefetch 文件的魔数字节 |
| 路径哈希 | 基于可执行文件路径的 CRC 哈希,构成 .pf 文件名的一部分 |
| 运行次数 | 可执行文件启动次数(可能会回绕) |
| 最后运行时间戳 | Windows 8+ 存储最多 8 个最近的执行时间戳 |
| 引用文件 | 执行开始后前 10 秒内访问的文件和目录列表 |
| 卷信息 | 标识源卷的驱动器序列号和创建日期 |
| MAM 压缩 | Windows 10 Prefetch 文件使用 MAM4 压缩,解析前需要解压 |
| 工具 | 用途 |
|---|---|
| PECmd | Eric Zimmerman 的 Prefetch 解析器,支持 CSV/JSON 输出 |
| WinPrefetchView | NirSoft 的 GUI 工具,用于查看 Prefetch 文件 |
| python-prefetch | 用于解析 Prefetch 文件的 Python 库 |
| Prefetch Hash Calculator | 从可执行文件路径计算预期哈希的工具 |
| KAPE | 自动化制品收集工具,包含 Prefetch |
| Autopsy | 带有 Prefetch 分析模块的取证平台 |
| Plaso/log2timeline | 超级时间线工具,包含 Prefetch 解析器 |
| Velociraptor | 带有 Prefetch 收集和分析制品的终端 Agent |
场景 1:确认恶意软件执行 在 Prefetch 目录中搜索恶意软件可执行文件名,通过 Prefetch 存在确认执行,提取运行次数和最后运行时间,识别引用的 DLL 以了解恶意软件行为,与注册表自启动条目相关联。
场景 2:攻击者工具使用时间线 识别 PsExec、Mimikatz、BloodHound 和其他攻击者工具的 Prefetch 文件,建立工具执行的时间线,确定攻击顺序(侦察、凭据窃取、横向移动),将时间戳与网络连接日志匹配。
场景 3:数据暂存和外泄 查找压缩工具(7z、WinRAR、zip)的 Prefetch 条目,识别文件传输工具(rclone、FTP 客户端)的执行情况,检查云存储客户端执行,确定数据暂存和传输发生的时间。
场景 4:反取证检测 检查已知反取证工具(CCleaner、Eraser、SDelete)的执行情况,识别 Prefetch 目录是否最近被清除(活跃系统中文件少于预期),注意反取证工具执行时间戳与其他证据的关系。
Prefetch 分析摘要:
系统: Windows 10 Pro(Build 19041)
Prefetch 文件数: 234
分析范围: 所有可用执行历史
执行统计:
唯一可执行文件总数: 234
首次执行: 2023-06-15(系统安装)
最近执行: 2024-01-18 23:45 UTC
可疑执行:
MIMIKATZ.EXE-5F2A3B1C.pf
运行次数: 3 | 最后: 2024-01-16 02:30:15 UTC
PSEXEC.EXE-AD70946C.pf
运行次数: 7 | 最后: 2024-01-16 02:45:30 UTC
RCLONE.EXE-1F3E5A2B.pf
运行次数: 2 | 最后: 2024-01-17 03:15:00 UTC
POWERSHELL.EXE-022A1004.pf
运行次数: 145 | 最后: 2024-01-18 14:00:00 UTC
攻击时间线(来自 Prefetch):
2024-01-15 14:32 - POWERSHELL.EXE(初始访问)
2024-01-16 02:30 - MIMIKATZ.EXE(凭据窃取)
2024-01-16 02:45 - PSEXEC.EXE(横向移动)
2024-01-17 03:15 - RCLONE.EXE(数据外泄)
报告: /cases/case-2024-001/analysis/execution_timeline.csv