网络嗅探

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-18 14:35:46

网络嗅探

嗅探目标:基于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黑帽子 黑客与渗透测试编程之道》第三章

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!