WinPcap分析数据包

news/2024/12/29 2:29:25/

一、前言

通过前面的学习,我们已经知道了如何打开设备捕获数据了,接下来就可以捕获并过滤网络流量了。

本教程主要的目标是展示如何解析数据包的协议首部,选中分析和实现UDP协议,因为UDP协议相对于其它协议来说更简单,用于入门。


二、代码详解

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>#define HAVE_REMOTE
#include "pcap.h"#ifndef WIN32#include <sys/socket.h>#include <netinet/in.h>
#else#include <winsock2.h>#include <ws2tcpip.h>
#endif//4字节的IP地址
typedef struct ip_address
{u_char byte1;u_char byte2;u_char byte3;u_char byte4;
}ip_address;//IPv4首部
typedef struct ip_header
{u_char ver_ihl;             //版本(4 bits) + 首部长度(4 bits)u_char tos;                 //服务类型(Type of service)u_short tlen;               //总长(Total length)u_short identification;     //标识(Identification)u_short flags_fo;           //标志位(Flags)(3 bits) + 偏移量(Fragment offset)(13 bits)u_short ttl;                //存活时间(Time to live)u_char proto;               //协议(protocol)u_short crc;                //首部校验和(Header checksum)ip_address saddr;           //源地址(Source address)ip_address daddr;           //目的地址(Destination address)u_int op_pad;               //选项与填充
}ip_header;//UDP首部
typedef struct udp_header
{u_short sport;              //源端口(Source port)u_short dport;              //目的端口(Destination port)u_short len;                //UDP数据包长度(Datagram length)u_short crc;                //校验和(Checksum)
}udp_header;//回调函数原型
void packet_handler(u_char* param, const struct pcap_pkthdr* header, const u_char* pkt_data);int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();pcap_if_t *alldevs;pcap_if_t *d;int inum;int i=0;pcap_t* adhandle;char errbuf[PCAP_ERRBUF_SIZE];u_int netmask;char packet_filter[] = "ip and udp";struct bpf_program fcode;//获取本机适配器列表if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs, errbuf) == -1){qDebug() << "Error in pcap_findalldevs_ex: " <<errbuf;exit(1);}//打印适配器列表for(d = alldevs; d; d = d->next){//设备名(Name)qDebug()<<"Name: "<<d->name;++i;//设备描述(Description)if (d->description) {qDebug()<<"Description: "<<d->description;}else {qDebug()<<"No description available";}qDebug()<<"====================================================================";}if(i==0) {qDebug()<<"No interfaces found! Make sure WinPcap is installed.";return -1;}qDebug()<<QString("Enter the interface number (1-%1): ").arg(i);//scanf("%d",&inum);inum = 5;qDebug()<<"inum: "<<inum;if(inum < 1 || inum > i){qDebug()<<"Interface number out of range.";//释放适配器列表pcap_freealldevs(alldevs);return -1;}//跳转到选中的适配器for(d=alldevs,i=0; i<inum-1; d=d->next,i++);//打开适配器if((adhandle = pcap_open(d->name,                       //设备名65536,                         //65535包证能捕获到不同数据链路层上的每个数据包的全部内容PCAP_OPENFLAG_PROMISCUOUS,     //混杂模式1000,                          //读取超时时间NULL,                          //远程机器验证errbuf                         //错误缓冲池)) == NULL) {qDebug()<<"Unable to open the adapter."<<QString("%1 is not support by WinPcap").arg(d->name);//释放适配器列表pcap_freealldevs(alldevs);return -1;}//检查数据链路层,为了简单,只考虑以太网if(pcap_datalink(adhandle) != DLT_EN10MB) {qDebug()<<stderr<<endl<<"This program works only on Ethernet networks.";//释放设备列表pcap_freealldevs(alldevs);return -1;}if(d->addresses != NULL) {//获得接口第一个地址的掩码netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;}else {//如果接口没有地址,那么假设一个C类的掩码netmask = 0xffffff;}//编译过滤器if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask) < 0) {qDebug()<<stderr<<endl<<"Unable to compile the packet filter. Check the syntax";//释放设备列表pcap_freealldevs(alldevs);return -1;}//设置过滤器if(pcap_setfilter(adhandle,&fcode) < 0) {qDebug()<<stderr<<endl<<"Error setting the filter.";pcap_freealldevs(alldevs);return -1;}qDebug()<<QString("Listening on %1...").arg(d->description);//释放适配器列表pcap_freealldevs(alldevs);//开始捕捉pcap_loop(adhandle,0,packet_handler,NULL);return a.exec();
}//回调函数,当收到每一个数据包时会被libpcap所调用
void packet_handler(u_char* param, const struct pcap_pkthdr* header, const u_char* pkt_data)
{struct tm* ltime;char timestr[16];ip_header* ih;udp_header* uh;u_int ip_len;u_short sport,dport;time_t local_tv_sec;//将时间戳转换为可识别的格式local_tv_sec = header->ts.tv_sec;ltime = localtime(&local_tv_sec);strftime(timestr,sizeof timestr,"%H:%M:%S",ltime);//打印数据包的时间戳和长度qDebug()<<timestr<<header->ts.tv_usec<<header->len;//获取IP数据包头部的位置ih = (ip_header*)(pkt_data + 14); //14是以太网头部长度//获得UDP首部的位置ip_len = (ih->ver_ihl & 0xf) * 4;uh = (udp_header*)((u_char*)ih + ip_len);//将网络字节序列转换成主机字节序列sport = ntohs(uh->sport);dport = ntohs(uh->dport);//打印IP地址和UDP端口qDebug()<<ih->saddr.byte1<<":"<<ih->saddr.byte2<<":"<<ih->saddr.byte3<<":"<<ih->saddr.byte4<<"  "<<sport;qDebug()<<ih->daddr.byte1<<":"<<ih->daddr.byte2<<":"<<ih->daddr.byte3<<":"<<ih->daddr.byte4<<"  "<<dport;qDebug()<<"===================================================================";
}

