从 0 到可运行:PenGym 单智能体基线 izumi 的部署、调试与复现

一、这篇文章要解决什么问题

这次目标不是直接做多智能体,也不是一上来就接 PPO/LSTM,而是先把一个可运行的自动渗透实验基座搭起来。具体拆成三件事:

  1. PenGym 环境在 Ubuntu 虚拟机里跑起来。
  2. 跑通官方自带的单智能体基线:deterministicrandom
  3. 接入自己的规则型单智能体 izumi,验证它能在 NASim 仿真环境中完成一条有效攻击路径。

最终结果是:

  • PenGym 已成功部署。
  • NASim simulation 模式可正常运行。
  • randomdeterministic 基线均可执行。
  • 自定义 agent izumi 已成功接入,并能完成扫描、利用与横向推进。

二、实验环境

1. 宿主与虚拟机

  • 宿主机:Windows
  • 虚拟机:Ubuntu
  • 虚拟化软件:VMware

2. 本次实际使用的软件栈

  • PenGym
  • NASim simulation
  • Python 虚拟环境 venv
  • 自定义单智能体基线:izumi

3. 本阶段刻意不做的内容

为了先把实验基座搭稳,这一阶段暂不做

  • LangGraph 接入
  • PPO / LSTM
  • 多智能体协同
  • 真实 cyber range
  • Metasploit / CyRIS 全链路靶场

也就是说,这一阶段的定位是:

先把仿真环境中的单智能体自动渗透基线搭起来。


三、PenGym 是什么

PenGym 可以理解为一个把渗透测试任务包装成强化学习环境的实验框架。

它提供的不是一个真实攻击工具,而是一个可交互、可重复、可训练的网络攻防仿真环境。在这个环境里,智能体可以执行诸如:

  • OS 扫描
  • 服务扫描
  • 子网扫描
  • 漏洞利用
  • 提权

这样的动作。

从实验角度看,它的价值在于:

  • 可重复复现实验
  • 可做规则基线
  • 可接强化学习算法
  • 可后续扩展到多智能体

四、整体操作顺序

这次实际做的顺序如下:

  1. 准备 Ubuntu 虚拟机网络。
  2. 解压 PenGym 源码。
  3. 创建 Python 虚拟环境。
  4. 安装 PenGym 最小依赖。
  5. 修改 CONFIG.yml 中的本地路径。
  6. -n -d 进入 NASim simulation 模式。
  7. 跑通官方 deterministic 单智能体。
  8. 修复 random agent 的兼容性问题。
  9. 新增自定义 agent:izumi
  10. izumi 从静态动作列表整理为规则路径生成器。
  11. 验证 izumi 能成功完成一条有效攻击路径。

五、具体部署过程

1. 解压源码并进入项目目录

假设压缩包在桌面:

1
2
3
4
mkdir -p ~/lab/pengym_lab
unzip ~/Desktop/Pengym.zip -d ~/lab/pengym_lab
cd ~/lab/pengym_lab
ls

如果解压后目录是 PenGym-main,继续:

1
2
cd ~/lab/pengym_lab/PenGym-main
ls

正常情况下应能看到:

  • run.py
  • pengym/
  • 其他项目文件

2. 创建 Python 虚拟环境

1
2
3
4
cd ~/lab/pengym_lab/PenGym-main
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel

激活后,终端提示符前一般会出现:

1
(.venv)

3. 安装最小依赖

1
2
sudo apt update
sudo apt install -y python3-venv python3-pip python3-tk nmap

然后安装 Python 依赖:

1
pip install nasim python-nmap pymetasploit3 pyyaml psutil

可用下面命令快速验证:

1
python -c "import nasim; print('nasim ok')"

4. 修改 CONFIG.yml

这是整个部署阶段最关键的一步之一。因为源码里的默认路径往往不是当前机器的真实路径。

打开配置文件:

1
nano ./pengym/CONFIG.yml

重点检查并修改以下字段:

1
2
3
4
pengym_source: home/test1/lab/pengym_lab/PenGym-main
cyber_range_dir: /home/test1/lab/pengym_lab/PenGym-main/cyber_range
host_account: test1
scenario_name: medium-multi-site

为什么这里要改

因为如果保留原作者机器里的路径,比如:

1
/home/cyuser/public/PenGym/...

