代码之家  ›  专栏  ›  技术社区  ›  bulkmoustache

Wireshark未收到Scapy Modbus响应

  •  0
  • bulkmoustache  · 技术社区  · 12 年前

    我在运行Wireshark的远程PLC上运行下面的代码示例。为什么我只能得到查询(我也应该得到响应)?似乎PLC发送了响应,因为Scapy的输出显示 Received 1 packets, got 1 answers, remaining 0 packets .

    你知道为什么会这样吗?

    我还使用Scapy的sniff()函数执行了嗅探,但结果是相同的(只获取查询)。

    #! /usr/bin/env python
    
    import logging
    logging.getLogger("scapy").setLevel(1)
    
    from scapy import *
    from modLib import *
    
    # IP for all transmissions
    ip = IP(dst="192.168.10.131")
    
    # Sets up the session with a TCP three-way handshake
    # Send the syn, receive the syn/ack
    tcp = TCP( flags = 'S', window = 65535, sport = RandShort(), dport = 502, options = [('MSS', 1360 ), ('NOP', 1), ('NOP', 1), ('SAckOK', '')])
    synAck = sr1 ( ip / tcp )
    
    # Send the ack
    tcp.flags = 'A'
    tcp.sport = synAck[TCP].dport
    tcp.seq = synAck[TCP].ack
    tcp.ack = synAck[TCP].seq + 1
    tcp.options = ''
    send( ip / tcp )
    
    # Creates and sends the Modbus Read Holding Registers command packet
    # Send the ack/push i.e. the request, receive the data i.e. the response
    tcp.flags = 'AP'
    adu = ModbusADU()
    pdu = ModbusPDU03()
    adu = adu / pdu
    tcp = tcp / adu
    data = sr1(( ip / tcp ), timeout = 2)
    data.show()
    
    # Acknowledges the response
    # Ack the data response
    # TODO: note, the 17 below should be replaced with a read packet length method...
    tcp.flags = 'A'
    tcp.seq = data[TCP].ack
    tcp.ack = data[TCP] + 17
    tcp.payload = ''
    finAck = sr1( ip / tcp )
    
    1 回复  |  直到 12 年前
        1
  •  0
  •   Pierre    12 年前

    首先,您的代码中有一个bug(在原始版本中存在 http://www.digitalbond.com/scadapedia/security-controls/scapy-modbus-extensions/ ),您需要添加 .seq 在那里: tcp.ack = data[TCP].seq + 17 .

    正如评论中所说,你可以写 tcp.ack = data[TCP].seq + len(data[TCP].payload) .

    无论如何,对于您尝试做的那种事情,TCP堆栈的工作通常是无用的。

    我会这样做:

    from scapy import *
    from modLib import *
    import socket
    
    sock = socket.socket()
    sock.connect(("192.168.10.131", 502))
    s = StreamSocket(sock, basecls=ModbusADU)
    
    ans, unans = s.sr(ModbusADU()/ModbusPDU03())
    ans.show()
    

    这样做更好吗?