Thought:
Based on the UDP protocol to traverse all IP addresses in the subnet, send the UDP packets to a closed port (which you think might shut down the port, if you can specify multiple) if the ICMP packet being responded to indicates that this host is present. UDP send packet cost is relatively small. On this basis, you can add or subtract the functions of the Namp call, and the full scan discovers the ports on the host.
Python module used: Netaddr,socket,ctypes,struct,threading,time,os
#!/usr/bin/python
From NETADDR import ipaddress,ipnetwork
Import time
Import threading
From socket Import *
From ctypes Import *
Import struct
Import OS
Two key classes are defined, and the struct module is used to construct a struct similar to C language structure. Name a list of your own build _fields_, depending on the structure of the IP header, the _fields_ list for the IP class is:
_fields_=[
("IHL", c_ubyte,4),
("Version", c_ubyte,4),
("TOS", C_ubyte),
("Len", C_ushort),
("id", C_ushort),
("offset", c_ushort),
("TTL", C_ubyte),
("Protocol_num", C_ubyte),
("sum", C_ushort),
("src", c_uint),
("DST", C_uint),]
Each of these tuples represents a variable in the structure, and the string is the variable name followed by the type. c_ubyte,4 stands for 4 bits.
Defines the __new__ method that writes the incoming Socket_buffer data to the structure when the class is just created.
def __new__ (self, socket_buffer = None):
Return Self.from_buffer_copy (Socket_buffer)
Defines the __init__ method, which executes when the __new__ is executed. Create a Protocol_map dictionary in which to identify the protocol type. Use the pack function of the struct module to convert the source address SRC and the destination address in the IP packet to the small-endian byte order of the network large segment byte order as a parameter to the SOCKET.INET_NTOA function into a decimal string assignment to the class attribute. The dictionary is then used to indicate the protocol type. or direct str.
def __init__ (self, socket_buffer = None):
Protocol_map = {1: "ICMP", 6: "TCP", +: "UDP"}
self.src_address = Inet_ntoa (Struct.pack ("<l", SELF.SRC))
self.dst_address = Inet_ntoa (Struct.pack ("<l", SELF.DST))
Try
Self.protocol = Protocol_map[self.protocol_num]
Except
Self.protocol = str (protocol_num)
ICMP processing class (same IP)
Class ICMP (Structure):
_fields_=[
("type", C_ubyte),
("Code", C_ubyte),
("checksum", C_ushort),
("unused", C_ushort),
("Next_hop_mtu", C_ushort),]
def __new__ (self, raw_buffer = None):
Return Self.from_buffer_copy (Raw_buffer)
def __init__ (self, raw_buffer = None):
Pass
def udp_sender (subnet, message):
#time. Sleep (5)
SENDUDP = socket (af_inet, SOCK_DGRAM)
For IP in ipnetwork (subnet):
Try
Sendudp.sendto (Message, ("%s"%ip,65532))
Except
Pass
Define the Udp_sender function and use the NETADDR module to traverse the subnet IP to send UDP packets,
First, you create a socket socket based on the UDP protocol. Second, the subnet IP can be traversed using ipnetwork. Send a validation string to port 65532 (any closed port) to verify that the ICMP packet being received responds to the packet you sent.
def udp_sender (subnet, message):
#time. Sleep (5)
SENDUDP = socket (af_inet, SOCK_DGRAM)
For IP in ipnetwork (subnet):
Try
Sendudp.sendto (Message, ("%s"%ip,65532))
Except
Pass
This program only two threads as needed can be added, chunked scan. The packet is processed in the main thread, and the word thread is used to send the UDP packet.
t = Threading. Thread (target = udp_sender, args = (subnet, message,))
T.start ()
The incoming subnet for "10.114.234.0/24" our school dormitory building 5 floor one of the subnets, the actual use of the time can be changed to other. Message is a validation string "Pythonsniffer"
The main thread packet processing is the key place to build a raw socket for listening, first based on whether the value of Os.name is NT to determine whether it is a Windows system. Because the original socket can only accept ICMP packets under Linux. Then, according to the decision, set the original socket to accept the protocol type of the packet.
F os.name = = "NT":
Sock_protocol = Ipproto_ip
Else
Sock_protocol = ipproto_icmp
Then create the original set of machine words. The second parameter of the Socket.socket () function is Sock_raw, which establishes the original socket. Note that the original socket needs to be created under root. The bind,setsockopt function then sets the socket to preserve the IP header. Sniffer = socket (af_inet, Sock_raw, Sock_protocol)
Sniffer.bind ((host, Port))
Sniffer.setsockopt (Ipproto_ip, IP_HDRINCL, 1)
If the Windows system then uses the IOCTL to turn on listening mode
if Os.name = = "NT":
Sniffer.ioctl (Sio_rcvall, rcvall_on)
It then loops through the data and instantiates the IP,ICMP object. Because the IP header is the first 20 bytes of packets that are accepted to keep the IP header. The 8-byte ICMP header requires a 20-byte IP header to be removed, and the slice starts at 20. First instantiate the IP object processing IP header, if accepted as ICMP packet, then instantiate the ICMP object, determine whether the IP header src is within the subnet range, and then determine whether the data after the head is a validation string pythonsniffer.
While True:
data = Sniffer.recvfrom (65565) [0]
Ip_header = IP (data[:20])
# print "Protocol:%s,%s"% (ip_header.src_address, ip_header.dst_address)
if Ip_header.protocol = = "ICMP":
offset = ip_header.ihl*4
Icmp_header = ICMP (data[offset:offset+sizeof (ICMP)))
# print "ICMP Type:%d, Code:%d"% (Icmp_header.type, Icmp_header.code)
if Icmp_header.code = = 3 and Icmp_header.type = = 3:
If IPAddress (ip_header.src_address) in ipnetwork (subnet):
If Data[len (data)-len (message):] = = "Pythonsniffer":
Print "Host up:%s"% (ip_header.src_address)
Finally, if you encounter a keyboard exception exit, turn off Windows promiscuous mode.
Scan 10.114.234.0 Effect:
The complete source code is as follows:
#!/usr/bin/python
From NETADDR import ipaddress,ipnetwork
Import time
Import threading
From socket Import *
From ctypes Import *
Import struct
Import OS
#host = "127.0.0.1"
Host = "10.114.234.133"
Port = 0
Subnet = "10.114.234.0/24"
message = "Pythonsniffer"
Class IP (Structure):
_fields_=[
("IHL", c_ubyte,4),
("Version", c_ubyte,4),
("TOS", C_ubyte),
("Len", C_ushort),
("id", C_ushort),
("offset", c_ushort),
("TTL", C_ubyte),
("Protocol_num", C_ubyte),
("sum", C_ushort),
("src", c_uint),
("DST", C_uint),]
def __new__ (self, socket_buffer = None):
Return Self.from_buffer_copy (Socket_buffer)
def __init__ (self, socket_buffer = None):
Protocol_map = {1: "ICMP", 6: "TCP", +: "UDP"}
self.src_address = Inet_ntoa (Struct.pack ("<l", SELF.SRC))
self.dst_address = Inet_ntoa (Struct.pack ("<l", SELF.DST))
Try
Self.protocol = Protocol_map[self.protocol_num]
Except
Self.protocol = str (protocol_num)
Class ICMP (Structure):
_fields_=[
("type", C_ubyte),
("Code", C_ubyte),
("checksum", C_ushort),
("unused", C_ushort),
("Next_hop_mtu", C_ushort),]
def __new__ (self, raw_buffer = None):
Return Self.from_buffer_copy (Raw_buffer)
def __init__ (self, raw_buffer = None):
Pass
def udp_sender (subnet, message):
#time. Sleep (5)
SENDUDP = socket (af_inet, SOCK_DGRAM)
For IP in ipnetwork (subnet):
Try
Sendudp.sendto (Message, ("%s"%ip,65532))
Except
Pass
t = Threading. Thread (target = udp_sender, args = (subnet, message,))
T.start ()
if Os.name = = "NT":
Sock_protocol = Ipproto_ip
Else
Sock_protocol = ipproto_icmp
Sniffer = socket (af_inet, Sock_raw, Sock_protocol)
Sniffer.bind ((host, Port))
Sniffer.setsockopt (Ipproto_ip, IP_HDRINCL, 1)
if Os.name = = "NT":
Sniffer.ioctl (Sio_rcvall, rcvall_on)
Try
While True:
data = Sniffer.recvfrom (65565) [0]
Ip_header = IP (data[:20])
# print "Protocol:%s,%s"% (ip_header.src_address, ip_header.dst_address)
if Ip_header.protocol = = "ICMP":
offset = ip_header.ihl*4
Icmp_header = ICMP (data[offset:offset+sizeof (ICMP)))
# print "ICMP Type:%d, Code:%d"% (Icmp_header.type, Icmp_header.code)
if Icmp_header.code = = 3 and Icmp_header.type = = 3:
If IPAddress (ip_header.src_address) in ipnetwork (subnet):
If Data[len (data)-len (message):] = = "Pythonsniffer":
Print "Host up:%s"% (ip_header.src_address)
Except Keyboardinterrupt:
if Os.name = = "NT":
Sniffer.ioctl (Sio_rcvall, Rcvall_off)
Python UDP sniffer host discovery tool