(一) Modbus协议

前言

最近因任务需要,要求这方面的知识基础,因此打算开一个系列来自己学习巩固一下,充实自己。。。。

Modbus协议是什么?

Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。

Modbus作为一种通信协议,它是一种应用层的报文传输协议,它既可以在物理层面上选择串口进行简单的串行通信,也可以使用TCP的方式进行传输。

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

在这里插入图片描述
Modbus有自己的数据链路层定义,其实主要是对于传输数据格式和校验等方面的规定。具体来说,modbus定义了自己的数据单元,功能码与具体的数据组成了PDU(协议数据单元 Protocol Data Unit),所谓的功能码也就是代表了主向从下达的指令是什么,数据也就是这次指令要用到的“参数”。

在这里插入图片描述

Modbus功能码

功能码主设备能够对从设备下达指令,功能码有效范围在1~255之间。其中大部分都是保留的,如128-255为异常响应保留,例如:

  • 01 读线圈状态
  • 02 读离散输入状态
  • 03 读保持寄存器
  • 04 读输入寄存器
  • 05 写单个线圈
  • 15 写多个线圈
  • 16 写多个保持寄存器
  • 20 读文件记录
  • 21 写文件记录
  • 08 获取异常状态
    更多功能码可去查询手册来获取具体信息。。。

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一样,可读但不可写,可以理解为外部对于系统的多位输入。

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、协议标识符等。

在这里插入图片描述

实例

黑客通过外网进入一家工厂的控制网络,之后对工控网络中的操作员站系统进行了攻击,最终通过工控协议破坏了正常的业务。我们得到了操作员站在攻击前后的网络流量数据包,我们需要分析流量中的蛛丝马迹,找到FLAG,flag形式为 flag{}。

在这里插入图片描述

​ 使用wireshark打开流量包,限定范围为modbus协议的数据包,根据功能码来判断异常,筛选功能码为16的数据包进行ASCII码转换即可发现flag。

利用payload:

import pyshark
func_code = [1,2,3,4]
def find_flag():
     pcap = pyshark.FileCapture("q1.pcap")
     for c in pcap:
         for pkt in c:
             if pkt.layer_name == "modbus":
                 temp = int(pkt.func_code)
                 if temp not in func_code:
                     payload = str(c["TCP"].payload).replace(":", "")
                     print("content[*] is " + payload)

​ 解析:整体上没有什么异常,接下来就该考虑是否有数据的写入,flag很有可能就是写入的数据。那么首先排除12345的功能码,因为flag既不可能是位操作,也不可能是字操作,都太短了,所以聚焦的就应该是包长度大的,或者是类似16功能码那样写多个字的指令。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值