基于ARP和WinPcap的网络嗅探

原创 2015年11月21日 20:19:24

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,不然发不出去。

  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. }
版权声明:本文为博主原创文章,未经博主允许不得转载。

Winpcap网络编程九之Winpcap实战,ARP协议获得MAC表及主机通信

利用Winpcap 完成两台主机之间的数据通信(数据链路层) 仿真ARP协议获得网段内主机的MAC表 使用帧完成两台主机的通信(Hello! I’m …)...
  • u010467643
  • u010467643
  • 2014年10月18日 20:45
  • 5956

WinPcap实战(一)——发送ARP包

ARP包的结构: ARP包格式:物理帧头(14B)——ARP帧结构(28B)——填充数据(18B)——CRC(4B)。这里给出一张图(图中没有18字节的填充数据和4字节的校验位): 物理帧头(14B)...
  • u013539342
  • u013539342
  • 2015年09月17日 17:00
  • 3394

WinPcap实战(二)——接收ARP包

ARP帧结构ARP帧结构(28B):硬件类型(2B,Ethernet:0x1)——上层协议类型(2B,IP:0x0800)——硬件地址长度(1B,0x6)——IP地址长度(1B,0x4)——操作(2B...
  • u013539342
  • u013539342
  • 2015年09月17日 18:21
  • 1712

利用WinPcap编程,实现基于ARP欺骗的中间人攻击

*******此实验旨在交流学习,请勿用在非正常合法途径*******利用WinPcap编程,实现基于ARP欺骗的中间人攻击 一、实验内容 利用WinPcap,分别向被欺骗主机和网关发送APR请求包,...
  • Ni9htMar3
  • Ni9htMar3
  • 2017年01月19日 08:51
  • 2152

【WinPcap】自制抓包+分析+ARP攻击(一)

【WinPcap】自制抓包+分析+ARP攻击 开篇 刚学习WinPcap,所以想练练手,做一个抓包的,不是很好玩么,或许还可以写一下自己的ARP包,来个LAN欺骗~于是乎,花了5天的时间,把TCP...
  • yzt33
  • yzt33
  • 2015年04月21日 14:09
  • 1874

基于MFC+WinpCap构造ARP请求发送包

MFC WinpCap ARP 请求吧
  • forever19911314
  • forever19911314
  • 2016年09月03日 09:53
  • 985

Windows下使用winpcap-2.1ARP探测局域网活动主机(发送ARP请求)

通过上一次的配置环境,现在就可以使用了,那么这里我们就先来发一个arp请求吧,这里建议大家安装一个wireshark(抓包工具,操作简单),以便于我们随时查看数据包,方便调试。 首先,我们需要知道的是...
  • u012198947
  • u012198947
  • 2016年04月06日 20:33
  • 936

Winpcap网络编程八之Winpcap学习教程,发包,发包!

时间问题,  使用 pcap_sendpacket() 发送单个数据包 下面的代码展示了发送一个数据包的最简单的方式。打开适配器以后,调用 pcap_sendpacket() 来发送手工制...
  • u010467643
  • u010467643
  • 2014年10月18日 19:00
  • 4024

基于Winpcap的Windows网络抓包与还原心得

新的一年工作的第一天想对过去两个月的学习做一个总结,这段时间对自我的认识和工作的心态发生了变化。对工作更加认真了,也意识到自己的责任。言归正传,下面的程序是基于winpcap的网络抓包与还原,望一同学...
  • Mjt_csdn
  • Mjt_csdn
  • 2015年03月02日 20:45
  • 1843

基于ARP和WinPcap的网络嗅探

WinPcap是windows下的一个开源库,简单来说就是用户自己可以发送数据包,比如windows XP之后就不能用socket发送SYN数据包了,因为操作系统进行了封装。所以想要发送自己的数据包,...
  • zhang1990214
  • zhang1990214
  • 2015年04月03日 16:40
  • 304
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于ARP和WinPcap的网络嗅探
举报原因:
原因补充:

(最多只允许输入30个字)