Python Forum
getting wrong source IP address using socket and struct
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
getting wrong source IP address using socket and struct
#1
I'm sending a ping from a lab environment to my looback on machine. Whether I send the ping sourced from routers in the lab, virtual ips on my pc, other NIC's its always resolves to source ip as the loopback and dest as the loopbak. I used some basic code from the book black hat python, on Windows 10 environment:

import ipaddress
import os
import socket
import struct
import sys
class IP:
    def __init__(self, buff=None):
        header = struct.unpack('<BBHHHBBH4s4s', buff)
        self.ver = header[0] >> 4
        self.ihl = header[0] & 0xF
        self.tos = header[1]
        self.len = header[2]
        self.id = header[3]
        self.offset = header[4]
        self.ttl = header[5]
        self.protocol_num = header[6]
        self.sum = header[7]
        self.src = header[8]
        self.dst = header[9]


        # human readable IP addresses
        self.src_address = ipaddress.ip_address(self.src)
        self.dst_address = ipaddress.ip_address(self.dst)
        # map protocol constants to their names
        self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"}
        try:
            self.protocol = self.protocol_map[self.protocol_num]
        except Exception as e:
            print('%s No protocol for %s' % (e, self.protocol_num))
        self.protocol = str(self.protocol_num)
    def sniff(host):
        # should look familiar from previous example
        if os.name == 'nt':
            socket_protocol = socket.IPPROTO_IP
        else:
            socket_protocol = socket.IPPROTO_ICMP
        sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
        sniffer.bind((host, 0))
        sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
        if os.name == 'nt':

            sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
        try:
            while True:
                # read a packet
                raw_buffer = sniffer.recvfrom(65535)[0]
                (payload, (ip_src, _)) = sniffer.recvfrom(65535)
                if ip_src == b'10.0.0.1':
                    print("source is 10.0.0.1")
                # create an IP header from the first 20 bytes
                ip_header = IP(raw_buffer[0:20])
                # print the detected protocol and hosts
                print('Protocol: %s %s -> %s' % (ip_header.protocol,
                ip_header.src_address,
                ip_header.dst_address))
                print(ip_header.tos)
                print(ip_src)
                print(ip_header.sum)


        except KeyboardInterrupt:
            # if we're on Windows, turn off promiscuous mode
            if os.name == 'nt':
                sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)



if __name__ == '__main__':
    from ping_listener import IP
    if len(sys.argv) == 2:
        host = sys.argv[1]
    else:
        host = '192.168.56.1'
    IP.sniff(host)
here's the output of every ping:
Protocol: 1 192.168.56.1 -> 192.168.56.1
0
192.168.56.1


I need to get the source address to trigger a python script, I'm not sure what I'm doing wrong at this point, if somebody could help.

I've played around with socket_protocol = socket.IPPROTO_ICMP/ _IP
and passing in different parameters to the socket object, source address resolves to 192.168.56.1.
Reply
#2
Here is a printout after some updated code:

Protocol: 1 192.168.56.1 -> 192.168.56.1
Version: 4
Header Length: 5 TTL: 128
ICMP -> Type: 0 Code: 0


It seems my headers are fine, except maybe the Type 0 code meaning unreachable.
class ICMP:
    def __init__(self, buff):
        header = struct.unpack('<BBHHH', buff)
        self.type = header[0]
        self.code = header[1]
        self.sum = header[2]
        self.id = header[3]
        self.seq = header[4]
            try:
            while True:
                raw_buffer = sniffer.recvfrom(65535)[0]

                ip_header = IP(raw_buffer[0:24])
                print(f'Version: {ip_header.ver}')
                print(f'Header Length: {ip_header.ihl} TTL: {ip_header.ttl}')
                offset = ip_header.ihl * 4
                buf = raw_buffer[offset:offset + 8]
                icmp_header = ICMP(buf)
                print('ICMP -> Type: %s Code: %s\n' %
                      (icmp_header.type, icmp_header.code))
                print('Protocol: %s %s -> %s' % (ip_header.protocol,
                                         ip_header.src_address,
                                                 
                                         ip_header.dst_address))
any suggestions?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  struct.error: unpack requires a buffer of 14 bytes upasana 0 8,644 Apr-18-2018, 11:06 AM
Last Post: upasana

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020