0

Context -- I have been running python automation scripts for Common Industrial Protocol using scapy as the means to create packets in this format.

There were no problems running the scripts in a python 3.4 environment, but when trying to migrate to a new environment, basically running the same scripts in a slightly upgraded environment using python 3.6 I get the error below.

2020-08-26T12:14:02: %EASYPY-ERROR: Caught error during task execution: Task-2: id_cip_test1.py
2020-08-26T12:14:02: %EASYPY-ERROR: Traceback (most recent call last):
2020-08-26T12:14:02: %EASYPY-ERROR:   File "/users/alpeck/pyats3.6/lib/python3.6/site-packages/pyats/aetest/main.py", line 187, in run
2020-08-26T12:14:02: %EASYPY-ERROR:     testscript = TestScript.from_source(self.testable, self.reporter)
2020-08-26T12:14:02: %EASYPY-ERROR:   File "/users/alpeck/pyats3.6/lib/python3.6/site-packages/pyats/aetest/script.py", line 68, in from_source
2020-08-26T12:14:02: %EASYPY-ERROR:     module = loader.load(testable)
2020-08-26T12:14:02: %EASYPY-ERROR:   File "/users/alpeck/pyats3.6/lib/python3.6/site-packages/pyats/utils/import_utils/flex.py", line 64, in load
2020-08-26T12:14:02: %EASYPY-ERROR:     module = self.load_module_from_file(obj)
2020-08-26T12:14:02: %EASYPY-ERROR:   File "/users/alpeck/pyats3.6/lib/python3.6/site-packages/pyats/utils/import_utils/flex.py", line 117, in load_module_from_file
2020-08-26T12:14:02: %EASYPY-ERROR:     module = loader.load_module()
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap_external>", line 399, in _check_name_wrapper
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap_external>", line 823, in load_module
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap_external>", line 682, in load_module
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap>", line 265, in _load_module_shim
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap>", line 684, in _load
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap_external>", line 678, in exec_module
2020-08-26T12:14:02: %EASYPY-ERROR:   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
2020-08-26T12:14:02: %EASYPY-ERROR:   File "/users/alpeck/pyats/Automation/CIP_Automation/cip_sanity/17_4/petra/id_cip_test1.py", line 40, in <module>
2020-08-26T12:14:02: %EASYPY-ERROR:     client = plc.PLCClient(str(cip_interface.connections['a'].ip))
2020-08-26T12:14:02: %EASYPY-ERROR:   File "/users/alpeck/pyats3.6/lib/python3.6/site-packages/plc.py", line 65, in __init__
2020-08-26T12:14:02: %EASYPY-ERROR:     self.sock.send( bytes(sessionpkt,'utf-8'))
2020-08-26T12:14:02: %EASYPY-ERROR: TypeError: encoding without a string argument

This error points to a few scripts, but I have narrowed this issue down to clarify this problem further.

File "/users/alpeck/pyats3.6/lib/python3.6/site-packages/plc.py", line 65, in __init__
     self.sock.send( bytes(sessionpkt,'utf-8'))

-- This traceback points to the plc.py block below --

class PLCClient(object):
    """Handle all the state of an Ethernet/IP session with a PLC"""

    def __init__(self, plc_addr, plc_port=44818):
        if not NO_NETWORK:
            try:
                self.sock = socket.create_connection((plc_addr, plc_port))
                print('Printing self sock')             --> Printing self sock
                print(self.sock)                    --> <socket.socket fd=17, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('64.101.134.34', 15065), raddr=('10.89.157.229', 44818)>
            except socket.error as exc:
                logger.warn("socket error: %s", exc)
                logger.warn("Continuing without sending anything")
                self.sock = None
        else:
            self.sock = None
        self.session_id = 0
        self.enip_connid = 0
        self.sequence = 1



        # Open an Ethernet/IP session
        sessionpkt = ENIP_TCP() / ENIP_RegisterSession()
        print('Printing session packet')        --> Printing session packet
        print(sessionpkt)               --> b'e\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00'
        if self.sock is not None:
            self.sock.send( bytes(sessionpkt,'utf-8'))
            reply_pkt = self.recv_enippkt()
            self.session_id = reply_pkt.session



The problem is highlighted above, there is either no data or corrupt data in the session packet being shown.

sessionpkt = ENIP_TCP() / ENIP_RegisterSession()

The session packet is created in another directory shown below.

class ENIP_RegisterSession(scapy_all.Packet):
    name = "ENIP_RegisterSession"
    fields_desc = [
        scapy_all.LEShortField("protocol_version", 1),
        scapy_all.LEShortField("options", 0),
    ]



class ENIP_TCP(scapy_all.Packet):
    """Ethernet/IP packet over TCP"""
    name = "ENIP_TCP"
    fields_desc = [
        scapy_all.LEShortEnumField("command_id", None, {
            0x0004: "ListServices",
            0x0063: "ListIdentity",
            0x0064: "ListInterfaces",
            0x0065: "RegisterSession",
            0x0066: "UnregisterSession",
            0x006f: "SendRRData",  # Send Request/Reply data
            0x0070: "SendUnitData",
        }),
        scapy_all.LEShortField("length", None),
        scapy_all.LEIntField("session", 0),
        scapy_all.LEIntEnumField("status", 0, {0: "success"}),
        scapy_all.LELongField("sender_context", 0),
        scapy_all.LEIntField("options", 0),
    ]


If there is anything else that would help to solve this error I can give further information.

  • It looks like `session_pkt` is already a `bytes` instance, so there is no need to try to encode it. – snakecharmerb Aug 28 '20 at 15:11
  • Thanks for responding @snakecharmerb , but when I run this same code after taking out the bytes encoding it gives me this error instead::TypeError: a bytes-like object is required, not 'ENIP_TCP' – peckzenit Aug 31 '20 at 18:51
  • Ok, so it seems `seesionpkt` is actually an instance of `ENIP_TCP`. Calling `bytes` on such an object won't work, because it isn't a string. Maybe this helps https://stackoverflow.com/questions/34791583/converting-a-sniffed-scapy-packet-to-bytes? Scapy isn't really my beat I'm afraid. – snakecharmerb Aug 31 '20 at 19:00
  • Given that you're using Python2, `str(sessionpkt)` might be worth a try. – snakecharmerb Aug 31 '20 at 19:01
  • I just tried running the code with your suggested edit and oddly enough I get this error TypeError: a bytes-like object is required, not 'str' , But thanks for trying I will try the link you provided. – peckzenit Aug 31 '20 at 19:36

0 Answers0