初探工控安全,主要分为协议安全、网络安全和固件安全等。
Terminologies
- SCADA(Supervisory Control And Data Acquisition):数据采集与监视控制系统
- ICS(Industrial Control System):工业控制系统
- DCS(Distributed Control System):分布式(集散)控制系统
- PCS(Process Control System):过程控制系统
- ESD(Emergency Shutdown Device):紧急停车系统
- PLC(Programmable Logic Controller):可编程序控制器
- 工业场景需要控制许多的机械设备,而大部分机械设备需要用电路信号直接控制,比如许许多多的开关,对应到电上就是电路的通断。所以需要一些可以满足这种应用场景的专用计算机,并且还需要低时延,稳定性高,防震防潮等,即 PLC
- 使用一种叫”梯形图”的语言编写控制输入输出逻辑的程序(实现通过梯形图控制硬件 IO)
- RTU(Remote Terminal Unit):远程终端控制系统
- IED(Intelligent Electronic Device):智能检测单元
- HMI(Human Machine Interface):人机界面
- MIS(Management Information System):管理信息系统
- SIS(Supervisory Information System):生产过程自动化监控和管理系统
- MES(Manufacturing Execution System):制造执行管理系统
ICS Structure
工业控制系统结构:
- 传感器和执行器;
- 可编程控制器(PLC);
- 工业网络及现场总线;
- 工业计算机及工业组态软件。
- 过程自动化控制系统
- 应用在流程行业,比如:石油、化工、医药、冶金、水处理等
- 对应的控制系统:DCS 居多,大型 PLC 为主,单台控制器 IO 点数多数在 2000 点以上,全冗余架构
- 工厂自动化控制系统
- 应用在离散行业,比如:汽车、港口、烟草等
- 对应的控制系统:主要以 PLC 为主,采用和设备捆绑为主,单台控制 IO 点数少于 2000 点,单机为主
常见工业控制系统架构
- Enterprise Zone:包括数据库、服务器等一些基础设备;
- ICS DMZ:和一般网络架构中的 DMZ 类似,通常用于给外网提供服务,同时保护内网;
- Process Control Zone:相当于内网的部分,通常外部对其的访问权限为只读;
工业控制系统整体分层:
- Upper Layer(Engineering Workstation):包括 HMI、SCADA 等设备。
- Middle Layer:包括 PLC 等设备;
- Lower Layer:包括传感器等设备。
工控产品厂商和产品介绍
- Siemens
- 控制系统家族
- S7-1500 控制系统
- S7-1200 控制系统
- S7-300/400 控制系统
- S7-WINAC 控制系统
- 组态软件家族
- TIA 博图/Step7
- WINCC 组态监控软件
- PLCSIM 模拟仿真软件
- 通讯协议及端口
- S7 Comm 协议(私有协议)
- 通讯端口 102
- 控制系统家族
- Rockwell Automation
- 控制系统家族
- Controllogix 控制系统
- Compactlogix 控制系统
- MicroLogix 控制系统
- Softlogix 控制系统
- 组态软件家族
- Studio5000/RSLogix 5000 组态软件
- FactoryTalk View SE 组态监控软件
- Emulation 模拟仿真软件
- 通讯协议及端口
- Ethernet/IP(公开协议)
- 通讯端口 44818/2222
- 控制系统家族
Protocols
安全问题:
- 缺乏身份认证:仅需要使用一个合法的 Modbus 地址和合法的功能码即可以建立一个 Modbus 会话;
- 缺乏授权机制:没有基于角色的访问控制机制,任意用户可以执行任意的功能;
- 缺乏加密保护:地址和命令明文传输,可以很容易地捕获和解析。
Modbus
Modbus 是一种应用层的报文传输协议,它既可以在物理层面上选择串口进行简单的串行通信,也可以使用 TCP 的方式进行传输。Modbus 协议定义了一个与基础通信层无关的简单协议数据单元(PDU)。特定总线或网络上的 Modbus 协议映射能够在应用数据单元(ADU)上引入一些附加域。
因为 Modbus 是应用层的协议,所以其安全漏洞并不只是它本身,TCP/IP 的漏洞也可以利用在 Modbus 上。
Modbus 对应的协议栈:
Layer | ISO/OSI Model | Protocol |
---|---|---|
7 | Application | MODBUS Application Protocol |
6 | Presentation | Empty |
5 | Session | Empty |
4 | Transport | Empty |
3 | Network | Empty |
2 | Data Link | MODBUS Serial Line Protocol |
1 | Physical | EIA/TIA-485 (or EIA/TIA-232) |
Function code | Function name |
---|---|
1 | Read coils |
3 | Read holding registers |
5 | Write single coil |
6 | Write single register |
16 | Write multiple registers |
23 | Read/Write multiple registers |
PROFIBUS
一种用于工厂自动化车间级监控和现场设备层数据通信与控制的现场总线技术,可实现现场设备层到车间级监控的分散式数字控制和现场通信网络。
DNP3
- DNP(Distributed Network Protocol,分布式网络协议)是一种应用于自动化组件之间的通讯协议,常见于电力、水处理等行业;
- 简化 OSI 模型,完全基于 TCP/IP,只包含了物理层、数据层与应用层的体系结构(EPA),在应用层实现了对传输数据的分片、校验、控制等诸多功能;
- DNP 借助 TCP 在以太网上运行,使用的端口是 20000 端口;
- SCADA 可以使用 DNP 协议与主站、RTU、及 IED 进行通讯。
ICCP
电力控制中心通讯协议。
OPC
过程控制的 OLE(OLE for Process Control)。OPC 包括一整套接口、属性和方法的标准集,用于过程控制和制造业自动化系统。
BACnet
楼宇自动控制网络数据通讯协议(A Data Communication Protocol for Building Automation and Control Networks)。BACnet 协议是为计算机控制采暖、制冷、空调 HVAC 系统和其他建筑物设备系统定义服务和协议。
CIP
通用工业协议,被 DeviceNet、ControlNet、EtherNet/IP 三种网络所采用。
S7comm(Siemens S7)
S7comm 全称 S7 Communication,是西门子专有协议,在西门子 S7-300/400 系列的 PLC 之间运行,用于 PLC 编程,PLC 之间的数据交换。S7 协议被封装在 TPKT 和 ISO-COTP 协议中。通过 TSAP,可加载 MPI、DP、以太网等不同物理结构总线或网络上,PLC 一般可以通过封装好的通讯功能快实现。
S7comm 对应的协议栈:
Layer | ISO/OSI Model | Protocol |
---|---|---|
7 | Application | S7 communication |
6 | Presentation | S7 communication (COTP) |
5 | Session | S7 communication (TPKT) |
4 | Transport | ISO-on-TCP (RFC 1006) |
3 | Network | IP |
2 | Data Link | Ethernet |
1 | Physical | Ethernet |
应用层 S7comm 协议结构体包含三部分:
- Header
- Parameter
- Data
Header
Name | Start | Length |
---|---|---|
Protocol Id | 0 | 1 |
ROSCTR | 1 | 1 |
Redundancy Identification (Reserved) | 2 | 2 |
Protocol Data Unit Reference | 4 | 2 |
Parameter length | 6 | 2 |
Data length | 8 | 2 |
Error class | 10 | 2 |
Error code | 12 | 2 |
- Protocol Id:协议 ID,通常为 0x32;
- ROSCTR:PDU 的类型;
- 0x01(JOB):作业请求,如读/写存储器,读/写块,启动/停止设备,设置通信;
- 0x02(ACK):确认响应,是没有数据的简单确认;
- 0x03(ACK_DATA):确认数据响应,一般是相应 JOB 的请求;
- 0x07(USERDATA):扩展协议,其参数字段包括请求/相应 ID,一般用于编程/调试、读取 SZL 等。
- Redundancy Identification:冗余数据,通常为 0x0000;
- Protocol Data Unit Reference:协议数据单元参考,通过请求时间增加;
- Parameter length:参数的总长度;
- Data length:数据长度,如果读取 PLC 内部数据则为 0x0000;而对于其他功能则为 Data 部分的数据长度;
- Error class:错误类型;
- 0x00(No error):没有错误;
- 0x81(Application relationship):应用关系;
- 0x82(Object definition):对象定义;
- 0x83(No resources available):没有可用资源;
- 0x84(Error on service processing):服务处理种错误;
- 0x85(Error on supplies):请求错误;
- 0x87(Access error):访问错误。
- Error code:错误码
Parameter & Data
S7comm 协议的 Parameter 部分与 Data 部分,则是根据 Header 中 PDU type 的功能码的不同、协议扩展(Userdata)的内容不同而变得不同。当 PDU 类型是 JOB 和 ACK_DATA 时,常见的功能码如下:
- 0x00(CPU services):CPU 服务
- 0xf0(Setup communication):建立通信
- 在每个会话开始时被发送,然后才可以交换任何其他消息,主要用于协商 ACK 队列的大小和最大 PDU 长度,双方声明它们的支持值(和计算机网络中的最大传送长度声明类似),ACK 队列的长度决定了可以同时启动而不需要确认的并行作业的数量。PDU 和队列长度字段都是大端。
Name | Start | Length |
---|---|---|
Function(函数声明) | 0 | 1 |
Reserved(保留字节,一般为 0x00) | 1 | 1 |
Max AmQ (parallel jobs with ack) calling | 2 | 2 |
Max AmQ (parallel jobs with ack) called | 4 | 2 |
PDU length | 6 | 2 |
- 0x04(Read Var):读取值
- 读数据操作,通过指定变量的存储区域,地址(偏移量)及其大小或类型来执行。
当 PDU 类型是 JOB 时,Parameter 部分的结构如下(没有 Data 部分):
Name | Start | Length |
---|---|---|
Function | 0 | 1 |
Item count | 1 | 2 |
Item [n] |
2+12n | 12 |
其中一个 Item 的结构如下:
Name | Start | Length |
---|---|---|
Variable specification(结构标识,通常为 0x12,代表变量规范) | 0 | 1 |
Length of following address specification(地址规范长度,主要是以此往后的地址长度) | 1 | 1 |
Syntax Id(IDS 的地址规范的格式类型,用于确定寻址模式和其余项目结构的格式) | 2 | 1 |
Transport size(数据传输大小,常见值如下表) | 3 | 1 |
Length(数据的长度) | 4 | 2 |
DB number(DB 编号,如果访问的不是 DB 区域,此处为 0x0000) | 6 | 2 |
Area(区域) | 8 | 1 |
Address(地址) | 9 | 3 |
当 PDU 类型是 ACK_DATA 时,Parameter 部分的结构如下:
Name | Start | Length |
---|---|---|
Function | 0 | 1 |
Item count | 1 | 2 |
Data 部分存储 Item 结构体,其中一个 Item 的结构如下:
Name | Start | Length |
---|---|---|
Return code(返回码) | 0 | 1 |
Transport size(数据传输大小) | 1 | 1 |
Length(数据的长度) | 2 | 2 |
Data | 4 | 4 + Length of Data |
Fill byte(填充字节,如果数据的长度不满足 Length 的话,填充 0x00) | / | / |
- 0x05(Write Var):写入值
- 写数据操作,通过指定变量的存储区域,地址(偏移量)及其大小或类型来执行。大部分和 Read Var 的结构相同,只是多了写的 Data 结构。
- 0x1a(Request download):请求下载
当 PDU 类型是 JOB 时,结构如下:
Name | Start | Length |
---|---|---|
Function(函数声明) | 0 | 1 |
Unknown byte(s) in blockcontrol(blockcontrol 中的所有未知字节) | 2 | 2 |
Unknown byte(s) in blockcontrol(无意义,一般为 0x00000000) | 4 | 4 |
Filename Length(文件名长度) | 8 | 1 |
Filename(文件名) | 9 | 9 |
其中文件名结构如下:
Name | Start | Length |
---|---|---|
File identifier(文件标识符,_ ——Complete Module、$ ——Module header for up-loading 两种) |
0 | 1 |
Block type(块类型,西门子设备中有 8 种不同类型的功能块) | 1 | 2 |
Block number(请求的块编号) | 3 | 5 |
Destination filesystem(请求的目标文件系统) | 8 | 1 |
Length part(接下来的字段长度) | 18 | 1 |
Unknown char before load mem(加载 mem 之前的未知字符) | 19 | 1 |
Length of load memory(装载长度) | 20 | 6 |
Length of MC7 code(MC7 代码长度) | 26 | 6 |
当 PDU 类型是 ACK_DATA,Parameter 部分仅有一个 Function 字段。
- 0x1b(Download block):下载块
- 和 Request download 相比少了目标文件系统后面的部分。Parameter 内容仅有 Function 确认和 Function 状态,但是多出了 Data 结构,内容主要为数据长度、未知字节以及数据内容,数据内容的长度。
- 0x1c(Download ended):下载结束
- 结构和 Download block 类似。Parameter 中只有一个 Function 确认。
- 0x1d(Start upload):开始上传
- 和 Request download 的前部分结构一致。
Name | Start | Length |
---|---|---|
Function(函数声明) | 0 | 1 |
Function Status(功能状态,包含错误是否发生、是否使用另一个检索块/文件来请求) | 1 | 1 |
Unknown byte(s) in blockcontrol(blockcontrol 中的所有未知字节) | 2 | 2 |
UploadID(上传文件会话的 ID) | 4 | 4 |
Blocklengthstring Length(块长字符串后的字节长度) | 8 | 1 |
Blocklength(完整上传块的长度(以字节为单位),可以拆分为多个 PDU) | 9 | 7 |
- 0x1e(Upload):上传
当 PDU 类型为 JOB 时,Upload 结构中没有 Data,Parameter 的结构如下(和 Start upload 类似):
Name | Start | Length |
---|---|---|
Function(函数声明) | 0 | 1 |
Function Status(功能状态,包含错误是否发生、是否使用另一个检索块/文件来请求) | 1 | 1 |
Unknown byte(s) in blockcontrol(blockcontrol 中的所有未知字节) | 2 | 2 |
UploadID(上传文件会话的 ID) | 4 | 4 |
- 0x1f(End upload):上传结束
- 当 PDU 类型为 JOB 时,结构和 Upload 相同;
- 当 PDU 类型为 ACK_DATA 时,仅有一个功能确认的结构。
- 0x28(PI-Service):程序调用服务
- 用于 PLC 修改执行/内存状态的日常工作。这些命令可以用于启动或停止 PLC 控制程序、激活或删除程序块。
Name | Start | Length |
---|---|---|
Function(函数声明) | 0 | 1 |
Unknown bytes(未知字节) | 1 | 7 |
Parameter block length(参数块长度) | 8 | 2 |
String length(PI service 的字符串长度) | 12 | 1 |
PI (program invocation) Service(程序调用服务名) | 13 | 9 |
- 0x29(PLC Stop):关闭 PLC
- 机构和 PI-Service 一致。
其他工控协议
IEC 60870-5-104、EtherNet/IP、Tridium Niagara Fox、Crimson V3、OMRON FINS、PCWorx、ProConOs、MELSEC-Q 等。
工控协议仿真资源
- Modbus 协议
- ModSim、ModScan、mod_RSsim
- 西门子 S7 协议
- snap7 client、snap7 server
- IEC104 协议
- PMA 规约分析软件
- DNP3 协议
- opendnp3 Simulator
- IEC61850 协议
- Protocol Test Harness
- BACnet 协议
- BACnet Server
- OPC UA 和 OPC DA 协议
- KEPServerEX、UAEXpect
Vulnerabilities
除了上面讲的协议部分,其他还有很多方面存在漏洞。
Code Logic Vulnerability in PLC
工控编程是工控系统运行的核心和重点:
- 工控编程核心为明白工控业务逻辑,而工控编程遵循 IEC61131-3(工控史上首例实现 PLC、DCS、运动控制、 SCADA 等联合编程的标准——IEC61131-3),包括 5 种编程语言标准,3 种是图形化语言(梯形图、顺序功能图和功能块图),两种是文本化语言(指令表和结构文本)。
- 工控设备往往可以在线调试,从而可以控制某些输入输出端口,实现强制启停的功能,如果这些功能可以采用 Remote 方式重发,那攻击危害就更为严重。
- 工控设备的连接方式多样,一般采用串口,但是目前设备发展支持以太网、USB 接口等新的方式,如果网口不行试试串口、USB。
- 工控组态可以非常复杂,甚至连接成百上千个输入输出都有可能,组态中会由于添加了新的组件而更加麻烦,这时候要慢慢看,一点一点缕出来。
PLC 代码逻辑漏洞
- 计算逻辑漏洞
- 看门狗超时漏洞
- 缓冲区溢出漏洞
Communication Hijack
通信劫持是工控场景中最经典利用方式,例如 ARP 劫持、PLC/HMI 通信劫持、PLC 会话劫持、PLC 命令执行等内容。通信劫持的方法:
- ARP 劫持,ARP 劫持可以阻断 PLC 与其他设备的通信,鉴于工程会存在写死 IP 等交互地址,未必管用,但是值得一试;
- PLC/HMI 通信劫持,采用旁路设备接入或控制 PLC 设备,对 IO 进行强制重写或输出;
- PLC 命令执行,针对工控设备最敏感的部分是设备宕机(无法恢复的)、设备启停、设备强制更新参数,等等这些对普通工艺能够产生较大的影响。
工业以太网链路漏洞
- MAC 泛洪攻击
- ARP 溢出/中间人攻击
- 环网 Beacon 协议攻击
- VLAN 跳转攻击
- 交换机 WEB 漏洞攻击
Host Security Vulnerability
主机上可能会自带的漏洞:
- 防火墙关闭
- 没有杀毒软件防护
- 缺乏 USB 准入
- Windows 本身的漏洞
- SMB v1.0 Port 445
- RDP Port 3389
- AD 域攻击
- DNS 污染攻击
Vulnerability in SCADA
- DoS 拒绝式服务攻击
- 缓冲区溢出漏洞
- COM 服务组件未授权访问漏洞
- SQL 数据库注入的漏洞
Physical Security Vulnerability
- 设备所在地无防护
- 机房机柜未上锁
- 网络端口未加固
- 控制器钥匙未拔出
- 供电电源为单路
- 接地系统不完善
Firmware Reversing
工具:
- Binwalk
- BAT(Binary Analysis Toolkit)
- …
Device | Vendor | OS | Binwalk | BAT |
---|---|---|---|---|
Camera | STL | Linux | 不支持 | 支持 |
Router | Bintec | - | 不支持 | 不支持 |
ADSL Gateway | Zyxel | ZynOS | 支持 | 支持 |
PLC | Siemens | - | 支持 | 支持 |
DSLAM | - | - | 支持 | 支持 |
PC | Intel | BIOS | 支持 | 支持 |
ISDN Server | Planet | - | 支持 | 支持 |
Voip | Asotel | Vxworks | 支持 | 支持 |
Modem | - | - | 不支持 | 不支持 |
Home Automation | Belkin | Linux | 不支持 | 不支持 |
Discovering
主机发现
使用 Shodan 几乎可以搜索到网络上所有的 PLC、SCADA 等设备。
端口探测
目前针对工控设备扫描中,在 Nmap、Metasploit、Censes 集成了大量的工具,用于挖掘当前在线 PLC、DCS 等 ICS 设备。
基于端口
端口 | 协议 / 设备 | 来源 |
---|---|---|
102(TCP) | Siemens S7 | nmap --script s7-info.nse -p 102 [HOST] \ nmap -sP --script s71200-enumerate-old.nse -p 102 [HOST] |
502(TCP) | Modbus | nmap --script modicon-info -p 502 [HOST] |
2404(TCP) | IEC 60870-5-104 | nmap -Pn -n -d --script iec-identify.nse --script-args='iec-identify.timeout=500' -p 2404 [HOST] |
20000(TCP) | DNP3 | nmap -sT --script dnp3-enumerate.nse -p 20000 [HOST] / nmap --script dnp3-info -p 20000 [HOST] |
44818(TCP) | Ethernet/IP | nmap --script enip-enumerate -sU -p 44818 [HOST] |
47808(UDP) | BACnet | nmap --script BACnet-discover-enumerate.nse -sU -p 47808 [HOST] |
1911(TCP) | Tridium Nixagara Fo | nmap --script fox-info.nse -p 1911 [HOST] |
789(TCP) | Crimson V3 | nmap --script cr3-fingerprint.nse -p 789 [HOST] |
9600(TCP) | OMRON FINS | nmap --script omrontcp-info -p 9600 [HOST] |
1962(TCP) | PCWorx | nmap --script pcworx-info -p 1962 [HOST] |
20547(TCP) | ProConOs | nmap --script proconos-info -p 20547 |
5007(TCP) | Melsec-Q | nmap --script melsecq-discover -sT -p 5007 [HOST] |
5006 | Melsec-Q | nmap --script melsecq-discover-udp.nse -sU -p 5006 [HOST] |
1200(TCP) | Codesys | nmap --script codesys-v2-discover.nse [HOST] |
10001 | ATG | nmap --script atg-info -p 10001 [HOST] |
基于组态软件的组件
端口 | 协议 / 设备 | 连接方法 |
---|---|---|
102(TCP) | Siemens S7 | 西门子软件 Step7 自带扫描当前网段 PLC 设备功能 |
502(TCP) | Modbus | 施耐德 SoMachine Basic 连接 PLC 设备自带扫描内网网段功能 |
Defence
工业控制系统安全防御:
- 区域边界
- 工业防火墙
- 区域防火墙
- 网闸
- 网络安全
- 交换机空余端口关闭
- Native VLAN
- 禁用 CDP 或 LLDP
- 握手报文加密
- 主机安全
- 杀毒软件
- 防火墙
- 基线安全
- USB 口准入
- 应用白名单
- 控制器安全
- 协议加密
- 准入控制
- 身份认证
- 物理安全
- 接地安全
- 双路供电
- 电柜上锁
Appendix
错误码的含义
错误码 | 含义 |
---|---|
0x0000 | 没有错误 |
0x0110 | 块号无效 |
0x0111 | 请求长度无效 |
0x0112 | 参数无效 |
0x0113 | 块类型无效 |
0x0114 | 找不到块 |
0x0115 | 块已存在 |
0x0116 | 块被写保护 |
0x0117 | 块/操作系统更新太大 |
0x0118 | 块号无效 |
0x0119 | 输入的密码不正确 |
0x011A | PG 资源错误 |
0x011B | PLC 资源错误 |
0x011C | 协议错误 |
0x011D | 块太多(与模块相关的限制) |
0x011E | 不再与数据库建立连接,或者 S7DOS 句柄无效 |
0x011F | 结果缓冲区太小 |
0x0120 | 块结束列表 |
0x0140 | 可用内存不足 |
0x0141 | 由于缺少资源,无法处理作业 |
0x8001 | 当块处于当前状态时,无法执行请求的服务 |
0x8003 | S7 协议错误:传输块时发生错误 |
0x8100 | 应用程序,一般错误:远程模块未知的服务 |
0x8104 | 未在模块上实现此服务或报告了帧错误 |
0x8204 | 对象的类型规范不一致 |
0x8205 | 复制的块已存在且未链接 |
0x8301 | 模块上的内存空间或工作内存不足,或者指定的存储介质不可访问 |
0x8302 | 可用资源太少或处理器资源不可用 |
0x8304 | 无法进一步并行上传。存在资源瓶颈 |
0x8305 | 功能不可用 |
0x8306 | 工作内存不足(用于复制,链接,加载 AWP) |
0x8307 | 保持性工作记忆不够(用于复制,链接,加载 AWP) |
0x8401 | S7 协议错误:无效的服务序列(例如,加载或上载块) |
0x8402 | 由于寻址对象的状态,服务无法执行 |
0x8404 | S7 协议:无法执行该功能 |
0x8405 | 远程块处于 DISABLE 状态(CFB)。该功能无法执行 |
0x8500 | S7 协议错误:帧错误 |
0x8503 | 来自模块的警报:服务过早取消 |
0x8701 | 寻址通信伙伴上的对象时出错(例如,区域长度错误) |
0x8702 | 模块不支持所请求的服务 |
0x8703 | 拒绝访问对象 |
0x8704 | 访问错误:对象已损坏 |
0xD001 | 协议错误:非法的作业号 |
0xD002 | 参数错误:非法的作业变体 |
0xD003 | 参数错误:模块不支持调试功能 |
0xD004 | 参数错误:作业状态非法 |
0xD005 | 参数错误:作业终止非法 |
0xD006 | 参数错误:非法链路断开 ID |
0xD007 | 参数错误:缓冲区元素数量非法 |
0xD008 | 参数错误:扫描速率非法 |
0xD009 | 参数错误:执行次数非法 |
0xD00A | 参数错误:非法触发事件 |
0xD00B | 参数错误:非法触发条件 |
0xD011 | 调用环境路径中的参数错误:块不存在 |
0xD012 | 参数错误:块中的地址错误 |
0xD014 | 参数错误:正在删除/覆盖块 |
0xD015 | 参数错误:标签地址非法 |
0xD016 | 参数错误:由于用户程序错误,无法测试作业 |
0xD017 | 参数错误:非法触发号 |
0xD025 | 参数错误:路径无效 |
0xD026 | 参数错误:非法访问类型 |
0xD027 | 参数错误:不允许此数据块数 |
0xD031 | 内部协议错误 |
0xD032 | 参数错误:结果缓冲区长度错误 |
0xD033 | 协议错误:作业长度错误 |
0xD03F | 编码错误:参数部分出错(例如,保留字节不等于 0) |
0xD041 | 数据错误:非法状态列表 ID |
0xD042 | 数据错误:标签地址非法 |
0xD043 | 数据错误:找不到引用的作业,检查作业数据 |
0xD044 | 数据错误:标签值非法,检查作业数据 |
0xD045 | 数据错误:HOLD 中不允许退出 ODIS 控制 |
0xD046 | 数据错误:运行时测量期间非法测量阶段 |
0xD047 | 数据错误:“读取作业列表”中的非法层次结构 |
0xD048 | 数据错误:“删除作业”中的非法删除 ID |
0xD049 | “替换作业”中的替换 ID 无效 |
0xD04A | 执行’程序状态’时出错 |
0xD05F | 编码错误:数据部分出错(例如,保留字节不等于 0,…) |
0xD061 | 资源错误:没有作业的内存空间 |
0xD062 | 资源错误:作业列表已满 |
0xD063 | 资源错误:触发事件占用 |
0xD064 | 资源错误:没有足够的内存空间用于一个结果缓冲区元素 |
0xD065 | 资源错误:没有足够的内存空间用于多个结果缓冲区元素 |
0xD066 | 资源错误:可用于运行时测量的计时器被另一个作业占用 |
0xD067 | 资源错误:“修改标记”作业过多(特别是多处理器操作) |
0xD081 | 当前模式下不允许使用的功能 |
0xD082 | 模式错误:无法退出 HOLD 模式 |
0xD0A1 | 当前保护级别不允许使用的功能 |
0xD0A2 | 目前无法运行,因为正在运行的函数会修改内存 |
0xD0A3 | I / O 上活动的“修改标记”作业太多(特别是多处理器操作) |
0xD0A4 | ‘强制’已经建立 |
0xD0A5 | 找不到引用的作业 |
0xD0A6 | 无法禁用/启用作业 |
0xD0A7 | 无法删除作业,例如因为当前正在读取作业 |
0xD0A8 | 无法替换作业,例如因为当前正在读取或删除作业 |
0xD0A9 | 无法读取作业,例如因为当前正在删除作业 |
0xD0AA | 处理操作超出时间限制 |
0xD0AB | 进程操作中的作业参数无效 |
0xD0AC | 进程操作中的作业数据无效 |
0xD0AD | 已设置操作模式 |
0xD0AE | 作业是通过不同的连接设置的,只能通过此连接进行处理 |
0xD0C1 | 访问标签时至少检测到一个错误 |
0xD0C2 | 切换到 STOP / HOLD 模式 |
0xD0C3 | 访问标记时至少检测到一个错误。模式更改为 STOP / HOLD |
0xD0C4 | 运行时测量期间超时 |
0xD0C5 | 块堆栈的显示不一致,因为块被删除/重新加载 |
0xD0C6 | 作业已被删除,因为它所引用的作业已被删除 |
0xD0C7 | 由于退出了 STOP 模式,因此作业被自动删除 |
0xD0C8 | 由于测试作业和正在运行的程序之间不一致,“块状态”中止 |
0xD0C9 | 通过复位 OB90 退出状态区域 |
0xD0CA | 通过在退出前重置 OB90 并访问错误读取标签退出状态范围 |
0xD0CB | 外设输出的输出禁用再次激活 |
0xD0CC | 调试功能的数据量受时间限制 |
0xD201 | 块名称中的语法错误 |
0xD202 | 函数参数中的语法错误 |
0xD205 | RAM 中已存在链接块:无法进行条件复制 |
0xD206 | EPROM 中已存在链接块:无法进行条件复制 |
0xD208 | 超出模块的最大复制(未链接)块数 |
0xD209 | (至少)模块上找不到给定块之一 |
0xD20A | 超出了可以与一个作业链接的最大块数 |
0xD20B | 超出了一个作业可以删除的最大块数 |
0xD20C | OB 无法复制,因为关联的优先级不存在 |
0xD20D | SDB 无法解释(例如,未知数) |
0xD20E | 没有(进一步)阻止可用 |
0xD20F | 超出模块特定的最大块大小 |
0xD210 | 块号无效 |
0xD212 | 标头属性不正确(与运行时相关) |
0xD213 | SDB 太多。请注意对正在使用的模块的限制 |
0xD216 | 无效的用户程序 - 重置模块 |
0xD217 | 不允许在模块属性中指定的保护级别 |
0xD218 | 属性不正确(主动/被动) |
0xD219 | 块长度不正确(例如,第一部分或整个块的长度不正确) |
0xD21A | 本地数据长度不正确或写保护错误 |
0xD21B | 模块无法压缩或压缩早期中断 |
0xD21D | 传输的动态项目数据量是非法的 |
0xD21E | 无法为模块(例如 FM,CP)分配参数。系统数据无法链接 |
0xD220 | 编程语言无效。请注意对正在使用的模块的限制 |
0xD221 | 连接或路由的系统数据无效 |
0xD222 | 全局数据定义的系统数据包含无效参数 |
0xD223 | 通信功能块的实例数据块错误或超出最大背景数据块数 |
0xD224 | SCAN 系统数据块包含无效参数 |
0xD225 | DP 系统数据块包含无效参数 |
0xD226 | 块中发生结构错误 |
0xD230 | 块中发生结构错误 |
0xD231 | 至少有一个已加载的 OB 无法复制,因为关联的优先级不存在 |
0xD232 | 加载块的至少一个块编号是非法的 |
0xD234 | 块在指定的内存介质或作业中存在两次 |
0xD235 | 该块包含不正确的校验和 |
0xD236 | 该块不包含校验和 |
0xD237 | 您将要加载块两次,即 CPU 上已存在具有相同时间戳的块 |
0xD238 | 指定的块中至少有一个不是 DB |
0xD239 | 至少有一个指定的 DB 在装载存储器中不可用作链接变量 |
0xD23A | 至少有一个指定的 DB 与复制和链接的变体有很大不同 |
0xD240 | 违反了协调规则 |
0xD241 | 当前保护级别不允许该功能 |
0xD242 | 处理 F 块时的保护冲突 |
0xD250 | 更新和模块 ID 或版本不匹配 |
0xD251 | 操作系统组件序列不正确 |
0xD252 | 校验和错误 |
0xD253 | 没有可用的可执行加载程序; 只能使用存储卡进行更新 |
0xD254 | 操作系统中的存储错误 |
0xD280 | 在 S7-300 CPU 中编译块时出错 |
0xD2A1 | 块上的另一个块功能或触发器处于活动状态 |
0xD2A2 | 块上的触发器处于活动状态。首先完成调试功能 |
0xD2A3 | 块未激活(链接),块被占用或块当前被标记为删除 |
0xD2A4 | 该块已被另一个块函数处理 |
0xD2A6 | 无法同时保存和更改用户程序 |
0xD2A7 | 块具有“未链接”属性或未处理 |
0xD2A8 | 激活的调试功能阻止将参数分配给 CPU |
0xD2A9 | 正在为 CPU 分配新参数 |
0xD2AA | 当前正在为模块分配新参数 |
0xD2AB | 当前正在更改动态配置限制 |
0xD2AC | 正在运行的激活或取消激活分配(SFC 12)暂时阻止 R-KiR 过程 |
0xD2B0 | 在 RUN(CiR)中配置时发生错误 |
0xD2C0 | 已超出最大工艺对象数 |
0xD2C1 | 模块上已存在相同的技术数据块 |
0xD2C2 | 无法下载用户程序或下载硬件配置 |
0xD401 | 信息功能不可用 |
0xD402 | 信息功能不可用 |
0xD403 | 服务已登录/注销(诊断/ PMC) |
0xD404 | 达到的最大节点数。不再需要登录诊断/ PMC |
0xD405 | 不支持服务或函数参数中的语法错误 |
0xD406 | 当前不可用的必需信息 |
0xD407 | 发生诊断错误 |
0xD408 | 更新已中止 |
0xD409 | DP 总线错误 |
0xD601 | 函数参数中的语法错误 |
0xD602 | 输入的密码不正确 |
0xD603 | 连接已合法化 |
0xD604 | 已启用连接 |
0xD605 | 由于密码不存在,因此无法进行合法化 |
0xD801 | 至少有一个标记地址无效 |
0xD802 | 指定的作业不存在 |
0xD803 | 非法的工作状态 |
0xD804 | 非法循环时间(非法时基或多个) |
0xD805 | 不能再设置循环读取作业 |
0xD806 | 引用的作业处于无法执行请求的功能的状态 |
0xD807 | 功能因过载而中止,这意味着执行读取周期所需的时间比设置的扫描周期时间长 |
0xDC01 | 日期和/或时间无效 |
0xE201 | CPU 已经是主设备 |
0xE202 | 由于闪存模块中的用户程序不同,无法进行连接和更新 |
0xE203 | 由于固件不同,无法连接和更新 |
0xE204 | 由于内存配置不同,无法连接和更新 |
0xE205 | 由于同步错误导致连接/更新中止 |
0xE206 | 由于协调违规而拒绝连接/更新 |
0xEF01 | S7 协议错误:ID2 错误; 工作中只允许 00H |
0xEF02 | S7 协议错误:ID2 错误; 资源集不存在 |
Item 结构中 Syntax Id 取值
Hex | 值 | 描述 |
---|---|---|
0x10 | S7ANY | Address data S7-Any pointer-like DB1.DBX10.2 |
0x13 | PBC-R_ID | R_ID for PBC |
0x15 | ALARM_LOCKFREE | Alarm lock/free dataset |
0x16 | ALARM_IND | Alarm indication dataset |
0x19 | ALARM_ACK | Alarm acknowledge message dataset |
0x1a | ALARM_QUERYREQ | Alarm query request dataset |
0x1c | NOTIFY_IND | Notify indication dataset |
0xa2 | DRIVEESANY | seen on Drive ES Starter with routing over S7 |
0xb2 | 1200SYM | Symbolic address mode of S7-1200 |
0xb0 | DBREAD | Kind of DB block read, seen only at an S7-400 |
0x82 | NCK | Sinumerik NCK HMI access |
Item 结构中 Transport size 取值
Hex | 值 | 描述 |
---|---|---|
0 | NULL | |
3 | BIT | bit access, len is in bits |
4 | BYTE/WORD/DWORD | byte/word/dword access, len is in bits |
5 | INTEGER | integer access, len is in bits |
6 | DINTEGER | integer access, len is in bytes |
7 | REAL | real access, len is in bytes |
9 | OCTET STRING | octet string, len is in bytes |
Item 结构中 Area 取值
Hex | Value | 描述 |
---|---|---|
0x03 | System info of 200 family | 200 系列系统信息 |
0x05 | System flags of 200 family | 200 系列系统标志 |
0x06 | Analog inputs of 200 family | 200 系列模拟量输入 |
0x07 | Analog outputs of 200 family | 200 系列模拟量输出 |
0x80 | Direct peripheral access (P) | 直接访问外设 |
0x81 | Inputs (I) | 输入(I) |
0x82 | Outputs (Q) | 输出(Q) |
0x83 | Flags (M) | 内部标志(M) |
0x84 | Data blocks (DB) | 数据块(DB) |
0x85 | Instance data blocks (DI) | 背景数据块(DI) |
0x86 | Local data (L) | 局部变量(L) |
0x87 | Unknown yet (V) | 全局变量(V) |
0x1c | S7 counters (C) | S7 计数器(C) |
0x1d | S7 timers (T) | S7 定时器(T) |
0x1e | IEC counters (200 family) | IEC 计数器(200 系列) |
0x1f | IEC timers (200 family) | IEC 定时器(200 系列) |
Item 结构中 Return code 取值
Hex | 值 | 描述 |
---|---|---|
0x00 | Reserved | 未定义,预留 |
0x01 | Hardware error | 硬件错误 |
0x03 | Accessing the object not allowed | 对象不允许访问 |
0x05 | Invalid address | 无效地址,所需的地址超出此 PLC 的极限 |
0x06 | Data type not supported | 数据类型不支持 |
0x07 | Data type inconsistent | 日期类型不一致 |
0x0a | Object does not exist | 对象不存在 |
0xff | Success | 成功 |
西门子设备中 8 种不同类型的功能块
Hex | 类型 | 描述 |
---|---|---|
0x3038 | OB,ASCII 为’08’,组织块 | OB 决定用户程序的结构 |
0x3039 | CMod,ASCII 为’09’ | |
0x3041 | DB,ASCII 为’0A’,数据块 | DB 是用于存储用户数据的数据区域,除了指定给一个功能块的数据,还可以定义可以被任何块使用的共享数据 |
0x3042 | SDB,ASCII 为’0B’,系统和数据块 | 由编程软件自动生成主要存放 PLC 的硬件组态等信息,用户无法直接打开和更改 |
0x3043 | FC,ASCII 为’0C’,功能 | FB、FC 本质都是一样的,都相当于子程序,可以被其他程序调用(也可以调用其他子程序),FC 使用的是共享数据块 |
0x3044 | SFC,ASCII 为’0D’,系统功能 | SFB 和 SFC 集成在 S7 CPU 中可以让你访问一些重要的系统功能 |
0x3045 | FB,ASCII 为’0E’,功能块,带背景数据块 | FB、FC 本质都是一样的,都相当于子程序,可以被其他程序调用(也可以调用其他子程序),FB 使用的是背景数据块 |
0x3046 | SFB,ASCII 为’0F’,系统功能块 | SFB 和 SFC 集成在 S7 CPU 中可以让你访问一些重要的系统功能 |
OB、FB、SFB、FC 和 SFC 都包含部分程序,因此也称作逻辑块。每种块类型所允许的块的数量以及块的长度视 CPU 而定。
请求下载的目标文件系统类型
- P(Passive copied, but not chained module):被动文件系统;
- A(Active embedded module):主动文件系统;
- B(Active as well as passive module):既主既被文件系统。
程序调用服务名
服务名称 | 值(描述) |
---|---|
UNKNOWN |
PI-Service 目前不详 |
_INSE |
PI-Service _INSE (激活 PLC 模块) |
_DELE |
PI-Service _DELE (从 PLC 的被动文件系统中删除模块) |
P_PROGRAM |
PI-Service P_PROGRAM (PLC 启动/停止) |
_MODU |
PI-Service _MODU (PLC Copy Ram to Rom) |
_GARB |
PI-Service _GARB (压缩 PLC 内存) |
N_LOGIN |
PI-Service _N_LOGIN_ (登录) |
_N_LOGOUT |
PI-Service _N_LOGOUT (退出) |
_N_CANCEL |
PI-Service _N_CANCEL (取消 NC 报警) |
_N_DASAVE |
PI-Service _N_DASAVE (用于将数据从 SRAM 复制到 FLASH 的 PI-Service) |
_N_DIGIOF P |
I-Service _N_DIGIOF (关闭数字化) |
_N_DIGION |
PI-Service _N_DIGION (打开数字化) |
N_DZERO |
PI-Service _N_DZERO_ (设置所有 D nos。对于函数无效“唯一 D 号。”) |
_N_ENDEXT |
PI-Service _N_ENDEXT |
_N_F_OPER |
PI-Service _N_F_OPER (以只读方式打开文件) |
_N_OST_OF |
PI-Service _N_OST_OF (Overstore OFF) |
_N_OST_ON |
PI-Service _N_OST_ON (Overstore ON) |
N_SCALE |
PI-Service _N_SCALE_ (测量单位设置) |
_N_SETUFR |
PI-Service _N_SETUFR (激活用户帧) |
_N_STRTLK |
PI-Service _N_STRTLK (设置全局启动禁用) |
_N_STRTUL |
PI-Service _N_STRTUL (重置全局启动禁用) |
_N_TMRASS |
PI-Service _N_TMRASS (重置活动状态) |
_N_F_DELE |
PI-Service _N_F_DELE (删除文件) |
_N_EXTERN |
PI-Service _N_EXTERN (选择外部程序执行) |
_N_EXTMOD |
PI-Service _N_EXTMOD (选择外部程序执行) |
_N_F_DELR |
PI-Service _N_F_DELR (即使没有访问权限也删除文件) |
_N_F_XFER |
PI-Service _N_F_XFER (选择要上传的文件) |
N_LOCKE |
PI-Service _N_LOCKE_ (锁定活动文件以进行编辑) |
_N_SELECT |
PI-Service _N_SELECT (选择要执行的程序) |
_N_SRTEXT |
PI-Service _N_SRTEXT (文件正在 _N_EXT_DIR 中标记) |
_N_F_CLOS |
PI-Service _N_F_CLOS (关闭文件) |
_N_F_OPEN |
PI-Service _N_F_OPEN (打开文件) |
_N_F_SEEK |
PI-Service _N_F_SEEK (定位文件搜索指针) |
N_ASUP_ |
PI-Service _N_ASUP (分配中断) |
_N_CHEKDM |
PI-Service _N_CHEKDM (对 D 号码启动唯一性检查) |
_N_CHKDNO |
PI-Service _N_CHKDNO (检查工具是否具有唯一的 D 编号) |
_N_CONFIG |
PI-Service _N_CONFIG (重新配置机器数据) |
_N_CRCEDN |
PI-Service _N_CRCEDN (通过指定边数来创建切削刃) |
_N_DELECE |
PI-Service _N_DELECE (删除最前沿) |
_N_CREACE |
PI-Service _N_CREACE (创造最前沿) |
_N_CREATO |
PI-Service _N_CREATO (创建工具) |
_N_DELETO |
PI-Service _N_DELETO (删除工具) |
_N_CRTOCE |
PI-Service _N_CRTOCE (生成具有指定边数的工具) |
_N_DELVAR |
PI-Service _N_DELVAR (删除数据块) |
_N_F_COPY |
PI-Service _N_F_COPY (复制 NCK 中的文件) |
_N_F_DMDA |
PI-Service _N_F_DMDA (删除 MDA 内存) |
_N_F_PROT |
PI-Service _N_F_PROT (为文件指定保护级别) |
_N_F_RENA |
PI-Service _N_F_RENA (重命名文件) |
_N_FINDBL |
PI-Service _N_FINDBL (激活搜索) |
_N_IBN_SS |
PI-Service _N_IBN_SS (设置设置开关) |
_N_MMCSEM |
PI-Service _N_MMCSEM (MMC-Semaphore) |
_N_NCKMOD |
PI-Service _N_NCKMOD (正在设置 NCK 工作的模式) |
_N_NEWPWD |
PI-Service _N_NEWPWD (新密码) |
_N_SEL_BL |
PI-Service _N_SEL_BL (选择新块) |
_N_SETTST |
PI-Service _N_SETTST (激活替换工具组的工具) |
_N_TMAWCO |
PI-Service _N_TMAWCO (在一个杂志中设置有效磨损组) |
_N_TMCRTC |
PI-Service _N_TMCRTC (创建具有指定边数的工具) |
_N_TMCRTO |
PI-Service _N_TMCRTO (在工具管理中创建工具) |
_N_TMFDPL |
PI-Service _N_TMFDPL (搜索空白处加载) |
_N_TMFPBP |
PI-Service _N_TMFPBP (搜索空位) |
_N_TMGETT |
PI-Service _N_TMGETT (使用 Duplono 确定特定工具 ID 的 T 编号) |
_N_TMMVTL |
PI-Service _N_TMMVTL (加载或卸载工具) |
_N_TMPCIT |
PI-Service _N_TMPCIT (设置计件器的增量值) |
_N_TMPOSM |
PI-Service _N_TMPOSM (定位杂志或工具) |
_N_TRESMO |
PI-Service _N_TRESMO (重置监控值) |
_N_TSEARC |
PI-Service _N_TSEARC (通过搜索屏幕进行复杂搜索) |
References
https://wooyun.js.org/drops/%E5%B7%A5%E6%8E%A7%E5%AE%89%E5%85%A8%E5%85%A5%E9%97%A8%E5%88%86%E6%9E%90.html
https://xuanxuanblingbling.github.io/ics/2020/01/10/ics/
https://www.cnpanda.net/sec/592.html
https://ctf-wiki.github.io/ctf-wiki/ics/ctfs-zh/
https://www.cnpanda.net/sec/578.html
https://www.bilibili.com/video/BV1Ft41177cs
https://www.bilibili.com/video/BV15J411P77f
https://www.youtube.com/watch?v=LyzIrE6DpOM