modbus基础知识 https://www.anquanke.com/post/id/185513#h2-0
modbus协议最初是由Modicon公司在1971年推出的全球第一款真正意义上用于工业现场的总线协议,最初是为了实现串行通信,运用在串口(如RS232、RS485等)传输上的,分为ModbusRTU、Modbus ASCII两种,后来施耐德电气将该公司收购,并在1997年推出了基于TCP/IP的Modbus TCP。现在使用最多的就是Modbus TCP了,我们今天的主角也是它。

Modbus作为一种通信协议,它和我们之前介绍的Zigbee有很大不同,Zigbee有自己完整的协议栈,而Modbus是一种应用层的报文传输协议,它既可以在物理层面上选择串口进行简单的串行通信,也可以使用TCP的方式进行传输。

上图可以看到Modbus的协议栈仅仅是在传统ISO/OSI模型的基础上对数据链路层和应用层做了定义。也正是因为modbus是应用层的协议,所以它的安全漏洞并不只是它本身,TCP/IP的漏洞也可以利用在modbus上,最典型的就是18年工控比赛的题目,中间人。

modbus是一种主从协议,主设备的一方向从设备的一方下达指令,从设备的一方根据指令做出反应并回复主设备,主设备可以有多个从设备。具体来说,工作人员的计算机可认为是master,而PLC之类的具体设备就是slave了。每个设备有自己的“代号”,主设备通过“代号”来找到某一个对应的设备,当然也可以使用广播的方式,代号0即为广播。

从协议栈还可以看到,Modbus有自己的数据链路层定义,其实主要是对于传输数据格式和校验等方面的规定。具体来说,modbus定义了自己的数据单元,功能码与具体的数据组成了PDU(协议数据单元 Protocol Data Unit),所谓的功能码也就是代表了主向从下达的指令是什么,这是很重要的一个知识,后面我们会具体讲功能码代指的功能,数据也就是这次指令要用到的“参数”。

很显然,只有PDU并不够,我们还需要知道从设备的“代号”才能知道数据往哪发,还要想办法保证数据的完整性、一致性和可靠性。所以在PDU的基础上我们还需要添加一个地址,和一个差错校验,这就构成了ADU(Application Data Unit)。但要注意,由于三种Modbus在传输中存在差异,所以ADU,特别是校验部分会有不同。

modbus功能码
前面说过通过功能码主设备能够对从设备下达指令,功能码有效范围在1~255之间。其中大部分都是保留的,如128-255为异常响应保留,举几个栗子:

01 读线圈状态
02 读离散输入状态
03 读保持寄存器
04 读输入寄存器
05 写单个线圈
可能看到这里大家就懵了,这都是啥啊。其实很简单,modbus可以说是将读写指令分为了两大类,一类是离散的,也就是位操作,非1即0;第二类是模拟的,也就是数字,可以叫做字操作。而每一类下面都有输出和输出之分,于是就有了下面四种说法:

DO(digital output 数字量输出),所谓线圈就是离散的输出状态,01即读一个离散的输出状态,举个不恰当的栗子,你家灯泡接到某个控制器上(实际上并不会存在这种情况……),我们可以通过01加上数据,比如1,让他亮,加上0,让他灭。
DI (digital input 数字量输入),所谓的离散输入就是它,还是上面的栗子,我们想知道灯的开关是咋样的呢?就用02指令看看,如果是1,哦,按下去了,如果是0就是没按。通过这个不恰当的栗子我们大概也可以猜到,这是不可写的(如果你随便一个指令把开关给按死了,那我这灯不是彻底开不了了?),可以理解为外部对工控系统所带来的“开关”影响。
AO(AnalogOutput 模拟输出),保持寄存器的功能,和DO最大的不同就是它不再是0或1,可以是一个数值,比如,我们设定的PID运行参数,或者是温度的上下限等等
AI(Analog Input 模拟输入),也就是输入寄存器,和DI一样,可读但不可写,可以理解为外部对于系统的多位输入
当然有写单个的就必然有写多个的,比如15就是写多个线圈,16是写多个保持寄存器。此外还有读文件记录的20,写文件记录的21,获取异常状态的08等等,这里就不在多说了,具体的大家可以自行查看手册。

当然,说到功能码就不得不提Modbus在施耐德设备上的一个重要漏洞了。这就是在defcon上展示过的fun with 0x5a,这个0x5a的功能码是由施耐德自己实现的非标准的功能码,该功能码实现了Modbus标准未允许的功能。在defcon中大佬为我们展示了以下几项

获取项目和PLC信息
开启、停止PLC
下载程序
更改程序
这里先不做过多介绍,在之后我们再详细看一看0x5a攻击的流量包。

Modbus TCP
上面说了我们这次的主角是Modbus TCP。我们可以通过wireshark对Modbus的流量包进行抓取进而观察Modbus TCP的数据格式

Transaction identifier : 事务标识符
Protocol identifier : 默认为0
Length : 数据的长度
Unit identifier : 从机地址,因为使用了TCP/IP所以用ip地址来标识从机,所以该位可忽视,或者做进一步分发
Function code : modbus的功能码
Data :具体的数据
可以看到在遵从TCP/IP的基础上Modbus加了自己的修改,主要有以下三个部分:

由于TCP/IP本身具有数据校验部分,所以ADU的差错校验没有了
实用ip可以确定从机,ADU的附加地址也不再有效。但是目标可以继续是一个主机,再向其他从机发送数据,这时ADU的附加地址可以作为下一个主机分发数据包时的地址。
增加了TCP/IP的头部,比如length、协议标识符等

posted on 2019-09-04 14:53  fish_pompom  阅读(350)  评论(0)    收藏  举报