ModbusTcp协议的实验室测试浅析
协议概述
Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)通信而发表。1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:ModbusTCP。目前,modbus协议已经是工控网络中最常用的通信协议之一。
Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。本文主要介绍基于以太网TCP/IP的ModbusTCP协议在实验室的测试方法。
ModbusTcp数据结构
ModbusTcp的数据帧可以分为两部分MBAP+PDU,如图:
MBAP为报文头,长度为7字节,结构如下:
长度 | 含义 |
2字节(例如00 01) | 事务处理标识,主机发出的检验信息,一般每次通信后加1,从机slave将这个两个字节放在响应报文中。 |
2字节(例如00 00) | 协议标识符,00 00为modbus的TCP/IP协议 |
2字节(例如00 06) | 数据长度,用来指示接下来数据的长度,单位字节。 |
1字节(例如01) | 设备地址,用以标识连接在网络上的远程服务端的地址。 |
PDU由功能码+数据组成。功能码长度为1字节,数据长度由具体功能决定。由于多数网络安全设备主要控制request方向的报文,这里只列举ModbusTcp协议request方向报文的PDU结构:
◇ 01 (0x01) Read Coils
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x01 |
Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity of coils | 2 | 0X0001 to 0x07D0 |
◇ 02 (0x02) Read Discrete Inputs
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x02 |
Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity of Inputs | 2 | 0X0001 to 0x07D0 |
◇ 03 (0x03) Read Holding Registers
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x03 |
Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity of Registers | 2 | 0X0001 to 0x007D |
◇ 04 (0x04) Read Input Registers
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x04 |
Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity of Input Registers | 2 | 0X0001 to 0x007D |
◇ 05 (0x05) Write Single Coil
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x05 |
Output Address | 2 | 0x0000 to 0xFFFF |
Output Value | 2 | 0X0000 or 0xFF00 |
◇06 (0x06) Write Single Register
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x05 |
Register Address | 2 | 0x0000 to 0xFFFF |
Register Value | 2 | 0X0000 to 0xFFFF |
◇15 (0x0F) Write Multiple Coils
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x0F |
Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity of Outputs | 2 | 0X0001 to 0x07D0 |
Byte Count | 1 | N* |
Outputs Value | N*x1 |
◇16 (0x10) Write Multiple registers
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x10 |
Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity of Registers | 2 | 0x0001 to 0x007D |
Byte Count | 1 | 2xN* |
Registers Value | N*x2 | value |
◇20 (0x14) Read File Record
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x14 |
Byte Count | 1 | 0x07 to 0xF5 |
Sub-Req. x, Reference Type | 1 | 06 |
Sub-Req. x, File Number | 2 | 0x0001 to 0xFFFF |
Sub-Req. x, Record Number | 2 | 0x0000 to 0x270F |
Sub-Req. x, Record Length | 2 | N |
Sub-Req. x+1, ... |
◇21(0x15)Write File Record
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x15 |
Request data length | 1 | 0x09 to 0xFB |
Sub-Req. x, Reference Type | 1 | 06 |
Sub-Req. x, File Number | 2 | 0x0001 to 0xFFFF |
Sub-Req. x, Record Number | 2 | 0x0000 to 0x270F |
Sub-Req. x, Record Length | 2 | N |
Sub-Req. x, Record data | Nx2 | |
Sub-Req. x+1, ... |
◇22(0x16)Mask Write Register
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x16 |
Reference Address | 2 | 0x0000 to 0xFFFF |
And_Mask | 2 | 0x0000 to 0xFFFF |
Or_Mask | 2 | 0x0000 to 0xFFFF |
◇23 (0x17) Read/Write Multiple registers
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x17 |
Read Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity to Read | 2 | 0x0001 to 0x007D |
Write Starting Address | 2 | 0x0000 to 0xFFFF |
Quantity to Write | 2 | 0x0001 to 0X0079 |
Write Byte Count | 1 | 2 x N * |
Write Registers Value | N *x 2 |
*N = Quantity to Write
◇24 (0x18) Read FIFO Queue
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x18 |
FIFO Pointer Address | 2 | 0x0000 to 0xFFFF |
◇43 ( 0x2B) Encapsulated Interface Transport
名称 | 长度 (字节) | 值 |
Function code | 1 | 0x2B |
MEI Type* | 1 | 0x0D or 0x0E |
MEI type specific data | n |
ModbusTcp常用测试工具及方法
报文回放
实验室环境下,利用数据包回放工具将捕获的网络数据包按照测试人员的意愿回放到网络环境中,从而模拟真实的网络环境进行系统测试。
☆ Windows环境
科来数据包播放器和数据包生成器是在Windows环境下回放和编辑数据包的常用工具。科来数据包播放器会把选取的数据包从指定的网卡发出,若选取的数据包为双向报文,则发出的也是双向报文,适用于测试旁路部署的网络安全设备对ModbusTcp协议的支持和解析能力。
测试组网:
科来数据包播放器操作页面及回放报文结果:
科来数据包生成器,可以直接编辑修改指定数据包内容,以及发送目标报文,比较适用于轻量级的数据包编辑。例如删除数据包三次握手信息、制造旁路设备中间流接入场景下首包为response方向报文的协议识别、篡改某些字节数据进行异常测试等,然后结合科来数据包播放器进行回放测试。
科来数据包生成器操作界面:
☆ Linux环境
tomahawk是一款Linux环境下用于测试网桥型(串联部署)网络设备的工具。它通过分析截获的网络数据包文件,分辨出其中的Client和Server端,再通过指定的两个网卡发送出去。
测试组网:
tomahawk命令格式:
tomahawk [ -i interface1 ] [ -j interface2] [ -R rate ] [ -a startIpAddr ] [ -A (0|1) ] [ -t timeout ] [ -l loops ] [-f file ]
• -i interface1 从interface1网口发送client到server方向的包,必填参数;
• -j interface2 从interface2 网口发送 server到client方向的包,必填参数;
• -R rate 限制tomahawk发送测试网络速率, MB/秒, 这个数可以是浮动数, 比如100Kbps的流量,可以使用-R 0.1表示,选填参数;
• -a startIpAddress 当重写IP地址时, 可以从startIpAddress开始分配IP地址,选填参数;
• -A (0|1) 是否需要修改包中的IP地址标记,0为不修改,选填参数;
• -l loops 循环回放文件的次数,必填参数;
• -f file 要回放的数据包文件,必填参数;
操作举例:
将modbus.pcap通过tomahawk工具回放报文2次。
操作命令:./tomahawk -i p3p1 -j p3p2 -l 2 -f modbus.pcap
操作结果:
tomahawk工具在未配置 -A 和 -a 参数时,缺省配置下会修改回放报文中的IP地址,多次回放同一报文时IP地址会自动递增。图示组网方式可同时测试串联和旁路设备,适合于在已有固定报文的情况下测试网络安全产品基于不同的五元组对ModbusTcp报文的解析和处理能力,以及模拟测试网络安全设备在工业现场数千、数万条流中自动学习并生成白名单基线的完整性和准确性,大流量高速率下的协议解析和转发能力等。
功能和使用场景跟tomahawk工具类似的还有tcpreplay,tcpreplay是一系列工具的总称,包括tcpreplay、tcprewrite和tcpprep等工具,它也常用来在Unix系统或者linux系统上重放pcap格式的数据包;
1 .tcpprep: 对pcap数据包进行预处理,区分pcap数据包的流向,即划分哪些包是client的,哪些包是server的,发包的时候client和server的数据包从不同的网卡发出;
2. tcprewrite:修改报文内容,主要修改2层,3层,4层报文头,即MAC地址,IP地址和port地址;
3. tcpreplay: 数据包发包工具,可以选择主网卡、从网卡、发包速度等;
仿真模拟
☆ ModScan32工具
ModScan32是一个运行在windows下,作为在RTU或ASCII传输模式下的Modbus协议主设备的应用程序。把一个或多个Modbus从站设备通过网络连接到电脑上,就可以使用ModScan 读取和修改数据点。实验室模拟环境中,从站可以使用PLC或者ModSim。
测试组网:
modscan客户端界面:
界面元素及配置:
• Address:起始地址;
• Length:显示(读取)长度;
• Device id:设备ID
• Modbus Point Type:功能码类型,可选择01、02、03、04号功能码,读01功能码时写操作为05号功能码,读03号功能码时写操作为06号功能码;
• Connection/connect/connect:选择连接方式;
• Connection/connect/IP Address:远端从机的IP地址;
• Connection/connect/rotocol Selection/Force modbus...:勾选之后,读01功能码时写操作为15号功能码,读03号功能码时写操作为16号功能码;
• Setup/Display options/:选择显示的数据类型;
• Setup/Display Definition:可设置读取速率(单位毫秒)以及modbus数据信息;
ModScan32可以用来测试网络安全设备对ModbusTcp的01-16号功能码的读写解析功能,包括五元组信息、功能码信息、起止地址、值域信息。
演示案例:
通过ModScan32工具向目标IP地址192.168.77.211模拟写16号功能码,地址15,数据类型Float单精度浮点数,点值1.0E11。(其他功能码操作基本相同)
步骤:
1. 运行ModScan32程序,Address输入0001,Length输入100,Device id输入1,Modbus Point Type选择03功能码;
2. Connection/connect 页面中Connect 选择 Remote TCP/IP Server,IP Address 输入192.168.77.211,点击rotocol Selection弹出页面勾选Force modbus......,选择OK保存后会自动连接;
3 .Setup/Display options/Floatin Pt 配置显示单精度浮点数,双击界面目标地址15可弹出写操作界面,Value中输入点值1.0E11点击update,即完成写操作。
操作界面如图:
wireshark抓包结果:
威努特网络安全设备解析结果:
☆ KEPServerEX客户端
ModScan32在测试ModbusTcp协议应用中,具有安装简单,配置快捷,操作方便等特点,但是对于浮点数的显示不够直观(数值较大时显示为???),因此在实验室仿真测试过程中我们也可以借助于KEPServerEX软件进行ModbusTcp协议的测试。
环境安装:
KEPServerEX左侧树形表中右键添加新Channel并命名为modbus:
选择Device driver为Modbus TCP/IP Ethernet
之后默认“下一步”安装直到device driver添加完成(中间NetworkAdapter可默认也可选则指定的IP地址)。
树形表中选中modbus,右侧区域右键new device 添加device,命名为value
device model选择modbus
device id <>中的IP地址填写从机的IP,.后边填写从机的设备ID。
然后,默认“下一步”直到device添加完成。
左侧树形表中选中value,右侧区域右键new tag 添加tag(以写16号功能码,地址15,数据类型Float单精度浮点数,点值1.0E11为例,其他功能码操作基本相同)
Address可参考上图“?”中的帮助信息,数据类型等按测试目标填写;
添加完成后,可通过下图红圈中的快捷方式,启动OPC Quick Client进行读写操作。
如上图中显示,读取出来的value值1E+011非常直观,选中item右键即可进行读写操作。
数据包构造
前两节主要介绍通过报文回放和模拟软件对ModbusTcp的01-16号功能码进行读、写以及值域测试,本小节主要介绍使用Scapy进行16号之后功能码的数据包构造。Scapy是一个强大的,用Python编写的交互式数据包处理程序,它能让用户发送、嗅探、解析,以及伪造网络报文,从而用来侦测、扫描和向网络发动攻击。Scapy可以轻松地处理扫描(scanning)、路由跟踪(tracerouting)、探测(probing)、单元测试(unit tests)、攻击(attacks)和发现网络(network discovery)之类的传统任务。开始前先复习下网络基础知识,如图:
在scapy中可以通过ls()函数来查看scapy支持的网络协议,ls(IP())查看IP数据包参数,其他数据包同理,通过lsc()函数来查看scapy的指令集(函数)。常用的指令集(函数)包括arpcachepoison(用于arp欺骗),arping(用于构造一个ARP的who-has包) ,send(用于发3层报文),sendp(用于发2层报文), sr(发送+接收3层报文),srp(发送+接收2层报文),sniff(用于网络嗅探)等。下图截取部分指令集。
了解了报文的层次、每层的封装、scapy指令集、以及ModbusTcp的数据结构,可以开始通过scapy进行ModbusTcp的报文构造。
注:
◇ RandShort()函数会在1-65535的范围内随机生成一个TCP端口号。
◇ scapy发送报文时可通过/将不同层次的报文拼接到一起,然后通过send()函数发送出去;
◇ b‘\x01\x01...’可以把字符串进行转义
1. 构造ModbusTcp协议20号功能码报文
报文构造命令:
>>>ModbusTcp20=IP(dst=’192.168.77.211’)/TCP(sport=RandShort(),dport=502)/b'\x01\x00\x00\x00\x00\x0a\x01\x14\x07\x06\x00\x01\x00\x00\x00\x00'
>>> send(ModbusTcp20)
抓包结果如图:
2.构造ModbusTcp协议21号功能码报文
报文构造命令:
>>>ModbusTcp21=IP(dst=’192.168.77.211’)/TCP(sport=RandShort(),dport=502)/b'\x01\x00\x00\x00\x00\x0c\x01\x15\x09\x06\x00\x01\x00\x00\x00\x01\x00\x00'
>>> send(ModbusTcp21)
抓包结果如图:
3.构造ModbusTcp协议22号功能码报文
报文构造命令:
>>>ModbusTcp22=IP(dst=’192.168.77.211’)/TCP(sport=RandShort(),dport=502)/b'\x01\x00\x00\x00\x00\x08\x01\x16\x00\x00\x00\x00\x00\x00'
>>> send(ModbusTcp22)
抓包结果如图:
4.构造ModbusTcp协议23号功能码报文
报文构造命令:
>>>ModbusTcp23=IP(dst=’192.168.77.211’)/TCP(sport=RandShort(),dport=502) /b'\x01\x00\x00\x00\x00\x0d\x01\x17\x00\x00\x00\x01\x00\x00\x00\x01\x02\x00\x00'
>>> send(ModbusTcp23)
抓包结果如图:
5.构造ModbusTcp协议24号功能码报文
报文构造命令:
>>>ModbusTcp24=IP(dst=’192.168.77.211’)/TCP(sport=RandShort(),dport=502)/b'\x01\x00\x00\x00\x00\x04\x01\x18\xff\xff'
>>> send(ModbusTcp24)
抓包结果如图:
6.构造ModbusTcp协议43号功能码报文
报文构造命令:
>>>ModbusTcp43=IP(dst=’192.168.77.211’)/TCP(sport=RandShort(),dport=502)/b'\x01\x00\x00\x00\x00\x04\x01\x2b\x0d\x00'
>>> send(ModbusTcp43)
抓包结果如图:
除上述功能码外,还可以利用scapy构造各种违反ModbusTcp协议规约的报文来验证网络安全设备对违规报文的识别和检测能力,这里不再赘述。
威努特产品推荐
威努特工业防火墙和智能监测终端搭载了威努特自主研发的深度数据包解析引擎,对工控协议做到实时和精准的识别,为解决针对工控网络的安全问题提供了技术基础保障。全面支持各大主流工控协议,并且能够对各类数据包进行快速有针对性的捕获与深度解析。对不同行业的工控系统,采取针对性的数据包探测机制和策略解析。在遵循工业控制系统可用性与完整性的基础上,能够检测出数据包的有效内容特征、负载和可用匹配信息,如恶意软件、具体数据和应用程序类型。解析引擎执行时能够满足工业控制系统在生产和制造过程中的通信效率保障和冗余机制等要求。
深度数据包解析引擎支持涵盖OPC、Modbus、IEC 60870-5-104、IEC 61850 MMS、Siemens S7、Ethernet/IP(CIP)、DNP3、Profinet、Fins等在内的各大主流工控协议,可以对OPC、S7、ModbusTcp等工控协议做到指令级控制和值域控制。
工业防火墙典型部署场景如图:
北京威努特技术有限公司(以下简称“威努特”), 是国内工控网络安全领军企业、全球六家荣获国际自动化协会安全合规学会ISASecure CRT Tool认证企业之一和亚太地区唯一国际自动化学会(ISA)全球网络安全联盟(GCA)创始成员。
威努特作为国家高新技术企业,以创新的“白环境”整体解决方案为核心,自主研发了全系列工控网络安全专用产品,拥有52项发明专利、50项软件著作权、52项原创漏洞证明等核心知识产权。积极牵头和参与工控网络安全领域国家、行业标准制定,受邀出色完成新中国70周年庆典、中共十九大、两会等重大活动的网络安保任务,被授予“国家重大活动网络安保技术支持单位”,得到了中央网信办、公安部、工信部等国家政府部门的高度认可。迄今已成功为电力、轨道交通、石油石化、军工、烟草、市政、智能制造、冶金等国家重要行业1000多家工业企业提供了全面有效的安全保障。
威努特始终以“专注工控,捍卫安全”为使命,致力于为我国关键信息基础设施网络空间安全保驾护航!
渠道合作咨询 张先生 18201311186
稿件合作 微信:Luo_xiaoran