![](https://habrastorage.org/storage2/613/8b2/648/6138b264876e76799c9471decb96c15f.png)
ICMP протокол
Протокол ICMP является одним из компонентов стека TCP/IP (Transmission Control Protocol/Internet Protocol — протокол управления передачей/протокол сети Internet), который компенсирует неспособность протокола IP гарантированно доставлять данные. Вместе с тем протокол ICMP не устраняет ненадежность передачи данных протоколом IP. Он лишь уведомляет отправителя данных о том, что при их доставке возникли проблемы.
На рисунке показано место протокола ICMP в модели TCP/IP.
![](https://habrastorage.org/storage2/09a/779/ddd/09a779ddddf31e1e100cc4e5d488083b.png)
Протокол ICMP является механизмом отправки сообщений об ошибках для протокола IP.
Если при доставке дейтаграммы происходит ошибка, протокол ICMP сообщает об этом отправителю дейтаграммы. Например, предположим, что PC1, показанный на следующем рисунке, посылает дейтаграмму PC4. Если соответствующий интерфейс маршрутизатора Вorder выходит из строя, этот маршрутизатор использует протокол ICMP для отправки PC1 сообщения о том, что доставка дейтаграммы оказалась невозможной. Протокол ICMP не устраняет возникшую в сети проблему.
![](https://habrastorage.org/storage2/5c0/820/820/5c0820820dc1c518531f34d10a2e5157.png)
Сообщения протокола ICMP доставляются с использованием протокола IP.
ICMP-сообщения инкапсулируются в дейтаграммы, точно так же, как и обычные данные, доставляемые по протоколу IP. В таблице показана инкапсуляция ICMP-пакета в поле данных IP-дейтаграммы. Заголовок фрейма может формироваться по протоколу локальной сети, такому, как Ethernet, или по протоколу распределенной сети, такому, например, как HDLC.
Заголовок фрейма Заголовок IP-дейтаграммы Заголовок протокола ICMP Данные протокола ICMP
Заголовок фрейма Заголовок IP-дейтаграммы Поле данных IP-дейтаграммы
Заголовок фрейма Поле данных IP-дейтаграммы
Заголовок фрейма Поле данных фрейма
Когда данные поступают на сетевой уровень, они инкапсулируются в дейтаграмму. После этого дейтаграмма и инкапсулированные в ней данные вновь инкапсулируются во фрейм на канальном уровне. Сообщения протокола ICMP содержат в заголовках свою собственную информацию. Однако эта информация вместе с данными протокола ICMP инкапсулируется в дейтаграмму и передается таким же образом, что и все остальные данные. Поэтому сообщения об ошибках также подвержены риску быть утерянными при передаче. Таким образом, может возникнуть ситуация, в которой сами сообщения об ошибках могут создать новые ошибки, что лишь усложнит ситуацию с затором в уже работающей со сбоями сети. По этой причине ошибки, созданные сообщениями ICMP, не генерируют свои собственные ICMP-сообщения. Следовательно, возможен случай, когда при доставке дейтаграммы происходит ошибка, но о ней не сообщается отправителю данных.
Бодание с WinpCap и отправка ping’ов
Все знают команду ping, которая предназначена для отправки эхо-запроса и получения эхо-ответа. Мы же решили, что системного ping’a нам мало и попытались реализовать свою программу ping.
Инструментом для реализации был компилятор С++ и библиотечка WinPcap. WinPcap — Низкоуровневая библиотека для взаимодействия с драйверами сетевых интерфейсов.
И так начинаем сборку ICMP-пакета.
Формат ICMP-пакета успешно был взят с Wiki.
Октет | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0—3 | Тип | Код | Контрольная сумма | |||||||||||||||||||||||||||||
… | Данные (формат зависит от значений полей «Код» и «Тип») |
u_char packet[1514]; //собственно наш пакет
//MAC-адрес получателя
packet[0]=0x08;
packet[1]=0x00;
packet[2]=0x27;
packet[3]=0x4c;
packet[4]=0x18;
packet[5]=0xDA;
////MAC-адрес отправителя
packet[6]=0x08;
packet[7]=0x00;
packet[8]=0x27;
packet[9]=0xca;
packet[10]=0xb8;
packet[11]=0x44;
//Формирование IP-заголовка
packet[12]=0x08;
packet[13]=0x00;
packet[14]=0x45;
packet[15]=0x00;
//Длинна пакета
*(WORD *)&packet[16] = htons(1500);
packet[18]=0x11; //id
packet[19]=0x22;
packet[20]=0; //фрагментацию отключаем
packet[21]=0;
packet[22]=0x80; //ttl
packet[23]=1; //icmp
packet[24]=0; //контрольная сумма
packet[25]=0;
//От кого
packet[26]=192;
packet[27]=168;
packet[28]=1;
packet[29]=1;
//куда
packet[30]=192;
packet[31]=168;
packet[32]=1;
packet[33]=128;
chS=ComputeIPChecksum(&packet[14],20); //считаем контрольную сумму
printf("%x\n", chS);
*(WORD *)&packet[24] = chS;
//****************************************************
packet[34]=8; //icmp
packet[35]=0;
packet[36]=0x29; //csum
packet[37]=0x31;
packet[38]=0x11; //icmp
packet[39]=0x11;
packet[40]=0x22; //csum
packet[41]=0x22;
chS=ComputeIPChecksum(&packet[34],8);
printf("%x\n", chS);
for(i=42; i<1514; i++)
{
packet[i]= 'A';
}
//отправляем
if (pcap_sendpacket(fp, // Adapter
packet, // buffer with the packet
1514 // size
) != 0)
{
fprintf(stderr,"\nError sending the packet: %s\n", pcap_geterr(fp));
return 3;
}
Результаты посмотрим на следующем рисунке.
![](http://habrastorage.org/storage2/b49/85c/701/b4985c7011fc47319fb93dde11c1c790.png)
Видим запрос и ответ. Все ОК.
А что, если поставить левый MAC-адрес отправителя?
А что, если поставить левый IP-адрес отправителя?
А что, если MAC = FF-FF-FF-FF-FF-FF?
Можно пойти на Wiki и увидеть следующее:
ICMP-пакеты никогда не генерируются в ответ на IP-пакеты с широковещательным или групповым адресом, чтобы не вызывать перегрузку в сети (так называемый «широковещательный шторм»).
Попробуем нарушить это правило. С машины с IP 192.168.1.2 будем отправлять ping на 192.168.1.3, при этом IP отправителя будет равен 192.168.1.1, а MAC отправителя FF-FF-FF-FF-FF-FF.
![](http://habrastorage.org/storage2/d7e/27e/5a7/d7e27e5a7868ad7fb8635f5e80792ea3.png)
Оказалось, что мы заставили 192.168.1.3 отвечать 192.168.1.1, при том, что последний этого не хотел. Самое интересное, то, что это был широковещательный ping и он прошел!
Смотрим что на других машинах.
![](http://habrastorage.org/storage2/ee9/74b/c7c/ee974bc7c6ef1b094f7f9b018a6b7627.png)
![](http://habrastorage.org/storage2/638/e69/a24/638e69a2464c69e8096cd25449162904.png)
На других машинках мы ловим широковещательные запросы.
А раз так, то есть повод написать в программе while(1) и наслаждаться DOS-атакой.
Список литературы:
Одом У. — CISCO Официальное руководство по подготовке к сертификационным экзаменам CCENTCCNA ICND1 — 2010
ru.wikipedia.org