基于ARP和WinPcap的网络嗅探

WinPcapwindows下的一个开源库,简单来说就是用户自己可以发送数据包,比如windows XP之后就不能用socket发送SYN数据包了,因为操作系统进行了封装。所以想要发送自己的数据包,就要绕开操作系统,WinPcap就提供了这样的功能。

     再说ARP——地址解析协议,ARP是数据链路层的协议。一般来说,一个局域网会用一个或多个路由器与Internet连接,那么当外部数据要发送到目的主机是怎么样的呢?同样,局域网内部主机间通信是怎么样的。我们都知道,网络通信的本质是寻找MAC地址,但是在socket编程中我们只是给了目标机的IP地址,并没有MAC地址。

      MAC的工作原理:外来的数据包到达路由器时,路由器取出数据包中的目的IP地址,如果路由器知道这个IP地址是哪台主机,那么路由器会直接将数据包发过去。假如路由器不知道这个IP是哪台主机,则路由器会广播一个ARP请求包,意思是“192.168.0.10是谁的IP?”。当局域网的主机收到数据包后会检查自己的IP,看是不是192.168.1.10,如果不是,则丢弃,假如是,则该主机会把发送方的IP和MAC地址记录下来,同时把自己的MAC发过去。

      既然ARP的请求是广播形式,那我们可以用ARP来嗅探局域网中的主机,简单来说就是发送一个ARP数据请求包,看有没有回应,如果有,则说明局域网中有对应的IP主机。     


0           8             16                         32
+-------------------------+-------------------------+
|       硬件类型          |         协议类型        |
+-------------------------+-------------------------+
|  硬件长度  |   协议长度 |            操作         |
+------------+------------+-------------------------+
|              发送端硬件地址 6字节                 |
+---------------------------------------------------+
|                 发送端协议地址                    |
+---------------------------------------------------+
|                  目的端硬件地址 6字节             |
+---------------------------------------------------+
|                  目的端协议地址                   |
+---------------------------------------------------+

    硬件类型:以太网上填 1

    协议类型:如果是IPV4,则写0x0800

    硬件长度:物理地址的长度以字节为单位,mac地址的长度为6

    协议长度:逻辑地址长度,即IP地址,以字节为单位,IPV4的长度为4字节

    操作:1表示ARP请求,2表示ARP应答

    发送端硬件地址 / 发送端协议地址:发送端的mac地址和IP地址

    目的端硬件地址 / 目的端协议地址:目的端mac地址和IP地址,ARP请求数据包是以广播的形式发送的,所以他不知道目的硬件地址。《TCP-IP协议簇》上说对于ARP请求报文,目的端硬件地址全为0,但我测试时全为1也可以。

    只是一个ARP数据包还是不能发送的,得加上以太网头,最后组成如下格式:

        0                   6                  12       14

+-------------------+------------------+--------+-----------+
|   以太网目的地址  |   以太网源地址   | 帧类型 |  ARP报文  |
+-------------------+------------------+--------+-----------+

     注意:对于ARP请求报文来说,它是广播发送的,所以以太网目的地址全写1,不然发不出去。

