当前位置:文档之家› 【个人总结系列-50】应用层协议分析原理与过程-WinPcap-抓包程序

【个人总结系列-50】应用层协议分析原理与过程-WinPcap-抓包程序

1.1 应用层协议分析 要对应用层协议进行分析,首先必须抓取网络数据包,根据数据包的格式对其进行一层一层的剥离头部信息,最后得到应用层的数据,然后再根据获得的数据进行应用层行为的分析。因此必须对各层的数据包格式特别清楚,并且熟悉怎么编制抓包程序。

1.1.1 抓包程序 在编写抓包程序时,一般借助winpcap或libpcap提供的API对网络数据包进行抓取。winpcap是为windows开发环境提供的库函数,而libpcap则是为Linux开发环境提供的库函数。它们都是一个强大的网络开发库,可以实现许多功能,如获取可用的网络适配器、获取指定适配器信息(比如名称和描述信息)、捕获指定网卡的数据封包、发送数据封包、过滤捕获的包以获取特定包等。两者提供的接口基本一致,只是某些函数名略有不同。在使用前必须将winpcap或libpcap安装在系统上,在使用时必须在工程中加入对应的开发包并在程序中声明。

1. 安装和部署winpcap 由于在Linux下安装和部署libpcap非常简单,将libpcap安装到Linux系统中,在程序编译时加上-l pcap即可。本段主要介绍在windows中安装和使用winpcap,具体的部署过程如下所示:  下载安装winpcap驱动和DLL组件,即一个winpcap的安装程序,和普通安装程序一样,点击下一步进行安装,直至完毕  下载winpcap的开发包(如WpdPack_4_0_2),将其解压缩到某个路径  在工程和程序中加入开发包  在工程中指定WpdPack_4_0_2中的Lib和Include路径  设置编译条件(添加WPCAP和HAVE_REMOTE)  设置连接器的选项(添加wpcap.lib和ws2_32.lib)  包括头文件#include "pcap.h"

2. winpcap的使用:  常用数据结构: pcap_if_t * allAdapters; //适配器列表 –>next获得下一个适配器 pcap_t * adapterHandle;//适配器句柄 struct pcap_pkthdr * packetHeader; const u_char * packetData;

 常用函数: 查找系统上所有适配器: if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&allAdapters,errorBuffer)==-1) //获得所有设备信息,存放在allAdapters中 pcap_freealldevs( allAdapters ); //释放适配器列表 打开适配器并获取其句柄: adapterHandle = pcap_open( adapter->name, // name of the adapter 65536, // portion of the packet to capture 65536 guarantees that the whole packet will be captured PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode 1000, // read timeout - 1 millisecond NULL, // authentication on the remote machine errorBuffer // error buffer ); 发送数据包: if( pcap_sendpacket( adapterHandle, // the adapter handle packet, // the packet u_char packet[20]; //待发送的数据封包 20 // the length of the packet ) != 0 )

1.1.2 数据包格式和分析 其实协议就是为了规定一种大家都遵循的格式,在应用层、传输层、网络层、数据链路层都有自己的协议数据单元(PDU),按照数据包在网络中传输的过程,首先是应用层将实际的数据根据应用层的协议(格式)封装成一个应用层数据包(相当于一个字符串,更确切的是一个字节串),然后向下传,传到传输层,传输层将拿到的串作为自己数据包的数据部分,并在前面加上自己的头部,头部有许多字段,每个字段都有各自的含义,这样就生成了一个新的串,继续向下传。传到了网络层,网络层进行和上面类似的操作,继续传到数据链路层。数据链路层也加上自己的头部,生成一个新的串,并且在串的头部和尾部都做好标记,然后继续向下传。传到了物理层,物理层就直接将收到的串转化成二进制的电信号进行传输。假如传输到最后的目的地(端系统中),首先是物理层收到电信号,将其转化成一串字节,向上传。传到了数据链路层,数据链路层根据之前对串的头部和尾部做好的记号将有用信息提取出来,并根据头部信息提取出数据部分,只将数据部分向上传。传到了网络层,网络层根据网络层的头部信息,提取出数据部分,传给上一层,依次类推。数据在网络中(整个传输过程不包括两个端系统的部分)的传输过程只有3层,即物理层到数据链路层,再到网络层,传输的过程和上面描述的一样。 由于在对包进行分析时都要参考数据包的格式,所以数据包的格式是相当重要的。在抓包时,首先是获得链路层的帧,根据帧头可以获得源mac和目的mac以及上层的协议。一般帧头是14byte,链路层帧的包头结构在程序中的表示如下:

/* 6字节的mac地址 */

typedef struct mac_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4; u_char byte5; u_char byte6; } mac_address;

/* 14字节的ether帧头 */ typedef struct ether_header { mac_address dest_mac; mac_address src_mac; u_short protocal; } ether_header;

根据帧头的长度将指针往后移,然后可以获得IP数据报的头部指针,根据报头信息可以获得源IP、目的IP、上层协议、头部长度、总长度等信息,IP数据报的头部格式如下图所示:

图2.2.2.1 IPV4头部格式 图2.2.2.2 IPV6头部格式 IPV4报文结构在程序中的表示:

/* 4字节的IP地址 */

typedef struct ip_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4; } ip_address; /* IP头部 */ 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;

然后根据报头长度又可以计算出TCP或UDP的头部指针,根据TCP或UDP的头部信息可以获得源端口号和目的端口号等信息,一般TCP的头部长度为20bytes,UDP的头部长度为8bytes,TCP和UDP的报文格式如下所示:

图2.2.2.3 TCP报文格式 图2.2.2.4 UDP报文格式 TCP/UDP包头结构在程序中的表示: /* TCP头部 */

typedef struct tcp_header { u_short srcPort; // 源端口号 16bits u_short destPort; // 目的端口号 16bits u_int seqNum; // 序号 32bits u_int ackNum; // 确认号 32bits u_short headLen_other; // 首部长度+保留未用+其他字段 16bits u_short windowSize; // 窗口大小 16bits u_short checkSum; // 检验和 16bits u_short pointer; // 紧急数据指针 16bits u_int option; // 选项 可选、不定长 } tcp_header;

/* UDP头部 */ typedef struct udp_header { u_short srcPort; // 源端口号 16bits u_short destPort; // 目的端口号 16bits u_short udpLen; // udp长度 16bits u_short checkSum; // 检验和 16bits } udp_header;

最后就是应用层的数据了,根据上层的报文头部信息可以计算出应用层数据的头部指针,同时根据IP数据包的头部信息可以计算出应用层数据的长度,因此就可以通过程序将应用层的数据取出来,应用层又根据不同的协议取出实际有用的数据。应用层协议主要有FTP、HTTP、DNS等。 通过以上对数据包格式的了解,那么就可以很容易对捕获的数据包进行一层一层的解析了,一般捕获的数据包都是取得链路层的帧,然后再根据头部信息一层一层地剥离,具体的程序分析流程如下图所示:

相关主题