这一节是本系列教程的结尾了,内容也比较简单,主要是对网络协议进行分析,其实学过计算机网络的同学完全可以略过

在整个项目中需要有一个头文件存放各层协议的头部定义,我把它们放在了head.h中,这个头文件都有什么呢,首先放几个关于协议的宏定义,这样可以让整个程序显得更加清晰:

 /* 网络层协议类型 */
#define IP 0x0800
#define ARP 0x0806
#define RARP 0x8035 /* 传输层类型 */
#define ICMP 0x01
#define IGMP 0x02
#define TCP 0x06
#define EGP 0x08
#define UDP 0x11
#define IPv6 0x29
#define OSPF 0x59

之后就是存放协议的头部定义了,对照着头部定义,用合适的类型定义各个字段,比如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_char ttl; // 生存时间(Time to live)
u_char type; // 协议(Protocol)
u_short crc; // 首部校验和(Header checksum)
ip_address saddr; // 源地址(Source address)
ip_address daddr; // 目的地址(Destination address)
u_int op_pad; // 选项与填充(Option + Padding)
}ip_header;

当然有些位置的意义是小于一个字节大小的,比如TCP协议中的标志位字段,有URG,ACK,PSH,RST,SYN,FIN,这些在之后用&&运算可以方便求得

当数据包被pcap_next_ex()函数捕获后,我们需要其中的两个参数,pcap_next_ex()函数原型如下:

 int     pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);

第一个参数是一个已打开的捕捉实例,也就是之前我们选择的适配器,第二个参数是一个结构体,其中内容有:

 struct pcap_pkthdr
{
struct timeval ts; ts是一个结构struct timeval,它有两个部分,第一部分是1900开始以来的秒数,第二部分是当前秒之后的毫秒数
bpf_u_int32 caplen; 表示抓到的数据长度
bpf_u_int32 len; 表示数据包的实际长度
}

因为在某些情况下你不能保证捕获的包是完整的,例如一个包长1480,但是你捕获到1000的时候,可能因为某些原因就中止捕获了,所以caplen是记录实际捕获的包长,也就是1000,而len就是1480。第三个参数就是数据包的内容后两个参数是对我们有用的,将其传递到显示数据包概略的函数ShowPacketList中

每当捕获以个数据包,需要进行保存,在MFC中可以用CArray,CArray是一个动态数组,它的用法是:CArray<Object,Object> Var1;前一个参数是指定存储在数组中的对象的类型,后一个参数是指定用于访问存储在数组中对象的参数类型。其实这两个参数一般是一样的类型,程序中存储每次抓包的pkt_header和pkt_data就用如下CArray表示:

CArray<const struct pcap_pkthdr *,const struct pcap_pkthdr *>  m_pktHeaders;
CArray<const u_char *,const u_char *> m_pktDatas;

CArray类的一些常用成员函数有:GetAt返回在给定索引上的值;Add增加一个元素;GetSize获得此数组中的元素数

存储完捕获的数据包,就可以利用pkt_data的信息来分析数据包,在分析数据包中的数据时注意,数据包的数据是按照小端模式存储的,对于大于1字节的内容需要用noths或是nothl进行转化(前者对应short,后者对应Long)。举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:0x78 | 0x56 | 0x34 | 0x12 ,这时就需要noths来转化为正确的顺序。显示数据包概要的函数部分代码如下:

 ethernet_header *eh;
