kbandla / dpkt

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

Possible endianess problem in radiotap header parsing (and others?) #132

Closed kbandla closed 3 years ago

kbandla commented 9 years ago

From hso...@gmail.com on April 15, 2013 09:13:17

What steps will reproduce the problem? 1. Use dpkt to parse packets captures with pypcap using airmon-ng on a wireless interface.

  1. When using the radiotap.Radiotap class to parse the packet, the length seems to be read incorrectly, using native byte order rather than network order. What is the expected output? What do you see instead? Packet starts with 0x00 0x00 0x12 0x00, so packet length field should be 18 (0x0012), but instead is read as 4608 (0x1200). What version of the product are you using? On what operating system? dpkt version 1.7. running on Ubuntu 13.04. Please provide any additional information below. Seems like the issue is in radiotap.py at line 75: ('length', 'H', 0),

which should read something like: ('length', '>H', 0),

Original issue: http://code.google.com/p/dpkt/issues/detail?id=106

kbandla commented 9 years ago

From hso...@gmail.com on April 15, 2013 06:49:46

Ok. Still seems to be a bug, but I mixed up the endianess. Radiotap is little-endian, so it's the fact that dpkt.Packet.unpack uses big endian that seems to be the problem.

kbandla commented 9 years ago

From hso...@gmail.com on April 15, 2013 07:39:21

Currently fixed by me (on r88 version) by adding the line: byte_order = "<" at line 69 in radiotap.py

kbandla commented 9 years ago

From dick.mar...@gmail.com on October 15, 2014 11:28:03

I have the same issue when using linux 3.16.4-200.fc20.x86_64 and pypcap.

using the following script: import dpkt, pcap pc = pcap.pcap('mon0') while 1: p = pc.next() if pc.datalink() == 127: ts, pkt = p tap = dpkt.radiotap.Radiotap(pkt)

tap.data is always empty and tap.length is 4608.

Setting byte_order in Radiotap fixes the issue for me. Please fix.

saylenty commented 9 years ago

I think it can be fixed like this:

if sys.byteorder == 'little': __byte_order__ = '<'
gendx commented 8 years ago

I had the same problem with the gzip parser, the __byte_order__ parameter is the correct way to change endianess. No need to check for sys.byteorder however, because '<' and '>' are cross-platform for struct.unpack (see https://docs.python.org/2/library/struct.html#byte-order-size-and-alignment).

Note that if the endianess changes inside the same packet (unlikely), I guess that you need to set __byte_order__ = '' and then explicitly prepend < or > for each parameter (see https://github.com/kbandla/dpkt/blob/master/dpkt/dpkt.py#L37).

stamparm commented 5 years ago

Reference: http://web.mit.edu/freebsd/head/contrib/wpa/src/utils/radiotap.h

/* The radio capture header precedes the 802.11 header.
 * All data in the header is little endian on all platforms.
 */

Example:

>>> packet.channel.freq  # should be 2417 for BG channel 2 (Reference: http://niviuk.free.fr/wifi_band.php)
28937
>>> struct.unpack("<H", struct.pack(">H", packet.channel.freq))[0]  # default byte-order used in dpkt.Packet is Big-Endian (Reference: https://github.com/PaulMcMillan/dpkt/blob/master/dpkt/dpkt.py#L34)
2417

p.s. channel frequency (from upper example) properly decoded in Wireshark:

foobar

stamparm commented 5 years ago

Dirty patch (Note: switching to Little-Endian order inside dpkt.radiotap.Radiotap):

for name, value in dpkt.radiotap.Radiotap.__dict__.items():
    if isinstance(value, type):
        if issubclass(value, dpkt.Packet):
            class _(value):
                __byte_order__ = '<'

            setattr(dpkt.radiotap.Radiotap, name, _)
obormot commented 3 years ago

Fixed in https://github.com/kbandla/dpkt/pull/517