Теория построения крупных p2p ботнетов


Как много пафоса в этих словах: p2p ботнет. И многие считают, что создать такой ботнет могут лишь настоящие гуру. Но на самом деле это не так. Главное понять теорию p2p. А она "ужасно" проста.

Итак, главная цель - связать ip ботов между собой и передавать команды от бота к боту. Рассмотрим две p2p модели обмена сообщениями.


Архитектуры:


1. Временной обмен нодами (ip ботов).

Каждый бот хранит у себя таблицу (роутинговая таблица) со следующей структурой:

struct NODE{
	uint32 ip;
	uint16 port;
	uint32 time;
};

где ip - ип бота, time - время добавления бота, port - порт.

Пусть таблица будет ограничена размером в 255 элементов NODE [255]; т.е. максимальное число соседей бота будет 255. Таблица содержит уникальные IP и упорядочивается по времени. Это, например, можно сделать с помощью функции qsort.

8.5.1.2 - 10:55:10 01.09.2013
1.5.1.2 - 10:53:10 01.09.2013
1.1.1.2 - 10:53:01 01.09.2013
1.1.1.2 - 06:33:10 01.09.2013
....

Бот "смотрит" в свою таблицу, извлекает из неё последовательно элементы и отправляет сообщения с запросом нового списка. Бот, до которого дошло такое сообщение, отвечает актуальными ip (из вершины таблицы). Но отсылает не все 255 ип. А часть, например, 10 элементов NODE[10]; Бот, инициатор запроса нового списка ip, получает эти NODE[10], проверяет, есть ли они в его списке. Если да, то обновляет время. Если нет, то добавляет новые, если таблица заполнена (255 элементами) - обновляет самый "старый" элемент.

Таким образом, поддерживается постоянный обмен IP. Причем в таблицу заносятся актуальные IP. В качестве времени при передаче ip между ботами лучше передавать дельту time_delta=now()-time. Где now() - текущее время (чтобы избежать некоторых атак, связанных с передачей "запредельного" значения времени).

Вся сеть представляет один большой сегмент, в качестве координат которого будет время, и вся сеть стремится к текущему времени.
В качестве реальных примеров такой сети можно выделить ZAccess. Он использует как раз такую архитектуру p2p сети.


2. Обмен нодами по расстоянию (распределенные хеш таблицы DHT)

У каждого бота имеется роутинговая таблица:

struct NODE{
	uint8 nid[16]; //ид ноды (бота)
	uint32 ip;	//ип
	uint16 port;	//порт
	uint32 time;	//время
};

Количество элементов ограничено NODE[255]. Каждый бот при своей установке генерирует ид и запоминает его - это nid, например, 0x00000000000000000000000000000004.
При обмене нодами бот заносит в свою роутинговую таблицу только близкие к себе nid, и только потом ориентируется на время time.

Допустим, есть список:

0x00000000000000000000000000000000
0x00000000000000000000000000000001
0x00000000000000000000000000000002
0x00000000000000000000000000000003
0x00000000000000000000000000000005
0x00000000000000000000000000000006
0x00000000000000000000000000000007
0x00000000000000000000000000000008

Соответственно близкими для 0x00000000000000000000000000000004 будут:

0x00000000000000000000000000000003 (4-3) = 1
0x00000000000000000000000000000005 (5-4) = 1
0x00000000000000000000000000000002 (4-2) = 2
0x00000000000000000000000000000006 (6-4) = 2

и т.д.

Для работы с близкими nid нужно как-то вычислять их расстояния и потом упорядочивать. Для этого применяется побитовая (побайтовая) операция XOR. Давайте посмотрим, что будет, если проксорить список на 0x00000000000000000000000000000004:

(0x00000000000000000000000000000000^0x00000000000000000000000000000004)=0x00000000000000000000000000000004
(0x00000000000000000000000000000001^0x00000000000000000000000000000004)=0x00000000000000000000000000000005
(0x00000000000000000000000000000002^0x00000000000000000000000000000004)=0x00000000000000000000000000000006
(0x00000000000000000000000000000003^0x00000000000000000000000000000004)=0x00000000000000000000000000000007
(0x00000000000000000000000000000004^0x00000000000000000000000000000004)=0x00000000000000000000000000000000
(0x00000000000000000000000000000005^0x00000000000000000000000000000004)=0x00000000000000000000000000000001
(0x00000000000000000000000000000006^0x00000000000000000000000000000004)=0x00000000000000000000000000000002
(0x00000000000000000000000000000007^0x00000000000000000000000000000004)=0x00000000000000000000000000000003
(0x00000000000000000000000000000008^0x00000000000000000000000000000004)=0x0000000000000000000000000000000С