eh = (ethernet_header *)pkt_data;
str.Format(_T("%x:%x:%x:%x:%x:%x"),eh->saddr.byte1,eh->saddr.byte2,eh->saddr.byte3,eh->saddr.byte4,eh->saddr.byte5,eh->saddr.byte6);
m_list1.SetItemText(nCount,,str);
str.Format(_T("%x:%x:%x:%x:%x:%x"),eh->daddr.byte1,eh->daddr.byte2,eh->daddr.byte3,eh->daddr.byte4,eh->daddr.byte5,eh->daddr.byte6);
m_list1.SetItemText(nCount,,str);
str.Format(_T("%ld"),pHeader->len);
m_list1.SetItemText(nCount,,str);
/*处理网络层*/
switch(ntohs(eh->type))
{
case IP:
{
ip_header *ih;
const u_char *ip_data;
ip_data=pkt_data+;
ih = (ip_header *)ip_data;
u_int ip_len;//IP首部长度
ip_len = (ih->ver_ihl & 0xf) * ;
str.Format(_T("%d.%d.%d.%d"),ih->saddr.byte1,ih->saddr.byte2,ih->saddr.byte3,ih->saddr.byte4);
m_list1.SetItemText(nCount,,str);
str.Format(_T("%d.%d.%d.%d"),ih->saddr.byte1,ih->saddr.byte2,ih->saddr.byte3,ih->saddr.byte4);
m_list1.SetItemText(nCount,,str);
/*处理传输层*/
switch(ih->type)
{
case TCP:

就这样陷入一层一层的分析中,对于数据包的详细分析,也就是在树形结构中显示的代码也与次类似,不做分析。

在统计部分,除了有统计各种数据包的数目外,还有一部分是流量分析:

这一部分的实现也比较简单,对于某些常用的软件,都是通过固定端口进行数据传输的,比如QQ 默认采用 UDP 通讯方式,端口 8000,8001。如果 UDP 的两个端口不通,会自动转换到 TCP 80 端口或者 TCP 443 端口进行通讯。 QQ 同时也支持 HTTP 代理模式及 SOCK5代理模式。阿里旺旺采用 TCP 通讯方式,默认登录端口为 16000,当 16000 端口不通时,则跳转到 443 端口进行通讯。所以通过对固定端口的监听,可以知道哪些软件产生了流量(这样做并不完美,有兴趣的可以分析应用层协议)

     if(ntohs( th->sport ) == 0x3E80 || ntohs( th->dport ) == 0x3E80)    //阿里旺旺流量为TCP端口16000
m_wangCount++;
if(ntohs( th->sport ) == 0x747 || ntohs( th->dport ) == 0x747) //MSN流量为TCP端口1863
m_msnCount++;

写在最后:

整体感觉编写一个嗅探器的技术层面上并不困难,但是比较繁琐,尤其是在界面方面,但是对理解网络协议还是很有帮助的。如果您需要源代码可以点此下载。源码中有一些冗余,有些数据在传递过程中并不安全,有些变量为了方便放在了public中,还请酌情参考。

MFC+WinPcap编写一个嗅探器之七(协议)的更多相关文章

  1. MFC+WinPcap编写一个嗅探器之六(分析模块)

    这一节是程序的核心,也是最复杂的地方 首先需要明白的一点是,一般对于一个有界面的程序来说,往往需要多线程.本程序中除了界面线程外,抓包需要另外创建一个新的线程.在写抓包函数之前,首先要将前面两个模块的 ...

  2. MFC+WinPcap编写一个嗅探器之五(过滤模块)

    这一节主要介绍如何获设置捕获过滤,这里的过滤是指在捕获前过滤 设置捕获过滤主要是在CFilterDlg中完成,也就是对应之前创建的设置过滤规则对话框,如图: 首先要根据用户的选择来生成一个合法的过滤规 ...

  3. MFC+WinPcap编写一个嗅探器之四(获取模块)

    这一节主要介绍如何获取设备列表,比较简单 获取设备列表主要是在CAdpDlg中完成,也就是对应之前创建的选择适配器模块,如图: 当打开选择适配器对话框后,在列表视图控件中显示当前主机所有适配器及适配器 ...

  4. MFC+WinPcap编写一个嗅探器之三(WinPcap)

    介绍程序模块前,这一节再复习一下WinPcap WinPcap开发一个嗅探器的主要步骤如下: (1)获取嗅探设备 WinPcap提供了pcap_findalldevs_ex() 函数来实现这个功能: ...

  5. MFC+WinPcap编写一个嗅探器之一(准备)

    知识准备: MFC:http://www.jizhuomi.com/software/257.html WinPcap:http://www.ferrisxu.com/WinPcap/html/ind ...

  6. MFC+WinPcap编写一个嗅探器之零(目录)

    零零散散写了三天,完成了编写嗅探器的文章,旨在让自己加深印象,是初学者少走一些弯路.因为先前未接触MFC,之后也不打算精通,完全是0基础,所以文章技术含量不高,但难点基本上都都包括了,凑合这看吧,接下 ...

  7. MFC+WinPcap编写一个嗅探器之二(界面)

    选择新建->项目->MFC应用程序->基于对话框完成,这里文件名为sniffer 打开资源视图中的Dialog列表,打开项目总默认创建的话框,将对话框中的所有控件删除,之后按照最终效 ...

  8. C++编写一个简单的DLL

    什么是DLL: 自从微软推出16位的Windows操作系统起,此后每种版本的Windows操作系统都非常依赖于动态链接库(DLL)中的函数和数据,实际上 Windows操作系统中几乎所有的内容都由DL ...

  9. 如何编写一个稳定的网络程序(TCP)

    本节我们看一下怎样才能编写一个基于TCP稳定的客户端或者服务器程序,主要以试验抓包的方式观察数据包的变化,对网络中出现的多种情况进行分析,分析网络程序中常用的技术及它们出现的原因,在之后的编程中能早一 ...

随机推荐

  1. ElasticStack系列之十三 & 联想补全策略

    业务需求 1. 实现搜索引擎前缀搜索功能(中文,拼音前缀查询及简拼前缀查询功能) 2. 实现摘要全文检索功能,及标题加权处理功能(按照标题权值高内容权值相对低的权值分配规则,按照索引的相关性进行排序, ...

  2. Java操作Kafka执行不成功的解决方法,Kafka Broker Advertised.Listeners属性的设置

    创建Spring Boot项目继承Kafka,向Kafka发送消息始终不成功.具体项目配置如下: <?xml version="1.0" encoding="UTF ...

  3. 科学计算三维可视化---Mayavi入门(Mayavi介绍和安装)

    Mayavi介绍 是基于VTK开发的可视化软件(更加高效),Mayavi完全由python编写,方便使用,而且可以使用python编写扩展,嵌入到用户程序中 安装要求 VTK >pip3 ins ...

  4. JAVA-JSP隐式对象

    JSP隐式对象 在本章中,我们将讨论和学习JSP中的隐式对象.这些对象是JSP容器为每个页面中的开发人员提供的Java对象,开发人员可以直接调用它们而不用显式地声明它们再调用. JSP隐式对象也称为预 ...

  5. angularJS $resource

    $resource是一个更方便地与RESTful服务器API进行交互,可以方便地定义一个REST资源,而不必手动所有的声明CRUD方法的Service. 使用 1.要使用$resource首先要在HT ...

  6. 洛谷P3953 [NOIP2017]逛公园

    K<=50,感觉可以DP 先建反图求出从n到各个点的最短路,然后在正图上DP 设f[当前点][比最短路多走的距离]=方案数 转移显然是 $f[v][res]=\sum f[u][res+tmp] ...

  7. addclass,removeclass

    定义和用法 addClass() 方法向被选元素添加一个或多个类. 该方法不会移除已存在的 class 属性,仅仅添加一个或多个 class 属性. 提示:如需添加多个类,请使用空格分隔类名. rem ...

  8. 20165230 《Java程序设计》实验四 Android程序设计实验报告

    20165230 <Java程序设计>实验四 Android程序设计实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:田坤烨 学号:20165230 成绩: 指导 ...

  9. WCF REST 工作总结

    首先引用System.ServiceModel;System.ServiceModel;System.ServiceModel.Activation;命名空间 [ServiceContract] pu ...

  10. java 压缩与解压

    最近复习到IO,想找个案例做一做,恰好下载了许多图片压缩包,查看图片很不方便,所以打算用IO把图片都解压到同一个文件夹下.然后集中打包. 本例使用jdk自带的ZipInputStream和ZipOut ...