运行时就会报类似错误:

1
FileNotFoundError: No such file or directory

5. 进入 NASim simulation 模式

这一阶段不连接真实靶场,只跑仿真模式,所以使用:

1
python3 run.py -n -d ./pengym/CONFIG.yml

这两个参数的含义是:

  • -n:启用 NASim simulation
  • -d:禁用 PenGym cyber range 执行

如果参数顺序写错,可能会导致程序没有按预期进入仿真模式。因此建议固定写法:

1
python3 run.py -n -d ./pengym/CONFIG.yml

六、先跑通官方基线

1. 官方 deterministic

1
python3 run.py -n -d -a deterministic ./pengym/CONFIG.yml

这个 agent 使用固定动作序列,作用是确认:

  • 环境本身可运行
  • 场景加载正常
  • action 执行链条没有问题

2. 官方 random

1
python3 run.py -n -d -a random ./pengym/CONFIG.yml

最开始这里遇到了一个兼容性问题:

1
AssertionError: When using flat action space, action must be an integer or an Action object

原因

env.action_space.sample() 返回的是 numpy.int64,但 get_action() 这里要求原生 int

修复方法

找到 run_random_agent(env),把动作采样部分改成:

1
2
3
4
5
6
7
8
action = env.action_space.sample()

if not isinstance(action, int):
action = int(action)

step_count = step_count + 1
print(f"- Step {step_count}: {env.action_space.get_action(action)}")
observation, reward, done, truncated, info = env.step(action)

修复后,random agent 可以正常运行。


七、接入自定义单智能体 izumi

这一阶段不直接做强化学习,而是先做一个规则型单智能体基线

1. 新增 agent 类型

run.py 中新增:

1
AGENT_TYPE_IZUMI = "izumi"

并修改帮助信息:

1
print("-a, --agent_type <AGENT_TYPE>  Agent type (random/deterministic/izumi)")

2. 新增 izumi 分支

main() 中加入:

1
2
3
4
5
elif agent_type == AGENT_TYPE_IZUMI:
print("* Perform pentesting using IZUMI agent...")

izumi_path = build_izumi_path()
done, truncated, step_count = run_deterministic_agent(env, izumi_path)

这里暂时继续复用已经稳定的 run_deterministic_agent(),但把动作序列改为我们自己的规则路径生成函数。


3. 新增规则路径构造函数

run.py 中加入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def build_izumi_path():
target_order = [HOST5_1, HOST2_0, HOST3_1, HOST6_1]

exploit_rule = {
HOST5_1: EXPLOIT_HTTP,
HOST2_0: EXPLOIT_SMTP,
HOST3_1: EXPLOIT_HTTP,
HOST6_1: EXPLOIT_SAMBA,
}

subnet_scan_hosts = {HOST5_1, HOST2_0}

path = []

for host in target_order:
path.append((host, OS_SCAN))
path.append((host, SERVICE_SCAN))

if host in exploit_rule:
path.append((host, exploit_rule[host]))

if host in subnet_scan_hosts:
path.append((host, SUBNET_SCAN))

return path

这一段代码在做什么

它定义了一条规则路径:

  1. 先打 HOST5_1
  2. 再打 HOST2_0
  3. 再打 HOST3_1
  4. 再打 HOST6_1

对每台主机,先:

  • OS_SCAN
  • SERVICE_SCAN

再根据规则选择 exploit:

  • HOST5_1EXPLOIT_HTTP
  • HOST2_0EXPLOIT_SMTP
  • HOST3_1EXPLOIT_HTTP
  • HOST6_1EXPLOIT_SAMBA

其中前两跳还会做 SUBNET_SCAN,用于继续发现网络。


八、运行 izumi

命令如下:

1
python3 run.py -n -d -a izumi ./pengym/CONFIG.yml

当前实际结果

这一版 izumi 已经能够完成一条有效攻击路径,关键成功点包括:

  1. HOST5_1 -> e_http 成功,拿到 USER
  2. HOST2_0 -> e_smtp 成功,拿到 ROOT
  3. HOST3_1 -> e_http 成功,拿到 USER
  4. HOST6_1 -> e_samba 成功,拿到 ROOT

对应输出中的关键日志可以概括为:

