Alessandro Lodi
Alessandro Lodi

Reputation: 553

Raw socket packet sniffer in Python 3.6 on Windows

I am trying to sniff packets but i am getting strange output and i don't understand the reason..
So that's my code please help me
(I'm using Python 3.6 on Windows 8.1)

Code:

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
    conn = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
    conn.bind((host, 0))

    # Include IP headers
    conn.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
    # Enable promiscuous mode
    conn.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

    while True:
        # Recive data
        raw_data, addr = conn.recvfrom(65536)

        # Unpack data
        dest_mac, src_mac, eth_proto, data = ethernet_frame(raw_data)

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

# Unpack ethernet frame
def ethernet_frame(data):
    dest_mac, src_mac, proto = struct.unpack('!6s6s2s', data[:14])
    return get_mac_addr(dest_mac), get_mac_addr(src_mac), get_protocol(proto), data[14:]

# Return formatted MAC address AA:BB:CC:DD:EE:FF
def get_mac_addr(bytes_addr):
    bytes_str = map('{:02x}'.format, bytes_addr)
    mac_address = ':'.join(bytes_str).upper()
    return mac_address

# Return formatted protocol ABCD
def get_protocol(bytes_proto):
    bytes_str = map('{:02x}'.format, bytes_proto)
    protocol = ''.join(bytes_str).upper()
    return protocol

main()

From this code i get this output:

IP: 192.168.1.12

Ethernet Frame:
Destination MAC: 45:00:00:43:00:00
Source MAC: 40:00:2C:11:48:D3
Protocol: 4266

Ethernet Frame:
Destination MAC: 45:00:00:42:11:E7
Source MAC: 00:00:80:11:00:00
Protocol: C0A8

Ethernet Frame:
Destination MAC: 45:00:00:33:04:D6
Source MAC: 00:00:80:11:00:00
Protocol: C0A8

.
.
.

According to EtherType list this protocols don't exist and analysing my traffic with Wireshark i am sure that this MACs don't exist in my LAN

So I'm definitely doing something wrong but I do not understand what
Thanks in advance

Upvotes: 2

Views: 13541

Answers (2)

Alessandro Lodi
Alessandro Lodi

Reputation: 553

Ok thanks to selbi i understand the problem, thank you very much
But to catch Ethernet header with Python in windows you have to use:

1. PyPCap

2. Dpkt

  • To install dpkt just open cmd as admin and type:

    py -2 -m pip install dpkt

Here references of Python Docs

3. Python 2.7

But you need to install Python 3.4> to get pip

And finally that's the code:

#!/usr/bin/env python

import getopt, sys
import dpkt, pcap
import socket
import struct
import binascii
import textwrap

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

    name = None            
    pc = pcap.pcap(name)
    decode = { pcap.DLT_LOOP:dpkt.loopback.Loopback,
               pcap.DLT_NULL:dpkt.loopback.Loopback,
               pcap.DLT_EN10MB:dpkt.ethernet.Ethernet }[pc.datalink()]
    try:
        print 'listening on %s: %s' % (pc.name, pc.filter)
        for ts, pkt in pc:
            pkt = str(decode(pkt))
            dest_mac, src_mac, eth_proto, data = ethernet_frame(pkt)

            print '\nEthernet Frame:'
            print "Destination MAC: {}".format(dest_mac)
            print "Source: {}".format(src_mac)
            print "Protocol: {}".format(eth_proto)
    except KeyboardInterrupt:
        nrecv, ndrop, nifdrop = pc.stats()
        print '\n%d packets received by filter' % nrecv
        print '%d packets dropped by kernel' % ndrop

# Unpack ethernet frame
def ethernet_frame(data):
    dest_mac, src_mac, proto = struct.unpack('!6s6s2s', data[:14])
    return binascii.hexlify(dest_mac), binascii.hexlify(src_mac), binascii.hexlify(proto), data[14:]

if __name__ == '__main__':
    main()

Output:

Ethernet Frame:
Destination MAC: 5404a6f2740c <- My NIC MAC
Source: 6459f81dc690
Protocol: 0800 <- Right protocol

Ethernet Frame:
Destination MAC: 6459f81dc690
Source: 5404a6f2740c
Protocol: 0800

Ethernet Frame:
Destination MAC: 5404a6f2740c
Source: 6459f81dc690
Protocol: 0800

I hope you enjoy thanks again selbie

(Sorry i can't put more links cause of my reputation)

Upvotes: 5

selbie
selbie

Reputation: 104569

The hint is that all your Destination Mac addresses start with 0x45. That's the first byte of the IP header. So your code is getting all the IP packets, but not the MAC header for those frames.

Upvotes: 2

Related Questions