упорядочиваем по результату:

(0x00000000000000000000000000000004^0x00000000000000000000000000000004)=0x00000000000000000000000000000000
(0x00000000000000000000000000000005^0x00000000000000000000000000000004)=0x00000000000000000000000000000001
(0x00000000000000000000000000000006^0x00000000000000000000000000000004)=0x00000000000000000000000000000002
(0x00000000000000000000000000000007^0x00000000000000000000000000000004)=0x00000000000000000000000000000003
(0x00000000000000000000000000000000^0x00000000000000000000000000000004)=0x00000000000000000000000000000004
(0x00000000000000000000000000000001^0x00000000000000000000000000000004)=0x00000000000000000000000000000005
(0x00000000000000000000000000000002^0x00000000000000000000000000000004)=0x00000000000000000000000000000006
(0x00000000000000000000000000000003^0x00000000000000000000000000000004)=0x00000000000000000000000000000007
(0x00000000000000000000000000000008^0x00000000000000000000000000000004)=0x0000000000000000000000000000000С

Упорядочивать можно опять функцией qsort, так как у нас не используется таблиц с большим количеством элементов. Но, если вы планируете использовать большие роутинговые таблицы, то следует использовать бинарное дерево.

Таким образом, каждый бот концентрирует близкие к себе nidы. Этим сеть разбивается на множество сегментов, равных количеству ботов.
В качестве реального примера - это сеть Zeus GameOver (P2P).
В такой сети можно выполнять поиск nid. А если прикрепить к nid, например, файл, то и поиск определенного файла. Скажем, от файла считается md5 (как раз 16 байт для нашего примера) h1. Среди своей роутинговой таблицы ищется nid, близкий к h1 (или несколько, так как не все ноды могут быть онлайн), выполняется запрос к списку близких nid с запросом h1. Удаленная нода получает такой запрос и по своему списку ищет близкие к h1, и отправляет их обратно. После нескольких таких запросов, если расстояние сокращается, nid^h1 может превысить некоторое значение. То можно считать, что файл найден, и выполнить запрос на скачку файла с ноды. Таким образом, происходит поиск файлов в сетях KAD.


Файлы в p2p сети:

Рассмотренные выше типы сетей хоть и по разному, но связывают между собой ip ботов. А значит, боты могут отправлять сообщения своим "соседям". В качестве таких сообщений могут быть файлы. Скажем так. Если загрузить на одного бота файл, то он может передать его своим соседям, а они своим соседям и так далее, пока файл не распространится по всей сети.

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


Туннели (прокси):

Из вышесказанного можно заметить, что такая сеть не имеет командного центра, а его иметь бы хотелось, для сбора статистики о ботах, данных формграббера, вебинжектах и прочем. И чтобы этот командный центр был скрыт за нодами.

Для реализации такой идеи можно в каждого бота добавить возможность туннелировать трафик.

  1. ботмастер выбирает среди своего списка ботов тех, которые будут туннелировать трафик;
  2. подключается к ним и отправляет подписанный цифровой подписью пакет с IPcc:PORTcc своего CC, превращая, тем самым, бота в туннель;
  3. создает конфиг, в котором подписывает цифровой подписью IPproxy:PORTproxy - бота, которого он превратил в туннель;
  4. рассылает по сети конфиг стандартным способом, как для обычных файлов.

Боты начинают ломиться на туннель, который пересылает пакеты на CC:

			bot1 ___
				|
			bot2----IPproxy:PORTproxy-->IPcc:PORTcc
				|
			bot3____|

Обычно для обмена списками ip применяется UDP протокол, а для загрузки/скачки файлов TCP, для туннелей TCP.

Удачи вам в ботостроительстве.


______________________________
pest
2013

Inception E-Zine