Chinaunix首页 | 论坛 | 博客
  • 博客访问: 336054
  • 博文数量: 56
  • 博客积分: 2058
  • 博客等级: 中尉
  • 技术积分: 688
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-11 09:19
个人简介

code rush

文章分类

全部博文(56)

文章存档

2012年(2)

2011年(54)

分类: LINUX

2011-06-12 22:30:32

最近心血来潮,想自己抓抓网卡上的数据,于是插了以下资料,linux下有个libcap还不错。于是鼓捣着搞了稿。,写了个小例子。以后会把这个东西完善以下,包装成一个小工具。 还有一个办法是利用原始套接字接口,不过原始套接字还是略显复杂,后面会详细的总结以下。

执行这样的操作一般需要较高的权限~~

libpcap这个数据包捕获函数库,通过网卡抓取网络以太网中的数据包。为用户提供了一组的相对清晰整洁的c函数编程接口。

基于pcap的检测程序的总体架构,其流程如下:可以参考
 获取API的说明

首先要决定用哪一个接口进行嗅探开始。
我们也可以用一个字符串来定义这个设备,或者采用pcap提供的接口名来工作。

函数名称:char *pcap_lookupdev(char *errbuf) 
函数功能:用于返回可被pcap_open_live()或pcap_lookupnet()函数调用的网络设备名指针。
参数说明:如果函数出错,则返回NULL,同时errbuf中存放相关的错误消息。
或者直接定义 *dev=“eth0” 也可。


初始化pcap。在这里需要告诉pcap对什么设备进行嗅探,可以嗅探多个设备。
pcap_t *pcap_open_live(char *device, int snaplen int promisc, int to_ms, char *ebuf)

 获得用于捕获网络数据包的数据包捕获描述字。device参数为指定打开的网络设备名。snaplen参数定义捕获数据的最大字节数。promisc指定是否将网络接口置于混杂模式。to_ms参数指定超时时间(毫秒)。ebuf参数则仅在pcap_open_live()函数出错返回NULL时用于传递错误消息。


怎样区分它们呢?使用 文件句柄。就像打开一个文件进行读写一样,必须命名我们的嗅探“会话”,
以此使它们各自区别开来。

如果只想嗅探特定的传输(如TCP/IP包,发往端口23的包等等),我们必须创建一个规则集合,
编译并且使用它。定义filter_exp 字符数组定义规则。 这个选项有很多选择,需要查阅官方文档。
函数名称:int pcap_setfilter(pcap_t *p, struct bpf_program *fp) 
函数功能:指定一个过滤程序。 
参数说明:fp参数是bpf_program结构指针,通常取自pcap_compile()函数调用。
出错时返回-1;成功时返回0。


这个过程分为三个相互紧密关联的阶段。规则集合被置于一个字符串内,并且被转换成能被pcap读的格式,
详细见官方文档。


最后,我们告诉pcap进入它的主体执行循环。在这个阶段内pcap一直工作到它接收了所有我们想要的包为止。
每当它收到一个包就调用另一个已经定义好的函数,这个函数可以做我们想要的任何工作,它可以剖析所部获
的包并给用户打印出结果,它可以将结果保存为一个文件,或者什么也不作。

函数名称:int pcap_loop(pcap_t *p, int cnt,pcap_handler callback, u_char *user) 
函数功能:功能基本与pcap_dispatch()函数相同,只不过此函数在cnt个数据包被处理或出现错误时才返回,
但读取超时不会返回。而如果为pcap_open_live()函数指定了一个非零值的超时设置,然后调用
pcap_dispatch()函数,则当超时发生时pcap_dispatch()函数会返回。cnt参数为负值时pcap_loop()
函数将始终循环运行,除非出现错误。

要求用户对网络包的结构比较熟悉,才能取到合适的数据。 callback 函数可以执行分析数据包的功能,获得
数据包的一些信息,不过有些内容是不可看的乱码,如果是一些网页传送数据,可以获得一些信息。准备下一步
就整理一个可以检测敏感信息的版本。定义一些规则。提醒非法的一些数据信息。

在嗅探到所需的数据后,我们要关闭会话并结束。
函数名称:void pcap_close(pcap_t *p) 
函数功能:关闭p参数相应的文件,并释放资源。 或者也可以保存当文件

