Python提供了原始套接字(Raw Sockets)的支持,这使得我们可以使用Python进行流量嗅探和网络数据包分析。原始套接字允许我们直接访问网络层的数据包,而不经过操作系统的传输层协议栈。
Windows 上的包嗅探
#!/usr/bin/python
import socket
import os
#监听的主机
host = "10.10.10.160"
#创建原始套接字,然后绑定在公开接口上
if os.name == "nt":
socket_protocol = socket.IPPROTO_IP
else:
socket_protocol = socket.IPPROTO_ICMP
sniffer = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket_protocol)
sniffer.bind((host,0))
#设置在捕获的数据包中包含IP头
sniffer.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)
#在Windows平台上,我们需要设置IOCTL以启动混杂模式
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
#读取单个数据包
print sniffer.recvfrom(65565)
#在Windows平台上关闭混杂模式
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
使用scapy DNS 嗅探
# -*- coding: UTF-8 -*-
from scapy.all import *
scapy.config.conf.sniff_promisc=True #设置混杂模式
def packetHandler(pkt):
print(pkt.summary())
udp = pkt.getlayer(UDP)
print(udp.show())
if __name__ == '__main__':
dev = "en0"
filter = "udp port 53"
sniff(filter=filter,prn=packetHandler,iface=dev)
使用scapy DNS 欺骗
#coding=utf-8
import os
import sys
import subprocess
from scapy.all import *
RSN = 48 #管理帧信息元素(Dot11Elt)ID48是RSN信息
WPA = 221 #管理帧信息元素ID221是WPA信息
Dot11i = {0:'GroupCipher',
1:'WEP-40',
2:'TKIP',
4:'CCMP',
5:'WEP-104'
} #RSN信息的第6字节
WPA_Auth = {1:'802.11x/PMK',
2:'PSK'
} #RSN信息的第22字节
DN = open(os.devnull,'w')
def get_wlan_interfaces():
'''
返回当前PC上所有的无线网卡以及网卡所处的模式
'''
interfaces = {'monitor':[],'managed':[],'all':[]}
proc = subprocess.Popen(['iwconfig'],stdout=subprocess.PIPE,stderr=DN)
lines = proc.communicate()[0].split('\n')
for line in lines:
if line:
if line[0] != ' ':
iface = line.split(' ')[0]
if 'Mode:Monitor' in line:
interfaces['monitor'].append(iface)
if 'IEEE 802.11' in line:
interfaces['managed'].append(iface)
interfaces['all'].append(iface)
if len(interfaces['managed']) == 0:
sys.exit('[!]没有无线网卡,请插入网卡')
return interfaces
interfaces = get_wlan_interfaces() #获取当前的无线网卡
def get_strongest_inface():
'''
通过iwlist dev scan命令,根据无线网卡可获取到的AP数量来判断哪个网卡的功率最强
'''
iface_APs = []
#interfaces = get_wlan_interfaces()
for iface in interfaces['managed']:
count = 0
if iface:
proc = subprocess.Popen(['iwlist',iface,'scan'],stdout=subprocess.PIPE,stderr=DN)
lines = proc.communicate()[0].split('\n')
for line in lines:
if line:
if '- Address:' in line:
count += 1
iface_APs.append((count,iface))
interface = max(iface_APs)[1]
return interface
def start_monitor_mode():
'''
通过airmon-ng工具将无线网卡启动为监听状态
'''
if interfaces['monitor']:
print '[*]监听网卡为:%s' % interfaces['monitor'][0]
return interfaces['monitor'][0]
interface = get_strongest_inface()
print '[*]网卡%s开启监听模式...' % interface
try:
os.system('/usr/sbin/airmon-ng start %s' % interface)
moni_inface = get_wlan_interfaces()['monitor']
print '[*]监听网卡为:%s' % moni_inface[0]
return moni_inface
except:
sys.exit('[!]无法开启监听模式')
def get_AP_info(pkt):
'''
从Dot11数据包中获取AP的SSID,BSSID,chanle,加密等信息
'''
AP_info = {}
bssid = pkt[Dot11][Dot11Elt].info
ssid = pkt[Dot11].addr2
chanle = str(ord(pkt[Dot11][Dot11Elt][:3].info))
AP_infos = [bssid,chanle]
wpa_info,cipher_info = get_Dot11_RSN(pkt)
if wpa_info and cipher_info:
AP_infos = AP_infos + [wpa_info,cipher_info]
AP_info[ssid]=AP_infos
return AP_info
APs_info = {}
def get_APs_info(pkt):
global APs_info
if pkt.haslayer(Dot11) and (pkt.haslayer(Dot11Beacon) or pkt.haslayer(Dot11ProbeResp)):
AP_info = get_AP_info(pkt)
if not APs_info.has_key(AP_info.keys()[0]):
APs_info.update(AP_info)
return APs_info
already_shows = []
def show_APs_info(pkt):
global already_shows
APs_info = get_APs_info(pkt)
for (key,value) in APs_info.items():
if key not in already_shows:
already_shows.append(key)
print '-' * 40
print ' [+]AP的BSSID:%s' % value[0]
print ' [+]AP的SSID:%s' % key
print ' [+]AP当前的chanle:%s' % value[1]
if len(value) == 4:
print ' [+]AP的认证方式为:%s' % value[2]
print ' [+]AP的加密算法为:%s' % value[3]
else:
print ' [+]开放验证!!'
print '-' * 40
def get_Dot11_RSN(pkt):
'''
从Beacon帧以及ProbeResponse帧获取cipher及auth信息
'''
ssid = pkt[Dot11].addr2
len_Elt = len(pkt[Dot11Elt].summary().split('/'))
#print pkt.show()
for i in range(len_Elt):
if pkt[Dot11Elt][i].ID == RSN:
try:
RSN_info = hexstr(pkt[Dot11Elt][i].info)
cipher_index = RSN_info.find('ac') #第一个00 0f ac 02中的‘02’代表cipher
auth_index = RSN_info.rfind('ac') #从后往前数第一个00 0f ac 02中的‘02’代表AUTH
cipher_num = int(RSN_info[(cipher_index + 3):(cipher_index + 5)])
auth_num = int(RSN_info[(auth_index + 3):(auth_index + 5)])
for key,value in Dot11i.items():
if cipher_num == key:
cipher_info = value
for key,value in WPA_Auth.items():
if auth_num == key:
wpa_info = value
#print wpa_info,cipher_info
return wpa_info,cipher_info
except:
pass
return None,None
def sniffering(interface,action):
'''
嗅探5000个数据包
'''
print '[*]附近AP信息如下:'
sniff(iface=interface,prn=action,count=5000,store=0)
def main():
moni_inface = start_monitor_mode()
sniffering(moni_inface, show_APs_info)
if __name__ == '__main__':
main()
自己实现IP层的解码
#!/usr/bin/python
#coding=utf-8
import socket
import os
import struct
from ctypes import *
#监听的主机
host = "192.168.1.2"
#IP头定义
class IP(Structure):
"""docstring for IP"""
_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_ulong),
("dst", c_ulong)
]
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"}
#可读性更强的IP地址
self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))
self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))
#协议类型
try:
self.protocol = self.protocol_map[self.protocol_num]
except:
self.protocol = str(self.protocol_num)
#下面的代码类似于之前的例子
if os.name == "nt":
socket_protocol = socket.IPPROTO_IP
else:
socket_protocol = socket.IPPROTO_ICMP
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":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
try:
while True:
#读取数据包
raw_buffer = sniffer.recvfrom(65565)[0]
#将缓冲区的前20个字节按IP头进行解析
ip_header = IP(raw_buffer[0:20])
#输出协议和通信双方IP地址
print("Protocol : %s %s -> %s"%(ip_header.protocol,ip_header.src_address,ip_header.dst_address))
#处理CTRL-C
except KeyboardInterrupt:
#如果运行在Windows上,关闭混杂模式
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
改进的可在Kali中运行的代码
#!/usr/bin/python
import socket
import os
import struct
from ctypes import *
#监听的主机
host = "192.168.1.2"
#IP头定义
class IP(Structure):
"""docstring for IP"""
_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"}
#可读性更强的IP地址
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)
#下面的代码类似于之前的例子
if os.name == "nt":
socket_protocol = socket.IPPROTO_IP
else:
socket_protocol = socket.IPPROTO_ICMP
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":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
try:
while True:
#读取数据包
raw_buffer = sniffer.recvfrom(65565)[0]
#将缓冲区的前20个字节按IP头进行解析
ip_header = IP(raw_buffer[0:20])
#输出协议和通信双方IP地址
print "Protocol : %s %s -> %s"%(ip_header.protocol,ip_header.src_address,ip_header.dst_address)
#处理CTRL-C
except KeyboardInterrupt:
#如果运行在Windows上,关闭混杂模式
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
本文介绍了如何使用Python进行网络流量嗅探与分析,包括利用原始套接字和Scapy库进行数据包捕获,以及如何解析IP层数据。
800

被折叠的 条评论
为什么被折叠?



