Упаковщик:
отсутствует
Дата компиляции:
06.05.2019 08:35:45
SHA1-хеш:
693f0bd265e7a68b5b98f411ecf1cd3fed3c84af
Описание
Многокомпонентный троян-бэкдор, написанный с использованием языков С/С++ и Assembler, предназначенный для работы в 32- и 64-разрядных операционных системах семейства Microsoft Windows. Используется для целевых атак на информационные системы и несанкционированного доступа к данным для их передачи на управляющие серверы. Основная функциональность содержится в дополнительных подключаемых модулях. Представляет собой вредоносную DLL-библиотеку, оригинальное имя которой находится в таблице экспорта — hpqhvsei.dll. Как и BackDoor.ShadowPad.1, эта модификация имеет много общего с образцами вредоносных программ семейства BackDoor.PlugX.
Принцип действия
Экспортируемые функции отсутствуют. Временная метка из таблицы экспорта аналогична таковой из PE-заголовка.
Первые шаги исполнения в целом соответствуют BackDoor.ShadowPad.1
- расшифровка шелл-кода и передача на него управления;
- загрузка шелл-кодом основного модуля Root, хранящегося в специальном формате;
- загрузка модулем Root остальных модулей.
Исключение составляет отсутствие перебора дескрипторов объектов с именем TosBtKbd.exe.
Алгоритм шифрования строк практически идентичен, при этом отличаются константы:
def decrypt(addr):
key = get_wide_word(addr)
result = b""
i = 2
b = get_wide_byte(addr + i)
while i < 0xFFA:
result += bytes([b ^ (key & 0xFF)])
key = (((key * 0xDB070000) - ((key >> 0x10) * 0x390624F9)) - 0x71A4D6B1) & 0xFFFFFFFF
i += 1
b = get_wide_byte(addr + i)
if not result[-1]:
break
return result[:-1]
Алгоритм загрузки дополнительных модулей также аналогичен BackDoor.ShadowPad.1, однако в рассмотренном образце присутствуют новые модули. Всего программа имеет 16 модулей. Список их имен с кодами и временными метками представлен в следующей таблице:
Имя модуля | Код | Временная метка |
---|---|---|
Config | 0x66 | 2019-05-06 08:33:07 |
Disk | 0x12C | 2019-05-06 08:29:55 |
ImpUser | 0x6A | 2019-05-06 08:33:18 |
Install | 0x67 | 2019-05-06 08:33:34 |
KeyLogger | 0x132 | 2019-05-06 08:30:26 |
Online | 0x68 | 2019-05-06 08:33:13 |
PIPE | 0xCF | 2019-05-06 08:29:11 |
Plugins | 0x65 | 2019-05-06 08:33:02 |
Process | 0x12D | 2019-05-06 08:30:00 |
RecentFiles | 0x13D | 2019-05-06 08:31:23 |
Register | 0x12F | 2019-05-06 08:30:10 |
Screen | 0x133 | 2019-05-06 08:30:31 |
Servcie (не опечатка) | 0x12E | 2019-05-06 08:30:05 |
Shell | 0x130 | 2019-05-06 08:30:15 |
TCP | 0xC8 | 2019-05-06 08:28:45 |
UDP | 0xCA | 2019-05-06 08:28:56 |
Для каждого загружаемого модуля формируется структура, которая добавляется в список, с помощью которого модули могут вызывать функции друг друга. Для работы с этим списком и для других вспомогательных задач модуль Root экспортирует таблицу функций.
Во время инициализации модуля Plugins регистрируется обработчик исключений верхнего уровня. В BackDoor.ShadowPad.1 подобный обработчик в целях отладки формировал строку с информацией об исключении. Однако, в данном образце он лишь завершает поток, который вызвал исключение. В данном случае механизм работы схож с BackDoor.PlugX.28.
Ключевое отличие в работе функций в данном случае состоит в том, что PlugX оперирует объектом, содержащим связный список всех работающих потоков, в то время как ShadowPad напрямую завершает текущий поток. Однако в целом можно провести аналогию с объектом ShadowPad, который хранит загруженные модули в виде списка.
struct all_modules //shadowpad
{
LIST_ENTRY list;
DWORD modules_count;
CRITICAL_SECTION crit_sect;
}
struct obj_threads //plugx
{
CRITICAL_SECTION crit_sect;
LIST_ENTRY list;
DWORD threads_running;
}
Исполнение основной нагрузки начинается с модуля Install. Аналогично BackDoor.ShadowPad.1, в начале этого этапа бэкдор получает необходимые привилегии. Стоит отметить, что начало работы схоже с механизмами изученных нами бэкдоров семейства PlugX. Ниже на иллюстрациях представлено сравнение алгоритмов BackDoor.ShadowPad.3 и BackDoor.PlugX.38.
Затем инициализирует конфигурацию с помощью модуля Config. Здесь также прослеживается схожесть с BackDoor.PlugX. В начале бэкдор проверяет первые четыре байта буфера, в котором должна храниться зашифрованная конфигурация. Если байты равны 0x58585858 (XXXX" в кодировке ASCII), то:
- в BackDoor.ShadowPad.3 инициализируется пустая конфигурация;
- в BackDoor.ShadowPad.1 инициализируется конфигурация по умолчанию;
В BackDoor.PlugX проверяются первые 8 байтов на равенство строке XXXXXXXX.
struct config
{
WORD off_id;
WORD offset_1;
WORD bin_path_offset;
WORD svc_name_offset;
WORD svc_display_name_svc;
WORD svc_description_off;
WORD reg_key_install_off;
WORD reg_value_name_off;
WORD inject_target_1;
WORD inject_target_2;
WORD inject_target_3;
WORD inject_target_4;
WORD off_srv_0;
WORD off_srv_1;
WORD off_srv_2;
WORD off_srv_3;
WORD off_srv_4;
WORD off_srv_5;
WORD off_srv_6;
WORD off_srv_7;
WORD off_srv_8;
WORD zero_2A;
WORD zero_2C;
WORD zero_2E;
WORD zero_30;
WORD zero_32;
WORD zero_34;
WORD zero_36;
WORD off_proxy_1;
WORD off_proxy_2;
WORD off_proxy_3;
WORD off_proxy_4;
DWORD DNS_1;
DWORD DNS_2;
DWORD DNS_3;
DWORD DNS_4;
DWORD timeout_multiplier;
DWORD field_54;
WORD port_to_scan;
WORD scan_by_adapter_flag;
DWORD ip_addr_1;
DWORD ip_addr_2;
};
Ниже на иллюстрациях представлено сравнение алгоритмов BackDoor.ShadowPad.3 и BackDoor.PlugX.28.
После инициализации конфигурации проверяется значение mode в структуре shellarg, переданной от загрузчика модуля. Действия в соответствие со значением mode аналогичны таковым у BackDoor.ShadowPad.1.
При значениях mode 5 или mode 6 бэкдор ищет в списке модуль с кодом 0x6A (ImpUser) и вызывает функцию из его таблицы. В BackDoor.ShadowPad.1 модуль ImpUser отсутствовал. Данный модуль служит для внедрения в процесс, созданный либо с окружением текущей сессии, либо от имени пользователя, подключенного удаленно. В контексте этого процесса в дальнейшем будут обрабатываться команды от управляющего сервера, которые должны быть получены через пайп от другого запущенного экземпляра бэкдора. Таким образом, бэкдор запущенный с mode 5 или mode 6, является «сервером» для пайп-соединения, а второй его экземпляр ретранслирует ему команды от управляющего сервера. Список процессов, в которые бэкдор пытается внедрить полезную нагрузку:
- dllhost.exe
- conhost.exe
- svchost.exe
Аналогичная функциональность существует и в бэкдорах семейства PlugX. Например, в BackDoor.PlugX.38 за это отвечает именованный поток DoImpUserProc.
При значениях mode 7 или mode 8 бэкдор пытается выполнить UAC Bypass с помощью DLL-hijacking библиотеки dpx.dll, загружаемой процессом wusa.exe (обладает свойством autoElevate), и COM-интерфейса IFileOperation. Для этого он извлекает свою копию dpx.dll (1d4a2acc73a7c6c83a2625efa8cc04d1f312325c), которая пытается запустить исходную копию бэкдора с повышенными привилегиями.
Характер действий BackDoor.ShadowPad.3 в зависимости от значения параметра shellarg.mode схож с поведением PlugX. В структуре shellarg бэкдора BackDoor.PlugX.28 присутствует параметр op_mode, который определяет характер работы вредоносной программы (установка в систему, инжект, перехват функций и т. д.).
Основная функциональность
BackDoor.ShadowPad.3, аналогично BackDoor.ShadowPad.1, может быть закреплен в системе либо как служба, либо с помощью ключа автозапуска. Имя службы, описание, отображаемое имя, имя параметра реестра хранятся в конфигурации. Как и семейство PlugX, рассматриваемый бэкдор использует мьютексы с именами, зависящими от идентификатора процесса для синхронизации перезапущенного процесса программы и родительского процесса.
BackDoor.ShadowPad.3 также использует мьютекс для предотвращения повторного запуска. Имя для такого мьютекса генерируется специальной функцией модуля Config.
Эта же функция используется также и для генерации имени файла, хранящего конфигурацию, директории хранения скриншотов экрана и т. д. Результат генерации зависит от переданного функции инициализирующего значения и серийного номера системного тома. Аналогичный подход к генерации уникальных имен использовался в BackDoor.PlugX.28
int __usercall gen_string@(DWORD seed@, s *result, LPCWSTR base)
{
DWORD v3; // edi
DWORD v4; // eax
signed int v5; // ecx
signed int i; // edi
DWORD v7; // eax
WCHAR Buffer; // [esp+10h] [ebp-250h]
__int16 v10; // [esp+16h] [ebp-24Ah]
__int16 name[34]; // [esp+210h] [ebp-50h]
DWORD FileSystemFlags; // [esp+254h] [ebp-Ch]
DWORD MaximumComponentLength; // [esp+258h] [ebp-8h]
DWORD serial; // [esp+25Ch] [ebp-4h]
v3 = a1;
GetSystemDirectoryW(&Buffer, 0x200u);
v10 = 0;
if ( GetVolumeInformationW(
&Buffer,
&Buffer,
0x200u,
&serial,
&MaximumComponentLength,
&FileSystemFlags,
&Buffer,
0x200u) )
{
v4 = 0;
}
else
{
v4 = GetLastError();
}
if ( v4 )
serial = v3;
else
serial ^= v3;
v5 = (serial & 0xF) + 3;
for ( i = 0; i < v5; serial = 8 * (v7 - (serial >> 3) + 20140121) - ((v7 - (serial >> 3) + 20140121) >> 7) - 20140121 )
{
v7 = serial << 7;
name[i++] = serial % 0x1A + 'a';
}
name[v5] = 0;
string::wcopy(a2, base);
string::wconcat(a2, (LPCWSTR)name);
return 0;
}
Перед подключением к управляющему серверу бэкдор с помощью функции генерирует строку с использованием значения инициализатора 0x434944 (CID в кодировке ASCII). Эта строка используется в качестве имени ключа и параметра реестра для сохранения идентификатора зараженного компьютера. Сам идентификатор представляет собой массив из 8 случайных байтов. Таким образом, бэкдор пытается сохранить в реестре по адресу <HKEY>\Software\<CID_generated>\<CID_generated> (также сохранение возможно в разделы HKLM или HKCU) следующую структуру:
struct id_time
{
BYTE id[8];
SYSTEMTIME current_time;
}
Заметим, что изученные образцы PlugX перед началом диалога с сервером также генерируют идентификатор компьютера и сохраняют его в реестре. Для генерации используется некоторое инициализирующее значение.
После создания идентификатора запускается сканирование сети и взаимодействие с сервером управления. Сканирование сети необходимо для поиска других зараженных систем в локальной сети. Для этого запускаются 4 отдельных потока:
- сканирование диапазона между двумя IP-адресами, заданными в конфигурации бэкдора;
- сканирование по всему диапазону адресов для каждого найденного в системе сетевого адаптера;
- открытие порта, заданного в конфигурации;
- открытие заданного порта и ретрансляция пакетов между локальным клиентом и реальным управляющим сервером.
Сканирование заключается в отправке TCP-пакета, в теле которого содержится уникальный идентификатор зараженного компьютера. В ответ приходит аналогичный пакет. Если идентификаторы не совпадают, то IP-адрес, с которого получен пакет, становится адресом управляющего сервера для клиента. Для локального взаимодействия используется порт, зашитый в конфигурации в параметре config.port_to_scan. При этом предусмотрено 2 режима сканирования:
- сканируются все адреса в диапазоне между двумя, указанными в конфигурации (config.ip_addr_1 и config.ip_addr_1);
- сканирование по всем подсетям, доступным зараженному компьютеру (перебор сетевых адаптеров).
Для открытия порта прослушивания входящего соединения создается правило сетевого экрана Network Discover (TCP).
Правило создается с использованием функций FirewallAPI COM-интерфейса INetFwMgr.
Для работы в режиме сервера бэкдор открывает порт из конфигурации и ожидает входящего соединения от клиентов. При получении нового соединения запускается туннель между локальным клиентом и реальным управляющим сервером. Сетевое взаимодействие в режиме сканирования и туннелирования ведется с помощью модуля TCP. Формат и структура пакета аналогичны BackDoor.ShadowPad.1.
Функциональность работы бэкдора в режиме сервера в локальной сети присутствует и в образцах семейства PlugX. В частности, в BackDoor.PlugX.38 для этого используются именованные потоки JoProc:
- JoProcListen (туннель между локальным клиентом и управляющим сервером);
- JoProcBroadcast (рассылка по сети);
- JoProcBroadcastRecv (обработка ответов на рассылку).
После инициализации локального туннеля BackDoor.ShadowPad.3 запускает подключение к управляющему серверу. На первом этапе бэкдор пытается напрямую подключиться к серверу, указанному в конфигурации в виде строки. Если попытка не удалась, извлекает из конфигурации параметры прокси-сервера и пытается подключиться к серверу через прокси.
После удачного подключения отправляет пакет, в тело которого записаны от 0 до 31 случайных байтов. В ответ приходит команда для какого-либо плагина. Команды для модулей Plugins, Config, Install, Online идентичны командам BackDoor.ShadowPad.1 за некоторыми исключениями:
- по команде 0x670001 для модуля Install выполняется деинсталляция бэкдора;
- форматом команд для модуля Online является 0x68005X вместо 0x68000X.
Обработка команд для модулей
ImpUser
ID команды | Описание |
---|---|
0x6A0000 | По этой команде устанавливается соединение с пайпом, предназначенным для ретрансляции данных от управляющего сервера в процесс с инжектом. После соединения создается туннель между управляющим сервером и процессом с инжектом. |
0x6A0001 | Отправляет информацию обо всех процессах, в которые выполнен инжект модулем ImpUser. |
Disk
ID команды | Описание |
---|---|
0x12C0000 | Получить список букв и типов дисков |
0x12C0001 | В команде указывается директория; в ответ отправляется список вложенных файлов и папок (глубина — 1 уровень). По каждому элементу отправляются следующие данные:
|
0x12C0002 | В команде указывается имя файла; проверка существования файла |
0x12C0003 | Создать заданную в команде директорию |
0x12C0004 | Получить информацию о заданном в команде файле: атрибуты и время (создания, последнего обращения и записи) |
0x12C0005 | Установить для указанного в команде файла атрибуты (файловые и временные) |
0x12C0006 | Выполнение SHFileOperationW с указанными в команде аргументами |
0x12C0007 | Выполнение CreateProcess с заданным в команде аргументом lpCommandLine |
0x12C0008 | Запись или чтение файла |
0x12C000A | Получение списка файлов по маске в заданной директории (рекурсивно). Маска может содержать «?» и «*» |
0x12C000C | Очистка кеша по заданному в команде URL (DeleteUrlCacheEntryW), затем скачивание файла по этому URL с повторной очисткой кеша |
Process
ID команды | Описание |
---|---|
0x12D0000 | Получить список процессов. По каждому процессу формируется блок данных:
|
0x12D0001 | Завершить процесс; в команде указывается идентификатор процесса |
Servcie
Название модуля с ошибкой содержится в коде.
ID команды | Описание |
---|---|
0x12F0000 | Получить список всех служб. По каждой службе указываются:
|
0x12F0000 | Остановка службы |
0x12F0000 | Удаление службы |
0x12F0001 | Запуска службы |
0x12F0002 | Приостановка службы |
0x12F0003 | Возобновление службы |
Register
ID команды | Описание |
---|---|
0x12F0000 | Получить список вложенных ключей в заданном командой ключе реестра |
0x12F0001 | Создать ключ реестра |
0x12F0002 | Удалить ключ реестра |
0x12F0003 | Получить список параметров и их значений в заданном командой ключе реестра |
0x12F0004 | Установить значение параметра |
0x12F0005 | Удалить параметр |
Shell
Модуль содержит одну команду — 0x1300000. По этой команде создается командная оболочка cmd.exe с перенаправлением ввода-вывода через пайпы на управляющий сервер.
KeyLogger
При инициализации модуля KeyLogger устанавливается хук типа WH_KEYBOARD_LL. Нажатия клавиш клавиатуры с названиями окон записываются в лог-файл. Имя и путь файла генерируется с помощью ранее указанной функции.
ID команды | Описание |
---|---|
0x1320000 | Получить лог |
0x1320001 | Удалить лог |
Screen
Модуль Screen при инициализации делает скриншот и сохраняет его в директории, имя и путь которой генерируются. Настройки скриншота и параметры кодирования JPEG содержатся в файле конфигурации, располагающемся в поддиректории Log домашнего каталога бэкдора.
ID команды | Описание |
---|---|
0x1330000 | Получить список подключенных дисплеев с указанием:
|
0x1330001 | Создать и отправить на сервер скриншот экрана |
0x1330002 | Запуск удаленного управления (имитация RDP) |
0x1330010 | Отправить путь хранения скриншотов |
0x1330011 | Отправить на сервер файл с параметрами скриншотов |
0x1330012 | Получить от сервера новый файл с параметрами скриншотов |
RecentFiles
Модуль предназначен для работы с недавними файлами и имеет одну команду — 0x13D0000. При получении команды бэкдор перечисляет все файлы с расширением .lnk в %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Recent и по каждому из них получает информацию с помощью COM-интерфейсов IShellLinkW и IPersistFile.
Также стоит отметить, что ShadowPad и PlugX используют идентичные алгоритмы шифрования:
BackDoor.ShadowPad
ShadowPad при помощи этого алгоритма шифрует шелл-код, который, в свою очередь, используется для шифрования плагинов и пакетов.
BackDoor.PlugX
Аналогичный алгоритм использует BackDoor.PlugX.26 для расшифровки шелл-кода из файла.