前言
本文分为两部分:第一部分对104协议进行解析,按照协议报文结构从前往后逐步进行解析,并结合相关的通信流量,以便读者更直观地理解;第二部分介绍了104协议模糊测试的一些策略和思路。笔者是也是因项目而初次接触104协议,如有不足之处,请谅解!在此特别感谢郑老师对104协议模糊测试方面的指导。
1. 简介
IEC 60870-5-104远动规约用于厂站与调度主站间的通讯,电力系统中常见的设备分为调度端(主站、控制站、客户机)典型设备如SCADA,服务端(子站、被控站、服务机)典型设备如FTU(馈线终端)、DTU(站所终端)、TTU(配变终端)、RTU(远程终端单元),两者之间通过104规约来进行数据通信与传输。
IEC 60870-5-104 协议是基于IEC 60870-5-101 协议在 TCP-IP 协议上使用的扩展。IEC 60870-5-101是基于串口的通信协议,IEC 60870-5-104是基于以太网的通信协议。默认端口是TCP2404
。
2. 规约数据结构
数据报文结构共分为三个部分:
应用规约控制信息:APCI(Application protocal control information)
应用服务数据单元:ASDU(Application service data unit)
应用规约数据单元:APDU(Application protocal data unit)
APDU=APCI+ASDU,104规约规定APDU报文最长为255个字节,所以ASDU最大为249。
2.1. APCI解析
启动字符
:68H,十六进制表示,长度为1字节。
APDU长度域
:定义了APDU体的长度,它包括 APCI 的四个控制域八位位组和ASDU长度。
控制域定义了保护报文不至丢失和重复传送的控制信息、报文传输启动/停止、以及传输连接的监视等控制信息。
控制域1和2
:为发送序列号,控制域1最后一位比特不参与发送序列号计算。
控制域3和4
:为接收序列号,控制域3最后一位比特不参与接收序列号计算,固定为0。
由于存储方式是小端模式,第一个开始计数的发送序列号是控制域1,第一个开始计数的接收序列号是控制域3,并且因为最后一位不参与计算,实际序列号*2=序列号值。
示例:
1、主站发送报文,序列号为(0,0)表示发送序列号为0,接收序列号为0。
控制域1和2
:0000 0000
0000 0000 (0000H)
控制域3和4
:0000 0000
0000 0000(0000H)
2、子站回复报文,序列号为(0,1)表示发送序列号为0,接收序列号为1。
控制域1和2
:0000 0000
0000 0000 (0000H)
控制域3和4
:0000 0010
0000 0000(0200H)传输时数据为:0002H
3、主站发送报文,序列号为(1,1)表示发送序列号为1,接收序列号为1。
控制域1和2
:0000 0010
0000 0000 (0200H)传输时数据为:0002H
控制域3和4
:0000 0010
0000 0000(0200H)传输时数据为:0002H
2.2. 控制域解析
I帧
为长帧,带有信息发送(ASDU)并确认对方帧,发送和接收序列号有效,最长度为255。
控制域1的最低位比特为0时,标识信息传输格式类型为:I格式即I帧。上图示例即为I帧。
S帧
为短帧,不带有信息,仅用于确认接收对方帧,仅接收序列号有效,长度为6字节。
控制域1的最低位比特为1,倒数第二位为0时,标识信息传输格式类型为:S格式即S帧。
U帧
为短帧,用于启动控制信息,仅控制域1有效,其余固定为0,长度为6字节。
控制域1的最低位比特为1,倒数第二位为1时,标识信息传输格式类型为:U格式即U帧。
00 00 01 11 启动命令 0x07,完整命令为:68 04 07 00 00 00
00 00 10 11 启动确认 0x0B,完整命令为:68 04 0b 00 00 00
00 01 00 11 停止命令 0x13,完整命令为:68 04 13 00 00 00
00 10 00 11 停止确认 0x23,完整命令为:68 04 23 00 00 00
01 00 00 11 测试命令 0x43,完整命令为:68 04 43 00 00 00
10 00 00 11 测试确认 0x83,完整命令为:68 04 83 00 00 00
2.3. ASDU解析
ASDU部分是I帧
信息帧独有的,ASDU部分其实是IEC 60870-5-104信息的有效数据的载荷,不同ASDU数据类型对应的信息元素内容也不同
完整类型标识如下表:参考链接:IEC104规约(一)协议结构阐述
- 监视方向过程信息
从站发送给主站;标度化值-类似INT16,短浮点值-类似float - 控制方向过程信息
主站发送给从站 - 监视方向系统信息
从站发送给主站,当厂站(从站)短重新上电、初始化参数、重新分配缓存区等情况下,厂站需要给主站发送该类型,而主站收到该类型的APDU包,主站一般会做一次总召唤 - 控制方向系统信息
主站发送给从站
分类 | 类型标识 | 类型名称 |
---|---|---|
监视方向过程信息(上行) | 1 | 单点信息 |
2 | 带短时标的单点信息 | |
3 | 双点信息 | |
4 | 带短时标的双点信息 | |
5 | 步长位置信息 | |
6 | 带短时标的步长位置信息 | |
7 | 32比特串 | |
8 | 带短时标的32比特串 | |
9 | 测量值,归一化值 | |
10 | 带短时标的测量值,归一化值 | |
11 | 测量值,标度化值 | |
12 | 带短时标的测量值,标度化值 | |
13 | 测量值,短浮点数 | |
14 | 带短时标的测量值,短浮点数 | |
15 | 累计值 | |
16 | 带短时标的累计值 | |
17 | 带时标的保护设备事件 | |
18 | 带时标的继电保护装置成组启动事件 | |
19 | 带时标的继电保护装置成组输出电路信息 | |
20 | 具有状态变位检出的成组单点信息 | |
21 | 测量值,不带品质描述的归一化值 | |
30 | 带CP56Time2a时标的单点信息 | |
31 | 带CP56Time2a时标的双点信息 | |
32 | 带CP56Time2a时标的步位置信息 | |
33 | 带CP56Time2a时标的32比特串 | |
34 | 带CP56Time2a时标的测量值规一化 | |
35 | 带CP56Time2a时标的测量值标度化 | |
36 | 带CP56Time2a时标的测量值短浮点 | |
37 | 带CP56Time2a时标的累计量 | |
38 | 带CP56Time2a时标的继电保护装置 | |
39 | 带CP56Time2a时标的继电保护装置成组启动事件 | |
40 | 带CP56Time2a时标的继电保护装置成组输出电路信息 | |
41-44 | 为将来的兼容定义保留 | |
控制方向过程信息(下行) | 45 | 单命令 |
46 | 双命令 | |
47 | 步调节命令 | |
48 | 设点命令,归一化值 | |
49 | 设点命令,标度化值 | |
50 | 设点命令,浮点数值 | |
51 | 32比特串 | |
52-57 | 为将来的兼容定义保留 | |
58 | 带CP56Time2a时标的单命令 | |
59 | 带CP56Time2a时标的双命令 | |
60 | 带CP56Time2a时标的步调命令 | |
61 | 带CP56Time2a时标的设点命令,归一化值 | |
62 | 带CP56Time2a时标的设点命令,标度化值 | |
63 | 带CP56Time2a时标的设点命令,浮点数值 | |
64 | 带CP56Time2a时标的32位比特串 | |
65-69 | 为将来的兼容定义保留 | |
监视方向系统信息(上行) | 70 | 初始化结束 |
71-99 | 为将来的兼容定义保留 | |
控制方向系统信息(下行) | 100 | 总召唤 |
101 | 电能脉冲召唤命令 | |
102 | 读命令 | |
103 | 时钟同步命令 | |
104 | 测试命令 | |
105 | 复位进程命令 | |
106 | 延时获得命令 | |
107 | 带CP56Time2a时标的测试命令 | |
108-109 | 为将来的兼容定义保留 | |
控制下行参数信息(下行) | 110 | 规一化值的参数 |
111 | 比例系数的参数 | |
112 | 浮点数值的参数 | |
113 | 参数的激活 | |
114-119 | 为将来的兼容定义保留 | |
文件传输 | 120 | 文件准备就绪 |
121 | 节准备就绪 | |
122 | 召唤目录,选择文件,召唤文件,召唤节 | |
123 | 最后节,最后段 | |
124 | 确认文件,确认节 | |
125 | 段 | |
126 | 目录 | |
127 | 为将来的兼容定义保留 |
2.3.2. 可变结构体(VSQ)
SQ=0:信息对象的地址不连续(意思就是每个信息对象都会一个对象地址),信息是无序的,接收方不需要按照顺序进行处理。
SQ=1:信息对象的地址连续 (只有第一个信息对象有地址,其他对象的地址就是累加1),信息是有序的,接收方需要按照顺序进行处理,以确保信息的正确性和完整性。
示例:
2.3.3. 传送原因(COT)
传送原因两字节分开,第1个字节高两位比特为T和P/N,COT 6比特。
T表示测试,只用于测试,不会控制处理器&更改系统状态
- T=0 (非测试模式), T=1 (测试模式)
P/N (positive/negative) bit
积极/消极的激活确认。 - 当使用主站下发命令时,这个位域是有意义的。该位域通常表示控制命令是否被成功执行 P/N=0表示肯定确认,P/N=1表示否定确认。
源发地址OA:用来标明响应来自那个主站的召唤,一般写0
传送原因如下表:
传送原因 | 语义 | 应用方向 |
---|---|---|
1 | 周期、循环 | 上行 |
2 | 背景扫描 | 上行 |
3 | 突发 | 上行 |
4 | 初始化 | 上行 |
5 | 请求或被请求 | 上行/下行 |
6 | 激活 | 下行 |
7 | 激活确认 | 上行 |
8 | 停止激活 | 下行 |
9 | 停止激活确认 | 上行 |
10 | 激活终止 | 上行 |
11 | 远方命令引起的返送信息 | 上行 |
12 | 当地命令引起的返送信息 | 上行 |
20 | 响应站召唤 | 上行 |
21 | 响应第 1组召唤 | 上行 |
… | 响应第 n组召唤 | 上行 |
36 | 响应第 16 组召唤 | 上行 |
37 | 响应累积量站召唤 | 上行 |
38 | 响应第 1组累积量召唤 | 上行 |
39 | 响应第 2 组累积量召唤 | 上行 |
40 | 响应第 3组累积量召唤 | 上行 |
41 | 响应第 4组累积量召唤 | 上行 |
44 | 未知类型标识 | 上行 |
45 | 未知的传送原因 | 上行 |
46 | 未知的应用服务数据单元公共地址 | 上行 |
47 | 未知的信息对象地址 | 上行 |
示例:
2.3.4. 应用服务数据单元地址即ASDU公共地址(Addr)
站地址:主站可以在一个104链路上连接多个子站,为了区分子站的报文而使用站地址,1-254为站地址,255为全局地址即广播地址。一般是主站和子站一对一通讯,默认值为1。
示例:
2.3.5. 信息对象地址(IOA)
信息对象地址:用于区分子站上不同应用的寻址,3字节,如遥控、遥信、遥调等地址不同。
当IOA=000000H时,表明本帧报文不携带数据,是功能性的报文,如总召、对时等。
02版本的104规约信息对象地址:
应用 | 地址 | 点号 |
---|---|---|
遥信 | 0001H | 1 |
0002H | 2 | |
0001H-4000H | 0003H | 3 |
0004H | 4 | |
0005H | 5 | |
0006H | 6 | |
遥测 | 4001H | 16385 |
4002H | 16386 | |
4001H-5000H | 4003H | 16387 |
4004H | 16388 | |
4005H | 16389 | |
4006H | 16390 | |
4007H | 16391 | |
遥控 | 6001H | 24577 |
6002H | 24578 | |
6001H-6100H | 6003H | 24579 |
6004H | 24580 | |
6005H | 24581 | |
6006H | 24582 | |
6007H | 24583 | |
6008H | 24584 | |
6009H | 24585 | |
600AH | 24586 | |
遥调 | 6201H | 25089 |
6202H | 25090 | |
6201H-6400H | 6203H | 25091 |
6204H | 25092 | |
6205H | 25093 | |
6206H | 25094 | |
6207H | 25095 |
示例:点号24577,单点命令
2.3.6. 信息元素集
具体不展开,可参考文章:详解IEC104 规约【最详细版】,后续章节介绍常用的一些信息对象。
3. 总召命令
控制站(client)可以在任何时候发送召唤命令,以同步受控站(Server)中的所有过程变量的值。召唤命令分为总召唤和群组召唤,现详细描述如下:
-
总召唤/general interrogation (GI)
总召唤命令会请求受控站(Server)中所有群组的所有数据对象的值的更新给控制站。 -
群组召唤
在受控站(Server)端,数据对象可以通过配置COT(传输原因)的值为20~36来设定数据对象的召唤群组。20代表总召唤,21~36 分别对应INRO1~INRO16,分别对应16个召唤群组。控制站(client) 在召唤时,可以通过指定召唤群组,来让该召唤组中的数据对象值更新。
总召流程:主站下发总召命令→子站回复确认总召命令→子站上送信息→子站回复激活终止报文
总召激活:68 0e 04 00 1a 0064
0106
00 01 00 00 00 0014
64:总召命令的类型标识
06:激活总召
14:总召-信息元素内容(站内询问-全局)
确认激活:68 0e 1a 00 06 00 64
01 07
00 01 00 00 00 00 14
子站上送单点信息:68 17 1c 00 06 00 01
8a 14
00 01 00 01 00 00
01 00 00
01
00 00 00 00 00 00
01:单点信息的类型标识
14:传送原因-响应总召
010000:IOA地址01
010000:第一个信息对象地址01
01:SIQ信息元素,最低位SPI标识单点遥信0分1合
又因为SQ的值为1,true状态,信息对象连续,后续信息对象地址在第一个地址基础上加1,故无地址,只有SIQ信息元素内容。
下面描述解释内容参考:https://blog.csdn.net/changqing1990/article/details/134327980
IV:VALID (0) / INVALID (1)。数据值是否有效,当采集系统识别到异常的情况(如更新设备丢失或无法运行),将这个位域标为1。该情况下信息对象的值,不会被定义。这个位为1表示信息对象的值是不正确的,不被使用
NT:TOPICAL (0) / NOT TOPICAL (1)。NT为刷新标志位,若最近的刷新成功则值就称为当前值(0),若一个指定的时间间隔内刷新不成功或者其值不可用,值就称为非当前值(1)。设备处于调试态或装置通讯中断都有可能造成非当前值。
SB:NOT SUBSTITUTED (0) / SUBSTITUTED (1)。SB为取代标志位,当信息对象的值由值班员(调度员)输入(即人工置数)或者由当地自动原因(模拟遥信)所提供时,即为被取代。如人工置数情况下。这意味着该值不是从正常测量中得出的。
BL:NOT BLOCKED (0) / BLOCKED (1)。BL为封锁标志位,信息对象的值为传输而被封锁,值保持封锁前被采集的状态。封锁和解锁可以由当地联锁机构或当地自动原因启动。
报文解析如下:
子站上送双点信息:68 0e 1e 00 06 00 03
81 14
00 01 00 0b 00 00
00
03:双点信息的类型标识
14:传送原因-响应总召
0b 00 00:IOA地址
00:DIQ信息元素内容,DPI最低两位比特标识双点遥信1开2合,0和3为中间状态
报文解析:
子站上送测量信息:68 8f 22 00 06 00 0d
9a 14
00 01 00 01 40 00
00 00 00 00 00
000000000000000000000000000000000000000000000000000000000000000000000054994b42
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0d:浮点遥测的类型标识
14:传送原因-响应总召
014000:IOA地址4001
00 00 00 00
00:前四字节为32位浮点值,00表示QOS限定符
示例:0x54994b42转化成32为浮点数
import struct
def hex_to_float(hex_string):
# 将十六进制字符串转换为整数
int_value = int(hex_string, 16)
# 将整数转换为32位浮点数
float_value = struct.unpack('<f', struct.pack('!I', int_value))[0]
return float_value
def float_to_hex_le(float_num):
# 将单精度浮点数转换为小端存储的字节序列
byte_data = struct.pack("<f", float_num)
# 将字节序列转换为十六进制字符串
hex_str = byte_data.hex()
return hex_str
报文解析:
激活终止:68 0e 2a 00 06 00 64
01 0a
00 01 00 00 00 00 14
64:总召命令的类型标识
0a:传送原因-激活终止
4. 遥控命令
单点即使用1个比特位标识开关状态,只采集一个常开的辅助接点,值为1表示合位,0表示分位。
双点即使用2个比特位标识开关状态,采集常开常闭两个辅助接点,当常开点值为1并且常闭点值为0,即10表示合位;当常开点值0并且常闭点值为1,即01表示分位;当两个位置值都为1,或两个值都为0,则认为开关位置不能确定,中间状态。
命令传输分位直接控制(Single command)和选择控制(Select and execute)
直控的流程: 主站下发执行命令→子站回复确认执行报文。
选控的流程:主站下发选择(预置)命令→子站回复确认选择报文→主站下发执行命令→子站回确认执行报文→子站回激活终止报文
4.1. 单点命令
单点即使用一个比特位标识开关状态,值为1表示合位,0表示分位。
1、单点遥合
激活预置选择:68 0e 0c 00 22 00 2d
01 06
00 01 00 01 60 00 81
2d:单点命令的类型标识
06:传送原因-激活
81:最低位值为1表示合位,0表示分位,当前为合位;最高位值为1表示选择,0表示执行
IOA:24577是0x006001的十进制数,即遥合的点位
确认预置选择:68 0e 22 00 0e 00 2d
01 07
00 01 00 01 60 00 81
07:传送原因-确认激活预置
激活执行:68 0e 0e 00 24 00 2d
01 06
00 01 00 01 60 00 01
01:最低位值为1表示合位,0表示分位,当前为合位;最高位值为1表示选择,0表示执行
确认执行:68 0e 24 00 10 00 2d
01 07
00 01 00 01 60 00 01
07:传送原因-确认激活执行
激活终止:68 0e 26 00 10 00 2d
01 0a
00 01 00 01 60 00 01
0a:激活终止,命令执行完成
2、单点遥分
激活预置:68 0e 04 00 16 00 2d
01 06
00 01 00 01 60 00 80
确认预置:68 0e 16 00 06 00 2d
01 07
00 01 00 01 60 00 80
激活执行:68 0e 06 00 18 00 2d
01 06
00 01 00 01 60 00 00
确认执行:68 0e 18 00 08 00 2d
01 07
00 01 00 01 60 00 00
激活终止:68 0e 1a 00 08 00 2d
01 0a
00 01 00 01 60 00 00
4.2. 双点命令
双点:低两位用来标识开关状态,01为分位,10为合位,11和00状态不确定。
1、双点遥分
激活预置:68 0e 08 00 1c 00 2e
01 06
00 01 00 01 60 00 81
2e:双点命令的类型标识
06:传送原因-激活
81:低2位值为01表示分位,10表示合位,当前为分位;最高位值为1表示选择,0表示执行
IOA:24577是0x006001的十进制数,即遥分的点位
确认预置:68 0e 1c 00 0a 00 2e
01 07
00 01 00 01 60 00 81
激活执行:68 0e 0a 00 1e 00 2e
01 06
00 01 00 01 60 00 01
06:激活执行遥分
01:执行遥分
确认执行:68 0e 1e 00 0c 00 2e
01 07
00 01 00 01 60 00 01
07:确认预置
01:确认执行遥分
激活终止:68 0e 20 00 0c 00 2e
01 0a
00 01 00 01 60 00 01
0a:激活终止
2、双点遥合
激活预置:68 0e 10 00 28 00 2e
01 06
00 01 00 01 60 00 82
确认预置:68 0e 28 00 12 00 2e
01 07
00 01 00 01 60 00 82
激活执行:68 0e 12 00 2a 00 2e
01 06
00 01 00 01 60 00 02
确认执行:68 0e 2a 00 14 00 2e
01 07
00 01 00 01 60 00 02
激活终止:68 0e 2c 00 14 00 2e
01 0a
00 01 00 01 60 00 02
5. 时钟同步
时钟同步流程:主站下发时钟同步命令→子站回复确认时钟同步
时钟同步激活:68 14 04 00 1e 00 67
01 06
00 01 00 00 00 00 ab b8 3a 10 0b 01 18
67:时钟同步命令的类型标识
06:激活时钟同步
ab b8 3a 10 0b 01 18:主站向子站同步的时钟值-Jan 11, 2024 16:58:47.275000000 中国标准时间
时钟同步激活确认:68 14 1e 00 06 00 67
01 07
00 01 00 00 00 00 ab b8 3a 10 0b 01 18
67:时钟同步命令的类型标识
07:激活确认
6. 复位进程
复位进程流程:主站下发复位进程命令→子站回复确认复位进程
复位进程激活:68 0e 08 00 2e 00 69
01 06
00 01 00 00 00 00 01
69:复位进程的类型标识
06:激活复位进程
01:QRP复位进程信息元素内容
复位进程激活确认:68 0e 2e 00 0a 00 69
01 07
00 01 00 00 00 00 01
69:复位进程的类型标识
07:激活复位进程确认