运行结果如下
在这里插入图片描述

  • 首先,我们将过滤器设置成“ip and udp”,在这种方式下,确信packet_handler()只会收到基于IPv4的UDP数据包,这将简化解析过程,提高程序的效率;
  • 我们还分别创建了用于描述IP首部和UDP首部的结构体,这些结构体中的各种数据会被packet_handler()合理地定位;
  • pack_handler(),尽管只受限于单个协议的解析(比如基于IPv4的UDP),不过它展示了捕捉器(sniffers)是多么的复杂,就像TcpDump或WinDump对网络数据流进行解码那样;
  • 因为我们对MAC首部不感兴趣,所以跳过它,为了简介,我们在开始捕捉前,使用了pcap_datalink()对MAC层进行了检测,以确保我们是在处理一个以太网,这样就能确保MAC首部是14位的 ;
  • IP数据包的首部就位于MAC首部的后面,我们将IP数据包的首部解析到源IP地址和目的IP地址;
  • 处理UDP的首部有一些复杂,因为IP数据包的首部并不是固定的,然而,我们可以通过IP数据包的length域来得到它的长度,一旦我们知道了UDP首部的位置,我们就能解析到源端口和目的端口;

http://www.ppmy.cn/news/701607.html

相关文章

树莓派播放mp3

import time import pygame# play mp3 函数定义 def play_mp3(): pygame.mixer.init() pygame.mixer.music.load(/home/pi/test.mp3)if pygame.mixer.music.get_busy()False: pygame.mixer.music.play() time.sleep(10) #停止播放 pygame.mixer.music.stop() # play mp3 函数使…

微软语音合成助手 v1.5+版本,新增火山与阿里接口

微软语音合成助手 By&#xff1a;bill3k 这款工具由bill3k使用易语言开发&#xff0c;虽然界面比较简陋&#xff0c;但在功能及使用体验上都是非常优秀的 软件调用官方接口&#xff0c;全部支持ssml&#xff0c;将文字转语音大部分功能都给集成了 虽然用的都是免费接口&#…

文件的下载与保存,以及mp3文件的播放

这里只是说说异步 单线程下载与文件的保存 以下载一个mp3文件并保存为例&#xff1a;-(void)loading {//设置文件下载地址 NSString *urlString [NSString stringWithFormat:"http://zhangmenshiting2.baidu.com/data2/music/14893666/14893666.mp3?xcodef7e142418de081…

使用Lame库实现wav、pcm转mp3

文章目录 前言 一、Lame库是什么&#xff1f; 二、使用步骤 0.创建native项目 1.下载Lame库 2.pcm转MP3 3.wav转MP3 4、native方法如下 三、注意 总结 前言 因为使用android录音后生成的文件是wav或者pcm格式&#xff0c;项目要求最后的文件需要是mp3格式&#xff0c;于…

WinPcap学习(九)发送数据包

原始的libcap库是不支持发送数据包的&#xff0c;因此&#xff0c;这是属于WinPcap的扩展。 使用pcap_sendpacket()发送单个数据包 打开适配器以后&#xff0c;调用pcap_sendpacket()来发送手工制作的数据包。pcap_sendpacket&#xff08;&#xff09;的参数有一个要包涵发送…

android内置mp3文件下载,Android下载mp3文件并播放它

我试图从Dropbox下载一些音频文件供用户下次没有互联网时使用&#xff0c;所以代码实际上下载文件&#xff0c;但我有麻烦播放该音频我不知道如果我要解析下载的文件什么的&#xff0c;希望你能帮助Android下载mp3文件并播放它 下载文件&#xff0c;并发挥它的类&#xff0c;它…

WinCE 下播放MP3代码

//我成功运行过的代码: #include "stdafx.h"#include <dshow.h>#include <streams.h> #pragma comment (lib,"Ole32.lib")#pragma comment (lib,"Strmiids.lib") void TestMP3(void); int WINAPI WinMain(HINSTANCE hInstance,H…

(三)ChatGLM-6B 的 DeepSpeed/P-Tuning v2微调

文章目录 模型文件和相关代码准备ChatGLM6B部署解决ninja报错 训练开始 模型文件和相关代码准备 安装日期&#xff1a;2023-04-19 模型文件地址&#xff1a;https://huggingface.co/THUDM/chatglm-6b/tree/main Hash: 35ca523 相对上一篇文章&#xff08;04-09&#xff09;&am…