工控竞赛笔记

准备比赛做的一小撮笔记,鸡肋鸡肋,食之无味,弃之可惜

wireshark过滤条件

IP

ip contains flag.txt

modbus

modbus&&modbus.func_code==16 //重点关注5,15,6,16

s7comm

加上初始化通信的包,刚好占一半,说明所有发送都是成功接收的。因此就不需要看Ack_Data
s7comm.header.rosctr == 3 & s7comm.data.returncode == 0xff

s7comm&&s7comm.param.func==0x05

查看ROSCTR为Job的Write Var的数据包
s7comm.header.rosctr == 1

mms

mms.confirmedServiceRequest==73

mms协议有关的流量分析题目,可以先搜索flag,png等关键字符串,如果检索不到可以尝试搜索对应的十六进制,比如666c(’fl’)

strings t3.pcap | grep -e 666c 或者 Zmxh

找到fileopen(72)对应的No.

接着使用这一条mms.confirmedServiceRequest==73过滤fileread(73)操作的条目

观察那一条大于fileopen的No.,找到invokeID,接着找对应的mms.invokeID==No.

Modbus

flag首先排除12345的功能码,聚焦的就应该是包长度大的,或者是类似16功能码那样写多个字的指令。筛选1234之外功能码的包

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)

读取相应功能码的数据

import pyshark
def find_flag():
    cap = pyshark.FileCapture("test.pcapng")
    idx = 1
    for c in cap:
        for pkt in c:
            if pkt.layer_name == "modbus":
                func_code = int(pkt.func_code)
                # func_code根据实际情况修改
                if func_code == 6:  
                    payload = str(c["TCP"].payload).replace(":", "")
                    print(hex_to_ascii(payload))
        idx += 1
def hex_to_ascii(payload):
data = payload
flags = []
for d in data:
    _ord = ord(d)
    if (_ord > 0) and (_ord < 128):
        flags.append(chr(_ord))
return ''.join(flags)
if __name__ == '__main__':
find_flag()

场景实操

控制开关

改寄存器

S7

PLC

'PE': 0x81,  #input 输入区,即I区
'PA': 0x82, #output 输出区,即Q区
'MK': 0x83, #bit memory 中间存储区(M区)
'DB': 0x84, #DB区
'CT': 0x1C, #counters
'TM': 0x1D, #Timers

工具

工控漏洞框架:https://github.com/dark-lbp/isf/

公众号

大禹工控安全实验室
IRTeam工控安全红队

发表评论