2

I'm trying to send raw Ethernet frames over wifi using Python 2.7 (under Ubuntu). My code looks like this

from socket import *

data = [0x24, 0x95, 0x04, 0x8a, 0x6c, 0xd0, 0x00, 0x21, 0x6a, 0x72, 0xd4, 0x80, 0x08, 0x00, 0x45, 0x00,
0x00, 0x54, 0xe3, 0x5a, 0x40, 0x00, 0x40, 0x01, 0xd3, 0x9b, 0xc0, 0xa8, 0x01, 0x61, 0xc0, 0xa8,
0x01, 0x01, 0x08, 0x00, 0xef, 0xae, 0x0e, 0x90, 0x00, 0x01, 0x75, 0x1d, 0xca, 0x5b, 0xcb, 0x43,
0x04, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
0x36, 0x37]

byteSequence = b"".join(map(chr, data))

s = socket(AF_PACKET, SOCK_RAW)
s.bind(("wls1", 0))
s.send(byteSequence)

The variable data should represent a valid Ethernet frame representing a ping request. When I run this script and inspect the frame in Wireshark, I see

0000 | 24 95 04 8a 6c d0 00 21  6a 72 d4 80 08 00 45 00
0010 | 00 54 e3 5a 40 00 40 01  d3 9b c0 a8 01 61 c0 a8
0020 | 01 01 08 00 ef ae 0e 90  00 01 75 1d ca 5b cb 43
0030 | 04 00 08 09 0a 0b 0c 0d  0e 0f 10 11 12 13 14 15
0040 | 16 17 18 19 1a 1b 1c 1d  1e 1f 20 21 22 23 24 25
0050 | 26 27 28 29 2a 2b 2c 2d  2e 2f 30 31 32 33 34 35
0060 | 36 37 2e 50 61 6e 65 6c  00 00 00 00 00 00 83 00

As you can see, this is the data I wanted to send, but with 14 extra bytes appending at the end (which converted to ASCII read .Panel ........).

The ping seems to be valid nonetheless, since I get a reply back from my router.

This seems to be a Python issue and not a Wireshark issue, since pings sent from the terminal with the ping program don't have this extra data.

What's going on?

martineau
  • 119,623
  • 25
  • 170
  • 301
Jack M
  • 4,769
  • 6
  • 43
  • 67
  • Have you checked that bytesequence is the expected data? – DisappointedByUnaccountableMod Oct 19 '18 at 21:05
  • @barny Yup - `print(hex(ord(byteSequence[-1])))` prints `0x37`. – Jack M Oct 19 '18 at 21:54
  • If Python is sending the right thing, is the packet somehow being padded up to a multiple of 16 bytes? What happens when you make bytesequence a few bytes longer? I.e. it could be a stack issue. – DisappointedByUnaccountableMod Oct 19 '18 at 23:03
  • @barny I was sure you would be right, but no! Adding a few extra bytes to the end of `data`, Wireshark again shows the intended data but with 14 extra bytes - so it's not just padding to be 16-byte aligned. For some reason it's adding 14 bytes every time. – Jack M Oct 19 '18 at 23:23
  • I would appreciate if somebody could even just try this on their own machine to see if they can reproduce the issue. – Jack M Oct 19 '18 at 23:24
  • Yes. Happening to me too. And strace confirms that the right bytes are being sent. I also wrote a C program: same result. I think you've found a bug in the `AF_PACKET / SOCK_RAW` code. I changed the C program to use `SOCK_PACKET` (an old linux thing that is now deprecated), and with that, I can successfully send without getting the trailer bytes added. It's my belief that the linux `SOCK_RAW` code is incorrectly adding `dev->hard_header_len` bytes (14) to the packet. I think that should only be happening for `SOCK_DGRAM` packets (because the kernel will add an Ethernet header for those). – Gil Hamilton Oct 19 '18 at 23:54
  • 1
    One liner to demonstrate with scapy package installed: `sudo ./python3 -c "from scapy.all import *; pkt = Ether(dst='24:95:04:8a:6c:d0', src='00:21:61:72:d4:80') / IP(src='192.168.1.97', dst='192.168.1.1') / ICMP(type='echo-request', code=0) / bytes(x&0xff for x in range(56)); sendp(pkt, iface='eth2')"` – Gil Hamilton Oct 19 '18 at 23:58
  • @GilHamilton Is there an issue tracker where this could be reported? (you're saying this is a bug in the Linux code, right?) – Jack M Oct 20 '18 at 08:11
  • @JackM I looked at this some more, and I cannot reproduce it on another system. The system where I *can* repro it is ubuntu with kernel version 4.4. I have three other ubuntu systems with 4.13 and 4.15 (twice) and cannot repro the issue on any of them. Perhaps it's already been fixed? In that case, you would just need to update your kernel. – Gil Hamilton Oct 22 '18 at 15:40
  • @GilHamilton My kernel version is 4.15. – Jack M Oct 22 '18 at 16:43
  • I can't reproduce either on 4.15 and 4.16. – pchaigno Oct 22 '18 at 20:57
  • Just as a point of information, I upgraded the 4.4 machine where I could repro this to 4.15 and I no longer see the extra bytes. – Gil Hamilton Oct 26 '18 at 16:58
  • So I was right: it’s not a Python issue, it’s lower-level in the stack... – DisappointedByUnaccountableMod Oct 29 '18 at 22:36

0 Answers0