
简介这是一款面向普通用户与维护人员的视窗系统使用痕迹检测工具能快速梳理电脑近期目录访问、文件打开、关键词搜索以及优盘和移动硬盘接入记录。工具只读取注册表中保存的信息对注册表、文件、事件日志等内容进行归纳展示不联网、不传输数据、不修改注册表适用于注重隐私的本机排查与基础取证。资源包包含三十九个文件类型覆盖可执行主程序、批处理辅助脚本、图标资源、配置文件、说明文档及运行库压缩包仅有四兆多便于携带和离线部署。使用者可借助主程序直接查看也可通过批处理增加或移除右键菜单按需检索历史痕迹。已有1656人学习下载适合需要盘点本地操作留痕、核验外接设备记录或开展系统运维排查的人群。1. 先别信“所有痕迹”Windows 痕迹检测的实际边界与适用场景市面上一搜“Windows使用痕迹检测工具”跳出来的多半是“扫一遍注册表、看最近打开文件、列出 USB 记录”的小工具。我的结论先说这类工具能解决 80% 的办公场景诉求但“追踪电脑使用所有痕迹”是个伪命题——内存里的驻留进程、锁屏密码、加密卷内容、固件级操作都不在持久化检测的射程内。真正能落地的范围是注册表、文件系统元数据和事件日志三类数据源。这套能力最适合三类人IT 运维要做离职电脑检查、安全岗做轻量应急响应、审计需要回答“这台机器上周到底被用来做了什么”。下面按数据源地图、采集脚本、日志关联、避坑、复核的顺序写全程用 Windows 自带命令和 Sysinternals不需要额外安装重型取证平台。2. 痕迹都在哪注册表、MFT、Prefetch 与外部设备记录的取证地图痕迹检测的第一步不是安装工具而是知道 Windows 自己把痕迹写在了哪里。系统为了运行效率几乎每天都会把用户行为落盘这些落盘点就是我说的数据源地图。再把“精准追踪某台机器某周行为”的需求代入你会发现只要目标机器没被重装过绝大部分痕迹都能在下面四个位置找到。2.1 用户活动痕迹注册表里五个拿到就能用的键注册表是用户动作的直接记录器按 HKCU 和 HKLM 分置。对个人用户痕迹最有效的是下面五个位置它们在 Win10 / Win11 / Server 2016 之后的路径基本一致。痕迹项注册表路径能证明什么注意点RecentDocsHKCU\...\Explorer\RecentDocs最近打开过的文档名只存文件名与扩展名,不带完整路径RunMRUHKCU\...\Explorer\RunMRU用户在“运行”框里敲过的命令能还原出直接执行的命令TypedPathsHKCU\...\Explorer\TypedPaths资源管理器地址栏输入过的路径常暴露共享目录名WordWheelQueryHKCU\...\Explorer\WordWheelQuery开始菜单搜索框查过的关键词能看出用户搜过什么文件UserAssistHKCU\...\Explorer\UserAssist按 GUI 方式启动过的程序与次数子键为 GUID数据经 ROT13 编码这里的...指的是一长串公共前缀Software\Microsoft\Windows\CurrentVersion。需要注意 RecentDocs 只记录文档名而非全路径单独看价值有限要和下文 MFT 里的文件路径关联起来才有意义。UserAssist 经常被忽略但它恰恰是“追踪电脑使用痕迹”里最接近黑匣子的数据源。它记录的是通过资源管理器、开始菜单等 GUI 方式启动的程序每条值都带最后执行时间。数据默认做了一层 ROT13 混淆网上有现成解析脚本但手动检测时我会用 Windows 自带 PowerShell 先把键值读出来再交给后续脚本解码。2.2 文件系统痕迹MFT 为什么是文件名取证的第一现场NTFS 的 MFT主文件表始终记录着卷内所有文件的元数据包括文件名、父目录 ID、创建时间、修改时间、MFT 变更时间和访问时间。哪怕文件被删除只要卷上没有被新数据覆盖这条记录就还在。也就是说MFT 是“这台电脑上出现过的文件名单”这是注册表补不了的能力。实际操作中检测脚本直接抓 MFT 需要管理员权限和卷影复制支持我更常见的做法是先按文件名遍历用户目录和临时目录拿一份存活文件清单再结合卷影或取证工具补删减文件。如果只做日常办公电脑审计一般到 Prefetch 和 LNK 这层就够用了只有涉及删文件抵赖的场景才值得把 MFT 完整捞出来重建。2.3 程序运行痕迹Prefetch 文件名规则与 LNK 的互补作用Prefetch 是 Windows 为了加速程序启动而生成的预读文件默认存放在C:\Windows\Prefetch文件名格式是“程序名-路径哈希.pf”。路径哈希是执行文件所在完整路径的哈希结果不是文件内容哈希。所以看到NOTEPAD.EXE-2F0A3B1C.pf就能推断出 notepad.exe 曾从某条固定路径启动过。Prefetch 记录的是程序级痕迹LNK 快捷方式记录的是文件级痕迹两者正好互补。用户在资源管理器里打开过的文档、插入过的 U 盘里的某个可执行文件都会在C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Recent下生成 LNK。LNK 文件内部保存着目标路径、所在卷序列号和最后访问时间解开它就能还原“用户点开过哪个 exe、哪个文档”。2.4 外部设备痕迹USBStor 与 MountedDevices 还原接入记录“拷走资料”是离职检查里最高频的诉求所以外部设备记录必须单独看。USBSTOR 键位于HKLM\SYSTEM\CurrentControlSet\Enum\USBSTOR记录着系统曾识别过的 U 盘、移动硬盘的厂商、产品名、序列号。MountedDevices 键在HKLM\SYSTEM\MountedDevices记录着卷标到设备实例的映射关系。两个键合起来能确定“某个序列号的移动存储设备在这台机器上挂载过”但要想精确定位插入时间还需要去翻C:\Windows\INF\setupapi.dev.log中的设备安装记录以及卷的首次挂载时间。这里有个常见误判USBSTOR 显示的是设备枚举状态不是操作时间单看它就说“某 U 盘在这天插过”是不严谨的。2.5 先声明射程哪些痕迹注定测不到做技术方案要诚实先把“测不到”讲清楚才能让读者信服后面测得准。普通痕迹检测工具射程之外的部分包括内存中正在运行的进程与明文口令、BitLocker 等加密卷内的内容、被安全擦除工具覆盖过的扇区、断网期间不落日志的操作。检测工具只能覆盖“持久化介质上仍能读到的行为记录”。3. 用 PowerShell 与 Sysinternals 搭一套可复现的最小痕迹采集流程原理理清了下面进入能抄作业的部分。我一般用 PowerShell 完成全部采集单文件复制到目标机器即可不需要安装额外运行时。这套流程本质上就是一次 Windows 主机信息收集把注册表、LNK、Prefetch 和 USB 记录四路数据统一下到同一目录再做哈希固化。3.1 为什么默认组合是 PowerShell Sysinternals选择 PowerShell 的核心理由有三个一是目标 Windows 机器必定自带不存在“少装依赖导致采集失败”的问题二是所有操作可以控制成只读不会向目标系统写入分析文件三是结果可以统一导出成 CSV方便后续合并时间线。Sysinternals 套件里的 autorunsc 和 strings 工具用来补充启动项分析与二进制字符串提取但不属于必需依赖。采集时我会建议在 Windows Terminal 里开一个管理员窗口先确认执行策略允许脚本运行。如果公司环境用 GPO 锁死了 Set-ExecutionPolicy可以直接用powershell -ExecutionPolicy Bypass -File trace.ps1的方式绕过这个参数只对本次会话生效不改系统配置。3.2 先建采集目录与环境变量后续脚本都依赖这一行下面所有代码块都依赖同一个输出目录变量$outDir建议拼成一个.ps1文件连续执行。这段脚本负责生成带时间戳的目录避免二次采集时把上一次结果覆盖掉。# 采集根目录设置生成带时间戳的输出目录 $stamp Get-Date -Format yyyyMMdd_HHmmss $outDir $env:TEMP\WinTrace_$stamp New-Item -ItemType Directory -Path $outDir -Force | Out-Null Write-Host 结果将输出到: $outDir逻辑说明Get-Date -Format把时间格式化成适合做文件名后缀的字符串New-Item -Force确保目录创建成功且不会报错。参数说明$env:TEMP是当前用户临时目录在标准企业环境里可写如果你需要把结果落到 U 盘可改成D:\Trace这类绝对路径但注意输出介质不能放在待检磁盘里否则会写脏证据。3.3 抓注册表用户活动痕迹五个目标的导出脚本注册表的读取是只读操作不会对被检系统造成影响这也是我优先查它的原因。下面脚本遍历前面提到的关键键只要键存在就把所有属性拍平导出。# 导出注册表中与用户活动相关的关键键值 $regTargets ( HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs, HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU, HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths, HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\WordWheelQuery, HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist ) $rows foreach ($path in $regTargets) { if (Test-Path $path) { Get-ItemProperty -Path $path | Select-Object PSPath, PSParentPath, * } } $rows | Export-Csv $outDir\registry_user_activity.csv -NoTypeInformation逻辑说明Test-Path先判断键是否存在避免对不存在的键报错Get-ItemProperty读取键下的所有值Select-Object PSPath, *会把键路径和全部值列一起输出。参数说明-NoTypeInformation是 Export-Csv 去掉类型行的常用参数保证产出干净的 CSV方便后面合并时间线时导入。3.4 展开 Recent 下的 LNK把快捷方式还原成目标路径LNK 文件是二进制格式直接读文本只能看到乱码。PowerShell 里最稳的办法是通过 WScript.Shell 的 COM 接口解析它能把目标路径、工作目录一次性取出。# 遍历每个用户的 Recent 目录解析 LNK 指向的目标 $shell New-Object -ComObject WScript.Shell $users Get-ChildItem -Path $env:SystemDrive\Users -Directory | Where-Object { $_.Name -notin (Public, Default, Default User) } $lnkRows foreach ($user in $users) { $recentDir Join-Path $user.FullName AppData\Roaming\Microsoft\Windows\Recent Get-ChildItem -Path $recentDir -Filter *.lnk -ErrorAction SilentlyContinue | ForEach-Object { $shortcut $shell.CreateShortcut($_.FullName) [PSCustomObject]{ User $user.Name LinkPath $_.FullName Target $shortcut.TargetPath LastWrite $_.LastWriteTime } } } $lnkRows | Export-Csv $outDir\lnk_targets.csv -NoTypeInformation逻辑说明Get-ChildItem遍历每个用户的 Recent 目录-ErrorAction SilentlyContinue跳过当前用户无权访问的其他账户目录CreateShortcut是 COM 接口的解析入口只读不改。参数说明Where-Object里的排除名单用于跳过系统自带用户目录如果目标机器只有一个用户直接把$user.Name硬编码成用户名更快。3.5 列出 Prefetch 目录程序名、路径哈希与最近运行时间Prefetch 文件的修改时间约等于程序最后一次运行时间这是重建时间线的重要锚点。用文件名拆解出进程名再按时间倒序排列能快速得到一台机器“最近动过哪些程序”。# 列举 Prefetch 目录拆解进程名和路径哈希 $pfDir $env:SystemRoot\Prefetch Get-ChildItem -Path $pfDir -Filter *.pf -ErrorAction SilentlyContinue | ForEach-Object { $base $_.BaseName $sep $base.LastIndexOf(-) [PSCustomObject]{ ProcessName if ($sep -gt 0) { $base.Substring(0, $sep) } else { $base } PathHash if ($sep -gt 0) { $base.Substring($sep 1) } else { N/A } LastRun $_.LastWriteTime FileSizeKB [Math]::Round($_.Length / 1KB, 2) } } | Sort-Object LastRun -Descending | Export-Csv $outDir\prefetch_list.csv -NoTypeInformation逻辑说明LastIndexOf(-)从文件名最后一个连字符处拆分左边是进程名右边是路径哈希Sort-Object LastRun -Descending按最近运行时间倒序一眼能看到最新动过的程序。参数说明Win7 和 Win10 的 Prefetch 文件名规则基本一致如果文件名里没有连字符少见-gt 0判断会兜底输出N/A。3.6 导出 USBSTOR 设备列表并做 SHA256 固化最后跟上外部设备记录同时对所有采集结果做哈希固化这是证据链的基本要求。哈希值保存后任何人再改 CSV 都能被查出来。# 导出 USBSTOR 设备枚举记录 $usbRows Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Enum\USBSTOR -ErrorAction SilentlyContinue | ForEach-Object { $props Get-ItemProperty -Path $_.PSPath [PSCustomObject]{ Class $_.PSChildName.Split()[0] FriendlyName $props.FriendlyName Serial $props.SerialNumber Path $_.PSChildName } } $usbRows | Export-Csv $outDir\usb_devices.csv -NoTypeInformation # 对所有采集结果生成 SHA256 哈希固化证据文件 Get-ChildItem -Path $outDir\* -File | ForEach-Object { Get-FileHash -Path $_.FullName -Algorithm SHA256 | Select-Object {nFile;e{$_.Path}}, Hash } | Export-Csv $outDir\hash_list.csv -NoTypeInformation逻辑说明USBSTOR 子键名格式是“类厂商PID版本”Split()[0]取第一段归类Get-FileHash遍历输出目录所有 CSV生成 SHA256 清单。参数说明-Algorithm SHA256是建议的最低标准如果你所在行业要求更高可换成 SHA384 或 SHA512。哈希清单生成后整个采集目录就冻结成了可复核的证据包。4. 用 Windows 安全日志与时间线重建把碎片痕迹拼成完整行为链前三步拿到的是分散的快照注册表告诉你打开过什么、Prefetch 告诉你运行过什么、LNK 告诉你双击过什么。要回答“他到底在几点做了什么”还得靠 Windows 安全日志把这些碎片按时间串起来。安全日志是这里面的主线也是最能直接对齐“精准追踪”需求的数据源。4.1 安全日志四类高价值事件4624、4625、4648、4688安全日志默认记录登录事件但进程创建审核默认是关闭的这点先说清楚。四类事件各自用途如下表事件 ID含义在痕迹检测里的价值4624登录成功证明某账户在特定时间成功登录含登录类型和来源 IP4625登录失败常见于暴力破解尝试或用户记错密码4648使用显式凭据登录可定位“用管理员账号去连别人机器”的行为4688进程创建记录新进程的可执行文件路径和命令行需提前开启审核其中 4688 需要手动开启路径是“本地安全策略 → 审核策略 → 审核进程创建”打开之后还能通过“审核命令行”参数记录完整命令行。对于已经临时接手的检测任务4688 没开就查不到历史这一点要写进报告避免后续误判“机器很干净”。4.2 用 Get-WinEvent 按事件 ID 和时间范围筛选Get-WinEvent 是 PowerShell 里读日志最快的方式配合 FilterHashtable 能一次筛出多个事件 ID不需要写花哨的 XML。# 按事件 ID 和时间范围筛选安全日志 $startTime (Get-Date).AddDays(-7) $events Get-WinEvent -FilterHashtable { LogName Security Id 4624,4625,4648,4688 StartTime $startTime } -ErrorAction SilentlyContinue $events | Select-Object TimeCreated, Id, {nLogMessage;e{$_.Message.Substring(0, [Math]::Min(120, $_.Message.Length))}} | Export-Csv $outDir\security_events.csv -NoTypeInformation逻辑说明-FilterHashtable是性能最优的筛选方式比Where-Object在日志服务器上快一个量级StartTime默认取七天按需可调整。参数说明LogName必须是 Security注意不能简写-ErrorAction SilentlyContinue用于日志权限不足时静默跳过但后面需要检查结果文件大小来确认是否真的读到了数据。4.3 从事件 XML 中提取用户名、登录类型与来源 IPSelect-Object 直接取 Message 字段的可读性差且不同事件 ID 的消息格式不统一。我的习惯是从事件 XML 里按数据名取值这样输出表结构固定合并时间线时省事。# 从事件 XML 中提取结构化字段 $cleaned $events | ForEach-Object { $xml [xml]$_.ToXml() $data {} $xml.Event.EventData.Data | ForEach-Object { $data[$_.Name] $_.#text } [PSCustomObject]{ Time $_.TimeCreated EventId $_.Id User $data[TargetUserName] LogonType $data[LogonType] SrcIp $data[IpAddress] Process $data[ProcessName] } } $cleaned | Export-Csv $outDir\security_events_structured.csv -NoTypeInformation逻辑说明[xml]$_.ToXml()把事件对象转成 XML 文档再遍历EventData里的 Data 节点按 Name 建字典后面用键名取值。参数说明LogonType 字段是登录类型判断的关键——2 代表交互式本地登录3 是网络登录10 是远程桌面登录。出现 10 时就需要重点排查远程桌面的操作行为了。4.4 合并三类数据源生成一条带时间戳的行为链数据齐全后我用一个脚本把注册表、LNK、Prefetch、安全日志合并成整体时间线。这里最容易翻车的点是 CSV 里的时间字段会在导入时变成字符串直接 Sort 会按字典序排必须先把时间列转成[datetime]类型。# 合并四路数据源生成统一时间线 $prefetch Import-Csv $outDir\prefetch_list.csv $lnk Import-Csv $outDir\lnk_targets.csv $events Import-Csv $outDir\security_events_structured.csv $timeline () $prefetch | ForEach-Object { $timeline [PSCustomObject]{ Time $_.LastRun; Source Prefetch; Detail $_.ProcessName } } $lnk | ForEach-Object { $timeline [PSCustomObject]{ Time $_.LastWrite; Source LNK; Detail $_.Target } } $events | ForEach-Object { $timeline [PSCustomObject]{ Time $_.Time; Source SecEvent_$($_.EventId); Detail $($_.User) / LogonType$($_.LogonType) } } $timeline | ForEach-Object { $_.Time [datetime]$_.Time; $_ } | Sort-Object Time | Export-Csv $outDir\timeline_all.csv -NoTypeInformation逻辑说明在数据量只有几千条时没问题如果目标机器是重度使用一年以上的主机会过万条建议改用List[object]的 Add 方式避免数组反复复制带来的性能浪费。参数说明Source列保留了数据来源复核阶段据此判断每条记录的可信度比如 LNK 时间来自文件写入时间Prefetch 时间来自预读文件修改时间两者相差可能有一两分钟这不影响行为链趋势但精准到秒的证据就要再找依据。5. Windows 痕迹检测避坑清单误判、假痕和取证污染的三类翻车现场做检测最怕的不是找不到痕迹而是找到了错误的痕迹、或者把检测工具自己的行为算成用户行为。下面五条全是实际踩过的坑每条按现象、原因、解决三步写。5.1 系统时区与事件时间不一致时间线整体漂移现象合并时间线后发现安全日志的时间比 Prefetch 和 LNK 晚或早整 8 小时事件顺序乱成一团。原因事件日志记录的是本地时间但日志文件中并不保存当时的时区偏移量。如果机器中途被改过时区或者手动调整过系统时间4930 事件会记录调整动作但后续所有日志都按新时区继续写。解决采集时先读HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation里的 TimeZoneKeyName 和 Bias把时区记录进哈希清单。合并时间线时先把所有时间统一换算成 UTC 再排序输出报告时再转回本地时区。5.2 检测脚本自身的运行痕迹污染了结果现象时间线里出现大量powershell.exe、conhost.exe的 Prefetch 记录且运行时间正好是检测执行时段容易误判成“这台机器在被检测时执行了恶意脚本”。原因你把检测脚本放到目标机上运行运行本身就会产生 Prefetch 记录、更新 MFT 时间戳、写入 PowerShell 历史。这就是取证污染。解决在检测开始时先记录脚本自身的哈希与启动时间生成时间线后把所有powershell.exe/脚本路径相关的记录剔除并在报告里单独列一节“检测动作自证痕迹”。如果严肃取证最稳的做法是先对磁盘做镜像再分析镜像而不是在目标机上直接跑脚本。5.3 Prefetch 缺失不代表程序没运行过现象报告中某个关键程序没有对应 .pf 文件结论写成“该程序从未运行”。实际后来查到程序是 U 盘里的绿色版。原因Prefetch 默认只对启动频率高的程序生成可移动介质上的程序不一定进入预读机制同时 Win10 在某些 SSD 上默认关闭 Prefetch 功能程序运行但预读文件不生成。解决Prefetch 缺失只能说明“没有留下预读痕迹”不能当成“没运行过”的证据。结论里要写“该程序未发现运行痕迹”并让 LNK、4688 日志、MFT 三者交叉验证。LNK 里有、4688 里有、Prefetch 里没有的情况一般就是介质或策略原因。5.4 杀软或 EDR 把采集动作当恶意行为拦截现象中间脚本执行到一半退出输出的 CSV 只有注册表结果后续 LNK 和 USB 文件都没有生成。检查发现是公司 EDR 对 PowerShell 的批量文件遍历动作产生了拦截告警。原因企业级 EDR 对 PowerShell 脚本的敏感操作有默认策略尤其是遍历多个用户目录和读取 Prefetch 的行为特征与某些信息窃取脚本高度相似。解决执行前先把检测脚本的 SHA256 提交给安全团队审批加白或者临时申请一个豁免窗口。不要在目标机器上写完脚本就跑那既容易触发告警也容易让脚本用户态出错。我习惯在本地虚拟机里先跑通全过程拷到目标机只执行不调试。5.5 事件日志服务被停或日志已被清理取证数据断裂现象安全日志只有最近两天但检测需求是回溯一个月或者 Get-WinEvent 直接报拒绝访问。原因一是 Windows 事件日志的默认容量有限计算机日志默认 20MBWin7或 1024MBWin10超容量后按策略覆盖二是用户的清理类工具触发了日志清除清除动作本身会产生 1102 事件但日志清空后就无从查起。解决采集时先检查 1102 事件是否存在存在就说明日志被清过。同时统计日志可用空间与最早一条记录的时间把“日志覆盖导致时间范围不完整”写进报告避免审计方误把超期数据当成“没有历史行为”。6. 让检测结果经得起复核用两次采集隔离“工具自身痕迹”前面避坑清单里提到检测工具会污染结果这里展开一个可复现的复核技巧对同一台机器做两轮采集用两轮结果的差异反推“哪些痕迹是检测工具自己产生的”然后把它们从时间线中剔除。这也是我每次交付报告前必做的自检步骤。第一轮采集按第 3 章的流程跑完生成hash_list.csv和timeline_all.csv间隔两小时或更久后对同一台机器再做第二轮采集。重点比对 Prefetch 列表和 LNK 目录中新增的记录正常情况下新增项就是检测脚本自己的powershell.exe执行痕迹以及脚本所在路径下被 Touched 过的文件记录。# 保留本轮采集脚本自身的哈希便于两轮结果比对时快速识别 $selfHash Get-FileHash -Path $PSCommandPath -Algorithm SHA256 $selfHash | Select-Object Hash, {nScriptPath;e{$_.Path}} | Export-Csv $outDir\self_evidence.csv -NoTypeInformation逻辑说明这行命令必须在采集脚本的第一行执行这样$PSCommandPath才能拿到当前脚本路径哈希值随后列入证据包。参数说明如果两轮采集交付时间隔得久建议把第二轮生成的所有 CSV 放进独立子目录而不是覆盖第一轮这样差异对比不会混淆。两轮比对完成后把第二轮新增的 PowerShell 相关记录标记为“检测工具自证痕迹”从最终时间线中剔除交付给审计方的时间线就是干净的。这个动作虽然不能消除检测对系统的写入但让每一处新增痕迹都有了解释报告才经得起复核。我的习惯是每次拿到“最后时间线”之前都要问自己一句这条记录如果是执行检测时产生的我凭什么把它算到用户头上看不出来就再做一轮采集。这套流程跑得越熟练定位速度越快误判越少。希望帮到你。本文还有配套的精品资源点击获取