一、实验目的
(1) 理解网络嗅探器的基本工作原理与实现方法。
(2) 掌握Raw Socket的基本工作原理。
(3) 掌握TCP/IP、ICMP等协议及Socket编程方法。
二、实验要求
(1) 利用原始套接字编写一个网络嗅探器捕获网络数据包。
(2) 分析基本的数据报信息。
(3) 实现简单的过滤器功能。
三、实验思路
先一直嗅探到达网卡的数据,记录并保存下来,然后停止嗅探;根据需要对数据进行筛选。
四、实验源码
# -*- coding: utf-8 -*-
"""
简单嗅探器的实现
@author WQ
@time 2021/5/7
"""
import socket
pcaps=[]
#捕获
def sniffIpData(ip):
#host_ip = socket.gethostbyname(socket.gethostname())
host_ip=ip #获取IP 即设置要捕获的网卡
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) #创建套接字、可接受协议类型为UDP、TCP、ICMP、IP
sniffer.bind((host_ip, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) #设置套接字options、包装ip头部
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) #接受所有的数据,设置网卡为混杂模式
print("[*]正在嗅探数据.....")
count=10
while count:
recv_data, addr = sniffer.recvfrom(1500) #接收数据,缓冲区为1500
if recv_data:
try:
decodeIpData(recv_data)
except:
continue
else:
continue
count-=1
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) # 关闭混杂模式
sniffer.close() #关闭套接字
return recv_data
#提取协议名
def check_protocol(flag):
if flag==1:
reasult="ICMP"
elif flag==2:
reasult="IGMP"
elif flag==6:
reasult="TCP"
elif flag==17:
reasult="UDP"
elif flag==89:
reasult="OSPF"
else:
reasult=flag
return reasult
#解析
def decodeIpData(package):
ip_data = {
}
#RFC791
ip_data['version'] = package[0] >> 4 #版本
ip_data['headLength'] = package[0] & 0x0f #头长度 #& 按位与操作
ip_data['DSField'] = package[1] # Tos服务字段
ip_data['totalLength'] = (package[2] << 8) + package[3] #总长度
ip_data['identification'] = (package[4] << 8) + package[5] #标识分片
ip_data['flag'] = package[6] >> 5 #标志位
ip_data['moreFragment'] = ip_data['flag'] & 1 #标识后面可否还有分片
ip_data['dontFragment'] = (ip_data['flag'] >> 1) & 1 #能否分片 0可分片
ip_data['fragmentOffset'] = ((package[6] & 0x1f) << 8) + package[7] #片偏移
ip_data['TTL'] = package[8] #生存周期
ip_data['protocol'] = check_protocol(package[9]) #协议 其中1,标识ICMP、2标识IGMP、6标识TCP、17标识UDP、89标识OSPF。
ip_data['headerCheckSum'] = (package[10] << 8) + package[11] #校验和
#以IP地址形式存储
ip_data['sourceAddress'] = "%d.%d.%d.%d" % (package[12], package[13], package[14], package[15])
ip_data['destinationAddress'] = "%d.%d.%d.%d" % (package[16], package[17], package[18], package[19])
ip_data['options'] = [] #可选项
#根据headerLength求出options
if ip_data['headLength'] > 5: #一般来说此处的值为0101,表示头长度为20字节、若超出则大于5(0101)
temp = 5
while temp < ip_data['headLength']:
ip_data['options'].append(package[temp * 4] + 0)
ip_data['options'].append(package[temp * 4] + 1)
ip_data['options'].append(package[temp * 4] + 2)
ip_data['options'].append(package[temp * 4] + 3)
temp += 1
#根据totalLength求出data
ip_data['data'] = ""
temp = ip_data['headLength'] * 4
while temp < ip_data['totalLength']:
ip_data['data']+=(str(hex(package[temp])).upper().replace("0X",""))
temp += 1
pcaps.append(ip_data)
#for i in ip_data.keys():
#print("{}:{}".format(i,ip_data[i]))
return ip_data
#过滤
def filter(options=1):
if options==1:
for pcap in pcaps:
for i in pcap.keys():
print("{}:{}".format(i,pcap[i]))
print("\n")
elif options==2:
source=input("请输入源IP地址:")
dest=input("请输入目的IP地址:")
index=0
for pcap in pcaps:
if pcap["sourceAddress"] == source and pcap["destinationAddress"]==dest:
index+=1
print("第{}条记录".format(index))
for i in pcap.keys():
print("{}:{}".format(i,pcap[i]))
print("\n")
if index==0:
print("IP输入错误或者无该记录!")
elif options==3:
protocol=input("请输入协议名:")
index=0
for pcap in pcaps:
if pcap['protocol']==protocol:
index+=1
print("第{}条记录".format(index))
for i in pcap.keys():
print("{}:{}".format(i,pcap[i]))
print("\n")
if index==0:
print("协议名错误或无该记录!")
#开始捕获
def sniffer(target):
sniffIpData(ip=target)
print('''
----菜单
--------1. 输出全部记录(默认)
--------2. 根据IP筛选
--------3. 根据协议筛选
--------4. 退出
''')
while True:
options=int(input("输入选项:"))
if options==4:
break
filter(options)
target=input("请输入要嗅探网卡的IP:")
sniffer(target)
五、实验结果
根据协议进行筛选数据:
根据IP地址筛选: