Пакер: Winlicense
Даты компиляции и SHA1-хэши:
- a0ea9b06f4cb548b7b2ea88713bd4316c5e89f32 (Mssv36.asi) - 13.09.2017 22:16:52
Описание
Является одним из компонентов троянца Belonard. Распространяется с пиратскими сборками клиента игры Counter-Strike 1.6. Выполняет функции протектора клиента, а также устанавливает в систему Trojan.Belonard.5.
Принцип действия
Троянец проверяет наличие запущенного сервиса WinDHCP. Если его нет - распаковывает и запускает Mssv24.asi (Trojan.Belonard.5), после чего подменяет полученному файлу время создания/модификации, взяв за образец файлы Mss32.dll, msmp3.asi, hw.dll или hl.exe. Затем создает поток, в котором будет отправлять информацию на управляющий сервер, и инициализирует массив структур, собирая информацию о загруженных модулях hl.exe, GameUI.dll, hw.dll, sw.dll, client.dll.
Полученная информация формируется в структуры:
struct st_mod
{
_DWORD ImageBase;
_DWORD SizeOfImage;
_DWORD pOverlay;
_DWORD pCode;
_DWORD SizeOfCode;
_DWORD pData;
_DWORD pPEHeader;
};
Троянец сканирует память модуля client.dll по маске:
Используемая маска соответствует коду функции CHudSpectator::VidInit:
pfnSPR_Load — первый указатель на функцию в структуре cl_enginefunc_t, содержащую указатели на различные функции игрового клиента.
Получив адрес структуры cl_enginefunc_t, вызывает функцию GetFirstCmdFunctionHandle() (адрес этой функции содержится в структуре cl_enginefunc_t). Вызванная функция возвращает адрес списка структур cmd_function_t, которые содержат информацию о консольных командах клиента. С помощью cmd_function_t троянец ищет адрес функции «version». Получив его, проверяет, является ли клиент официальным.
После этого троянец изменяет память модуля steamclient.dll, записав в нее свой мастер-сервер — suysfvtm[.]valve-ms[.]ru:27012 (порт 27013, если это официальный клиент), а также перехватывает одну из функций модуля.
Троянец сканирует память модуля sw.dll в поисках метода CBaseUI::Shutdown() и вставляет в него вызов своего метода, который при выставленной глобальной переменной прекращает процесс троянца.
Затем ищет в памяти sw.dll место, где адрес строки «ScreenFade» пушится на стэк, и берет адрес по смещению 0x10 или 0x13 от этого push’а.
Найденный адрес — это указатель на структуру cldll_func_t. Используя полученный указатель, троянец перехватывает функцию HUD_Frame, и в вызванной вместо нее функции инициализирует основную часть своих перехватчиков функций и изменений памяти.
В GameUI.dll троянец перехватывает вызов функции strstr из функции CL_ParseConsistencyInfo, чтобы исключить из проверки CRC файлы с путями:
../Steam.dll
../steamclient.dll
../rev.ini
../Mssv36.asi
../platform/resource/cs.tga
../voice_speex.dll
../Start Counter-Strike Game.bat
../Start Counter-Strike Server.bat
../Start Half-Life Game.bat
../Start Half-Life Server.bat
После чего троянец перехватывает обработчики команд playdemo, viewdemo и функцию CL_ConnectionlessPacket. В них отслеживает выполняемые консольные команды и отправляет на управляющий сервер информацию об использовании команд, не входящих в имеющийся у троянца список.
Троянец также перехватывает функции Netchan_CopyFileFragments и CL_BatchResourceRequest. Это позволяет ему отправлять на управляющий сервер имена файлов, переданных клиенту другими серверами. Кроме этого троянец определяет и фильтрует потенциально опасные файлы по следующим критериям:
- По наличию в пути ".." или символов '\', ':', '*', '?', '"', '<', '>', '|';
- Путь не начинается с "idema/" или "idema\";
- Файлы имею расширения: "asi", "bat", "cfg", "cmd", "com", "dll", "exe", "flt", "ini", "js", "log", "lst", "m3d", "mix", "ocx", "rc", "scr", "vbs".
Другие функции, перехватываемые троянцем:
- CL_Parse_StuffText – оповещает управляющий сервер об используемых командах;
- CL_Parse_Director - оповещает управляющий сервер о командах с типами DRC_CMD_BANNER и DRC_CMD_STUFFTEXT;
- CL_Parse_VoiceInit - оповещает управляющий сервер о командах voice_speex и voice_miles;
- CL_Send_CvarValue - оповещает управляющий сервер о попытках изменения Cvar, находящейся в списке троянца;
- CL_Send_CvarValue2 - оповещает управляющий сервер о попытках изменения Cvar, находящейся в списке троянца.
Троянец перехватывает обработчик события MOTD и отправляет на управляющий сервер текст, который пытались вывести с помощью этой функции. Затем перехватывает вызов NET_StringToAdr, чей адрес он находит из вызова в функции CL_CheckForResend. Если IP или порт сервера, с которым происходит соединение, не совпадает с известными троянцу данными, управляющий сервер оповещается об этом. После чего троянец вносит еще несколько модификаций в память модулей client.dll, sw.dll, ServerBrowser.dll, GameUI.dll.
CallHome
Троянец инициализирует контекст AES-CFB с длиной блока 128 бит. Ключ получается вызовом EVP_BytesToKey(cipher, md, 0, &aeskey, 32, 5, key, iv). При этом aeskey находится в троянце:
После чего он расшифровывает имена управляющих серверов: suysfvtm[.]valve-ms[.]ru:28447 и etmpyuuo[.]csgoogle[.]ru:28447.
Алгоритм дешифровки:
def decrypt(data):
s = 'e'
for i in range(0,len(data)-1):
s += chr((ord(s[i]) + ord(data[i]))&0xff)
print s
Все пакеты, отправляемые на сервер и принимаемые от него, зашифровываются с помощью AES. При этом в начало отправляемых данных дописывается нулевой байт, а «padding» в отправляемых пакетах — случайно сформированный массив байт.
В принимаемых пакетах размером <= 0x10 байт:
- первый байт — идентификатор команды;
- N последующих байт — полезная нагрузка (может отсутствовать);
- остальные байты (до 12) — сверяются с данными по такому же смещению в измененных отправленных данных, выполняя функцию подписи.
Heartbeat (client - 0x8b, server - 0xD9)
Heartbeat-пакет имеет размер 0x10 байт:
#pragma pack(push,1)
struct st_buf
{
_BYTE byte_8b;
_BYTE client_ver;
_DWORD counter;
_BYTE byte_05;
_BYTE padding[9];
};
#pragma pack(pop)
Где client_ver принимает значения в диапазоне от 0 до 3 в зависимости от:
- официальный или пиратский клиент;
- русскоязычный или англоязычный клиент.
После шифрования данных в исходном буфере 6-й байт заменяется на 0x29.
Если в памяти был изменен адрес мастер-сервера, выставляется глобальный флаг, активирующий отправку подозрительных действий игровых серверов на сервер разработчика троянца.
Полезной нагрузкой является DWORD, содержащий информацию о задержке между heartbeat-пакетами. Если длина пакета больше 0x10 байт, тогда 0x20 байт по смещению 0x10 байт - это SHA256 хэш от данных, начинающихся со смещения 0x30 байт. Данные представляют собой сообщение, которое выводится в консоль клиента игры.
CheckServer (client - 0x6F, server - 0xE1)
Пакет высылается с помощью кода, перехватывающего функцию NET_StringToAdr. Структура пакета:
#pragma pack(push, 1)
struct st_checksrv
{
_WORD word_56f;
_BYTE client_ver;
_BYTE byte_ab;
_BYTE srvaddr[6];
_BYTE padding[6];
};
#pragma pack(pop)
После шифрования пакета в исходных данных первые 4 байта заменяются значением 0x894DC6E1. Если проверки пакета прошли успешно, вызывается функция клиента игры «disconnect».
GameMenuAction (client - 0x80, server - 0x12)
Структура пакета:
#pragma pack(push, 1)
struct st_gamemenu_action
{
_BYTE byte_80;
_BYTE client_ver;
_WORD word_6005;
_BYTE padding[12];
};
#pragma pack(pop)
После шифрования пакета меняется изначальная структура:
- byte_80 заменяется на 0x12;
- word_6005 заменяется на 0xDAB1;
- client_ver заменяется на 0x87, если клиент пиратский, и 0x11, если официальный.
В полученном пакете полезная нагрузка — 6 байт, задающие IP:port. Троянец преобразует их в строку и выполняет команду клиента игры connect IP:port.
GameSecurityViolation (client - 0x05)
Отправляется из кода, перехватывающего функции игрового клиента. Формат пакета:
#pragma pack(push, 1)
struct st_report
{
_BYTE byte_05;
_BYTE client_ver;
_BYTE padding[0x0e];
_BYTE hash[0x20];
_DWORD ip;
_WORD port;
char msg[];
};
#pragma pack(pop)
В отличие от остальных пакетов, в начало этого зашифрованного пакета дописывается 0x02.






