WinPcap还原HTTP
2011-03-16 20:12
253 查看
WinPcap简介
WinPcap是Win32平台上开源库,用于网络分析和数据包捕获。操作系统提供的socket,隐藏了网络底层细节,如协议处理,数据包重组等,使用Socket编程类似于操作文件。但是,有些应用程序需要直接访问网络的原始数据,比如Http分析工具,网络监控工具等等,此时操作系统提供的Socket就无法满足我们的要求了。WinPcap可以直接捕获网络中原始数据,主要功能如下:
1.
捕获原始数据,既可以捕获本机数据包,还可以捕获传输给其它机器的数据包;
2.
根据用户自定义规则过滤包
3.
发送原始数据包到网络
4.
收集网络流量统计信息
WinPcap也有自己的局限。它对数据包的操作独立于其它应用程序的。它不能堵塞、过滤和操纵网络。它只能简单的“嗅探”网络中传输的数据包。因此,它不能用于开发类似防火墙的应用程序。
WinPcap安装
点击这里下载WinPcap。点击这里下载WinPcap Win32 SDK。WinPcap安装十分简单,只需要点击下一步就可以。WinPcap的SDK十分有用,里面主要有以下几个文件夹:
l Lib:WinPcap的静态库,里面有32位和64位两个版本。
l Include:WinPcap的头文件
l Docs:WinPcap手册,结合例子描述十分详细。
l Examples-remote和Examples-pcap:示例代码,使用VC 6.0的项目进行组织。
WinPcap还原HTTP
下面,我就是用WinPcap编写一个示例程序,演示WinPcap如何还原Http协议。WinPcap可以捕获到链路层的数据包,在本例子中对应的是以太网协议。对于一个装有Http数据的以太数据包,其结构如下图:
图中E_H是Ethernet
Header的缩写,E_D是Ethernet Data的缩写,HTTP_T是HTTP Text的缩写,其它的依次类推。从此图中,我们可以看出来,最右边(最里面)HTTP_T是由其他协议一层一层包裹起来的。由于http协议是可读文本形式,所以一旦获取以太数据包后,就可以直接分析包中的内容。但是以太包头文件没有长度信息,所以,无法直接分析,只有跳到上一层协议包,也就是ip包中,获取整个ip包的长度,然后在分析ip包数据,找到http协议文本。以太包头部长度为14(dmac,smac,type),以下代码说明了如何获取ip包长度。
在上面的代码中,尤其需要注意ntohs函数的使用,该函数是将一个short整数由网络字节序转化成主机字节序(net to host short)。如果不使用以上函数,无法保证ip包长度正确。
获取的ip包的长度和ip包的首地址,现在可以分析包中内容。HTTP协议的请求信息(request)一般是以“GET ”或“POST ”开头,响应(response)一般是以“HTTP/1.1 ”开头,所以在ip包中直接搜索这些字段即可。
最后,将所有可读字段打印出来,就实现了简单的HTTP协议还原,当然此例子还有些不足,无法实现图片的还原,也没有处理HTTP请求或响应由多个TCP数据包组成的情况,经过进一步的学习后,将改进这些功能。下面是整个示例程序的完整代码,在VS 2005中需要添加WinPcap的include文件夹,lib文件夹,定义宏“HAVE_REMOTE;WPCAP”和添加“wpcap.lib ws2_32.lib”连接输入。
WinPcap是Win32平台上开源库,用于网络分析和数据包捕获。操作系统提供的socket,隐藏了网络底层细节,如协议处理,数据包重组等,使用Socket编程类似于操作文件。但是,有些应用程序需要直接访问网络的原始数据,比如Http分析工具,网络监控工具等等,此时操作系统提供的Socket就无法满足我们的要求了。WinPcap可以直接捕获网络中原始数据,主要功能如下:
1.
捕获原始数据,既可以捕获本机数据包,还可以捕获传输给其它机器的数据包;
2.
根据用户自定义规则过滤包
3.
发送原始数据包到网络
4.
收集网络流量统计信息
WinPcap也有自己的局限。它对数据包的操作独立于其它应用程序的。它不能堵塞、过滤和操纵网络。它只能简单的“嗅探”网络中传输的数据包。因此,它不能用于开发类似防火墙的应用程序。
WinPcap安装
点击这里下载WinPcap。点击这里下载WinPcap Win32 SDK。WinPcap安装十分简单,只需要点击下一步就可以。WinPcap的SDK十分有用,里面主要有以下几个文件夹:
l Lib:WinPcap的静态库,里面有32位和64位两个版本。
l Include:WinPcap的头文件
l Docs:WinPcap手册,结合例子描述十分详细。
l Examples-remote和Examples-pcap:示例代码,使用VC 6.0的项目进行组织。
WinPcap还原HTTP
下面,我就是用WinPcap编写一个示例程序,演示WinPcap如何还原Http协议。WinPcap可以捕获到链路层的数据包,在本例子中对应的是以太网协议。对于一个装有Http数据的以太数据包,其结构如下图:
图中E_H是Ethernet
Header的缩写,E_D是Ethernet Data的缩写,HTTP_T是HTTP Text的缩写,其它的依次类推。从此图中,我们可以看出来,最右边(最里面)HTTP_T是由其他协议一层一层包裹起来的。由于http协议是可读文本形式,所以一旦获取以太数据包后,就可以直接分析包中的内容。但是以太包头文件没有长度信息,所以,无法直接分析,只有跳到上一层协议包,也就是ip包中,获取整个ip包的长度,然后在分析ip包数据,找到http协议文本。以太包头部长度为14(dmac,smac,type),以下代码说明了如何获取ip包长度。
ether_header *eh = (ether_header*)pkt_data; if(ntohs(eh->ether_type)==0x0800){ // ip packet only ip_header *ih = (ip_header*)(pkt_data+14); if(ntohs(ih->proto) == 0x0600){ // tcp packet only int ip_len = ntohs(ih->tlen);//ip_len = ip_body + ip_header … } } |
获取的ip包的长度和ip包的首地址,现在可以分析包中内容。HTTP协议的请求信息(request)一般是以“GET ”或“POST ”开头,响应(response)一般是以“HTTP/1.1 ”开头,所以在ip包中直接搜索这些字段即可。
bool find_http = false; string http_txt = ""; char* ip_pkt_data = (char*)ih; for(int i=0;i<ip_len;++i){ //check the http request if(!find_http && (i+3<ip_len && strncmp(ip_pkt_data+i,"GET ",strlen("GET ")) ==0 ) || (i+4<ip_len && strncmp(ip_pkt_data+i,"POST ",strlen("POST ")) == 0) ){ find_http = true; } //check the http response if(!find_http && i+8<ip_len && strncmp(ip_pkt_data+i,"HTTP/1.1 ",strlen("HTTP/1.1 "))==0){ find_http = true; } //collect the http text if(find_http && is_readable(ip_pkt_data[i])){ http_txt += ip_pkt_data[i]; } } |
#include "pcap.h" #include <iostream> #include <iomanip> #include <string> using namespace std; /*Ethernet Heder*/ struct ether_header { u_int8_t ether_dhost[6]; /* destination eth addr */ u_int8_t ether_shost[6]; /* source ether addr */ u_int16_t ether_type; /* packet type ID field */ }; /* 4 bytes IP address */ typedef struct ip_address{ u_char byte1; u_char byte2; u_char byte3; u_char byte4; }; /* IPv4 header */ typedef struct ip_header{ u_char ver_ihl; // Version (4 bits) + Internet header length (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 }; /* UDP header*/ typedef struct udp_header{ u_short sport; // Source port u_short dport; // Destination port u_short len; // Datagram length u_short crc; // Checksum }; /*TCP Header*/ struct tcp_header { u_int16_t th_sport; /* source port */ u_int16_t th_dport; /* destination port */ u_int32_t th_seq; /* sequence number */ u_int32_t th_ack; /* acknowledgement number */ u_int16_t th_len_resv_code; // Datagram length and reserved code u_int16_t th_win; /* window */ u_int16_t th_sum; /* checksum */ u_int16_t th_urp; /* urgent pointer */ }; /* * check whether a char is readable */ bool is_readable(char c){ return isalnum(c) || ispunct(c) || isspace(c) || isprint(c); } /* * This demo show how to use winpcap sdk to capture the http request/respone, then print the readable content. * Note: in Visual Studio 2005,it should set the "project->config->c/c++->language->default unsigned char" to yes(/J) * to stop the assution. */ void main(int argc,char* argv[]){ //retrieve the devices list pcap_if_t *all_devs; char err_buff[PCAP_ERRBUF_SIZE]; if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&all_devs, err_buff)==-1){ cerr<<"Error in pcap_findalldevs_ex "<<err_buff<<endl; return; } //get the device index,default is the first one int dev_idx = 0; if(argc == 2){ dev_idx = atoi(argv[1]); } pcap_if_t *dev=all_devs; for(int i=0;i<dev_idx;++i,dev=dev->next);//jump to the device of the specified index cout<<"Listen on: "<<dev->name<<endl; cout<<"****************************************"<<endl; //get the netcard adapter pcap_t *adpt_hdl = pcap_open(dev->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,err_buff); if(adpt_hdl==NULL){ cerr<<"Unable to open adapter "<<dev->name<<endl; pcap_freealldevs(all_devs); return; } /* At this point, we don't need any more the device list. Free it */ pcap_freealldevs(all_devs); //analyze each packet struct pcap_pkthdr *header; const u_char *pkt_data; int rst=0; while((rst=pcap_next_ex(adpt_hdl,&header,&pkt_data))>=0){ if(rst==0){ //time out and not packet captured continue; } ether_header *eh = (ether_header*)pkt_data; if(ntohs(eh->ether_type)==0x0800){ // ip packet only ip_header *ih = (ip_header*)(pkt_data+14); if(ntohs(ih->proto) == 0x0600){ // tcp packet only int ip_len = ntohs(ih->tlen);//ip_len = ip_body + ip_header bool find_http = false; string http_txt = ""; char* ip_pkt_data = (char*)ih; for(int i=0;i<ip_len;++i){ //check the http request if(!find_http && (i+3<ip_len && strncmp(ip_pkt_data+i,"GET ",strlen("GET ")) ==0 ) || (i+4<ip_len && strncmp(ip_pkt_data+i,"POST ",strlen("POST ")) == 0) ){ find_http = true; } //check the http response if(!find_http && i+8<ip_len && strncmp(ip_pkt_data+i,"HTTP/1.1 ",strlen("HTTP/1.1 "))==0){ find_http = true; } //collect the http text if(find_http && is_readable(ip_pkt_data[i])){ http_txt += ip_pkt_data[i]; } } //print the http request or response if(http_txt != ""){ cout<<http_txt; cout<<endl<<"***********************************************************"<<endl<<endl; } } } } } |
相关文章推荐
- WinPcap编程之HTTP协议还原
- WinPcap编程之HTTP协议还原
- WinPcap编程之HTTP协议还原
- WinPcap编程之HTTP协议还原
- WinPcap编程之HTTP协议还原
- Master数据库的重建/还原相关 http://wwh-999.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=cat%3d%25e6%2595%25b0%25e6%
- 基于Winpcap的Windows网络抓包与还原心得
- 还原Master (一) 引用:http://laimin666.blog.51cto.com/331841/72292
- 还原Master (二) 引用:http://laimin666.blog.51cto.com/331841/72312
- php函数http_build_query数组变为GET形式字符串方式,parse_str将get参数形式的字符串还原成数组
- Winpcap数据包的抓取及还原
- 基于Winpcap的邮件还原系统的实现
- QQ协议分析及还原 http://blog.csdn.net/qinggebuyao/article/details/7814499
- http还原
- C#对HTTP数据还原
- winpcap分段的多个TCP包组装HTTP数据
- ruby porter词干还原算法 http://tartarus.org/martin/PorterStemmer/
- 应用层HTTP数据包的截获与还原技术的实现
- Winpcap数据包的抓取及还原
- winpcap局域网抓包工具http