编写IE CSS漏洞、DNP3协议、TFTP协议、modbus功能码异常、wincc flexible缓冲区溢出的suricata规则-测试(9004104-9004134)
1.测试规则(9004104-9004108)
1.主机B开启9100端口 nc -l -p 9100 2.主机A发送请求 printf '@PJL FSDIRLIST NAME="0:\\" \r\n' | nc 10.10.10.2 9100 printf '@PJL FSUPLOAD NAME="0:\\config\\net.cfg" \r\n' | nc 10.10.10.2 9100 printf '@PJL FSDOWNLOAD NAME="0:\\tmp\\a.bin" \r\n' | nc 10.10.10.2 9100 printf '@PJL FSDELETE NAME="0:\\tmp\\a.bin" \r\n' | nc 10.10.10.2 9100 3.主机B分析测试流量 tshark -r pjl.pcap -o tcp.desegment_tcp_streams:TRUE -q -z follow,tcp,ascii,0
2.测试规则(9004109-9004110)
1.主机B开启监听20000 nc -l -p 20000 > /tmp/recv_20000.bin 2.主机A发送请求 python - << 'PY' import socket dst=("10.10.10.2",20000) p=bytearray() p += b"\x05\x64" # DNP3 start p += b"\x20" # payload[2] = 0x20 (通过 byte_test) p += b"\x00" * 20 # padding(让结构更像真实帧,但不必严格) p += b"\x01\x46" # 关键字段1 p += b"\x00" * 50 p += b"\x13" # 关键字段2(在 01 46 后 256 内) p += b"\x00" * 40 # 确保 dsize > 80 s=socket.socket() s.connect(dst) s.sendall(bytes(p)) s.close() print("sent",len(p),"bytes") PY
3.测试规则(9004111-9004113)
1.主机A发送请求 python - << 'PY' import socket dst=("10.10.10.2",69) pkt=b"\x00\x01" + b"NVRAM/D20.zlb" + b"\x00" + b"octet" + b"\x00" socket.socket(socket.AF_INET,socket.SOCK_DGRAM).sendto(pkt,dst) print("sent RRQ",pkt) PY python - << 'PY' import socket dst=("10.10.10.2",69) pkt=b"\x00\x02" + b"NVRAM/test.cfg" + b"\x00" + b"octet" + b"\x00" socket.socket(socket.AF_INET,socket.SOCK_DGRAM).sendto(pkt,dst) print("sent WRQ",pkt) PY python - << 'PY' import socket, time dst=("10.10.10.2",69) s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) for i in range(15): fn=f"file{i}.bin".encode() pkt=b"\x00\x01" + fn + b"\x00" + b"octet" + b"\x00" s.sendto(pkt,dst) time.sleep(1) print("sent 15 RRQ") PY
4.测试规则(9004114-9004115、9004127)
1.主机B开启502端口监听 nc -lk -p 502 >/dev/null 2.主机A发送请求,测试9004115、9004127 python - << 'PY' import socket, struct def send(payload): s=socket.socket() s.connect(("10.10.10.2",502)) s.sendall(payload) s.close() def mbap(func, extra=b""): tid=0x1234 pid=0x0000 length=1+1+len(extra) unit=0x01 return struct.pack(">HHHB", tid, pid, length, unit) + bytes([func]) + extra send(mbap(0x5A, b"\x11" + b"\x30" + b"\x00")) send(mbap(0x10, b"\x00\x00\x00\x01\x02\x12\x34")) print("sent") PY
5.测试规则(9004116-9004120)
1.主机B开启502监听 nc -lk -p 502 >/dev/null 2.主机A发送请求,测试9004116-9004120 ''' python umas_modbus.py --dst 10.10.10.2 --subfunc 0x31 # 9004116 python umas_modbus.py --dst 10.10.10.2 --subfunc 0x32 # 9004117 python umas_modbus.py --dst 10.10.10.2 --subfunc 0x33 # 9004118 python umas_modbus.py --dst 10.10.10.2 --subfunc 0x34 # 9004119 python umas_modbus.py --dst 10.10.10.2 --subfunc 0x35 # 9004120 ''' import socket import struct import time import argparse from socket import IPPROTO_TCP, TCP_NODELAY def mbap(tid: int, func: int, extra: bytes, unit: int = 1) -> bytes: # MBAP: TID(2) PID(2=0) LEN(2) UNIT(1) + FUNC(1) + EXTRA pid = 0 length = 1 + 1 + len(extra) # unit + func + extra return struct.pack(">HHHB", tid, pid, length, unit) + bytes([func]) + extra def send_umas_subfunc(dst_ip: str, subfunc: int, port: int = 502, sleep_s: float = 0.2): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) # 尽量避免粘包 s.connect((dst_ip, port)) session_key = 0x11 # 第1包:CTX 包(仅确保 flowbits 先被 set) # func=0x5A,offset9 填 0x00(无所谓) pkt_ctx = mbap(0x1111, 0x5A, bytes([session_key, 0x00, 0x00])) s.sendall(pkt_ctx) time.sleep(sleep_s) # 第2包:目标子功能包(offset9 = subfunc) pkt = mbap(0x1112, 0x5A, bytes([session_key, subfunc, 0x00])) s.sendall(pkt) time.sleep(sleep_s) s.close() if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("--dst", required=True, help="PLC/Server IP, e.g. 10.10.10.2") ap.add_argument("--subfunc", required=True, help="UMAS subfunc hex, e.g. 0x31") ap.add_argument("--sleep", type=float, default=0.2) args = ap.parse_args() sub = int(args.subfunc, 16) send_umas_subfunc(args.dst, sub, sleep_s=args.sleep) print(f"sent UMAS subfunc {hex(sub)} to {args.dst}:502")
6.测试规则(9004121-9004123)
1.主机B监听502 nc -lk -p 502 >/dev/null 2.主机A发送请求 ''' python umas_modbus_20_21_29.py --dst 10.10.10.2 --subfunc 0x20 # 9004121 python umas_modbus_20_21_29.py --dst 10.10.10.2 --subfunc 0x21 # 9004122 python umas_modbus_20_21_29.py --dst 10.10.10.2 --subfunc 0x29 # 9004123 ''' import socket import struct import time import argparse from socket import IPPROTO_TCP, TCP_NODELAY def mbap(tid: int, func: int, extra: bytes, unit: int = 1) -> bytes: pid = 0 length = 1 + 1 + len(extra) # unit + func + extra return struct.pack(">HHHB", tid, pid, length, unit) + bytes([func]) + extra def send_subfunc(dst_ip: str, subfunc: int, port: int = 502, sleep_s: float = 0.3): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) # 降低粘包概率 s.connect((dst_ip, port)) session_key = 0x11 # 1) 先发送 CTX 包:确保 9004114 命中并 set flowbit pkt_ctx = mbap(0x2001, 0x5A, bytes([session_key, 0x00, 0x00])) s.sendall(pkt_ctx) time.sleep(sleep_s) # 2) 发送目标 UMAS 子功能包:offset9 = subfunc # 额外补一些字节,让长度更像真实请求(不影响 offset 命中) extra = bytes([session_key, subfunc]) + b"\x00\x01\x00\x02\x00\x03" pkt = mbap(0x2002, 0x5A, extra) s.sendall(pkt) time.sleep(sleep_s) s.close() if __name__ == "__main__": ap = argparse.ArgumentParser() ap.add_argument("--dst", required=True, help="Server IP (10.10.10.2)") ap.add_argument("--subfunc", required=True, help="UMAS subfunc hex: 0x20 / 0x21 / 0x29") ap.add_argument("--sleep", type=float, default=0.3) args = ap.parse_args() sub = int(args.subfunc, 16) send_subfunc(args.dst, sub, sleep_s=args.sleep) print(f"sent UMAS subfunc {hex(sub)}")
7.测试规则(9004124-9004126)
1.主机B开启502服务 nc -lk -p 502 >/dev/null 2.主机A发送请求 import socket import struct import time from socket import IPPROTO_TCP, TCP_NODELAY DST = ("10.10.10.2", 502) def mbap(tid: int, unit: int, func: int, pdu: bytes) -> bytes: # MBAP: TID(2) PID(2=0) LEN(2) UNIT(1) + FUNC(1) + PDU pid = 0x0000 length = 1 + 1 + len(pdu) # unit + func + pdu return struct.pack(">HHHB", tid, pid, length, unit) + bytes([func]) + pdu def send_one(payload: bytes): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) # 减少粘包 s.connect(DST) s.sendall(payload) time.sleep(0.2) s.close() # 0x05 Write Single Coil: addr(2) + value(2) (0xFF00=ON, 0x0000=OFF) p05 = mbap(0x1234, 0x01, 0x05, struct.pack(">HH", 0x0001, 0xFF00)) # 0x0F Write Multiple Coils: start(2) qty(2) bytecount(1) values(n) # 写 8 个线圈 -> bytecount=1 -> values=0xFF (8 bits set) p0f = mbap(0x1235, 0x01, 0x0F, struct.pack( ">HHB", 0x0001, 0x0008, 0x01) + b"\xFF") # 0x06 Write Single Register: addr(2) + value(2) p06 = mbap(0x1236, 0x01, 0x06, struct.pack(">HH", 0x0001, 0x1234)) send_one(p05) # 触发 9004124 time.sleep(1) send_one(p0f) # 触发 9004125 time.sleep(1) send_one(p06) # 触发 9004126 print("sent 0x05 / 0x0F / 0x06 requests")
8.测试规则(9004128-9004134)
1.主机B开启2308监听 nc -lk -p 2308 >/dev/null 2.主机A发送请求至2308端口 import socket import struct import time DST = ("10.10.10.2", 2308) def send(pkt): s = socket.socket() s.connect(DST) s.sendall(pkt) time.sleep(0.2) s.close() # 选择一种 rel+23 类型:00 01 03 # 构造:type(3) + padding(23-3) + len(4,little) + filler def pkt_rel23(msg3=b"\x00\x01\x03", L=0x1200): pad = b"\x00"*(23-3) return msg3 + pad + struct.pack("<I", L) + b"A"*50 # 选择一种 rel+3 类型:00 04 02 # 构造:type(3) + len(4,little) + filler def pkt_rel3(msg3=b"\x00\x04\x02", L=0x1200): return msg3 + struct.pack("<I", L) + b"B"*50 # 先触发 CTX(任意家族类型即可) send(b"\x00\x01\x02" + b"\x00"*20) # 再触发 rel+23 组(9004129/30/31,看 L 大小) send(pkt_rel23(L=0x0500)) # >0x410 触发 9004129 send(pkt_rel23(L=0x2000)) # >0x1000 触发 9004130 send(pkt_rel23(L=0x5000)) # >0x4000 触发 9004131 # 再触发 rel+3 组(9004132/33) send(pkt_rel3(L=0x0500)) # >0x410 触发 9004132 send(pkt_rel3(L=0x2000)) # >0x1000 触发 9004133 print("sent")

浙公网安备 33010602011771号