Winpcap学习笔记
————————————————
版权声明:本文为CSDN博主「Ezioooooo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012877472/article/details/49817875
一、配置(VS2015)
项目右键属性,在C/C++目录预处理器添加WPCAP和HAVE_REMOTE,预编译头改为不使用预编译头,链接器输入wpcap.lib和ws2_32.lib,VC++目录包含目录添加下载的include文件,库目录添加下载的lib文件。
二、获取设备列表
(编写winpcap程序的第一件事)
pcap_findalldevs_ex()函数来实现这个功能:创建一个可以被函数pcap_open()打开的网络设备链表
pcap_findalldevs_ex(
char * source, //字符指针,保存来源的位置,设为PCAP_SRC_IF_STRING;
struct pcap_rmthauth* auth, //指向pcap_rmtauth结构体的指针,保存需要远程设备捕获协议认证的信息。捕获本地设备设为NULL;
pcap_if_t** alldevs, //一个pcap_if_t结构体指针,函数返回时用来保存找到的适配器的信息;
char* errbuf //用来保存错误信息;
); //返回值:如果返回0,表示函数运行成功,说明找到合适的适配器,通过alldevs参数返回;如果返回-1,发生错误,或者没有在本地找到合适的适配器;
pcap_if_t结构体定义如下:
pcap_if* next; //指向链表的下一个节点,如果不为空指向一个pcap_if元素;
char* name; //字符串指针,存储传向pcap_open_live函数的设备名称;
char* description; //设备的描述;
pcap_addr* addresses;//这项这个设备接口地址链表的第一个元素;
u_int flags; //当前唯一的值是PCAP_IF_LOOPBACK,当当前接口是回路接口的时候设置;
当我们完成设备列表的使用后,应当调用pcap_freealldevs()函数释放内存资源。
三、获取已安装设备的详细信息
函数pcap_findalldevs_ex()返回的pcap_if结构体中,都有一个pcap_addr的结构体,这个结构体用来保存地址信息。
pcap_addr* next;//指向下一个节点
sockaddr* addr;//一个地址列表
sockaddr* netmask;//一个掩码列表
sockaddr* broadaddr;//一个广播地址列表
sockaddr* dstaddr;//一个目的地址列表
sockaddr结构用来存储与Windows套接字通讯的计算机上的一个IP地址。
四、打开适配器并捕获数据包
①打开适配器:函数pcap_open():
pcap_t* pcap_open (
const char * source, //设备名称
int snaplen, //制定要捕获数据包中的哪些部分,将值定为65535确信总能收到完整数据包(比最大MTU大
int flags, //*最重要,用来指示适配器是否要被设置成混杂模式(不管这个数据包是不是发给我的,我都会去捕获。WinPcap能捕获其他主机的所有的数据包)
int read_timeout, //读取超时时间
struct pcap_rmtauth * auth, //远程机器验证
char * errbuf //错误缓冲池,存储错误信息
);
函数返回:一个可以作为调用参数的指向pcap_t结构的指针,并且指定一个WinPcap会话。如果出现错误,返回NULL,errbuf中存储错误信息。
typedef struct pcap pcap_t //一个已打开的捕捉实例的描述符
②捕获工作:
pcap_dispatch() 或 pcap_loop()函数:
int pcap_loop (
pcap_t * p, //pcap的句柄
int cnt, //捕获包的数量,如果是负数表示永不停止直到出现错误
pcap_handler callback, //回调函数,当捕获到数据包时调用此函数
u_char * user //留给用户使用的
);
其中回调函数:
void(*) pcap_handler(
u_char *user, //函数pcap_loop()传递过来的,就是pcap_loop()函数中的user参数
const struct pcap_pkthdr *pkt_header, //表示捕获到的数据包的基本信息
const u_char *pkt_data //表示捕获到的数据包的内容
);
结构体:
struct pcap_pkthdr {
struct timeval ts; /* 时间戳 */
bpf_u_int32 caplen; /* 已捕获部分的长度 */
bpf_u_int32 len; /* 该包的脱机长度 */
}; //保存捕获到的包的基本信息,由pcap_loop函数自动填充
③不用回调方法捕获:
pcap_next_ex()函数代替pcap_loop()函数来实现捕获数据包,当只有显示调用时才能捕获数据包。
int pcap_next_ex (
pcap_t * p, //句柄
struct pcap_pkthdr ** pkt_header, //指向一个pcap_pkthdr结构的指针,用于保存捕获数据包的基本信息
const u_char ** pkt_data //保存捕获的数据
);
//捕获一个数据包,然后用捕获的数据包填充pkt_header和pkt_data参数,根据结果不同,返回不同的数字(1成功)。
五、过滤数据包
pcap_compile() 和 pcap_setfilter() 函数:
int pcap_compile(
pcap_t *p, //返回数据包捕获的指针
struct bpf_program *fp, //一个bpf_program结构的指针,用于过滤,在pcap_compile()函数中被赋值。
char *str, //规定过滤规则
int optimize, //控制结果代码的优化。规定了在结果代码上的选择是否被执行
bpf_u_int32 netmask); //指定本地网络的网络掩码(该网卡的子网掩码),通过pcap_lookupnet()获取
将str指定的规则整合到分fp过滤程序中,并生成过滤程序入口地址,用于过滤选择期望的数据包。成功返回0,否则返回-1。
过滤规则str由一个或多个原语组成,如果为""表示不进行过滤。原语通常由一个标识id(名字或序列)和限定词(输入(type,指明哪些东西是id所代表的,可能的输入是host,net和port,默认host),方向(dir,id指明了一个特定的传输方向,可能的方向是src,dst,src or dst,默认src/dst),协议(proto,所匹配的协议ether,fddi,tr,ip,ip6,arp,rarp,decnet,tcp和udp,默认所有都可))组成。很复杂,记得查询。
六、分析数据包
此时已经可以可以捕获并过滤网络流量,以TCP/UDP为例分析。
网络中的数据包每经过一个层次都会加上那个层的报头来标注一些重要的信息。
捕获到的数据包首先有个mac报头,14字节,包含6字节目的mac地址、6字节源mac地址,和2字节上一层协议(不关注mac),接下来是IP数据包有20字节的报头。
IP报头定义:
/* 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_char 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; // 选项与填充(Option + Padding)
}ip_header;
通过首部长度(ip_len = (ih->ver_ihl & 0xf) * 4;)得到UDP数据包的位置。
UDP报头定义:
/* 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)
TCP报头定义:
/* tcp 首部 */
typedef struct tcp_header {
u_short sport; //源端口
u_short dport; //目的端口
u_int th_seq; //序列号
u_int th_ack; //确认号
u_short doff : 4, hlen : 4, fin : 1, syn : 1, rst : 1, psh : 1, ack : 1, urg : 1, ece : 1, cwr : 1; //4 bits 首部长度,6 bits 保留位,6 bits 标志位
u_short th_window; //窗口大小
u_short th_sum; //校验和
u_short th_urp; //紧急指针
}tcp_header;
}udp_header;
UDP报头:
TCP报头:
七、保存数据包到堆文件
①pcap_dump_open()函数打开一个可以保存数据的文件。
pcap_dumper_t* pcap_dump_open (
pcap_t * p, //一个libpcap存储文件的描述符,对用户不可见
const char * fname //要写入的文件名
);//只有当接口打开时,调用 pcap_dump_open() 才是有效的。 这个调用将打开一个堆文件,并将它关联到特定的接口上。
②pcap_dump()函数将数据包写入用户指定的文件中。
void pcap_dump (
u_char * user, //文件描述符dumpfp
const struct pcap_pkthdr * h, //pkt_header
const u_char * sp //要用pkt_data
);
八、从堆文件读取数据包
pcap_open_offline()函数将堆文件打开。
pcap_t* pcap_open_offline (
const char * fname, //要打开的文件名
char * errbuf //保存错误信息
);
通过pcap_createsrcstr()函数根据新WinPcap语法创建一个源字符串。
int pcap_createsrcstr (
char * source, //要存入的源字符串
int type, //要创建的源字符串类型
const char * host, //远程主机
const char * port, //远程端口
const char * name, //我们要打开的文件名
char * errbuf //存储错误信息
); //返回值:0:没有错误;-1:创建出错,错误写入errbuf中
Winpcap学习笔记的更多相关文章
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...
随机推荐
- 对c语言中static函数的理解
先看看前两篇博客:个人对头文件的理解.对声明和定义的理解. static 函数只在定义该static函数的cpp中可见,在其他cpp中是不可见的. 举个例子,我建立了一个project,该projec ...
- 【WPF学习】第四十五章 可视化对象
前面几章介绍了处理适量适中的图形内容的最佳方法.通过使用几何图形.图画和路径,可以降低2D图形的开销.即使正在使用复杂的具有分层效果的组合形状和渐变画刷,这种方法也仍然能够正常得很好. 然而,这样设计 ...
- 数据算法 --hadoop/spark数据处理技巧 --(9.基于内容的电影推荐 10. 使用马尔科夫模型的智能邮件营销)
九.基于内容的电影推荐 在基于内容的推荐系统中,我们得到的关于内容的信息越多,算法就会越复杂(设计的变量更多),不过推荐也会更准确,更合理. 本次基于评分,提供一个3阶段的MR解决方案来实现电影推荐. ...
- Nginx是什么 ? 能干嘛 ?
学习博客:https://blog.csdn.net/forezp/article/details/87887507 学习博客:https://blog.csdn.net/qq_29677867/ar ...
- bootstrap--网格化布局
1.响应式网格系统随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列 2.规则 行必须放置在 .container class 内,以便获得适当的对齐(alignment)和内边距 ...
- Solr系列2-Solr服务安装
1: Solr简介 1.1 简介: 1.2 下载: 2:Solr 安装 2.1 安装 2.2 目录结构 3 :启动Solr 3.1 启动 3.2使用Solr提供的测试数据 3.5 Solr配置文集 3 ...
- OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c0000000, 1073741824, 0) failed; error='Out of memory' (errno=12)
使用docker 安装kafka时启动失败 查看报错日志 # docker logs --since 30m 71846a96e514 Excluding KAFKA_HOME from broker ...
- 在debian10启动器中添加自定义应用
首先要添加一个desktop类型的文件,搜索一下即可 若将desktop文件放在/usr/share/applicatios/中,需要执行update-desktop-database使新添加的应用生 ...
- spring boot 打包jar后访问classes文件夹的文件提示地址不存在
报错内容:class path resource [client.p12] cannot be resolved to absolute file path because it does not r ...
- RT-Thread can - STM32F103ZET6
SDK版本v4.0.2 目前,RT-Thread Studio还不能够自定义添加can设备.下面介绍手动添加过程: 使用RT-Thread Studio创建一个简单工程 使用RT-Thread env ...