0

Okay, so I asked for some help regarding a socket listening script last week for icmp pings. i received a script here, and used one from Chapter 3 of Black Hat Python. The scipts work fine. They're picking up icmp pings as expected, and I can filter out ip protocol 1 (which is icmp), or use socket options to specify icmp. In running both scripts however the source address is always getting replaced with the destination address, after stripping the headers and printing them. In other words both dest and source are printed out as dest. I assumed maybe this is internal translation on host machine, then I bound the sockets to vmnet addresses, and then to my ethernet card. The address for source is printing out as dest, so something is going on. Id like to be able to strip/work with the header packet and get the proper source address as I'm testing in a router lab environment(I bridged the connection for no NAT in vmware). I will include both scripts, to show you what I mean. I don't think the scripts are wrong maybe something configured on my Windows 10 machine. Any tips would be appreciated.

here's the script i received help on from here, it is printing out gibberish payload and a source address of the destination I am pinging to:

import socket
import sys
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)

if sys.platform == 'win32':
    # bind on the actual host is required on Windows
    host = "192.168.1.200"
    s.bind((host, 0))  # bind on everything
    # on Windows, including the IP headers...
    s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
    # ... and listening to everything is required for ICMP
    s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

(payload, (ip_src, _)) = s.recvfrom(65535)
# skip the first 28 bytes of IP/ICMP headers
print("payload %r from %s" % (payload[28:].decode('latin1'), ip_src))

Here is part of the script basically taken from the Black hat python book:

import ipaddress
import os
import socket
import struct
import sys
from main import main_function
class ICMP:
    #snipped out
class IP:
    def __init__(self, buff=None):
        header = struct.unpack('<BBHHHBBH4s4s4s', 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]
        self.src_address = ipaddress.ip_address(self.src)
        self.dst_address = ipaddress.ip_address(self.dst)
        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):
        socket_protocol = socket.IPPROTO_ICMP
        sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
        sniffer.bind((host, 0))

        sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 0)
        if os.name == 'nt':
            sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)



        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))
                print(ip_header.trash)

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


if __name__ == '__main__':
    from ping_listener import IP
    if len(sys.argv) == 2:
        host = sys.argv[1]
    else:
        host = '192.168.209.1'

    IP.sniff(host)

Both scripts work as needed. I can modify headers, buffer sizes, socket options. After trying all of this, including listening in on various addresses i concluded it's either an internal translation, which doesn't make sense to me as the vmnet address/interface is printing itself as the source as well. Any tips would be helpful, I'm willing to give anything a shot.

Edit: by the way the black hat python chapter worked with ICMP pings and managed to get the correct source.

right now I'm reading a post with a similar issue

2 ip addresses printing same value

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
hfakoor222
  • 25
  • 7
  • Welcome to Stack Overflow. Please read [ask]. We do not find the bug for you here; we require a **specific** question - which will come out of your best attempt to [understand](//meta.stackoverflow.com/q/261592/) and [locate](//ericlippert.com/2014/03/05) a specific problem, and showcase it in a [mre]. – Karl Knechtel Sep 02 '23 at 02:55

0 Answers0