0

I am trying to extract the Destination & Source MACs from an ethernet frame using python and Linux. I used the code below to print the bytes of a frame.

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
packet = s.recvfrom(65565)
data = packet[0]
for byte in range(0, len(data)):
    print(data[byte])

How can I convert the byes corresponding to the Destination Mac (or the ones corresponding to the Source Mac) to an actual adress?

Alex Lazar
  • 103
  • 9
  • What kind of socket is `s`, can you share the code you used to create it? – Grismar Jan 10 '23 at 01:56
  • How is your question different from [this one](https://stackoverflow.com/questions/1722254/finding-the-mac-address-of-the-sender-of-a-multicast-udp-message-in-python)? It seems like you're trying to do the impossible. – Grismar Jan 10 '23 at 01:58
  • Yes depending on socket type and what OS your on you can in theory listen for ethernet frames. After that you just need to grab the bytes from the frame based on the frames structure. Which for ethernet is predefined. https://en.wikipedia.org/wiki/Ethernet_frame – TeddyBearSuicide Jan 10 '23 at 02:08
  • @Grismar I have made some edits to the question to provide the answer for your question. I have came across the question from above and the wikipedia page. What I did not understand and thought should be on stack overflow is the exact formatting, how the bytes translate to the MAC address, and maybe a snippet of code for this task. – Alex Lazar Jan 10 '23 at 09:35
  • @Grismar it shouldn't be impossible to decode this. Many packet sniffers use socket.recvfrom() with RAW sockets in Linux and in the end decode the information in the Ethernet frame. – Alex Lazar Jan 10 '23 at 09:40
  • I have managed to extract the addresses. `import json import socket import struct import sys s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP) data, addr = s.recvfrom(65565) dmac = ":".join(map(str, struct.unpack("BBBBBB", data[:6]))) smac = ":".join(map(str, struct.unpack("BBBBBB", data[6:12]))) ethertype = data[12:14] print(dmac, smac, ethertype) ` – Alex Lazar Jan 10 '23 at 10:17

1 Answers1

0

The data you receive through the socket does typically not include what you're looking for. An ethernet frame is a data link layer protocol unit, while the data received on the socket is the payload of the transport layer, with the network layer inbetween.

More info on the layers here: https://en.wikipedia.org/wiki/Internet_protocol_suite

Generally, this can't be done: Finding the MAC address of the sender of a multicast UDP message in Python?

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • This is correct if you create a IP based socket. But on linux you can create a lower level socket and listen to ethernet packets. Or use a third party library to allow low level access on windows. This is a link for ethernet socket on linux https://stackoverflow.com/questions/57133295/how-can-i-listen-for-raw-ethernet-frames-in-vanilla-python-3 – TeddyBearSuicide Jan 10 '23 at 02:06
  • Thanks for the comment, that's useful - it does underline the need for OP to share how they created their socket object `s` though, since that's not clear from the question (and perhaps the cause for their issues) – Grismar Jan 10 '23 at 07:09
  • @TeddyBearSuicide Indeed, that is correct. I am using Linux for this task and the sockets are of type RAW. – Alex Lazar Jan 10 '23 at 09:37