1

I am doing a simple raw packet sniffer in Python 3, and I encountered the following problem when I try to unpack the received socket data:

dest_mac, src_mac, proto = struct.unpack('!6s6s2s', ethHeader)
TypeError: a bytes-like object is required, not 'tuple'

This is the code I currently have, the error being in the ethernet_frame, after the socket receives some response.

import socket
import struct
import binascii
import textwrap

def main():
    # Get host
    host = socket.gethostbyname(socket.gethostname())
    print('IP: {}'.format(host))

    # Create a raw socket and bind it
    sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))

    while True:
        # Recive data
        raw_data = sock.recvfrom(2048)

        ethHeader = raw_data[0:14]
        ipHeader = raw_data[14:34]
        tcpHeader = raw_data[34:38]

        # Unpack data
        dest_mac = ethernet_frame(ethHeader)

        print('\nEthernet Frame:')
        print("Destination MAC: {}".format(dest_mac))

# Unpack ethernet frame
def ethernet_frame(data):
    dest_mac, src_mac, proto = struct.unpack('!6s6s2s', ethHeader)
    return dest_mac

And this is how the ethHeader looks like:

(b'\x00\x00\x00\x00\x...,"seq":8}', ('lo', 2048, 4, 772, b'\x00\x00\x00\x00\x00\x00'))

From what I could find in the search for a solution most of the socket codes are developed in python 2, where the struct.unpack seemingly works, and it also works unpacking ethernet and ip franmes for a tcp connection.

How could I process my ethernet header data if unpacking doesn't work?

EDIT: Full error text

IP: 127.0.1.1
Traceback (most recent call last):
  File "/home/myuser/Desktop/WIFI_ANALYZER/wifianalyzer.py", line 45, in <module>
    main()
  File "/home/myuser/Desktop/WIFI_ANALYZER/wifianalyzer.py", line 23, in main
    dest_mac = ethernet_frame(ethHeader)
  File "/home/myuser/Desktop/WIFI_ANALYZER/wifianalyzer.py", line 30, in ethernet_frame
    dest_mac, src_mac, proto = struct.unpack('!6s6s2s', ethHeader)
TypeError: a bytes-like object is required, not 'tuple'
Artyomska
  • 1,309
  • 5
  • 26
  • 53

1 Answers1

2

After some more research I Found a solution. Looks like raw_data is a tuple, and the actual byte array that I needed for decoding is on position [0] of raw_data.

So simply changing

ethHeader = raw_data[0:14]
ipHeader = raw_data[14:34]
tcpHeader = raw_data[34:38]

to

ethHeader = raw_data[0][0:14]
ipHeader = raw_data[0][14:34]
tcpHeader = raw_data[0][34:38]

did the trick.

Artyomska
  • 1,309
  • 5
  • 26
  • 53