1
2
3
4
Host (5, 1) Action 'e_http' SUCCESS: access=USER
Host (2, 0) Action 'e_smtp' SUCCESS: access=ROOT
Host (3, 1) Action 'e_http' SUCCESS: access=USER
Host (6, 1) Action 'e_samba' SUCCESS: access=ROOT

最后出现:

1
* INCOMPLETE execution: 14 steps

不是报错,只是说明:

  • 当前 izumi 路径一共只定义了 14 步
  • 动作执行完后程序结束
  • 并不代表环境失败

九、当前完成情况

到目前为止,已经完成了以下工作:

1. 环境侧

  • Ubuntu 虚拟机环境可用
  • PenGym 已部署完成
  • NASim simulation 模式可运行
  • 配置文件路径已修正

2. 基线侧

  • 官方 deterministic 可运行
  • 官方 random 可运行
  • 自定义规则型单智能体 izumi 可运行

3. 功能侧

izumi 已具备以下基础自动渗透能力:

  • 主机 OS 扫描
  • 服务扫描
  • 子网扫描
  • 根据规则选择漏洞利用
  • 获取 USER / ROOT 权限
  • 执行一条有效横向推进路径

十、现场复现怎么做

如果后续需要现场演示,不建议从零安装,而是直接在已经配置好的快照上复现。

复现命令清单

1
2
3
4
5
6
7
8
9
cd ~/lab/pengym_lab/PenGym-main
source .venv/bin/activate

grep -n "AGENT_TYPE_RANDOM\|AGENT_TYPE_DETERMINISTIC\|AGENT_TYPE_IZUMI" run.py
grep -n "def build_izumi_path" run.py

python3 run.py -n -d -a deterministic ./pengym/CONFIG.yml
python3 run.py -n -d -a random ./pengym/CONFIG.yml
python3 run.py -n -d -a izumi ./pengym/CONFIG.yml

最推荐的精简版演示

如果时间不多,只演示 izumi 就够了:

1
2
3
4
cd ~/lab/pengym_lab/PenGym-main
source .venv/bin/activate
grep -n "AGENT_TYPE_IZUMI\|def build_izumi_path" run.py
python3 run.py -n -d -a izumi ./pengym/CONFIG.yml

十一、这一阶段到底完成到了哪一步

如果要准确描述当前阶段,可以写成:

已完成 PenGym 仿真环境部署,跑通官方基线,并接入自定义规则型单智能体 izumi。当前 izumi 可在 NASim 仿真场景中完成扫描、服务识别、漏洞利用与横向推进,已成功获取多台主机的访问权限,其中两台拿到了 ROOT 权限。

这个表述是准确的。


十二、下一步怎么做

这一阶段结束后,最合理的下一步不是立刻上多智能体,而是继续把单智能体做扎实。

下一步建议

  1. izumi 从固定规则路径升级为真正的 run_izumi_agent(env)
  2. 让它根据扫描结果动态选 exploit,而不是预先写死整条路径
  3. 记录 random / deterministic / izumi 三类基线对比结果
  4. 再进一步接入 PPO / LSTM
  5. 最后才考虑 LangGraph 与多智能体扩展

十三、未来展望

如果继续往下推进,这条路线可以自然扩展成:

1. 规则型单智能体

当前已经完成。

2. 强化学习单智能体

izumi 替换成 PPO / LSTM policy,使其在 PenGym 中通过 reward 学习攻击路径,而不是依赖人工规则。

3. 多智能体协同

在单智能体稳定后,引入多个 worker agent,分别负责扫描、利用、横向移动等任务。

4. LangGraph 编排

用 LangGraph 作为上层编排框架,管理任务分解、角色分配、记忆与协同流程。

5. 更完整的自动渗透研究原型

最终形成“仿真环境 + 单智能体 / 多智能体 + 规则 / 强化学习 + 编排层”的完整研究原型。


十四、总结

这篇记录完成的不是一个最终版本的自动渗透系统,而是一个真正可运行的研究起点

当前最重要的成果不是“用了多少热门概念”,而是:

  • PenGym 环境已经跑通
  • 单智能体基线已经建立
  • 自定义 agent izumi 已经能够执行有效攻击路径
  • 后续接 PPO/LSTM、多智能体、LangGraph 都有了明确落点

这一步做完,后面的工作就不再是空谈,而是建立在一个已经可复现、可扩展、可展示的实验基座之上。