Amit_A
Amit_A

Reputation: 11

trying to build a MODBUS packet with scapy

i'm trying to build a MODBUS packet with scapy, but Wireshark can't recognize it. i mean, the MODBUS interpreted as the TCP data.

here is the python code of Scapy:

from scapy.all import *


class Modbus(Packet):
    name = "Modbus/tcp"
    fields_desc = [ ShortField("Transaction Identifier", 1),
                    ShortField("Protocol Identifier", 0),
                    ShortField("Length", 5),
                    XByteField("Unit Identifier",0),
                    ]

def make_test():
    pkt = TCP(sport=502, dport=502)
    return Ether()/IP(src="5.5.5.101",dst="5.5.5.100")/pkt/Modbus()


while True:
    send(make_test())

someone has an idea how to fix it?

Upvotes: 1

Views: 3987

Answers (2)

Myrat
Myrat

Reputation: 19

There is no 3-way TCP handshake in your code, which means no communication channel has been established between the hosts. To solve the problem socket needs to be created.

Here is my code, might be helpful for others.

from scapy.all import *
import time

# Modbus ADU
class ModbusTCP(Packet):
    name = "Modbus/TCP"
    fields_desc = [ ShortField("Transaction Identifier", 1),
                    ShortField("Protocol Identifier", 0),
                    ShortField("Length", 6),
                    XByteField("Unit Identifier", 247),
                    ]

# Modbus PDU
class Modbus(Packet):
    name = "Modbus"
    fields_desc = [ XByteField("Function Code", 4),
                    ShortField("Reference Number", 1),
                    ShortField("Word Count", 2),
                    ]

# Create a socket and connect
s = socket.socket()
s.connect(("192.168.95.10", 502))   # IP and port
ss = StreamSocket(s, Raw)

while True:
    try:
        # Encapsulate modbus inside the raw data, then send and receive
        # Anything can be done with response
        ss.sr1(Raw(ModbusTCP()/Modbus()))
        time.sleep(1)
    except KeyboardInterrupt:
        break

References:

Upvotes: 1

Medusa
Medusa

Reputation: 613

I ran the same code with 2 changes and Wireshark recognized it as Modbus:

First, as you are sending empty packets (n=0), the default value of the length field has to be 2, not 5 (n+2 according to Wikipedia.

Second, you're missing the field Function Code.

So, in the end my fields_desc looks like this:

fields_desc = [ ShortField("Transaction Identifier", 1),
                    ShortField("Protocol Identifier", 0),
                    ShortField("Length", 2),
                    XByteField("Unit Identifier",0),
                    ByteField("Function Code", 0)
                    ]

Wireshark complains because 0 is not actually a valid function code, but it correctly interprets it as modbus.

Upvotes: 1

Related Questions