python3使用libpcap库进行抓包及数据处理 - Mike_Zhang
source link: https://www.cnblogs.com/MikeZhang/p/pythonUseLibpcap20221029.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
python版本:python 3.9
libpcap版本:1.11.0b7
一、安装libpcap库
1、在线安装
2、离线安装
2.1 下载离线安装文件
可以在pypi页面源代码或whl文件。
2.2 执行离线安装操作
1) 可以使用源码进行安装
解压文件到当前目录,然后执行安装命令:
python -m pip install ./libpcap-1.11.0b7
2)也可以使用whl文件进行离线安装
安装命令如下:
python -m pip install libpcap-1.11.0b7-py3-none-any.whl
二、使用libpcap库
1、导入及指定pcap库
import libpcap libpcap.config(LIBPCAP="wpcap")
2、常用API介绍
tcpdump就是以libpcap为基础实现的,c语言libpcap的文档可以在tcpdump官网找的:
这里描述下python常用接口。
2.1 获取网络设备接口
-
lookupdev(errbuf)
功能:该函数用于查找网络设备,返回的值可以被open_live函数直接调用。
errbuf为c语言字符串类型,用于获取错误信息。
使用示例:
import ctypes as ct import libpcap as pcap errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1) device = pcap.lookupdev(errbuf) print(errbuf.value)
-
findalldevs(alldevs, errbuf)
功能:该函数用于查找所有网络设备。
alldevs为pcap_if_t结构体指针,用于存储查找到的所有网络设备信息。
errbuf为c语言字符串类型,用于获取错误信息。
使用示例:
import ctypes as ct import libpcap as pcap errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1) alldevs = ct.POINTER(pcap.pcap_if_t)() pcap.findalldevs(ct.byref(alldevs), errbuf) print(alldevs[0].name) pcap.freealldevs(alldevs)
2.2 抓包接口
-
open_live(device:bytes,snaplen:int,promisc:int,to_ms:int,errbuf)
功能:该函数用于打开一个用于捕获数据的网络设备
device为网络接口的名字,可通过api获取,也可以人为指定,如:"eth0"
snaplen是捕获数据包的长度,不能大于65535
promise用于标记是否开启混杂模式,1代表混杂模式,其它值代表非混杂模式
to_ms代表需要等待的毫秒数,超过这个时间后,获得数据包的函数会立即返回,0表示一直等待直到有数据包到来
errbuf为c语言字符串类型,用于获取错误信息。
返回值:返回pcap_t类型指针,后面的所有操作都要使用这个指针。
使用示例:
import ctypes as ct import libpcap as pcap device = b'eth0' # linux errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1) handle = pcap.open_live(device,4096,1,1000,errbuf) if errbuf.value: print("hanle error :",errbuf.value)
-
open_offline(fname:bytes,errbuf)
功能:该函数用于打开离线抓包文件
fname为文件名称,比如:b"/tmp/test1.cap"
errbuf为c语言字符串类型,用于获取错误信息。
返回值:返回pcap_t类型指针,后面的所有操作都要使用这个指针。
使用示例:
import ctypes as ct import libpcap as pcap errbuf = ct.create_string_buffer(pcap.PCAP_ERRBUF_SIZE + 1) handle = pcap.open_offline(fname,errbuf) if errbuf.value: print("hanle error :",errbuf.value)
2.3 数据包获取接口
-
next(handle,pheader)
功能:该函数用于获取数据包,一次只获取一个包。
handle为pcap_t类型指针
pheader为pcap_pkthdr结构体指针,可通过pkthdr函数创建
返回值:返回u_char类型指针,代表包数据,可使用struct.unpack函数解析
使用示例:
import libpcap as pcap pheader = pcap.pkthdr() packet = pcap.next(handle,pheader)
2.4 写文件接口
-
dump_open(handle,fname:bytes)
功能:该函数用于打开文件,存储获取到的数据包。
handle为pcap_t类型指针
fname为文件名称
返回值:返回pcap_dumper_t 类型指针,后面的所有操作都要使用这个指针。
使用示例:
import libpcap as pcap fname = b"realtime1.cap" fPcap = pcap.dump_open(handle,fname)
-
dump(handle,pheader,packet)
功能:该函数用于存储获取到的数据包。
handle为pcap_dumper_t类型指针
pheader为pcap_pkthdr结构体指针
packet是数据包
返回值:无返回值
使用示例:
fPcapUbyte = ct.cast(fPcap,ct.POINTER(ct.c_ubyte)) pcap.dump(fPcapUbyte,pheader,packet)
-
dump_flush(handle)
功能:该函数用于将缓存的数据刷到磁盘
handle为pcap_dumper_t类型指针
返回值:错误码,0代表成功,-1代表出错
2.5 资源释放接口
-
close(handle)
功能:释放pcap_t类型指针
handle为pcap_t类型指针
返回值:无返回值
-
dump_close(handle)
功能:释放pcap_dumper_t类型指针
handle为pcap_dumper_t类型指针
返回值:无返回值
3、典型使用场景
3.1、网卡实时抓包
可以使用libpcap库进行网卡实时数据抓包,这里进行简单的示例:
1)首先需要获取或指定抓包设备
方法1 :指定网卡接口名称
device = b'\Device\NPF_{BFDBF91E-9848-417D-B8AB-D3ED19990717}' # windows
device = b'eth0' # linux
Windows网卡接口名称可在wireshark的捕获界面看到,具体如下:
linux网卡名称获取:ifconfig
方法2 :使用lookupdev获取网卡接口名称
device = pcap.lookupdev(errbuf)
方法3 :使用findalldevs获取网卡接口名称
alldevs = ct.POINTER(pcap.pcap_if_t)()
pcap.findalldevs(ct.byref(alldevs), errbuf)
device =alldevs[0].name
2)使用open_live函数进行网卡抓包;
3)使用pkthdr函数创建header,获取包头信息(时间戳、包大小);
4)使用next函数循环读取数据包,需要注意的是,获取的packet对象的contents是C语言类型,需要使用它ctypes的pointer函数进行转换;
5)数据包(比如IP头)的解析可使用struct的unpack函数;
6)如果要将抓包数据存盘,可使用dump_open、dump、dump_flush系列函数进行操作,需要注意的是,dump_open函数的第二个参数必须是byte类型;
示例代码及运行效果:
完整代码获取途径:
关注微信公众号(聊聊博文,文末可扫码)后回复 202210290101 获取。
3.2、离线数据解析
完整代码获取途径:
网卡实时抓包和离线数据解析时,可以设置过滤条件,避免数据量过大。
过滤条件示例:
1) 过滤IP
-
host 过滤某个ip的所有包
host 8.8.8.8
-
src 过滤源ip
src 8.8.8.8
-
dst过滤目的ip
dst 8.8.8.8
2)过滤端口
-
port进行单个端口过滤
port 22
-
portange进行多个端口过滤
portange 1-1024
-
可使用src或dst指定端口方向
src port 22
dst port 22
3)指定协议
tcp
udp
icmp
4)使用组合条件
-
and 进行与逻辑
src localhost and dst port 22
src localhost && dst port 22
-
or 进行或逻辑
port 80 or 22
port 80 || 22
示例代码及运行效果:
完整代码获取途径:
三、资源下载
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK