0xDanielSec/duel-framework

GitHub: 0xDanielSec/duel-framework

一个基于 LLM 博弈的对抗性安全研究框架,通过离线模拟攻击与检测提升 KQL 规则质量。

Stars: 0 | Forks: 0

# DUEL — 双重无监督规避循环 ![Python 3.11+](https://img.shields.io/badge/Python-3.11%2B-blue?logo=python&logoColor=white) ![Ollama](https://img.shields.io/badge/Ollama-local%20inference-black?logo=ollama) ![MITRE ATT&CK](https://img.shields.io/badge/MITRE-ATT%26CK-red) ![License MIT](https://img.shields.io/badge/License-MIT-green) ## 什么是 DUEL? DUEL 是一个自包含的对抗性安全研究框架。两个本地运行的 LLM 代理将在可配置轮数内相互对抗。**攻击者**(`llama3.1:8b`)获得 MITRE ATT&CK 技术定义,并负责生成看起来像真实 Azure AD / Microsoft 365 攻击活动的合成遥测数据——凭证滥用、密码喷洒、OAuth 令牌窃取——同时主动推理上一轮防御者检测到了什么,并变异其方法以规避。**防御者**(`mistral:7b`)读取相同的遥测数据,研究之前哪些规则漏过了,并重写规则以填补漏洞。 在每一轮代理回合之间,DUEL 内置的检测引擎会在模拟真实 Microsoft Sentinel 模式(`SigninLogs`、`SecurityEvent`、`AuditLogs`)的 pandas DataFrame 上执行防御者的 KQL 规则。每一行都会被标记为唯一 ID,以便引擎精确报告哪些日志被捕获、哪些被规避。 评分器跟踪游戏状态——每条被规避日志给攻击者加分,每条检测成功给防御者加分,并将结果反馈到下一轮的提示中,使双方代理都能真正记住战斗历史。 所有轮次完成后,DUEL 生成三个输出工件:每轮的结构化 JSON 战斗日志、列出捕获至少一条攻击日志的每条 KQL 规则的最终报告,以及一份战后分析(`battle_analysis.md`),详细分解攻击者如何变异、每条防御者规则在字段层面为何失败、哪些检测信号被永久忽略,以及实际部署的 Sentinel 应添加哪些具体 KQL 规则。整个过程离线运行——不调用任何 Anthropic API、OpenAI 或其他付费服务。 ## 架构 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ DUEL ADVERSARIAL LOOP │ │ │ │ ┌──────────────────────────────────┐ │ │ │ TECHNIQUE LIBRARY │ │ │ │ techniques/T1078.004.json │ IOCs · Evasion variants │ │ │ techniques/T1110.003.json │ Sentinel tables · KQL hints │ │ └─────────────────┬────────────────┘ │ │ │ │ │ ┌──────────▼──────────┐ │ │ │ ATTACKER AGENT │ llama3.1:8b via Ollama │ │ │ agents/attacker.py │ │ │ │ │ Round 1: generate initial TTPs │ │ │ ┌───────────────┐ │ Round N: mutate based on what │ │ │ │ Mutation logic│ │ was detected last round │ │ │ └───────────────┘ │ │ │ └──────────┬──────────┘ │ │ │ Synthetic log entries (JSON) │ │ │ [{table, _duel_id, IPAddress, UserAgent, …}] │ │ ┌──────────▼──────────┐ │ │ │ DEFENDER AGENT │ mistral:7b via Ollama │ │ │ agents/defender.py │ │ │ │ │ Round 1: write initial KQL rule │ │ │ ┌───────────────┐ │ Round N: harden based on what │ │ │ │Hardening logic│ │ evaded last round │ │ │ └───────────────┘ │ │ │ └──────────┬──────────┘ │ │ │ KQL detection rule (string) │ │ ┌──────────▼──────────┐ │ │ │ DETECTION ENGINE │ engine/detection.py │ │ │ │ │ │ │ SigninLogs ◄──┤ KQL → pandas pipeline executor │ │ │ SecurityEvent ◄──┤ Mirrors real Sentinel schemas │ │ │ AuditLogs ◄──┤ Returns: set of detected _duel_id │ │ └──────────┬──────────┘ │ │ │ detected_ids: set[str] │ │ ┌──────────▼──────────┐ │ │ │ SCORER │ engine/scoring.py │ │ │ │ │ │ │ Attacker +1/evaded │ Writes round_NN_battle_log.json │ │ │ Defender +1/caught │ Feeds results → next round prompt │ │ └──────────┬──────────┘ │ │ │ (repeat for N rounds) │ │ ┌──────────▼──────────────────────────────┐ │ │ │ OUTPUT ARTIFACTS │ │ │ │ │ │ │ │ output/round_NN_battle_log.json │ │ │ │ output/full_battle_log.json │ │ │ │ output/final_report.md │ │ │ │ output/battle_analysis.md ◄── new │ │ │ └──────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ``` ## 快速开始 ### 1. 安装 Ollama 从 [ollama.ai](https://ollama.ai) 下载并安装,然后启动守护进程: ``` ollama serve ``` ### 2. 拉取所需模型 ``` ollama pull llama3.1:8b # Attacker ollama pull mistral:7b # Defender ``` ### 3. 克隆并安装依赖 ``` git clone https://github.com/yourhandle/duel-framework cd duel-framework pip install -r requirements.txt ``` ### 4. 运行你的第一场对决 ``` # Default: T1078.004, 5 rounds, 10 logs per round python main.py # Password spraying, 8 rounds, verbose output python main.py --technique T1110.003 --rounds 8 --verbose # Crank up attack volume python main.py --technique T1078.004 --rounds 10 --logs 20 ``` 输出将位于 `output/`。战后分析始终位于 `output/battle_analysis.md`。 ### CLI 参考 | 标志 | 默认值 | 描述 | |------|---------|------| | `--technique` | `T1078.004` | 模拟的 MITRE 技术 ID | | `--rounds` | `5` | 对抗轮数 | | `--attacker-model` | `llama3.1:8b` | 攻击者使用的 Ollama 模型 | | `--defender-model` | `mistral:7b` | 防御者使用的 Ollama 模型 | | `--logs` | `10` | 每轮生成的攻击日志数 | | `--verbose` | off | 每轮打印遥测和 KQL | ## 工作原理 ### 攻击者代理(`agents/attacker.py`) 攻击者接收完整的 MITRE 技术定义(IOC、规避变体、目标 Sentinel 表),并生成一批合成日志条目作为 JSON 数组。每条条目都是一个完整的日志记录,包含所有模式字段——真实的 UPN、地理定位、用户代理、结果代码等。 从第二轮开始,攻击者会看到上一轮的 KQL 规则及其捕获的日志,并被明确提示分析哪些字段值触发了检测,并在保留底层攻击模式的同时变异这些值。这就是产生**反应式变异**行为的地方——IP 范围轮换、用户代理切换、认证方式变化——所有这些都直接响应防御者在上轮针对的内容。 ``` Round 1: python-requests/2.28.0 → 185.220.101.5 → ResultType 50126 Round 2: curl/7.68.0 → 91.108.4.200 → ResultType 50158 [reactive] Round 3: Go-http-client/1.1 → 45.142.212.100 → ResultType 0 [reactive] ``` ### 防御者代理(`agents/defender.py`) 防御者接收当前轮的攻击日志、上一轮的 KQL 规则以及漏过的日志。它被限制只能查询实际包含数据的表(从攻击日志动态注入),并且明确禁止使用 `join` 或 `union` 运算符,以免对单表遥测产生空结果。 防御者的温度设置比攻击者更低(0.4 对比 0.85),以生成一致、可解析的 KQL,而不是可能破坏执行器的创造性变体。即便如此,模型仍然会学习:到第三、四轮时,它通常会放弃基于 IP 的规则,转而开始针对结构性信号,如 `ConditionalAccessStatus` 和 `AuthenticationRequirement`。 ### 检测引擎(`engine/detection.py`) 引擎是一个自定义的 KQL 到 pandas 解释器——不是 Azure Data Explorer 或任何云服务的包装器。它将 KQL 管道翻译为一系列 pandas 操作,并在根据攻击者日志构建的 DataFrame(应用完整的 Sentinel 模式并对缺失字段使用默认值)上逐阶段执行。 **支持的运算符:** | 类别 | 运算符 | |------|--------| | 过滤 | `where` 支持 `==`、`!=`、`>`、`<`、`>=`、`<=`、`contains`、`!contains`、`has`、`has_any`、`startswith`、`endswith`、`in`、`!in`、`in~`、`matches regex`、`isempty`、`isnotempty`、`isnull`、`isnotnull` | | 逻辑 | `and`、`or`、`not`(可任意嵌套带括号) | | 聚合 | `summarize count() by`、`summarize dcount() by` | | 投影 | `project`、`project-away` | | 转换 | `extend`、`top N by`、`order by`、`sort by`、`limit`、`take`、`distinct`、`count` | 防御性地防范两种故障模式:如果防御者的 KQL 以没有数据的表开头,引擎会重定向到有数据的表;`join` 和 `union` 阶段会被移除,原因相同。 ### 计分引擎(`engine/scoring.py`) 每条日志条目都携带唯一的 `_duel_id`。KQL 执行后,引擎返回被检测到的 ID 集合。评分器计算检测/规避率,为双方代理计分,将每轮日志持久化为 JSON,并将漏过和检测到的样本排队用于下一轮的提示。所有轮次结束后,运行战后分析器。 ### 战后分析器 分析器(`engine/scoring.py` 中的 `_BattleAnalyst`)从轮次记录中通过纯数据分析推导叙事洞察——不调用任何额外模型。它将每条日志的每个字段分类为**稳定**(每轮值相同,最高置信度 IOC)或**旋转**(至少变化一次,变异向量)。它解析每条 KQL 规则的正则表达式以提取字段引用和简单条件,然后将其与漏过日志的值交叉引用,生成每轮失败诊断。它识别**检测缺口**——在所有轮次中 100% 出现在漏过日志中的字段,但从未被任何规则提及——并映射到具体的 KQL 修复代码片段,按置信度排序。 ## 示例输出 以下是在一次 5 轮 T1110.003(密码喷洒)对决中 `output/battle_analysis.md` 的真实摘录。 ### 攻击者变异表 ``` | Field | Value(s) | Rounds Present | |---------------------|------------------------------------|----------------| | AuthenticationReq. | `Password` | all 5 | | ClientAppUsed | `Microsoft Authentication Broker` | all 5 | | ConditionalAccess | `Permitted` | all 5 | | CountryOrRegion | `US` | all 5 | ``` ``` Round 1 → Round 2: - IPAddress: dropped `192.168.1.100`; added `192.168.1.103` [reactive mutation] - ResultType: dropped `50126` [reactive mutation] - AppDisplayName: dropped `Teams`; added `Microsoft Bookings` Round 2 → Round 3: - IPAddress: dropped `192.168.1.103`; added `192.168.1.112` [reactive mutation] - AppDisplayName: dropped `Excel for the web`; added `SharePoint` ``` ### 检测缺口分析 ``` | Field | Stable Value(s) | % of Evaded Logs | Rounds Never Targeted | |---------------------|-----------------|------------------|-----------------------| | CountryOrRegion | `US` | 100% | all 5 | | City | `Redmond` | 100% | all 5 | ``` ### 生成的高置信度修复规则 ``` SigninLogs | where ConditionalAccessStatus == "notApplied" | where ResultType == 0 | project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName, CountryOrRegion ``` ## 支持的技术 | ID | 名称 | 主表 | 状态 | |----|------|------|------| | [T1078.004](https://attack.mitre.org/techniques/T1078/004/) | 有效账户:云账户 | `SigninLogs` | 包含 | | [T1110.003](https://attack.mitre.org/techniques/T1110/003/) | 暴力破解:密码喷洒 | `SigninLogs` | 包含 | ### 添加新技巧 创建 `techniques/.json` 并运行即可—— 无需代码更改。 攻击者和防御者代理在运行时读取技巧定义——IOC 为攻击者的初始遥测播种规避变体指导其变异策略,检测提示指导防御者的第一轮规则。 ## 路线图 ### 近期计划 - [ ] **T1566.002** — 钓鱼:鱼叉式钓鱼链接(`OfficeActivity`、`EmailEvents`) - [ ] **T1098.001** — 账户操纵:附加云凭证(`AuditLogs`) - [ ] **T1136.003** — 创建账户:云账户(`AuditLogs`) - [ ] **T1087.004** — 账户发现:云账户(`SigninLogs`、`AuditLogs`) ### 检测引擎 - [ ] 完整的 `join` 运算符支持用于跨表关联规则 - [ ] `let` 语句和变量绑定 - [ ] `arg_max` / `arg_min` 聚合 - [ ] 时间序列运算符(`make-series`、`series_decompose_anomalies`) ### 框架 - [ ] **Web UI** — 实时轮次可视化、并列 KQL 差异查看器、 实时得分计数器 - [ ] **MITRE ATT&CK 覆盖热图** — 跟踪哪些技术/战术单元已被对决及其平均规避率 - [ ] **多技巧战役** — 在单个对决中串联技巧(初始访问 → 持久化 → 渗出) - [ ] **模型锦标赛模式** — 将多个 Ollama 模型进行对抗,按平均检测率排名 - [ ] **Sentinel 导出** — 一键导出存活的 KQL 规则作为 ARM 模板分析规则,随时可部署 - [ ] **人工介入模式** — 每轮后暂停,由人工分析师审查并覆盖防御者规则后再继续 ## 项目结构 ``` duel-framework/ ├── main.py Adversarial loop orchestrator, CLI entry point ├── CLAUDE.md Permanent project briefing for Claude Code ├── requirements.txt │ ├── agents/ │ ├── attacker.py LLM agent: generates + mutates attack telemetry │ └── defender.py LLM agent: generates + hardens KQL rules │ ├── engine/ │ ├── detection.py KQL-to-pandas executor, Sentinel schema factories │ └── scoring.py Round scoring, battle logs, post-battle analyst │ ├── techniques/ │ ├── T1078.004.json Valid Accounts: Cloud Accounts │ └── T1110.003.json Brute Force: Password Spraying │ └── output/ Created at runtime ├── round_NN_battle_log.json ├── full_battle_log.json ├── final_report.md ├── battle_analysis.md └── duel.log ``` ## 道德使用 DUEL 生成**完全合成的遥测数据**,针对**内存中的 pandas DataFrame**。它不连接任何 Azure 租户、Microsoft 365 环境或实时 Sentinel 工作区。不涉及真实凭据、日志或系统。 该框架旨在用于安全研究、攻防演练和检测工程教育。 ## 许可证 MIT 许可证——请参见 [LICENSE](LICENSE)。 *DUEL 是一个独立研究项目。它与 Microsoft、Anthropic 或 MITRE 公司无关。MITRE ATT&CK® 是 The MITRE Corporation 的注册商标。*
标签:AI风险缓解, Azure AD, Cloudflare, KQL检测规则, LLM评估, Microsoft 365, MITRE ATT&CK, Ollama, Python, 安全博弈论, 对抗安全, 攻击模拟, 数据帧, 无后门, 无监督逃逸循环, 日志仿真, 本地推理, 机器学习博弈, 检测引擎, 红队攻防, 自包含框架, 蓝队检测, 逆向工具, 防御博弈, 驱动签名利用