-1

I have working code for Linux, but on Windows I got unexpected result. Code:

import socket
import sys
from struct import unpack
import platform


def main():
    local_ip = socket.gethostbyname(socket.gethostname())
    print local_ip
    try:
        if platform.system() == 'Linux':
            s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,
                              socket.ntohs(0x0003))
        elif platform.system() == 'Windows':
            s = socket.socket(socket.AF_INET, socket.SOCK_RAW,
                              socket.IPPROTO_IP)
            s.bind((local_ip, 0))
            s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
            s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
        else:
            sys.exit()
    except socket.error as msg:
        print('Socket could not be created. Error Code : ' + str(
            msg[0]) + ' Message ' + msg[1])
        sys.exit()

    # receive a packet
    i = 0
    while i < 10:
        i += 1
        packet = s.recvfrom(65565)
        # packet string from tuple
        packet = packet[0]
        # parse ethernet header
        eth_length = 14
        eth_header = packet[:eth_length]
        eth = unpack('!6s6sH', eth_header)
        eth_protocol = socket.ntohs(eth[2])
        ip_header = packet[eth_length:20 + eth_length]
        # unpack header
        iph = unpack('!BBHHHBBH4s4s', ip_header)
        version_ihl = iph[0]
        version = version_ihl >> 4
        ihl = version_ihl & 0xF
        ttl = iph[5]
        protocol = iph[6]
        s_addr = socket.inet_ntoa(iph[8])
        d_addr = socket.inet_ntoa(iph[9])
        print 'Header protocol:', eth[2], 'Unpacked protocol:', eth_protocol
        print 'Version : ' + str(
            version) + ' IP Header Length : ' + str(
            ihl) + ' TTL : ' + str(
            ttl) + ' Protocol : ' + str(
            protocol) + ' Source Address : ' + str(
            s_addr) + ' Destination Address : ' + str(d_addr)


if __name__ == '__main__':
    main()

I took this as example

So, on Linux I'm getting expected data

127.0.1.1 Header protocol: 2048 Unpacked protocol: 8 Version : 4 IP Header Length : 5 TTL : 64 Protocol : 17 Source Address : 127.0.0.1 Destination Address : 127.0.0.53 Header protocol: 2048 Unpacked protocol: 8 Version : 4 IP Header Length : 5 TTL : 64 Protocol : 17 Source Address : 127.0.0.1 Destination Address : 127.0.0.53 Header protocol: 2048 Unpacked protocol: 8 Version : 4 IP Header Length : 5 TTL : 64 Protocol : 17 Source Address : 127.0.0.53 Destination Address : 127.0.0.1 Header protocol: 2048 Unpacked protocol: 8 Version : 4 IP Header Length : 5 TTL : 64 Protocol : 17 Source Address : 127.0.0.53 Destination Address : 127.0.0.1 Header protocol: 2048 Unpacked protocol: 8 Version : 4 IP Header Length : 5 TTL : 64 Protocol : 6 Source Address : 10.0.2.15 Destination Address : 5.196.61.211

But on Windows all fields are incorrect

10.0.2.15

Header protocol: 2560 Unpacked protocol: 10 Version : 0 IP Header Length : 2 TTL : 8 Protocol : 70 Source Address : 183.96.34.40 Destination Address : 36.2.80.16 Header protocol: 2560 Unpacked protocol: 10 Version : 0 IP Header Length : 2 TTL : 8 Protocol : 70 Source Address : 183.96.34.40 Destination Address : 36.2.80.16 Header protocol: 2560 Unpacked protocol: 10 Version : 0 IP Header Length : 2 TTL : 8 Protocol : 70 Source Address : 183.96.34.40 Destination Address : 36.3.80.16 Header protocol: 2560 Unpacked protocol: 10 Version : 0 IP Header Length : 2 TTL : 8 Protocol : 70 Source Address : 183.96.34.40 Destination Address : 36.3.80.16 Header protocol: 2560 Unpacked protocol: 10 Version : 0 IP Header Length : 2 TTL : 8 Protocol : 70 Source Address : 183.96.34.40 Destination Address : 36.3.80.17

How can I get the correct data?

PS. I know about pypcap, scapy and other, but I need raw data parser without any third-party libs. If it possible, of course.

PPS. I looked here all similar topics, but solution still not found

Many thnx

stahh
  • 149
  • 5

1 Answers1

2

On Linux you are using SOCK_RAW with AF_PACKET to sniff at layer 2, which means that you first get the layer 2 information (ethernet) and then layer 3 information (IP). On Windows you are using AF_INET to sniff at layer 3 which means that you don't get any layer 2 information. Still, your code assumes layer 2 information (ethernet) in both cases.
A way to fix this would thus to skip handling any ethernet information on Windows since there will be none and start immediately with the IP header.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Thank you, I didn't think about this. May be you know - how I can get layer 2 information on Windows? Because I don't have AF_PACKET on Windows. – stahh Jun 24 '18 at 09:11
  • 1
    @stahh: Your question was answered and what you are asking now is a different question. Please don't ask new questions inside a comment but instead create a real new question so that you can profit from more visibility of the new question and others can profit from finding answers to this new question. You can not expect others to search for new questions and answers within the comments of another question. – Steffen Ullrich Jun 24 '18 at 09:34
  • Thank you. Finally I found answer: Unfortunately Some platforms don't provide access to the low-level network layer, this is true for windows, and may be true for OS X. – stahh Jun 24 '18 at 11:43
  • scapy pypcap... do propose low-level network layer, thanks to winpcap / npcap – Cukic0d Jun 24 '18 at 13:52