durck/applocker-viewer
GitHub: durck/applocker-viewer
一个零依赖的 AppLocker 策略检查工具,提供 CLI 解析过滤与交互式 HTML 查看器,帮助红蓝团队快速发现 Windows 应用控制策略中的风险配置。
Stars: 2 | Forks: 0
# AppLocker Viewer
[](https://github.com/durck/applocker-viewer/actions/workflows/tests.yml)
[](https://www.python.org/)
[](LICENSE)
专为红队设计的 `Get-AppLockerPolicy -Effective -Xml` 输出检查工具。
- **CLI** 支持 table / JSON / CSV 输出及任意过滤器
- **独立 HTML 查看器**(支持拖放、分面、AND/OR 过滤组、预设)
- **风险分析器** 采用原子标记(atomic flags)——通过过滤实现组合,而非硬编码
- 两个策略之间的 **Diff 对比**(增加 / 删除 / 修改,可感知身份)
- **PowerShell 包装器** 用于捕获实时策略
- **仅依赖标准库** 的 Python,无任何外部依赖
## 安装
```
git clone https://github.com/durck/applocker-viewer.git
cd applocker-viewer
```
就是这么简单——不需要 `pip install`。Python 3.10+ 是唯一的要求(使用了
`from __future__ import annotations`,PEP 604 联合类型等特性,3.10+ 版本自带)。
使用 `python -m pytest -q` 运行测试(pytest 是唯一的开发依赖)。
## 目录结构
```
applocker.py core parser, filter, analyzer, diff (CLI)
viewer.html standalone single-file viewer (no server, no deps)
Get-AppLockerPolicy.ps1 thin PS wrapper -> applocker.py
tests/ pytest suite + XML fixtures
```
## 快速开始
### 在活动的 Windows 主机上捕获并分析
```
.\Get-AppLockerPolicy.ps1 analyze
```
### 检查已保存的 XML
```
python applocker.py parse policy.xml --pretty
python applocker.py filter policy.xml --action allow --collection exe
python applocker.py filter policy.xml --risky --format json
python applocker.py analyze policy.xml
python applocker.py diff old.xml new.xml
```
### 在浏览器中打开
在任何浏览器中打开 `viewer.html`(无需服务器)。将 `applocker.py parse` 输出的 XML 或 JSON 拖入页面,或点击 **Open file**。
该查看器支持:
- 侧边栏顶部的 **搜索** —— 跨规则名称、描述、摘要、SID/主体名称以及序列化
条件/异常的不区分大小写子串匹配(因此 `mshta`、`\appdata\`、`S-1-5-32-544` 等均可生效)。
- **带 AND/OR 的过滤组**:
- 同一分面(例如 `risk flag`)内的多选为 **OR**。
- 同一组内不同分面之间为 **AND**。
- 不同组之间为 **OR**(使用 `+ Add group (OR)`)。
- **每个值的三种状态**:左键单击 = 包含,右键单击 = 排除。
- **内置预设** 提供常见的红队视图(宽泛路径允许、LOLBin 允许、用户可写允许、AuditOnly 规则、通配符发布者等),以及保存在 `localStorage` 中的 **用户自定义预设**。应用预设会替换当前的分组;一步 **撤销** 可恢复到先前状态。
- **可调整大小的列** 支持三种手势,均持久化到 `localStorage`:
- 向右拖动 ⇒ 池压缩右侧的所有内容(优先压缩最宽的),因此
表格右侧会趋于统一的轮廓,并且表格紧贴分区边缘;
- 向左拖动 ⇒ 池扩展右侧(优先扩展最窄的),即对称反向操作;
- **Shift + 拖动** ⇒ 自由增长(仅被拖动的列改变;如果溢出则出现水平滚动条);
- **双击** 手柄 ⇒ 自动将列调整为适合其内容的大小。
- **可调整大小的过滤器面板** —— 拖动侧边栏和表格之间的垂直手柄。宽度会被持久化;在窄视口(< 900px)上,该面板会自动折叠为一个 `☰ Filters` 按钮。
- **对比两个策略** —— 点击 `+ Compare`,放入第二个 XML/JSON。表格将显示带有 `+` / `−` / `~` / `=` 标记的 `Δ` 列,行会着色,并且修改过的规则会展开以显示每个更改字段的旧 → 新差异。侧边栏中的 `Change types` 面板(增加 / 删除 / 修改 / 未更改)支持多选。按 `Esc` 或点击 `Exit diff` 返回单一模式。
- **Esc** 会先关闭移动端过滤器抽屉,然后再退出差异对比模式。
- 过滤器、排序和详情状态在重新渲染期间保持不变(在切换分面时会保留滚动位置和搜索光标)。
## CLI 命令
### `parse`
输出标准化的 JSON 模型。
```
applocker.py parse [--pretty]
```
### `filter`
过滤规则并输出 table / JSON / CSV。
```
applocker.py filter
[--action allow|deny]
[--collection exe|msi|script|dll|appx]
[--type path|publisher|hash]
[--sid ]
[--search ]
[--has-exceptions | --no-exceptions]
[--risky]
[--flag ]
[--format table|json|csv]
```
### `analyze`
打印按风险分组的报告。
```
applocker.py analyze
```
### `diff`
对比两个策略。用于配对规则的身份键是规则的 **语义锚点** —— `(collection, rule_type, UserOrGroupSid, primary condition value)` —— 因此以下情况将被报告为 `modified`(并在 `changes` 下列出具体的更改字段),而不是作为一个 `removed` + `added` 对:
- 重命名或修改描述的规则;
- 在同一目标上 **`Action` 翻转**(在 `Allow` 和 `Deny` 之间切换)的同一规则;
- 条件微调(发布者版本范围缩小,添加了异常)。
CLI `diff` 也可作为 `viewer.html` 中的交互模式使用(点击 `+ Compare`)。
```
applocker.py diff [--format text|json]
```
## 风险标记(原子化)
每个标记都是一个 **单一的可观察属性**,绝不进行组合。当你需要表达诸如“宽泛路径 AND 允许 AND 非所有人”这样的假设时,请将它们与过滤器结合使用——即 `--collection exe --action allow --flag broad_wildcard_path` 并加上按 SID 的过滤,而不是使用一个单独的预制标记。
| 标记 | 含义 |
|------|---------|
| `audit_only` | 规则位于 `EnforcementMode=AuditOnly` 的集合中 |
| `user_writable_path` | 路径覆盖了已知的用户可写目录(`%TEMP%`、`%LOCALAPPDATA%`、`\Windows\Tasks` 等) |
| `broad_wildcard_path` | 路径以 `*` 开头或包含 `\*\`(跨越子树的通配符,未锚定到固定根目录) |
| `wildcard_path` | 路径包含任何 `*`(比 `broad_wildcard_path` 弱;也覆盖 `C:\App\*` 及类似的尾部通配符) |
| `wildcard_publisher` | `FilePublisher` 规则的 Publisher 字段为 `*` 或为空 |
| `lolbin_path` | 基础名与精心整理的 LOLBin 列表匹配(mshta、regsvr32、msbuild 等) |
| `has_exceptions` | 规则至少定义了一个 `Exceptions` 条目 |
| `non_everyone_sid` | `UserOrGroupSid` 不是 `S-1-1-0` (Everyone) |
外加一个在 `metadata.policy_flags` 下显示的 **策略级** 标记:
| 标记 | 含义 |
|------|---------|
| `missing_dll_collection` | 策略不包含任何 `Dll` 规则 → DLL 劫持不受约束 |
原子化原理:一条规则可能具有宽泛的路径,但只授予特定的高权限 SID。这是否可被利用取决于你当前拥有的用户上下文。不要将该决定预先硬编码到标记中——而是通过过滤器来实现。
### 精选列表
在 `applocker.py` 的顶部进行编辑:
- `USER_WRITABLE_SUBSTRINGS` —— 如果你有站点特有的可写路径,请进行扩展
- `LOLBIN_BASENAMES` —— 源自 GTFOBins 风格的 LOLBAS 目录,可根据你的任务需要删减或扩展
- `WELL_KNOWN_SIDS` —— 内置的 SID -> 名称映射表,用于更美观的输出
## 标准化 JSON 模型
```
{
"metadata": {
"schema_version": 1,
"source_file": "policy.xml",
"parsed_at": "2026-05-04T09:55:20+00:00",
"policy_flags": ["missing_dll_collection"]
},
"collections": [
{"type": "Exe", "enforcement_mode": "Enabled", "rule_count": 9}
],
"rules": [
{
"id": "e0771f6b5e2eb8f5",
"collection": "Exe",
"rule_type": "FilePath",
"action": "Allow",
"name": "(Default Rule) All files",
"description": "",
"user_or_group_sid": "S-1-1-0",
"user_or_group_name": "Everyone",
"conditions": [{"type": "path", "path": "*"}],
"exceptions": [],
"summary": "*",
"risk_flags": ["broad_wildcard_path"]
}
]
}
```
`risk_flags` 由 `analyze` / `filter` 添加。`parse` 返回的模型
不包含此项(因此解析层仅保留纯粹的内容)。
## 安全说明
- 解析器会预先拒绝包含 `DOCTYPE` 或 `ENTITY` 声明的 XML,以防通过恶意策略发起的 XXE 攻击。
- HTML 查看器在将文档交给浏览器的 `DOMParser` 处理之前,会执行相同的 XXE 检查。
- 两者完全在离线下运行;不会上传任何内容。
## 测试
```
python -m pytest -q
```
89 个测试覆盖了解析器、过滤器、输出器、分析器原子性以及差异对比的身份行为(包括 action 翻转作为修改的契约)。CI 在 Linux + Windows 平台上针对 Python 3.10–3.13 运行。
## 贡献
欢迎提交 PR。代码有意保持紧凑且仅依赖标准库——请使新功能保持相同的精神:
- `applocker.py` 或 `viewer.html` 没有外部运行时依赖。测试可以使用 pytest。
- 风险标记必须保持 **原子化** —— 每个标记一个可观察属性,不得组合。组合应属于查看器 / CLI 中的过滤组。
- 在引入新的解析或分析行为时,请在 `tests/fixtures/` 中添加或扩展测试夹具。
- 在推送前运行 `python -m pytest -q`。
## 已知限制
- 精选列表(LOLBin、用户可写路径)故意保持较小和保守——请根据你的环境进行扩展。
- DLL 集合规则会被解析,但分析器将缺失/0 条规则视为 `missing_dll_collection`。每条规则的 DLL 分析遵循与 Exe 规则相同的结构。
- `Appx` 打包应用的条件通过相同的发布者结构进行标准化;AppLocker 可能发出的打包专属属性不会被保留。
标签:AI合规, AppLocker, AppLockerPolicy, Conpot, EDR绕过, IPv6, OpenCanary, PowerShell, stdlib-only, TDD开发, Windows安全, XML解析, 后端开发, 多模态安全, 安全基线分析, 差异分析, 应用控制策略, 数据可视化, 数据展示, 离线HTML查看器, 策略审查, 红队, 网络安全, 逆向工具, 隐私保护, 风险分析, 高交互蜜罐