ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   Статьи (https://forum.antichat.xyz/forumdisplay.php?f=30)
-   -   ZeroAccess plugin P2P или спецификация сетевого протокола (https://forum.antichat.xyz/showthread.php?t=376172)

Unknown 12.03.2013 10:33

ZeroAccess plugin P2P или спецификация сетевого протокола как руководство для разработки

Общее

Представляет из себя простой P2P загрузчик. Реализован в ZeroAccess виде плагина. P2P сеть строится следующим образом. Каждый бот имеет свой список пар других ботов. И периодически обменивается с другими ботами своими актуальными IP. Кроме списка IP бот может получать сначала информацию о файле имеющуюся у другого бота, а потом сам файл. Все общение между ботами производится по UDP протоколу, лишь запрос информации и скачивание файлов TCP

Протокол

При старте бот начинает слушать порты UDP, TCP 16464

Введу некоторое обозначение:

Код:

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;

Бот считывает список нод из файла, формат файла:

Код:

struct CFG_NODE{
uint32 ip;
uint32 time;
};

Все сообщения имеют заголовок формат:

Код:

struct HEAD{
uint32 crc32;
uint32 cmd;
uint32 hop;
uint32 data;
};

За хидером следуют данные зависящие от команды cmd. Команд всего 3и:

Код:

getL - запросить список нод
retL - отдать список нод
newL - публикация ноды

данные за хидером шифруются таким алгоритмом:

Код:

void encrypt(uint8 *data, int len_data){
uint32 *p = (uint32*)data;
uint32 count=len_data>>2;
uint32 key = 'ftp2';
do{
*p ^= key;
key = ROL(key, 1);
p++;
--count;
}while ( count );
}

Команда getL

Бот считывает ноды из файла и с периодом в 1с рассылает сообщение вида:

Код:

struct HEAD{
uint32 crc32;
uint32 cmd; // 'getL'
uint32 hop;  // количество прыжков 0
uint32 data; // сессия, случайное число sess
};

HEAD head;

Нода получает это сообщение и в ответ оправляет информацию о своих нодах и файлах retL. И если hop=0, то выполняет проверку на внешний IP бота отправителя. Для этого отправляет пакет:

Код:

struct HEAD{
uint32 crc32;
uint32 cmd; // 'getL'
uint32 hop;  // количество прыжков 1
uint32 data; // ip отправителя
};

HEAD head;

замете количество прыжков стало равно 1, это сообщение доходит в том случае если бот имеет внешний IP.

Команда retL

Отправляет в ответ на getL

Код:

struct HEAD{
uint32 crc32;
uint32 cmd; // 'retL'
uint32 hop;  // значение из входящего сообщения (0 или 1)
uint32 data; // sess из входящего пакета
};

struct BLOCK_NODE{
uint32 ip;
uint32 time_delta;
};

struct BLOCK_SIGN{
uint32 name_file; //имя в виде числа 32 бита
uint32 time;
uint32 size;
uint8 sign[128];
};

HEAD head;
uint32 count_node; //количество нод не более 16
BLOCK_NODE node[count_node];
uint32 count_sign;  //количество файлов не более 16
BLOCK_SIGN sign[count_sign];

Ноды в BLOCK_NODE выбираются в зависимости от времени CFG_NODE.time. При этом ноды сначала упорядочиваются по убыванию. Самое большое значение CFG_NODE.time считается самым актуальным. Выбирается не более 16и самых актуальных нод. И выполняется формирование пакетов BLOCK_NODE, причем время рассчитывается так:

Определяется дельта для от текущей даты:

Код:

BLOCK_NODE.time_delta=now()-CFG_NODE.time
При приеме пакета retL время восстанавливается:

Код:

CFG_NODE.time =now()-BLOCK_NODE.time_delta
Новые ноды добавляются к имеющемуся списку, упорядочиваются, выбираются и сохраняются те которые не старше 32 дней.

Если во входящем пакете hop=1, то бот считает себя нодой с внешним IP (супернодой), и выполняет отправку пакета newL 16 нодам из своего конфига CFG_NODE

Команда newL

Формируется в ответ на retL с hop=1 или newL

Код:

struct HEAD{
uint32 crc32;
uint32 cmd; // 'newL'
uint32 hop;  // 8 прыжков или hop-1 из входящего
uint32 data; // ip отправителя
};

HEAD head;

Сообщение рассылается 16и нодам из конфига бота.

При получении ботами newL сообщения, извлекается HEAD.data (ip ноды), и проверяется наличие этого ip с имеющимся списком. Если такого ip не оказалось, то производится его добавление. И повторная рассылка 16и нодам с HEAD.hop - 1, так продолжается пока HEAD.hop не станет равным нулю или ip не будет известен всем нодам.

Загрузка файлов

В пакетах retL имеется количество count_sign и BLOCK_SIGN. Это информация о файлах которая имеется у бота. При получении такого пакета бот проверяет цифровую подпись BLOCK_SIGN.sign, затем смотрит есть ли у него имя файла BLOCK_SIGN.name_file, если такое имя имеется то выполняется проверка времени.

При выполнении всех этих условий выполняется tcp соединение, и отправляется пакет:

Код:

struct BLOCK_FILE{
uint32 name_file;
uint32 time;
uint32 size;
};

BLOCK_FILE info;

В ответ приходит файл зашифрованный RC4 с ключом md5(info). Файл расшифровывается и проверяется цифровая подпись, которая берётся из ресурсов принятого файла. Если все прошло успешно, то файл сохраняется.

Дополнительная литература

Старая версия протокола p2p модуля, и самого ZeroAccess

hxxp://www.kindsight.net/sites/default/files/Kindsight_Malware_Analysis-ZeroAcess-Botnet-final.pdf

p.s

Хочу заметить что этот протокол рассчитан лишь на загрузку файлов на машины юзеров. Но его можно немного модифицировать, добавить код который сможет туннелировать трафик. В качестве одного из файлов раздавать список IP на которые будут стучаться боты. А те боты на которые происходит обращение будут переправлять траф на наш CC. В результате между ботами и СС, будет прокладка в виде тех же ботов.


Время: 20:45