linux下使用libpcap抓去http数据包

转自http://hi.baidu.com/lj%5Fjjinl/blog/item/8dd51d2365f39cfed6cae2f7.html

源码如下,这个程序不是很完美,我使用的是 libpcap1.0.0,此程序简单,我就不多说,有问题可以给我发邮件[url=]jjinl@sohu.com[/url],我们共同探讨
#include <pcap.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <string.h>
char httpbuf[4000];
int get_get(char *data,char *buff)
{
int i=0;
if(data==NULL) return 0;

while(*data!='\r')
{
   if(*data==' ')
    i++;
   if(i!=2)
   {
    *buff++=*data++;
   }
   else
   {
    *buff='\0';
    return 1;
   }
}
}
int get_url_page(char *data,char *buff)
{
if(data==NULL) return 0;
data+=4;//去掉前面"get "

while(*data!='\0')
{
   if(*data!='?')
   {
    *buff++=*data++;
   }
   else
   {
    *buff='\0';
    return 1;
   }
}
*buff='\0';
return 1;
}
int is_real_page(char *data)
{
if(data==NULL)
   return -1;
while(*data!='\0')//指针移动URL最后
{
   data++;
}
while(*--data!='/')//eg: com/fgfg.asp?eeet=yuyuu; com/jjj?ddd=123
{
   if(*data=='.')
   {
    switch(*++data)
    {
    case 'a':
     if((*++data=='s') && (*++data=='p'))
      return 1;//asp,aspx
     return 0;
    case 'h':if((*++data=='t') && (*++data=='m')) return 1;return 0;//htm,html
    case 'j':if((*++data=='s') && (*++data=='p')) return 1;return 0;//jsp
    case 'p':if((*++data=='h') && (*++data=='p')) return 1;return 0;//php
    default:return 0;
    }
   }
}
return 1;
}
int get_host(char *data,char *buff)
{
if(data==NULL) return 0;
while(data!='\0')
{
   if((*data=='H') && (*++data=='o') &&(*++data=='s') &&(*++data=='t'))
   {
    data++;//去掉http请求头标中键值对的‘:’
    while(*data!='\r')//while((*data!='\r')&&(*++data!='\n'))
    {
     *buff++=*++data;
    }
    *buff='\0';
    return 1;
   }
  
   data++;
  
}
return 0;
}
int main()
{
char error_content[PCAP_ERRBUF_SIZE];
int http_len;
struct pcap_pkthdr protocol_header;
pcap_t *pcap_handle;
const u_char *packet_content;
bpf_u_int32 net_mask;
bpf_u_int32 net_ip;
char *net_interface;

struct ether_header *eptr; //以太网帧
struct iphdr *ipptr;    //ip数据报
struct in_addr addr;
struct tcphdr *tcpptr;//tcp
char *data;
char hostbuf[500];
char getbuf[100];
char url[100];


net_interface = pcap_lookupdev(error_content);
pcap_lookupnet(net_interface, &net_ip, &net_mask, error_content);
pcap_handle = pcap_open_live(net_interface, BUFSIZ, 1, 0, error_content);
printf("Capture a packet from : %s\n", net_interface);
while(1)
{
   packet_content = pcap_next(pcap_handle,&protocol_header);
   eptr=(struct ether_header *)packet_content;
  
   if(ntohs(eptr->ether_type)==ETHERTYPE_IP)//http 基于tcp/ip,只捕获此类型的帧
   {
    ipptr=(struct ipptr *)(packet_content+sizeof(struct ether_header));//获得ip数据报的内存地址
    if(ipptr->protocol==6)        //筛选出tcp报文
    {
     tcpptr=(struct tcphdr *)(packet_content+sizeof(struct ether_header)+sizeof(struct iphdr));
     /*printf("ports:%d\n",tcpptr->dest);
     printf("ports:%d\n",htons(tcpptr->dest));
     printf("ports:%d\n",ntohs(tcpptr->dest));*/
     if(htons(tcpptr->dest)==80)//拦截向外输出的数据
     {   
      addr.s_addr=ipptr->saddr;
      //printf("\nSoure IP %s\n",inet_ntoa(addr));
      addr.s_addr=ipptr->daddr;
      //printf("Destination IP %s\n",inet_ntoa(addr));
     
      /*printf("IP head length:%d\n",ipptr->ihl);
      printf("IP length:%d\n",htons(ipptr->tot_len));*/
      data=(char *)(packet_content+sizeof(struct ether_header)+sizeof(struct iphdr)+sizeof(struct tcphdr));
     
      http_len=ntohs(ipptr->tot_len)-(ipptr->ihl)*4-sizeof(struct tcphdr);
      if(http_len>0)
       if((*data=='G')&&(*++data=='E')&&(*++data=='T'))
       {
        //printf("http length:%d\n",http_len);
        memcpy(httpbuf,data-2,http_len);
        *(httpbuf+http_len)='\0';
        //printf("%s\n",httpbuf);
        get_host(httpbuf,hostbuf);
        printf("\nRequest:%s\n",hostbuf);
      
        get_get(httpbuf,getbuf);
        printf("%s\n",getbuf);
      
        get_url_page(getbuf,url);
        printf("[url=]Url:%s\n",url[/url]);
        printf("This is %s page\n",is_real_page(url)>0 ? "real":"not");
       }/**/
     }
    }
   }
}
pcap_close(pcap_handle);
}

编译过程

1.先安装libpcap-dev
apt-get install libpcap-dev m4 flex bison

2.为什么要安装四个软件?
m4是编译flex必备的环境,否则会提示“GNU M4 1.4 is required”的错误
没有flex,直接安装libpcap会提示“Your operating system's lex is insufficient to compile libpcap”错误。
在安装flex后直接安装libpcap会提示“don't have both flex and bison;reverting to lex/yacc”错误,前面安装的是flex,就需要搭配bison


3.编译
gcc -o libpcap libpcap.c -lpcap

备注:编译时要使用libpcap的参数-lpca,否则会提示“pcap_lookupdev 未定义的引用”的错误。

4.运行指令:./libpcap

参考:http://www.linuxdiyf.com/viewarticle.php?id=97470
http://taingg.blog.163.com/blog/static/1197204832010315114623539/ (如果不想apt-get安装,可参考这里)

上一篇: FCKEditor早更名为CKEditor   下一篇: CKEditor 3实现文件上传功能[PHP编程]

提交疑问

回顶部