[cpp]  view plain copy
  1. struct ARP_HEADER  
  2. {  
  3.     unsigned char ucHardwareType[2];  
  4.     unsigned char ucProtocolType[2];  
  5.     unsigned char ucHardwareLen;  
  6.     unsigned char ucProtocolLen;  
  7.     unsigned char ucOperatorType[2];  
  8.     unsigned char ucSenderMacAddr[6];  
  9.     unsigned char ucSenderIpAddr[4];  
  10.     unsigned char ucRecverMacAddr[6];  
  11.     unsigned char ucRecverIpAddr[4];  
  12.     unsigned char ucPadding[18];  
  13. };  
  14.   
  15. struct ETHERNET_HEADER  
  16. {    
  17.     unsigned char ucDstMacAddr[6];  
  18.     unsigned char ucSrcMacAddr[6];  
  19.     unsigned char ucEthernetType[2];  
  20. };  
  21.   
  22. struct DEVS_INFO  
  23. {  
  24.     char szDevName[512];  
  25.     char szDevsDescription[512];  
  26. };  
  27.   
  28. int GetAllDevs( DEVS_INFO devsList[] )  
  29. {  
  30.     int nDevsNum = 0;  
  31.     pcap_if_t *alldevs;  
  32.     char errbuf[PCAP_ERRBUF_SIZE];  
  33.     if ( pcap_findalldevs(&alldevs,errbuf) == -1 )  
  34.     {  
  35.         return -1;  
  36.         printf("error in pcap_findalldevs_ex: %s\n",errbuf);  
  37.     }  
  38.     for ( pcap_if_t *d = alldevs; d != NULL; d = d->next )  
  39.     {  
  40.         strcpy( devsList[nDevsNum].szDevName, d->name );  
  41.         strcpy( devsList[nDevsNum].szDevsDescription, d->description );  
  42.         nDevsNum++;  
  43.     }  
  44.     pcap_freealldevs(alldevs);  
  45.   
  46.     return nDevsNum;  
  47. }  
  48.   
  49. void HandlePacketCallBack(unsigned char *param,const struct pcap_pkthdr* packet_header, const unsigned char *ucCaptureContent)  
  50. {  
  51.     ETHERNET_HEADER *pEthHeader = ( ETHERNET_HEADER *)ucCaptureContent;  
  52.     if ( *((unsigned short *)(pEthHeader->ucEthernetType)) != ntohs(0x0806) )  
  53.     {  
  54.         return;  
  55.     }  
  56.   
  57.     ARP_HEADER *pArp = ( ARP_HEADER *)(ucCaptureContent + sizeof (ETHERNET_HEADER) );  
  58.     if ( inet_addr( (char *)param) != *((unsigned int *)(pArp->ucSenderIpAddr ) ) )  
  59.     {  
  60.         return ;  
  61.     }  
  62.     if ( htons(0x002) != *(unsigned short *)pArp->ucOperatorType )   
  63.     {  
  64.         return ;  
  65.     }  
  66.     printf("\nIP: ");  
  67.     for ( int i = 0; i < 4; ++i )  
  68.     {  
  69.         printf("%d.", pArp->ucSenderIpAddr[i]);  
  70.     }  
  71.     printf("\b MAC: ");  
  72.     for ( int i = 0; i < 6; ++i)  
  73.     {  
  74.         printf("0x%02x-", pArp->ucSenderMacAddr[i]);  
  75.     }  
  76.     printf("\b \n");  
  77. }    
  78.   
  79. int SendPacket( const unsigned char *ucSendBuffer, int size, const char *pszRecverIpAddr )  
  80. {  
  81.     DEVS_INFO devsList[64];  
  82.     int nDevsNum = GetAllDevs( devsList ); //列举所有网卡  
  83.     if ( nDevsNum < 1 )  
  84.     {  
  85.         printf("Get adapter infomation failed!");  
  86.         exit(0);  
  87.     }  
  88.   
  89.     for ( int i = 0; i < nDevsNum; ++i )  
  90.     {  
  91.         printf("%d. %s    %s\n", i + 1, devsList[i].szDevName, devsList[i].szDevsDescription);  
  92.     }  
  93.   
  94.     int selIndex = 0;  
  95.     printf("Input the index of adapter: ");  
  96.     scanf("%d", &selIndex );  
  97.   
  98.     char errbuf[PCAP_ERRBUF_SIZE];  
  99.     pcap_t *handle = pcap_open_live(devsList[selIndex-1].szDevName, 65536, 1, 1000, errbuf );  
  100.   
  101.     if ( NULL == handle )  
  102.     {  
  103.         printf("\nUnable to open the adapter. %s is not supported by WinPcap\n");  
  104.         return 0;  
  105.     }  
  106.   
  107.     int index = 0;  
  108.     while ( index ++ < 1 )  
  109.     {  
  110.     if ( pcap_sendpacket(handle, ucSendBuffer, size ) != 0)  
  111.     {  
  112.         printf("\nError sending the packet: %s\n", pcap_geterr(handle) );  
  113.         return 0;  
  114.     }  
  115.     }  
  116.     pcap_loop( handle, 64, HandlePacketCallBack, (unsigned char *)pszRecverIpAddr );  
  117.     pcap_close(handle);  
  118. }  
  119.   
  120. int main()  
  121. {  
  122.     const char *pszSenderIpAddr = "10.126.72.37"//源主机ip  
  123.     const char *pszRecverIpAddr = "10.126.72.35"//目的主机ip  
  124.     const unsigned char ucSenderMacAddr[6] = {0x90, 0x2B, 0x34, 0x9A, 0xC2, 0xBB};//源主机mac  
  125.   
  126.     ARP_HEADER arp;  
  127.     memset(&arp, 0x00, sizeof arp);  
  128.   
  129.     *(unsigned short *)&arp.ucHardwareType = htons(0x0001);  
  130.     *(unsigned short *)arp.ucProtocolType  = htons(0x0800);  
  131.   
  132.     arp.ucHardwareLen = 0x06;  
  133.     arp.ucProtocolLen = 0x04;  
  134.   
  135.     *(unsigned short *)arp.ucOperatorType = htons(0x0001);  
  136.   
  137.     memcpy( arp.ucSenderMacAddr, ucSenderMacAddr, sizeof ucSenderMacAddr );  
  138.     *( unsigned *)arp.ucSenderIpAddr = inet_addr(pszSenderIpAddr);  
  139.   
  140.     memset( &arp.ucRecverMacAddr, 0xff, sizeof arp.ucRecverMacAddr );  
  141.     *(unsigned *) arp.ucRecverIpAddr = inet_addr(pszRecverIpAddr);  
  142.   
  143.     memcpy( arp.ucPadding, "hello world", 18);  
  144.   
  145.     ETHERNET_HEADER eth;  
  146.     memset( ð.ucDstMacAddr, 0xFF, sizeof eth.ucDstMacAddr);  
  147.     memcpy( eth.ucSrcMacAddr, arp.ucSenderMacAddr, 6 );  
  148.     *(unsigned short *)eth.ucEthernetType = htons(0x0806);  
  149.   
  150.     unsigned char ucSend[1024];  
  151.     memset( ucSend, 0, sizeof  ucSend );  
  152.     memcpy( ucSend, ð, sizeof eth );  
  153.     memcpy( ucSend + sizeof eth, &arp, sizeof arp );  
  154.   
  155.     SendPacket(ucSend, sizeof arp + sizeof eth, pszRecverIpAddr );  
  156.     return 0;  
  157. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值