网络嗅探
嗅探目标:基于UDP发现目标网络存活的主机
嗅探基础:当发送一个UDP数据包到主机上的某个关闭端口时,目标主机返回ICMP包指示目标端口不可达,证明目标主机存活,否则证明目标主机不存在
import socket import os import struct import threading import time #导入netaddr包处理子网ip地址 from netaddr import IPNetwork,IPAdress from ctypes import * #扫描主机号 host="192.168.65.133" #扫描子网号 subnet="192.168.65.0/24" magic_message="PYTHONRULES" def udp_sender(subnet,magic_message): time.sleep(5) sender=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) for ip in IPNetwork(subnet): try: #发送数据到子网内所有主机 sender.sendto(magic_message,("%s" % ip,65212)) except: pass #对Ip数据报报头进行解析 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_uint32), ("dst",c_uint32) ] def __new__(self,socket_buffer=None): return self.from_buffer_copy(socket_buffer) def __init__(self,socket_buffer=None): self.protocol_map={1:"ICMP",6:"TCP",17:"UDP"} self.src_address=socket.inet_ntoa(struct.pack("@I",self.src)) self.dst_address=socket.inet_ntoa(struct.pack("@I",self.dst)) try: self.protocol=self.protocol_map[self.protocol_num] except: self.protocol=str(self.protocol_num) #对ICMP报头进行解析 class ICMP(Structure): _fields_=[ ("type",c_ubyte), ("code",c_ubyte), ("checksum",c_ushort), ("unused",c_ushort), ("next_hop_mtu",c_ushort) ] def __new__(self,socket_buffer): return self.from_buffer_copy(socket_buffer) def __init__(self,socket_buffer): pass if os.name =="nt": #windows下允许嗅探到所有数据包 socket_protocol=socket.IPPROTO_IP else : #linux下只能嗅探到ICMP包,所以区分进行参数设置 socket_protocol=socket.IPPROTO_ICMP #套接字初始化,选择使用原始套接字sock_RAW sniffer=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol) sniffer.bind((host,0)) sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1) if os.name=="nt": #发送IOCTL数据到网卡驱动上启动混杂模式,混杂模式下可以嗅探网卡上流经的所有数据包 sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON) #启动向子网发送数据报的线程 t = threading.Thread(target=udp_sender,args=(subnet,magic_message)) t.start() try: while True: #读取接收内容 raw_buffer=sniffer.recvfrom(65565)[0] #前20字节为ip数据报报头 ip_header=IP(raw_buffer[0:20]) print ("Protocol:%s %s ->%s"% (ip_header.protocol,ip_header.src_address,ip_header.dst_address)) if ip_header.protocol == "ICMP": #得到ip数据报报头真实长度,作为偏移量 offset = ip_header.ihl*4 #取ip数据报报头之后的数据 buf=raw_buffer[offset:offset+sizeof(ICMP)] icmp_header=ICMP(buf) print "ICMP -> Type:%d Code:%d" % (icmp_header.type,icmp_header.code) #code和type都为3的时候,是目标不可达信息 if icmp_header.code==3 and icmp_header.type==3: if ipaddress(ip_header.src_address) in IPNetwork(subnet): if raw_buffer[len(raw_buffer)-len(magic_message):]==magic_message: print ("Host Up: %s" % ip_header.src_address) except KeyboardInterrupt: if os.name=="nt": sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
错误:在windows下报错:OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。
解决:以管理员方式运行
参考资料:《Python黑帽子 黑客与渗透测试编程之道》第三章
来源:https://www.cnblogs.com/moonstars2333/p/12208831.html