OnyxOmega/USNJournal2EventLog
GitHub: OnyxOmega/USNJournal2EventLog
将 NTFS USN 更改日志实时转换为结构化 Windows 事件日志的取证监控服务,支持白名单过滤和长期归档。
Stars: 0 | Forks: 0
# 取证 NTFS USN 日志监控器
一个 Windows 原生后台服务,用于实时监控 **NTFS USN 更改日志**,根据用户定义的白名单过滤文件系统活动,并将取证元数据记录到专用的 Windows 事件日志 (`FileSystem`) 中。它专为终端审计、变更追踪和轻量级主机取证而设计。该服务无头运行,可在重启后保留状态,以 `LocalSystem` 身份运行,并自动管理其自身的滚动日志归档,因此可以无人值守地长时间运行,而不会塞满磁盘。
## 完整功能列表
查看完整的 **[功能列表](FEATURES.md)**
## 工作原理
```
USN Journal -> read record -> resolve parent directory by file-reference
-> O(1) whitelist match -> classify by reason -> Windows Event
```
1. 打开卷并查询(或创建) USN 日志。
2. 协商卷支持的最丰富读取格式(NTFS 上为 V2,ReFS 上为 V3)。
3. 对于每次更改,解析所在目录的路径(已缓存),并在常数时间内根据白名单进行检查。
4. 根据 USN reason 标志对更改进行分类,并使用特定类别的事件 ID 写入结构化事件。
## 系统要求
- Windows(NTFS 卷;ReFS 通过 V3 记录支持)
- Python 3.12+(64 位)
- [`pywin32`](https://pypi.org/project/pywin32/):`pip install pywin32`
- 管理员 / `LocalSystem` 权限(读取 USN 和执行 `Clear-EventLog` 需要提权)
- 存在 .NET Framework 4.x(使用其 `EventLogMessages.dll` 以便事件能够渲染出可读的描述;这几乎随附于所有现代 Windows 安装中)
## 快速开始
```
:: 1. Install dependencies
pip install pywin32
:: 2. Configure which directories to monitor (launches the GUI)
python usn_monitor.py
:: 3. Test in the foreground (Ctrl+C to stop)
python usn_monitor.py debug
:: 4. Install and start as a Windows service
python usn_monitor.py --startup delayed install
python usn_monitor.py start
```
## 事件 ID 参考
每次更改都根据其**主导** USN reason 标志进行分类(原因会累积到一个单独的关闭记录中,因此最显著的标志优先)。完整的原因字符串始终保留在事件正文中。
| 事件 ID | 类别 | 触发条件 |
|:--------:|----------------|---------------------------------------------------------------------|
| **100** | Create | `FileCreate` |
| **101** | Modify | `DataOverwrite`, `DataExtend`, `DataTruncation`, `NamedDataOverwrite`, `StreamChange` |
| **102** | Delete | `FileDelete` |
| **103** | Rename | `RenameOld`, `RenameNew` |
| **104** | SecurityChange | ACL / 所有权变更 (`SecurityChange`) |
| **105** | Other | `IndexableChange`, `BasicInfoChange`, `HardLinkChange` |
| **106** | RangeChange | `USN_RECORD_V4` 范围追踪(仅限 ReFS) |
**分类优先级:** `Delete > Create > Rename > Security > Modify > Other`。
在其关闭记录被报告之前创建并删除的文件将被报告为 **Delete**(磁盘上的净效果)。
### 查询事件
事件被写入 **`FileSystem`** 自定义日志中,可以在事件查看器中的 **Applications and Services Logs → FileSystem** 下找到。
```
# 所有删除
Get-WinEvent -FilterHashtable @{LogName='FileSystem'; Id=102}
# 创建和删除一起
Get-WinEvent -FilterHashtable @{LogName='FileSystem'; Id=100,102}
# 过去一小时内的所有内容,最新优先
Get-WinEvent -FilterHashtable @{LogName='FileSystem'; StartTime=(Get-Date).AddHours(-1)}
```
## EventData 字段(`{PARAM[n]}` 参考)
每个事件都包含一个完整且人类可读的字段块作为 `{PARAM[1]}`,以及六个高价值字段作为单独的插入字符串,以便在 **Event Log Explorer**(或任何使用位置 `EventData` 的工具)中提取列。使用下面的索引将字段提取为 `{PARAM[n]}` 自定义列。
| 索引 | 字段 | 备注 |
|-------|-------|-------|
| `{PARAM[1]}` | 完整块 | 全部 16 个字段,格式为 `Key: value` 行(可读的描述 + EvtxECmd 正则表达式源) |
| `{PARAM[2]}` | Hostname | 源主机名 |
| `{PARAM[3]}` | TargetFilename | 完整路径(映射 Sysmon — 关联键) |
| `{PARAM[4]}` | UtcTime | `YYYY-MM-DD HH:MM:SS.fff`(映射 Sysmon — 关联键) |
| `{PARAM[5]}` | MachineGuid | 稳定的机器标识符 |
| `{PARAM[6]}` | SourceIP | 服务启动时的 IP 地址 |
| `{PARAM[7]}` | VolumeSerial | NTFS 卷序列号 (`XXXX-XXXX`) |
**其余字段**(SchemaVersion, Category, Reason, Usn, JournalId, FQDN,
Domain, MachineSID, MAC, OSBuild)**不**作为单独的 `{PARAM[n]}`
字符串拆分 —— 它们存在于 `{PARAM[1]}` 块内部。可以在那里提取它们(Event Log
Explorer 支持对描述使用正则表达式),或者使用 EvtxECmd 映射,这些映射会通过正则表达式将每个字段从块中提取到 Timeline Explorer 列中。
**两种工具,两种访问方法(设计使然):**
- **Event Log Explorer** 读取原始插入字符串数组 → 对于六个拆分出的字段,请使用上面的 `{PARAM[n]}`。
- **EvtxECmd → Timeline Explorer** 渲染为单个 `Data` blob → 捆绑的映射 (`maps/`) 通过正则表达式将所有字段提取到 `PayloadData1–6` + `Computer` 中。
**注意:** 这些 `EventData` 元素是*按位置排列且未命名的*(这是经典事件报告的一个限制),因此 `{EventData\Usn}` 风格的**命名**查找**不**起作用。命名字段访问需要构建插桩清单(已计划),这将允许每个字段成为其自己的命名列。
## 选择要监控的路径
运行不带参数的 `python usn_monitor.py` 以打开配置 GUI:
- 树形结构会延迟加载目录(在大型驱动器上不会卡顿)。
- **双击文件夹**可递归地将其*及其所有子目录*添加(或移除)到白名单。递归遍历在 UI 线程之外运行,因此 GUI 绝不会卡死。
- **`[X]`** = 已监控,**`[ ]`** = 未监控。
- 使用搜索框按名称跳转到文件夹。
- 点击 **Save Config (JSON)** 以写入 `monitor_config.json`。
默认情况下,会监控 `C:\Windows` 及其所有子目录;其他所有内容均被排除。
### `monitor_config.json` 格式
配置文件位于 `usn_monitor.py` 旁边。服务在**启动时读取一次** —— 每次更改后都需要重启服务。
```
{
"paths": [
"C:\\Windows",
"C:\\Windows\\System32",
"C:\\Windows\\Temp"
],
"rotation_size_gb": 3.5,
"max_storage_gb": 60.0
}
```
| 键 | 含义 |
|--------------------|-------------------------------------------------------------------|
| `paths` | 受监控的目录(递归选择包括每个子目录) |
| `rotation_size_gb` | 当实时日志达到此大小时滚动日志 (GB) |
| `max_storage_gb` | 归档目录总容量上限;最旧的归档将被先入先出 (FIFO) 删除 (GB) |
## 日志滚动和保留
- **实时日志:** `FileSystem.evtx`(自定义的 `FileSystem` Windows 事件日志)。
- **滚动触发器(以先到者为准):**
- 实时日志达到 `rotation_size_gb`(默认 **3.5 GB**),或
- 日历到达**每月 1 日 01:00**。
- **归档命名:** `FileSystem___.evtx`
(例如 `FileSystem_June_2026_1.evtx`);计数器每月重置。
- **归档位置:** `C:\FileSystem_Archives`
- **存储上限:** 当归档目录超过 `max_storage_gb`
(默认 **60 GB**)时,**最旧的** `.evtx` 文件将首先被删除 (FIFO),直到目录回到上限以下。
滚动使用 `Clear-EventLog -Backup` 执行,这会原子地归档并清除实时日志。
## 服务管理
```
python usn_monitor.py --startup delayed install :: install (delayed auto-start)
python usn_monitor.py start :: start
python usn_monitor.py stop :: stop
python usn_monitor.py restart :: stop + start (reloads config)
python usn_monitor.py update :: re-register after editing the .py
python usn_monitor.py remove :: uninstall
sc query USNMonitorService :: check status
```
- 使用 `--startup auto` 代替 `delayed`,以便在启动时尽早开始运行。
- 编辑源代码后运行 **`update`**(而不是重新安装);SCM 会缓存脚本路径。
## 诊断
服务将其自身的操作日志(错误、启动信息、滚动活动)写入:
```
C:\FileSystem_Archives\usn_monitor.log
```
要进行深度故障排除,请通过将
`USN_VERBOSE` 环境变量设置为 `1`、`true`、`yes` 或 `on` 来启用定期计数器摘要(看到的记录数 /
解析失败 / 白名单匹配 / 发出的事件)。
```
:: Console (inherits your shell environment)
set USN_VERBOSE=1
python usn_monitor.py debug
:: Service (must be machine-wide, then restart so the SCM picks it up)
setx USN_VERBOSE 1 /m
python usn_monitor.py restart
```
详细统计信息行如下所示:
```
stats: seen=48 (v2=48 v3=0 v4=0) resolve_fail=0 no_match=3 emitted=45 last_resolve_err=None
```
`no_match` 计算白名单之外的更改(预计数量会很大 —— 这是您*未*捕获的整个卷的变动)。
## 部署到多台机器
有关组策略 / Active
Directory 和打包可执行文件选项,请参阅 **[DEPLOYMENT.md](DEPLOYMENT.md)** *(如果提供)*。简而言之:
1. **在目标机器上使用 Python:** 将 `usn_monitor.py` + `monitor_config.json` 复制到
每台主机,然后运行安装/启动命令(例如,通过 GPO 启动脚本或远程管理工具)。
2. **目标机器上没有 Python(建议规模化使用):** 使用 PyInstaller 冻结为独立
可执行文件并进行部署 —— 终端上不需要 Python 运行时。
3. 将标准的 `monitor_config.json` 推送到所有主机,以便它们共享一个白名单
和保留策略。
## 注意事项与警告
- 需要提权;在默认的 `LocalSystem` 帐户下,这是自动完成的。
- `FileSystem` 日志和事件源在首次运行时自动注册。
- 在 I/O 极高且白名单范围极广的卷上,实时日志会快速增长 —
3.5 GB / 60 GB 的滚动策略在发挥着实际作用;请根据您的保留需求进行调整。
- 路径解析按目录缓存;重命名/删除事件将绕过缓存,以避免路径过期。
## 许可证
见 **[LICENSE](LICENSE)**
标签:NTFS文件系统, Python, Windows服务, 取证, 子域名变形, 无后门, 逆向工具