一.Windows和Linux上的包嗅探
首先创建套接字对象,然后再判断程序在哪个平台上运行。在Windows平台上,我们需要通过套接字输入/输出控制(IOCTL)设置一些额外的标志,它允许在网络接口上启用混杂模式。下面例子只设置原始套接字嗅探器,读取一个数据包,然后退出即可
# -*- coding:utf -*-
import socket
import os
#监听主机
#Windows主机IP
host = "172.xx.xx.xx"
#Linux主机IP
#host = "192.168.233.1"
# 创建原始套接字,然后绑定在公开接口上
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)
在Windows系统上打开一个管理员模式的cmd窗口,然后运行脚本:
py -2 sniffer.py
二.解码IP层
刚才的代码只是接收了任何高层协议如TCP,UDP或ICMP的所有IP头信息。而且是二进制数的形式,非常难以理解。所以接下来就是解码数据包中IP头的部分,提取诸如协议类型(TCP,UDP和ICMP),源IP地址和目的IP地址等有用信息。下图为典型的IPv4头结构。
IP解码
#!/usr/bin/python
#coding=utf-8
import socket
import os
import struct
from ctypes import *
#监听的主机--Windows主机
host = "172.xx.xx.x"
#IP头定义
class IP(Structure):
"""docstring for IP"""
_fields_ = [
("ihl", c_ubyte, 4), #ip head length:头长度
("version", c_ubyte, 4), #版本
("tos", c_ubyte), #服务类型
("len", c_ushort), #ip数据包总长度
("id", c_ushort), #标识符
("offset", c_ushort), #片偏移
("ttl", c_ubyte), #生存时间
("protocol_num", c_ubyte), #协议数字,应该是协议类型,这里用数字来代表时哪个协议,下面构造函数有设置映射表
("sum", c_ushort), #头部校验和
("src", c_ulong), #源ip地址
("dst", c_ulong) #目的ip地址
]
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"}