PentestGPT V2源码研究之EGATS规划器

文章目录

  • [EGATS 规划器架构详解](#EGATS 规划器架构详解)
    • [一、EGATS 算法概述](#一、EGATS 算法概述)
      • [1.1 什么是 EGATS?](#1.1 什么是 EGATS?)
      • [1.2 核心组件关系图](#1.2 核心组件关系图)
    • 二、攻击树数据结构
      • [2.1 AttackNode(攻击节点)](#2.1 AttackNode(攻击节点))
      • [2.2 AttackTree(攻击树)](#2.2 AttackTree(攻击树))
      • [2.3 节点类型详解](#2.3 节点类型详解)
    • 三、TDI(任务难度指数)计算
      • [3.1 TDIScore 结构](#3.1 TDIScore 结构)
      • [3.2 TDI 计算流程](#3.2 TDI 计算流程)
      • [3.3 TDI 可视化](#3.3 TDI 可视化)
    • [四、UCB (上置信界) 节点选择策略](#四、UCB (上置信界) 节点选择策略)
      • [4.1 UCB (上置信界) 公式详解](#4.1 UCB (上置信界) 公式详解)
      • [4.2 UCB (上置信界) 实现代码](#4.2 UCB (上置信界) 实现代码)
      • [4.3 UCB (上置信界) 决策过程示例](#4.3 UCB (上置信界) 决策过程示例)
    • [五、EGATS 主循环流程](#五、EGATS 主循环流程)
      • [5.1 完整流程图](#5.1 完整流程图)
      • [5.2 主循环代码实现](#5.2 主循环代码实现)
    • 六、反向传播机制
      • [6.1 反向传播原理](#6.1 反向传播原理)
      • [6.2 反向传播示例](#6.2 反向传播示例)
    • 七、剪枝机制
      • [7.1 剪枝条件](#7.1 剪枝条件)
      • [7.2 剪枝可视化](#7.2 剪枝可视化)
    • 八、模式选择(BFS/DFS/Hybrid)
      • [8.1 模式选择器](#8.1 模式选择器)
      • [8.2 模式对比](#8.2 模式对比)
    • 九、横向移动(Pivot)机制
      • [9.1 Pivot 子树创建](#9.1 Pivot 子树创建)
      • [9.2 凭证传播](#9.2 凭证传播)
    • 十、研究源码的方法论总结
      • [10.1 阅读顺序建议](#10.1 阅读顺序建议)
      • [10.2 理解复杂代码的技巧](#10.2 理解复杂代码的技巧)
        • [技巧 1:从调用链入手](#技巧 1:从调用链入手)
        • [技巧 2:关注数据流](#技巧 2:关注数据流)
        • [技巧 3:理解设计模式](#技巧 3:理解设计模式)
        • [技巧 4:结合测试用例](#技巧 4:结合测试用例)
      • [10.3 调试技巧](#10.3 调试技巧)
    • 十一、完整公式详解
      • 概述
      • [11.1 TDI(任务难度指数)详细计算](#11.1 TDI(任务难度指数)详细计算)
        • [11.1.1 四个维度的计算公式](#11.1.1 四个维度的计算公式)
        • [11.1.2 TDI 综合计算公式](#11.1.2 TDI 综合计算公式)
        • [11.1.3 TDI 计算示例](#11.1.3 TDI 计算示例)
        • [11.1.4 TDI 权重配置](#11.1.4 TDI 权重配置)
      • [11.2 UCB(上置信界)详细计算](#11.2 UCB(上置信界)详细计算)
        • [11.2.1 UCB 公式详解](#11.2.1 UCB 公式详解)
        • [11.2.2 UCB 三项分解](#11.2.2 UCB 三项分解)
        • [11.2.3 UCB 计算示例](#11.2.3 UCB 计算示例)
      • [11.3 反向传播详细计算](#11.3 反向传播详细计算)
        • [11.3.1 指数平滑公式](#11.3.1 指数平滑公式)
        • [11.3.2 反向传播完整流程](#11.3.2 反向传播完整流程)
        • [11.3.3 反向传播示例](#11.3.3 反向传播示例)
      • [11.4 剪枝机制完整公式](#11.4 剪枝机制完整公式)
        • [11.4.1 剪枝条件](#11.4.1 剪枝条件)
        • [11.4.2 剪枝阈值配置](#11.4.2 剪枝阈值配置)
        • [11.4.3 剪枝决策表](#11.4.3 剪枝决策表)
      • [11.5 模式选择完整公式](#11.5 模式选择完整公式)
        • [11.5.1 模式选择逻辑](#11.5.1 模式选择逻辑)
        • [11.5.2 模式选择决策表](#11.5.2 模式选择决策表)
      • [11.6 凭证传播机制](#11.6 凭证传播机制)
        • [11.6.1 凭证相关性判断](#11.6.1 凭证相关性判断)
        • [11.6.2 凭证重新评估流程](#11.6.2 凭证重新评估流程)
      • [11.7 完整公式速查表](#11.7 完整公式速查表)
    • 附录:相关文件索引

EGATS 规划器架构详解

一、EGATS 算法概述

1.1 什么是 EGATS?

EGATS (Evidence-Guided Attack Tree Search) - 证据引导的攻击树搜索,是一种结合了蒙特卡洛树搜索 (MCTS) 和启发式评估的规划算法。

python 复制代码
# 核心组件概览
┌─────────────────────────────────────────────────────────────┐
│                      EGATSPlanner                           │
│  ┌──────────────┬──────────────┬──────────────┬────────────┐│
│  │   TDA        │    UCB       │ Backprop     │  Pruning   ││
│  │ (任务难度评估) │(节点选择策略)  │(反向传播)      │  (剪枝)    ││
│  └──────────────┴──────────────┴──────────────┴────────────┘│
│         ↓                   ↓                ↓              │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              Attack Tree (攻击树)                    │    │
│  │    Root → Children → Leaves                         │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘

1.2 核心组件关系图

EGATSPlanner
TDAComputer
UCB Selector
Backpropagation
Pruning
Pivot Manager
Mode Selector
TDIScore 计算
节点选择 UCB 公式
奖励反向传播
剪枝决策
横向移动子树
BFS/DFS/Hybrid 模式


二、攻击树数据结构

2.1 AttackNode(攻击节点)

位于 excalibur/planner/models.py

python 复制代码
class AttackNode(BaseModel):
    """
    攻击树中的单个节点,代表渗透测试中的一个观察、假设或动作。
    
    核心属性:
    - id: 节点唯一标识符 (8 字符短 ID)
    - node_type: 节点类型 (OBSERVATION/HYPOTHESIS/ACTION)
    - status: 生命周期状态 (PENDING/ACTIVE/COMPLETED/PRUNED/FAILED)
    - promise_score: UCB 承诺分数 φ(n),基于历史奖励
    - tdi: 任务难度指数,包含 4 个加权维度
    - visit_count: 节点被访问的次数(用于 UCB)
    - success_count/failure_count: 成功/失败计数
    """

2.2 AttackTree(攻击树)

python 复制代码
class AttackTree(BaseModel):
    """
    完整的攻击树,包含所有节点和根节点引用。
    
    核心属性:
    - root_id: 根节点的 ID
    - nodes: {node_id: AttackNode} 映射表
    - total_actions: 已执行的总动作数(用于 UCB)
    - budget_remaining: 剩余预算次数
    """

2.3 节点类型详解

类型 说明 使用场景
OBSERVATION 观察节点 信息收集、端口扫描结果
HYPOTHESIS 假设节点 基于证据的推测(如"可能存在 SQL 注入")
ACTION 动作节点 要执行的操作(如"运行 sqlmap")

三、TDI(任务难度指数)计算

3.1 TDIScore 结构

位于 excalibur/planner/models.py:87

python 复制代码
class TDIScore(BaseModel):
    """
    四个加权维度:
    - horizon: 视野深度(从根节点到该节点的深度)权重 0.3
    - success_rate: 成功率(拉普拉斯平滑后)权重 0.2
    - context_load: 上下文负载(token 预算利用率)权重 0.2
    - evidence_confidence: 证据置信度权重 0.3
    
    计算公式:
        TDI = w_h*H + w_e*(1-E) + w_c*C + w_s*(1-S)
    """

3.2 TDI 计算流程

python 复制代码
# excalibur/planner/tda.py:46
def compute_tdi(self, node, tree, context_load=0.0) -> TDIScore:
    """
    1. 计算 horizon:depth / max_depth(归一化深度)
    2. 计算 success_rate:(success + 1) / (total_visits + 2)
    3. 获取 context_load:当前 token 预算利用率
    4. 计算 evidence_confidence:沿路径的平均证据级别
    5. 组合成 TDIScore
    """

3.3 TDI 可视化

python 复制代码
# 示例:TDI 值分解
TDIScore(
    horizon=0.6,           # 深度适中
    success_rate=0.75,     # 成功率较高
    context_load=0.4,      # 上下文负载中等
    evidence_confidence=0.8, # 证据较可靠
    value=0.43             # 综合难度指数(越低越好)
)

四、UCB (上置信界) 节点选择策略

4.1 UCB (上置信界) 公式详解

位于 excalibur/planner/ucb.py

python 复制代码
# UCB(n) = φ(n) + c * √(ln(N) / N_n) - dp * δ(n)
#
# 其中:
#   φ(n)    = promise_score (承诺分数,基于历史奖励)
#   c       = exploration_constant (探索常数,默认 1.414 = √2)
#   N       = 树中已执行的总动作数
#   N_n     = 节点 n 被访问的次数
#   dp      = difficulty_penalty (难度惩罚权重,默认 0.5)
#   δ(n)    = TDI 值(难度指数)

4.2 UCB (上置信界) 实现代码

python 复制代码
# excalibur/planner/ucb.py:30-67
def select_node(
    tree: AttackTree,
    exploration_constant: float = 1.414,
    difficulty_penalty: float = 0.5,
) -> AttackNode | None:
    """
    选择具有最高 UCB 分数的活动叶子节点。
    
    平衡三个因素:
    1. Exploitation (利用): 高承诺分数的节点
    2. Exploration (探索): 访问次数少的节点获得奖励
    3. Difficulty Penalty (难度惩罚): 避免选择过于困难的节点
    """

4.3 UCB (上置信界) 决策过程示例

python 复制代码
# 假设当前状态:
total_actions = 100  # N

# 候选节点 A(已访问多次,承诺分数高)
node_A = AttackNode(
    promise_score=0.8,      # φ(n) 较高
    visit_count=50,         # N_n 较大
    tdi=TDIScore(value=0.3) # δ(n) 较低(难度小)
)
# UCB(A) = 0.8 + 1.414 * √(ln(100)/50) - 0.5 * 0.3
#        = 0.8 + 1.414 * 0.26 - 0.15
#        = 0.8 + 0.37 - 0.15 = 1.02

# 候选节点 B(访问较少,承诺分数中等)
node_B = AttackNode(
    promise_score=0.6,
    visit_count=10,
    tdi=TDIScore(value=0.4)
)
# UCB(B) = 0.6 + 1.414 * √(ln(100)/10) - 0.5 * 0.4
#        = 0.6 + 1.414 * 0.58 - 0.2
#        = 0.6 + 0.82 - 0.2 = 1.22

# 结果:选择节点 B(探索奖励更高)

五、EGATS 主循环流程

5.1 完整流程图

攻击路径
状态事实
模式指导
兄弟摘要
添加发现
扩展树
剪枝
上下文压缩
Pivot 生成


开始
选择节点

Select Node
计算 TDI

Compute TDI
选择模式

Select Mode
组装上下文提示

Assemble Context Prompt
攻击路径
主机/服务/凭证
模式指导
兄弟摘要
查询 LLM

Query LLM
处理响应

Process Response
更新树与状态存储

Update Tree & State Store
添加到节点
扩展新节点
反向传播

Backpropagate

更新 n 值
检查条件

Check Conditions
Pruning
Context Comp
Pivot spawn
预算 > 0?
结束

5.2 主循环代码实现

位于 excalibur/core/controller.py:411-603

python 复制代码
async def _egats_loop(self, initial_task: str) -> dict[str, Any]:
    """
    EGATS 规划循环,共 12 个步骤:
    
    1. UCB 选择节点 (select_next_node)
    2. 计算 TDI (compute_tdi)
    3. 选择模式 (select_mode) - BFS/DFS/LLM 决策
    4. 组装上下文提示词 (assemble context)
    5. 查询后端 LLM (backend.query)
    6. 处理响应并收集发现 (process message)
    7. 反向传播结果评估 (backpropagate)
    8. 用新发现扩展树的子节点 (expand_tree)
    9. 检查剪枝条件 (check_pruning)
    10. 检查上下文压缩条件 (compress if needed)
    11. 标记当前节点为已完成
    12. 循环直到预算耗尽或停止请求
    """

六、反向传播机制

6.1 反向传播原理

python 复制代码
# excalibur/planner/backpropagation.py:13
def backpropagate(tree, node, outcome, alpha=0.7):
    """
    将节点的操作结果沿路径反向传播到根节点。
    
    更新承诺分数 φ(n):
        φ(parent) = α * reward + (1-α) * φ(parent)
    
    其中:
    - α: 平滑因子(默认 0.7),控制新旧奖励的权重
    - reward: 当前结果对应的奖励值
        SUCCESS → 1.0
        PARTIAL → 0.5
        FAILURE → 0.1
    """

6.2 反向传播示例

python 复制代码
# 初始状态
node_A.promise_score = 0.5  # 中等承诺分数

# 执行后获得 SUCCESS 结果
backpropagate(tree, node_A, outcome=ActionOutcome.SUCCESS, alpha=0.7)

# 更新计算
new_promise = 0.7 * 1.0 + (1-0.7) * 0.5
           = 0.7 + 0.15
           = 0.85

# node_A.promise_score 从 0.5 提升到 0.85
# 下次 UCB 选择时,该节点会被优先考虑(利用)

七、剪枝机制

7.1 剪枝条件

位于 excalibur/planner/pruning.py

python 复制代码
# 剪枝决策逻辑
def should_prune(node, prune_threshold=0.8, min_attempts=3):
    """
    判断节点是否应该被剪枝:
    
    条件 1: TDI > prune_threshold (难度过高)
    条件 2: visit_count >= min_attempts (已充分尝试)
    
    只有同时满足两个条件时才剪枝
    """

7.2 剪枝可视化

python 复制代码
# 示例:剪枝决策过程
node = AttackNode(
    tdi=TDIScore(value=0.85),  # TDI > 0.8 (难度高)
    visit_count=5,              # >= 3 (已充分尝试)
    status=NodeStatus.ACTIVE
)

# should_prune(node) → True
# prune_branch(tree, node) → 将该节点及其子树标记为 PRUNED

八、模式选择(BFS/DFS/Hybrid)

8.1 模式选择器

位于 excalibur/planner/mode_selector.py

python 复制代码
def select_mode(tdi_value, bfs_threshold=0.6, dfs_threshold=0.3):
    """
    根据 TDI 值选择探索模式:
    
    - TDI > 0.6:   BFS (广度优先) - 快速扫描多个分支
    - TDI < 0.3:   DFS (深度优先) - 深入挖掘当前路径
    - 否则:        Hybrid (混合) - 平衡探索和利用
    """

8.2 模式对比

模式 适用场景 特点
BFS TDI 高,需要广泛扫描 快速发现新机会,但可能错过深度利用
DFS TDI 低,路径可靠 深入挖掘当前路径,充分利用已知信息
Hybrid TDI 中等 平衡策略,灵活调整

九、横向移动(Pivot)机制

9.1 Pivot 子树创建

python 复制代码
# excalibur/planner/pivot.py:23
def spawn_pivot(tree, host, parent):
    """
    当攻陷一个新主机时,创建横向移动子树。
    
    新节点描述:
    - type: ACTION (pivot action)
    - description: "Pivot to <host> from <parent.description>"
    - host: 新攻陷的主机地址
    """

9.2 凭证传播

python 复制代码
# excalibur/planner/pivot.py:56
def propagate_credentials(tree, credentials):
    """
    根据新发现的凭据重新评估被剪枝的节点。
    
    如果新凭据可能使之前困难的节点变得可行,则重新激活它们。
    """

十、研究源码的方法论总结

10.1 阅读顺序建议

bash 复制代码
# 推荐的文件阅读顺序:

# 第 1 层:入口点和核心架构
1. README.md                    # 整体概览
2. excalibur/core/controller.py  # 中央协调器(主循环)
3. excalibur/planner/egats.py    # EGATS 编排器

# 第 2 层:数据模型和核心算法
4. excalibur/planner/models.py   # 攻击树数据结构
5. excalibur/planner/ucb.py      # UCB 节点选择
6. excalibur/planner/tda.py      # TDI 计算
7. excalibur/planner/backpropagation.py  # 反向传播
8. excalibur/planner/pruning.py  # 剪枝算法

# 第 3 层:辅助组件
9. excalibur/memory/context_assembler.py   # 上下文组装
10. excalibur/memory/state_store.py         # 状态存储
11. excalibur/planner/mode_selector.py      # 模式选择
12. excalibur/planner/pivot.py              # 横向移动

10.2 理解复杂代码的技巧

技巧 1:从调用链入手
python 复制代码
# 找到入口点,追踪执行路径
excalibur/interface/main.py (CLI entry)
    ↓
excalibur/core/controller.run()
    ↓
excalibur/core/controller._egats_loop()
    ↓
excalibur/planner/egats.select_next_node()
技巧 2:关注数据流
python 复制代码
# 追踪关键数据结构的变化
AttackTree → AttackNode → TDIScore → ActionOutcome
     ↓            ↓           ↓              ↓
  创建树       选择节点    计算难度      评估结果
技巧 3:理解设计模式
  • 单例模式 : EventBus.get()
  • 观察者模式: 事件总线与 TUI 的解耦通信
  • 策略模式: UCB、剪枝、模式选择的可配置算法
  • 工厂模式 : ContextAssembler 组装上下文
技巧 4:结合测试用例
bash 复制代码
# 运行相关测试理解功能
cd tests/unit
python -m pytest test_egats_loop.py -v    # EGATS 循环测试
cat test_ucb.py                            # UCB 算法测试

10.3 调试技巧

python 复制代码
# 在代码中添加调试输出
import logging
logging.basicConfig(level=logging.DEBUG)

# 或在关键位置添加断点
async def _egats_loop(self, initial_task: str):
    # ... 
    current_node = self._planner.select_next_node(tree)
    print(f"Selected node: {current_node.id}, UCB score: {current_node.promise_score}")
    # ...

十一、完整公式详解

概述

本节将第十一章的快速参考卡片内容扩展为完整的公式详解,涵盖 EGATS 规划器的所有核心计算公式。

核心组件与公式概览
复制代码
┌─────────────────────────────────────────────────────────────┐
│                      EGATSPlanner                           │
│  ┌──────────────┬──────────────┬──────────────┬────────────┐│
│  │   TDA        │    UCB       │ Backprop     │  Pruning   ││
│  │ (任务难度评估) │(节点选择策略)  │(反向传播)      │  (剪枝)    ││
│  └──────────────┴──────────────┴──────────────┴────────────┘│
│         ↓                   ↓                ↓              │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              Attack Tree (攻击树)                    │    │
│  │    Root → Children → Leaves                         │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘
核心公式速览
类别 名称 完整公式 默认参数
TDI 综合难度指数 w_h·H + w_e·(1-E) + w_c·C + w_s·(1-S) weights: {h:0.3, e:0.3, c:0.2, s:0.2}
TDI Horizon (视野深度) depth / max_depth -
TDI Success Rate (成功率) (success + 1) / (visits + 2) (拉普拉斯平滑) -
TDI Evidence Confidence Σ(evidence_level) / path_length -
UCB 节点选择评分 φ(n) + c·√(ln(N)/Nₙ) - dp·δ(n) c=1.414, dp=0.5
Backprop 承诺分数更新 φ = α·R + (1-α)·φ_old α=0.7
Pruning 剪枝条件 TDI > threshold AND visits >= min_attempts threshold=0.8, min_attempts=3
Mode BFS 模式阈值 TDI > 0.6 -
Mode DFS 模式阈值 TDI < 0.3 -
配置参数速查
python 复制代码
# excalibur/planner/egats.py:39
_DEFAULT_CONFIG = {
    "exploration_constant": 1.414,   # UCB 探索常数 √2
    "difficulty_penalty": 0.5,       # TDI 难度惩罚权重
    "backprop_alpha": 0.7,           # 反向传播平滑因子
    "prune_threshold": 0.8,          # 剪枝阈值
    "min_prune_attempts": 3,         # 最小尝试次数
    "bfs_threshold": 0.6,            # BFS 模式切换阈值
    "dfs_threshold": 0.3,            # DFS 模式切换阈值
}

11.1 TDI(任务难度指数)详细计算

11.1.1 四个维度的计算公式
维度 符号 计算公式 取值范围 说明
Horizon (视野深度) H depth / max_depth [0, 1] 归一化深度,越深难度越大
Success Rate (成功率) S (success_count + 1) / (visit_count + 2) [0, 1] 拉普拉斯平滑避免除零
Context Load (上下文负载) C token_used / token_budget [0, 1] Token 预算利用率
Evidence Confidence (证据置信度) E Σ(evidence_level) / path_length [0, 1] 路径上所有节点证据级别的平均值
11.1.2 TDI 综合计算公式
python 复制代码
# excalibur/planner/models.py:137-142
def compute_tdi_value(self) -> float:
    """
    TDI = w_h·H + w_e·(1-E) + w_c·C + w_s·(1-S)
    
    各项含义:
    - w_h·H: 深度带来的难度(越深越难)
    - w_e·(1-E): 证据不足带来的难度(证据越少越难)
    - w_c·C: 上下文负载带来的难度(token 占用越多越难)
    - w_s·(1-S): 成功率低带来的难度(失败多则难)
    """
    return (
        self.weight_horizon * self.horizon
        + self.weight_evidence * (1.0 - self.evidence_confidence)
        + self.weight_context * self.context_load
        + self.weight_success * (1.0 - self.success_rate)
    )
11.1.3 TDI 计算示例
python 复制代码
# excalibur/planner/tda.py:62-74
node = AttackNode(
    success_count=3,
    failure_count=1,
    visit_count=4,
    evidence_level=EvidenceLevel.CONFIRMED  # 0.8
)
tree = AttackTree(...)  # 包含完整路径信息

tdi = TDAComputer().compute_tdi(node, tree, context_load=0.3)

# 计算过程:
# horizon = depth / max_depth = 3/5 = 0.6
# success_rate = (3+1)/(4+2) = 4/6 = 0.67 (拉普拉斯平滑)
# context_load = 0.3 (传入参数)
# evidence_confidence = 路径上所有节点证据级别的平均值

print(f"TDI: {tdi.value:.3f}")
# 输出示例:TDI: 0.425
11.1.4 TDI 权重配置
python 复制代码
# excalibur/planner/egats.py:47-52
"tda_weights": {
    "horizon": 0.3,             # 视野深度权重 - 中等重要性
    "evidence": 0.3,            # 证据权重 - 高重要性(证据不足会显著增加难度)
    "context": 0.2,             # 上下文负载权重 - 较低
    "success": 0.2,             # 成功率权重 - 较低
}

11.2 UCB(上置信界)详细计算

11.2.1 UCB 公式详解
python 复制代码
# excalibur/planner/ucb.py:37-40
UCB(n) = φ(n) + c · √(ln(N) / Nₙ) - dp · δ(n)
符号 含义 默认值 说明
φ(n) promise_score (承诺分数) [0,1] 基于历史奖励的节点价值估计
c exploration_constant 1.414 (=√2) 探索项权重,控制探索与利用的平衡
N total_actions - 树中已执行的总动作数
Nₙ visit_count - 节点 n 被访问的次数
dp difficulty_penalty 0.5 难度惩罚权重
δ(n) TDI 值 [0,1] 节点 n 的难度指数
11.2.2 UCB 三项分解
python 复制代码
# excalibur/planner/ucb.py:57-61
for node in candidates:
    visits = max(node.visit_count, 1)
    
    # 1. Exploitation (利用项): 基于历史表现
    exploitation = node.promise_score
    
    # 2. Exploration (探索项): 访问次数少的节点获得奖励
    exploration = c * sqrt(ln(N) / visits)
    
    # 3. Difficulty Penalty (难度惩罚): 高 TDI 的节点被 penalize
    difficulty_penalty = dp * tdi_value
    
    ucb = exploitation + exploration - difficulty_penalty
11.2.3 UCB 计算示例
python 复制代码
# excalibur/planner/ucb.py:57-64
total_actions = 100  # N

# 节点 A:已访问多次,承诺分数高
node_A = AttackNode(
    promise_score=0.8,      # φ(n) 较高
    visit_count=50,         # N_n 较大
    tdi=TDIScore(value=0.3) # δ(n) 较低(难度小)
)
# UCB(A) = 0.8 + 1.414 * √(ln(100)/50) - 0.5 * 0.3
#        = 0.8 + 1.414 * 0.26 - 0.15
#        = 0.8 + 0.37 - 0.15 = 1.02

# 节点 B:访问较少,承诺分数中等
node_B = AttackNode(
    promise_score=0.6,
    visit_count=10,
    tdi=TDIScore(value=0.4)
)
# UCB(B) = 0.6 + 1.414 * √(ln(100)/10) - 0.5 * 0.4
#        = 0.6 + 1.414 * 0.58 - 0.2
#        = 0.6 + 0.82 - 0.2 = 1.22

# 结果:选择节点 B(探索奖励更高)

11.3 反向传播详细计算

11.3.1 指数平滑公式
python 复制代码
# excalibur/planner/backpropagation.py:31
φ(parent) = α · R + (1-α) · φ_old(parent)
符号 含义 默认值
φ(parent) 更新后的承诺分数 -
α 平滑因子 0.7
R 当前结果奖励值 SUCCESS=1.0, PARTIAL=0.5, FAILURE=0.1
φ_old(parent) 之前的承诺分数 [0,1]
11.3.2 反向传播完整流程
python 复制代码
# excalibur/planner/backpropagation.py:42-51
def backpropagate(tree, node, outcome, alpha=0.7):
    path = tree.get_path_to_root(node.id)
    reward = outcome.value  # 根据结果获取奖励值
    
    for path_node in path:
        # 指数平滑更新承诺分数
        path_node.promise_score = (
            alpha * path_node.promise_score +
            (1 - alpha) * reward
        )
        
        # 更新访问统计
        path_node.visit_count += 1
        if outcome == ActionOutcome.SUCCESS:
            path_node.success_count += 1
        elif outcome == ActionOutcome.FAILURE:
            path_node.failure_count += 1
11.3.3 反向传播示例
python 复制代码
# excalibur/planner/backpropagation.py:46
node_A.promise_score = 0.5  # 初始承诺分数

# 执行后获得 SUCCESS 结果 (reward=1.0)
backpropagate(tree, node_A, outcome=ActionOutcome.SUCCESS, alpha=0.7)

# 更新计算
new_promise = 0.7 * 1.0 + (1-0.7) * 0.5
           = 0.7 + 0.15
           = 0.85

# node_A.promise_score 从 0.5 提升到 0.85

11.4 剪枝机制完整公式

11.4.1 剪枝条件
python 复制代码
# excalibur/planner/pruning.py:44-46
def should_prune(node, threshold=0.8, min_attempts=3):
    """
    剪枝决策逻辑:
    
    条件 1: TDI > threshold (难度过高)
    条件 2: visit_count >= min_attempts (已充分尝试)
    
    只有同时满足两个条件时才剪枝
    """
    if node.tdi is None:
        return False
    return node.tdi.value > threshold and node.visit_count >= min_attempts
11.4.2 剪枝阈值配置
python 复制代码
# excalibur/planner/egats.py:43-44
"prune_threshold": 0.8,         # TDI > 此值考虑剪枝
"min_prune_attempts": 3,        # 最小尝试次数后才允许剪枝
11.4.3 剪枝决策表
TDI 值 visit_count should_prune
> 0.8 >= 3 ✅ True (高难度且已充分尝试)
> 0.8 < 3 ❌ False (虽然难但还需更多尝试)
<= 0.8 >= 3 ❌ False (难度可接受,保留探索)
<= 0.8 < 3 ❌ False (难度低且未充分尝试)

11.5 模式选择完整公式

11.5.1 模式选择逻辑
python 复制代码
# excalibur/planner/mode_selector.py:42-46
def select_mode(tdi_value, bfs_threshold=0.6, dfs_threshold=0.3):
    """
    根据 TDI 值选择探索模式:
    
    - TDI > 0.6:   BFS (广度优先) - 快速扫描多个分支
    - TDI < 0.3:   DFS (深度优先) - 深入挖掘当前路径
    - 否则:        Hybrid (混合) - 平衡探索和利用
    """
    if tdi_value > bfs_threshold:
        return "reconnaissance"     # BFS 模式
    if tdi_value < dfs_threshold:
        return "exploitation"       # DFS 模式
    return "llm_decide"           # Hybrid 模式
11.5.2 模式选择决策表
TDI 值范围 返回模式 策略说明
> 0.6 reconnaissance (BFS) 高难度,需要广泛扫描发现更多机会
< 0.3 exploitation (DFS) 低难度,专注于已知可行路径的深度利用
[0.3, 0.6] llm_decide (Hybrid) 中等难度,让 LLM 根据具体情况决定

11.6 凭证传播机制

11.6.1 凭证相关性判断
python 复制代码
# excalibur/planner/pruning.py:102-117
def _cred_relevant(node, credential):
    """
    检查凭据是否可能与被剪枝的节点相关。
    
    使用关键词启发式方法:如果节点的描述提到了
    与认证相关的服务,则认为凭据可能相关。
    """
    auth_keywords = [
        "login", "auth", "ssh", "rdp", "smb",
        "ftp", "password", "credential", "winrm"
    ]
    desc_lower = node.description.lower()
    return any(kw in desc_lower for kw in auth_keywords)
11.6.2 凭证重新评估流程
python 复制代码
# excalibur/planner/pruning.py:71-98
def reevaluate_pruned(tree, new_credentials):
    """
    重新打开可能受益于新凭据的被剪枝分支。
    
    当发现新凭据时,之前被剪枝的与认证相关的分支
    可能变得可行。此函数会重置其状态和统计信息。
    """
    reopened = []
    if not new_credentials:
        return reopened
    
    for node in tree.nodes.values():
        # 检查节点是否被剪枝且凭据相关
        if (node.status == NodeStatus.PRUNED and
            any(_cred_relevant(node, cred) for cred in new_credentials)):
            # 重置状态和统计信息
            node.status = NodeStatus.PENDING
            node.visit_count = 0
            node.success_count = 0
            node.failure_count = 0
            reopened.append(node.id)
    
    return reopened

11.7 完整公式速查表

类别 名称 完整公式 默认参数
TDI 综合难度指数 w_h·H + w_e·(1-E) + w_c·C + w_s·(1-S) weights: {h:0.3, e:0.3, c:0.2, s:0.2}
TDI Horizon (视野深度) depth / max_depth -
TDI Success Rate (成功率) (success + 1) / (visits + 2) (拉普拉斯平滑) -
TDI Evidence Confidence Σ(evidence_level) / path_length -
UCB 节点选择评分 φ(n) + c·√(ln(N)/Nₙ) - dp·δ(n) c=1.414, dp=0.5
Backprop 承诺分数更新 φ = α·R + (1-α)·φ_old α=0.7
Pruning 剪枝条件 TDI > threshold AND visits >= min_attempts threshold=0.8, min_attempts=3
Mode BFS 模式阈值 TDI > 0.6 -
Mode DFS 模式阈值 TDI < 0.3 -

附录:相关文件索引

文件 路径 功能
EGATSPlanner excalibur/planner/egats.py:56 主编排器
AttackNode excalibur/planner/models.py:153:153 节点数据模型
AttackTree excalibur/planner/models.py:199:199 树数据模型
UCB Selector excalibur/planner/ucb.py:30 节点选择算法
TDA Computer excalibur/planner/tda.py:46 TDI 计算
Backpropagation excalibur/planner/backpropagation.py:13 反向传播
Pruning excalibur/planner/pruning.py 剪枝算法
Mode Selector excalibur/planner/mode_selector.py 模式选择
Pivot Manager excalibur/planner/pivot.py:23 横向移动
Controller excalibur/core/controller.py:59 主控制器
相关推荐
初九之潜龙勿用4 小时前
C# 解决“因为算法不同,客户端和服务器无法通信”的问题
服务器·开发语言·网络协议·网络安全·c#
0DayHP6 小时前
HTB:DarkZero[WriteUP]
网络安全·内网渗透
一名优秀的码农8 小时前
vulhub系列-52-ICA: 1(超详细)
安全·web安全·网络安全·网络攻击模型·安全威胁分析
大方子9 小时前
【好靶场】某博客存在SQL注入
网络安全·好靶场
heze0910 小时前
sqli-labs-Less-61
数据库·mysql·网络安全
Chockmans11 小时前
春秋云境CVE-2020-25483
web安全·网络安全·春秋云境·cve-2020-25483
菩提小狗12 小时前
每日安全情报报告 · 2026-04-01
网络安全·漏洞·cve·安全情报·每日安全
三七吃山漆12 小时前
BUUCTF[极客大挑战 2019]Http
web安全·网络安全·ctf·极客大挑战
RrEeSsEeTt12 小时前
【HackTheBox】- BoardLight 靶机学习
linux·学习·网络安全·渗透测试·kali·红队·hackthebox