函数名称:FILE *pcap_file(pcap_t *p) 
函数功能:返回被打开文件的文件名。
函数名称:void pcap_dump_close(pcap_dumper_t *p) 
函数功能:关闭相应的被打开文件。


  1. #include<stdio.h>
  2. #include<pcap.h>
  3. #include<errno.h>
  4. #include<sys/socket.h>
  5. #include<linux/ip.h>
  6. #include<linux/tcp.h>
  7. #include<netinet/in.h>
  8. #include<netinet/if_ether.h>

  9. //分析数据包的内容
  10. void callback(u_char * user, const struct pcap_pkthdr * pkthdr, const u_char * packet)
  11. {
  12.     struct in_addr addr;
  13.     struct iphdr *ipptr;
  14.     struct tcphdr *tcpptr;
  15.     char *data;
  16.     
  17.     pcap_t *descr=(pcap_t*)user;
  18.     struct pcap_pkthdr hdr= *pkthdr;
  19.     struct ether_header *eptr;
  20.     u_char *ptr;
  21.     int i;
  22.     
  23.     if(packet==NULL)
  24.     {
  25.         fprintf(stdout,"empty packet\n");
  26.     }
  27.     else
  28.     {
  29.         fprintf(stdout,"packet length %d recved at %s Ethernet hd length %d\n",hdr.len,ctime((const time_t*)&hdr.ts.tv_sec),ETHER_HDR_LEN);
  30.     }
  31.     
  32.     eptr=(struct ether_header *)packet;
  33.     if(ntohs(eptr->ether_type)==ETHERTYPE_IP)
  34.     {
  35.         fprintf(stdout,"Ethernet type hex %x dec %d is an ip packet\n",ntohs(eptr->ether_type),ntohs(eptr->ether_type));
  36.     }
  37.     else
  38.     {
  39.         if(ntohs(eptr->ether_type)==ETHERTYPE_ARP)
  40.             fprintf(stdout,"Ethernet type hex %x dec %d is an ARP packet\n",ntohs(eptr->ether_type),ntohs(eptr->ether_type));
  41.     }
  42.     
  43.     ptr=eptr->ether_dhost;
  44.     i=ETHER_ADDR_LEN;
  45.     fprintf(stdout,"i = %d\n",i);
  46.     do
  47.     {
  48.         fprintf(stdout,"%x:",(i==ETHER_ADDR_LEN? 0: *ptr++));
  49.     }while(--i>0);
  50.     fprintf(stdout,"\n");
  51.     
  52.     ipptr=(struct iphdr*)(packet+sizeof(struct ether_header));
  53.     fprintf(stdout,"packet length %d,protocol is %d\n",ipptr->tot_len,ipptr->protocol);
  54.     addr.s_addr=ipptr->saddr;
  55.     fprintf(stdout,"Souce IP %s\n",inet_ntoa(addr));
  56.     
  57.     tcpptr=(struct iphdr*)(packet+sizeof(struct ether_header)+sizeof(struct iphdr));
  58.     fprintf(stdout,"Destion port: %d SRC port %d seq %d\n",tcpptr->dest,tcpptr->source,tcpptr->seq);
  59.     
  60.     data=(char *)(packet+sizeof(struct ether_header)+sizeof(struct iphdr)+sizeof(struct tcphdr));
  61.     fprintf(stdout,"content: %s\n",data);
  62. }



  63. int main()
  64. {
  65.     char errbuf[PCAP_ERRBUF_SIZE];
  66.     pcap_t *phandle;
  67.     char *dev;
  68.     struct bpf_program fp;
  69.     char filter_exp[20]="port 80";// portrange 1-1024  有很多定义的方式
  70.     bpf_u_int32 mask;//netmask
  71.     bpf_u_int32 net; //ip address
  72.     struct pcap_pkthdr header ;
  73.     const u_char *packet;
  74.     
  75.     printf("%d\n",sizeof header);
  76.     
  77.     
  78.     dev=pcap_lookupdev(errbuf);
  79.     if(dev==NULL)
  80.     {
  81.         fprintf(stderr,"can't get dev %s\n",errbuf);
  82.         return 2;
  83.     }
  84.     else
  85.     fprintf(stdout,"dev %s get\n",dev);
  86.     
  87.     
  88.     if(pcap_lookupnet(dev,&net,&mask,errbuf) == -1)
  89.     {
  90.         fprintf(stderr,"can't get mask %s\n",errbuf);
  91.         net =0;
  92.         mask =0;
  93.         return (2);
  94.     }
  95.     
  96.     fprintf(stdout,"ip:mask %x:%x\n",net,mask);
  97.     
  98.     phandle=pcap_open_live(dev,BUFSIZ,0,1000,errbuf);
  99.     if(phandle==NULL)
  100.     {
  101.         fprintf(stderr,"open device failed %s: %s\n",dev,errbuf);
  102.         return 2;
  103.     }
  104.     
  105.     if(pcap_compile(phandle,&fp,filter_exp,1,net) == -1)
  106.     {
  107.         fprintf(stderr,"parse filter failed %s:%s\n",filter_exp,pcap_geterr((pcap_t*)errbuf));
  108.         return 2;
  109.     }
  110.     
  111.     if(pcap_setfilter(phandle,&fp)== -1)
  112.     {
  113.         fprintf(stderr,"install filter failed %s\n",filter_exp);
  114.     }    
  115.     
  116.     pcap_loop(phandle,0,callback,NULL);
  117.     
  118.     pcap_close(phandle);
  119.     
  120.     return 0;
  121. }

阅读(1873) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~