kbandla / dpkt

fast, simple packet creation / parsing, with definitions for the basic TCP/IP protocols
Other
1.09k stars 270 forks source link

Error while unpacking a well formed pcap file #472

Closed tinchoa closed 4 years ago

tinchoa commented 4 years ago

Hello, I created a simple program to read a pcap file:

    import dpkt
    import sys
    if __name__ == "__main__":
         FILE = sys.argv[1] 
         arq = open(FILE, 'rb')
         pcap = dpkt.pcap.Reader(arq)
         for ts, data in pcap:
            eth = dpkt.ethernet.Ethernet(data)
            print(eth)

The pcap file that I was trying to read is the following: https://mcfp.felk.cvut.cz/publicDatasets/CTU-Normal-20/2017-04-30_win-normal.pcap

And here is the traceback of the error:

Traceback (most recent call last): File "/usr/local/lib/python3.7/dist-packages/dpkt/dpkt.py", line 89, in init self.unpack(args[0]) File "/usr/local/lib/python3.7/dist-packages/dpkt/ethernet.py", line 133, in unpack dpkt.Packet.unpack(self, buf) File "/usr/local/lib/python3.7/dist-packages/dpkt/dpkt.py", line 171, in unpack struct.unpack(self.hdr_fmt, buf[:self.hdr_len])): struct.error: unpack requires a buffer of 14 bytes

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "feature-extractor.py", line 14, in eth = dpkt.ethernet.Ethernet(data) File "/usr/local/lib/python3.7/dist-packages/dpkt/ethernet.py", line 79, in init dpkt.Packet.init(self, *args, **kwargs) File "/usr/local/lib/python3.7/dist-packages/dpkt/dpkt.py", line 92, in init raise NeedData dpkt.dpkt.NeedData

I've tried to modify the unpack function on line 168 of dpkt.py with this code, but it did not work:

    def unpack(self, buf):
        """Unpack packet header fields from buf, and set self.data."""
        if (len(buf[:self.__hdr_len__])) < 14:
                aux = b'\x00\0\0\0\0\0\0\0\0\0\0\0\0\0'
        else:
        aux = buf[:self.__hdr_len__]       
        for k, v in compat_izip(self.__hdr_fields__,
                                struct.unpack(self.__hdr_fmt__, aux)):
            setattr(self, k, v)
        self.data = buf[self.__hdr_len__:]
obormot commented 4 years ago

I've looked at the pcap file, the crash happens at the very 1st packet - it's just 4 bytes, clearly not a valid Ethernet packet. The pcap file is likely truncated at the start. After skipping the 1st packet dpkt processes the rest of the file just fine. You could rewrite the handling loop to be resilient to truncated packets. Dpkt is doing the right thing.. closing.