/*winpcap 捕获http数据包*/
#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 *alldevs;
pcap_if_t *d;
int inum;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
/* 获取本机设备列表 */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
/* 打印列表 */
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
if(i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return ;
}
printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum);
if(inum < 1 || inum > i)
{
printf("\nInterface number out of range.\n");
/* 释放设备列表 */
pcap_freealldevs(alldevs);
return ;
}
/* 跳转到选中的适配器 */
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++)//jump to the device of the specified index
;
cout<<"Listen on: "<<d->name<<endl;
cout<<"****************************************"<<endl;
//get the netcard adapter
pcap_t *adpt_hdl = pcap_open(d->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,errbuf);
if(adpt_hdl==NULL){
cerr<<"Unable to open adapter "<<d->name<<endl;
pcap_freealldevs(alldevs);
return;
}
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
//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;
}
}
}
}
}