Chinaunix首页 | 论坛 | 博客
  • 博客访问: 529894
  • 博文数量: 18
  • 博客积分: 352
  • 博客等级: 二等列兵
  • 技术积分: 770
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-15 15:44
文章分类

全部博文(18)

文章存档

2013年(4)

2012年(1)

2011年(13)

分类: LINUX

2011-11-14 17:04:43

我们在确定想进行网络嗅探,也就是抓取网络当中的数据包的时候!可以有很多方式来实现这个功能
  • BPF(Berkeley Packet Filter)
  • DLPI(Data Link Provider Interface)
  • SOCKET_PACKET type sockets(Linux only)
  • using pcap library
这里主要介绍使用pcap库来实现该功能!
首先得安装pcap库,具体安装包的可以到上查看,或者点击,下载libpcap库代码,注意:在不同的库版本下的代码在移植上可能会有问题!
在开始嗅探之前,我们应该对于嗅探有一个从全局角度的把握!
  • We begin by determining which interface we want to sniff on!也就是我们得确定我们嗅探的接口
  • Initialize pcap.This is where we actually tell pcap what device we are sniffing no.初始化pcap,也就是告诉pcap我们选择那个接口进行嗅探!
  • we must set a rule what we want to sniff specific traffic(eg.only TCP/IP packets,only packets going to port 23 etc..),'complie' it ,and apply it.Then we tell pcap to apply it to whichever session we wish for it to filter.设置嗅探规则(过滤器)并应用!顾名思义:告知pcap库,我们需要嗅探什么样的数据:是TCP/IP数据、是仅仅通过23端口的数据等等..
  • we tell pcap to enter it's primary execution loop.In this state ,pcap waits data packets or grabs packets! 进入pcap的主循环!等待数据或者是获得数据并送至相应的函数处理
  • After our sniffing needs are statisfied,we close our session and are complete!关闭!!
Settting the device 
 
    1. #include <stdio.h>
    2.  #include <pcap.h>
    3.  
    4.  int main(int argc,char **argv)
    5.  {
    6.          char *dev;
    7.          char errbuf[PCAP_ERRBUF_SIZE];
    8.          dev = pcap_lookupdev(errbuf);
    9.          if(dev == NULL){
    10.                  fprintf(stderr,"Couldn't find default device %s:\n",errbuf);
    11.                   return 1;
    12.          }
    13.          return 0;
    14. }
    15. 编译:
    16. [#15#caopeng@laptop ~/pcap]$gcc device.c -o device -lpcap
    17. 执行:
    18. [#19#caopeng@laptop ~/pcap]$sudo ./device
    19. Device :eth0
我们可以通过char *pcap_lookupdev(char *errbuf);来获取当前系统的网络设备!在此有了一个比较感性的认知!原来是使用pcap库函数可以这样方便的获得当前的网络设备!下面从一段代码来详细的说明!详细的代码请点击下载!!下面从一些片段来说明!
开始的函数pcap_lookupdev在上面已经介绍,在此不再赘述!
int pcap_lookupnet(const char *device,bpf_u_int32 *netp,bpf_u_int32 *maskp,char *errbuf);
将网络设备dev关联相应的network number 和mask。
  1. /*Find the properties for the device*/
  2.     if(pcap_lookupnet(dev,&net,&mask,errbuf) == -1){
  3.         fprintf(stderr,"Couldn't get netmask for device :%s :%s\n",dev,errbuf);
  4.         net = 0;
  5.         mask = 0;
  6.     }
dev既就是通过pcap_lookupdev获得的返回值!,net同mask均为bpf_u_int32类型变量,errbuf用于保存异常信息!在调用了该函数之后,变将网络设备的net和mask关联起来了!
pcap_t *pacp_open_live(const char *device,int snaplen,int promisc,int to_ms,char *errbuf)
在网卡混杂模式的基础之上建立一会话!
  1. /*Open the session in promiscuous mode*/
  2.     handle = pcap_open_live(dev,BUFSIZ,1,1000,errbuf);
  3.     if(handle == NULL){
  4.         fprintf(stderr,"Couldn't open device %s : %s\n",dev,errbuf);
  5.         return 2;
  6.     }
dev略过;BUFSIZ是一常量,表示这次可以抓取的最大的数据大小(该数字最好设置为该常数,毕竟不同的系统可能对于此限制不同);1表示真,就说明网卡设置在了混杂模式!1000指定了read timeout为1000 milliseconds;errbuf还是保存一些异常信息!

int pacp_compile(pcap_t *p,struct bpf_program *fp,char *str,int optimize,bpf_u_int32 netmask)
int pcap_setfilter(pacp_t *p,struct bpf_program *fp)

  1.    /*complie and apply the filter*/
  2.     if(pcap_compile(handle,&fp,filter_exp,0,net) == -1){
  3.         fprintf(stderr,"Couldn't parse filter %s:%s\n",filter_exp,pcap_geterr(handle));
  4.         return 2;
  5.     }

  6.     if(pcap_setfilter(handle,&fp) == -1){
  7.         fprintf(stderr,"Couldn't install filter %s:%s\n",filter_exp,pcap_geterr(handle));
  8.         return 2;
  9.     }
handle:用来标识建立的会话fp是用来存储编译之后的过滤规则的;filter_exp就是过滤规则;0就是网卡不再混杂模式;net就是ip;
pcap_compile()函数就是将char *str编译成 struct bpf_program *fp。(pcap_compile() is used to compile the string str into a filter program)
pcap_setfileter()函数就是指定一个过滤规则.(pcap_setfileter() is used to specify a filter program);

从开头的步骤可以看出,下面的一步就是要获取数据了,
  1. /*Grab a pcaket*/
  2.     pcaket = pcap_next(handle,&hander);
hander:这个有点类似于linux当中链表的实现!仅仅是给出了节点的指针域,至于如何得到“数据”的地址,在稍候会作介绍,这个是pcap给我们抓取的数据信息的头;

最后一步当然是关闭打开的device

下面给出一部分英文解释,详情请访问:

For the sake of simplicity, we'll say that the address this pointer is set to is the value X. Well, if our three structures are just sitting in line, the first of them (sniff_ethernet) being located in memory at the address X, then we can easily find the address of the structure after it; that address is X plus the length of the Ethernet header, which is 14, or SIZE_ETHERNET.

Similarly if we have the address of that header, the address of the structure after it is the address of that header plus the length of that header. The IP header, unlike the Ethernet header, does not have a fixed length; its length is given, as a count of 4-byte words, by the header length field of the IP header. As it's a count of 4-byte words, it must be multiplied by 4 to give the size in bytes. The minimum length of that header is 20 bytes.

The TCP header also has a variable length; its length is given, as a number of 4-byte words, by the "data offset" field of the TCP header, and its minimum length is also 20 bytes.

So let's make a chart:

VariableLocation (in bytes)
sniff_ethernetX
sniff_ipX + SIZE_ETHERNET
sniff_tcpX + SIZE_ETHERNET + {IP header length}
payloadX + SIZE_ETHERNET + {IP header length} + {TCP header length}


转载请著名出处!
阅读(7871) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~