ПОЛЬЗОВАТЕЛЯМ

Поддержка
Круглосуточная поддержка

Позвоните

Бесплатно по России:
8-800-333-79-32

ЧаВо | Форум

Ваши запросы

  • Все: -
  • Незакрытые: -
  • Последний: -

Позвоните

Бесплатно по России:
8-800-333-79-32 | Skype

Свяжитесь с нами Незакрытые запросы: 

Профиль

Профиль

BackDoor.PlugX.28

Добавлен в вирусную базу Dr.Web: 2019-05-27

Описание добавлено:

Упаковщик: отсутствует

Дата компиляции: 16:43:21 02.02.2015

SHA1-хеш:

  • f6bf976a2fdef5a5a44c60cbfb0c8fcbdc0bae02

Описание

Многокомпонентный троян-бэкдор, написанный на языке С++ и предназначенный для работы в 64-разрядных операционных системах семейства Microsoft Windows. Устанавливается при помощи модуля-загрузчика, после чего функционирует в оперативной памяти зараженного компьютера. Используется в целевых атаках на информационные системы для несанкционированного доступа к данным и их передачи на управляющие серверы. Характерной особенностью является наличие плагинов, с помощью которых реализована основная функциональность бэкдора.

Принцип действия

Загружается посредством BackDoor.PlugX.27. Соглашения о вызовах разнятся от функции к функции и зачастую являются нестандартными — передача аргументов выполняется через произвольные регистры и/или через стек, что может говорить о компиляции вредоносной программы с опцией оптимизации.

Для работы определяется и используется множество различных объектов. Для передачи информации используются абстрактные объекты, которые просто реализуют интерфейс (прием/передача). Таким образом, функция не привязана к внутренней реализации объекта соединения, будь то TCP-сокет, RAW-сокет, HTTP-соединение или пайп. Класс объекта может явно определяться в коде, а также задаваться в конфигурации типом сервера или полученными данными от известных серверов.

Практически все строки в коде трояна зашифрованы. Скрипт дешифровки:

import idaapi
import struct
 
def dec(d):
    s = ''
    k = struct.unpack('<I', d[:4])[0]
    d = d[4:]
    a = k ^ 0x13377BA
    b = k ^ 0x1B1
    for i in range(len(d)):
        a = (a + 4337) & 0xffffffff
        b = (b - 28867) & 0xffffffff
         
        a0 = (a & 0x000000ff)
        a1 = (a & 0x0000ff00) >> 8
        a2 = (a & 0x00ff0000) >> 16
        a3 = (a & 0xff000000) >> 24
        b0 = (b & 0x000000ff)
        b1 = (b & 0x0000ff00) >> 8
        b2 = (b & 0x00ff0000) >> 16
        b3 = (b & 0xff000000) >> 24       
                         
        s += chr(ord(d[i]) ^ (((b2 ^ (((b0 ^ (((a2 ^ ((a0 - a1)&0xff)) - a3)&0xff)) - b1)&0xff)) - b3) & 0xff))
         
    return s
     
def decrypt(addr, size):
    d = ''
    for i in range(size):
        d += chr(idaapi.get_byte(addr + i))
     
    s = dec(d)
    print s
     
    for i in range(len(s)):
        idaapi.patch_byte(addr + i, ord(s[i]))
    idaapi.patch_dword(addr + i + 1, 0)

Подготовка к работе

BackDoor.PlugX28 может получить конфигурацию несколькими способами. Загрузчик передает аргумент, представляющий собой указатель на структуру shellarg:

#pragma pack(push,1)
struct st_data
{
  _DWORD size;
  _BYTE *data;
};
  
struct shellarg
{
  _DWORD shellcode_ep;
  _DWORD field_4;
  st_data* mod;
  _DWORD comp_size;
  st_data* cfg;
  _DWORD field_14;
  _DWORD op_mode;
};
#pragma pack(pop)

Затем проверяется значение по указателю shellarg->cfg:

  • если первые 8 байтов по данному адресу равны XXXXXXXX, то бэкдор самостоятельно подготавливает так называемую базовую конфигурацию, использующуюся по умолчанию;
  • в противном случае используется расшифрованная и разжатая конфигурация, полученная от загрузчика.

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

int __usercall gen_string@<eax>(DWORD seed@<eax>, 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;
}

Инициализирующим значением для имени конфигурационного файла служит значение 0x4358 ("CX").

В путях для файлов и директорий (в том числе домашней) может использоваться переменная %AUTO%, которая в зависимости от версии ОС преобразуется в:

  • "<drive>:\\Documents and Settings\\All Users\\DRM" — для ОС Windows 2000, Windows XP;
  • "<drive>:\\Documents and Settings\\All Users\\Application Data" — для ОС Windows Server 2003;
  • "<drive>:\\ProgramData" — для более поздних версий ОС Windows.

При этом <drive> берется из пути до каталога Windows.

Полученная конфигурация представляет собой следующую структуру ("st_config"):

struct config_timestamp
{
  BYTE days;
  BYTE hours;
  BYTE minutes;
  BYTE seconds;
};
struct srv
{
  WORD type;
  WORD port;
  BYTE address[64];
};
struct proxy_info
{
  WORD type;
  WORD port;
  BYTE serv_addr_str[64];
  BYTE username_str[64];
  BYTE password[64];
};
struct st_config
{
  DWORD hide_service;
  DWORD gap_0[4];
  DWORD cleanup_files_flag;
  DWORD keylog_log_event;
  DWORD dword_0;
  DWORD skip_persistence;
  DWORD dword_1;
  DWORD sleep_timeout;
  config_timestamp timestamp;
  BYTE timetable[672];
  DWORD DNS_1;
  DWORD DNS_2;
  DWORD DNS_3;
  DWORD DNS_4;
  srv srv1_basic_type3;
  srv srv2_basic_type;
  srv srv3_basic_type_6;
  srv srv3_basic_type_7;
  srv srv5_basic_type_8;
  srv srv6_basic_type_5;
  srv srv7;
  srv srv8;
  srv srv9;
  srv srv10;
  srv srv11;
  srv srv12;
  srv srv13;
  srv srv14;
  srv srv15;
  srv srv16;
  BYTE url_1[128];
  BYTE url_2[128];
  BYTE url_3[128];
  BYTE url_4[128];
  BYTE url_5[128];
  BYTE url_6[128];
  BYTE url_7[128];
  BYTE url_8[128];
  BYTE url_9[128];
  BYTE url_10[128];
  BYTE url_11[128];
  BYTE url_12[128];
  BYTE url_13[128];
  BYTE url_14[128];
  BYTE url_15[128];
  BYTE url_16[128];
  proxy_info proxy_data_1;
  proxy_info proxy_data_2;
  proxy_info proxy_data_3;
  proxy_info proxy_data_4;
  DWORD persist_mode;
  DWORD env_var_AUTO_X[128];
  DWORD service_name[128];
  DWORD ServiceDisplayName[128];
  BYTE ServiceDescription[512];
  DWORD reg_predefined_key;
  BYTE reg_sub_key[512];
  BYTE reg_value_name[512];
  DWORD process_injection_flag;
  BYTE inject_target_dummy_proc_1[512];
  BYTE inject_target_dummy_proc_2[512];
  BYTE inject_target_dummy_proc_3[512];
  BYTE inject_target_dummy_proc_4[512];
  DWORD elevated_process_injection_flag;
  BYTE elevated_inject_target_dummy_proc_1[512];
  BYTE elevated_inject_target_dummy_proc_2[512];
  BYTE elevated_inject_target_dummy_proc_3[512];
  BYTE elevated_inject_target_dummy_proc_4[512];
  BYTE campaign_id[512];
  BYTE str_X_4[512];
  BYTE mutex_name[512];
  DWORD make_screenshot_flag;
  DWORD make_screenshot_time_interval;
  DWORD screen_scale_coefficient;
  DWORD bits_per_pixel;
  DWORD encoder_quality;
  DWORD screen_age;
  BYTE screenshots_path[512];
  DWORD subnet_scan_flag_mb;
  DWORD port_54D_1;
  DWORD raw_socket_subnet_flag;
  DWORD port_54D_2;
  DWORD type_7_subnet_flag;
  DWORD portl_54D_3;
  DWORD flag_1_6;
  DWORD port_54D_4;
  DWORD flag_1_7;
  DWORD first_IP_range_addr_beg;
  DWORD first_IP_range_addr_end;
  DWORD first_IP_range_addr_beg_2;
  DWORD first_IP_range_addr_beg_3;
  DWORD last_IP_range_addr_beg;
  DWORD last_IP_range_addr_end;
  DWORD last_IP_range_addr_beg_2;
  DWORD last_IP_range_addr_beg_3;
  BYTE mac_addr[6];
  BYTE gap_2[2];
} config;

В случае использования конфигурации по умолчанию значения некоторых полей следующие:

  • домашний каталог трояна: %AUTO%\\X;
  • имя службы: X;
  • отображаемое имя службы: X;
  • описание службы: X;
  • имя процесса для запуска и внедрения шелл-кода: %windir%\\system32\\svchost.exe;
  • имя процесса для запуска с привилегиями администратора и внедрения шелл-кода: %windir%\\system32\\svchost.exe;
  • каталог хранения скриншотов экрана: %AUTO%\\XS;
  • имя мьютекса: X.

Выполнение

Получает привилегии SeDebugPrivilege и SeTcbPrivilege, после чего запускает отдельный поток, в котором будут происходить дальнейшие действия.

Проверяет наличие у зараженного компьютера сетевого адаптера с зашитым в трояна MAC-адресом. Если адаптер присутствует, троян завершает свою работу (в исследованном образце адрес не задан).

Проверяет значение shellarg->op_mode. Список возможных значений:

  • больше 4 — проверка закрепления в системе, далее — основной режим работы;
  • 4 — перехват функции WinInet.dll и выход;
  • 3 — внедрение в процесс Internet Explorer и выход;
  • 2 — основной режим работы без проверки закрепления.

Проверка и закрепление в системе (op_mode>4)

В конфигурации проверяется флаг config.skip_persistence и, если он установлен, то этапы проверки пути, создания мьютексов и закрепления пропускаются, и управление переходит к инициализации службы.

Затем проверяет путь, откуда запущен текущий процесс. Если он совпадает с %AUTO%\\EHSrv.exe, то пропускает фазу установки в систему.

Создает два мьютекса вида Global\\<rndname>. Для имени первого мьютекса инициализирующим значением является PID текущего процесса, а для второго — PID родительского процесса. Далее — переход к установке в систему.

В конфигурации проверяется параметр config.persist_mode, определяющий вариант закрепления:

  • 0, 1 — установка службы;
  • 2 — создание значения в реестре.

В обоих случаях копирует в домашнюю директорию (%AUTO%\\X в конфигурации по умолчанию) свои файлы http_dll.dll и EHSrv.exe, а также сохраняет зашифрованный шелл-код в ключи реестра [HKLM\\SOFTWARE\\BINARY] 'ESETSrv' и [HKCU\\SOFTWARE\\BINARY] 'ESETSrv'. Подделывает временные атрибуты файлов, меняя их на атрибуты системного файла ntdll.dll.

Для установки службы троян создает и запускает службу типа SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS с автоматическим запуском. Имя, отображаемое имя, а также описание службы берутся из конфигурации (параметры config.service_name, config.ServiceDisplayName, config.ServiceDescription). Параметр lpBinaryPathName в функции CreateService задается как <path>\EHSrv.exe -app.

Для записи в реестре создает значение <path>\EHSrv.exe -app в ключе реестра. Дескриптор, имя ключа и значения заданы в конфигурации:

#drweb

Затем троян запускает новый процесс.

После этого происходит инициализация службы путем вызова функции StartServiceCtrlDispatcherW.

В конфигурации проверяется флаг config.process_injection_flag. Если флаг установлен, то из конфигурации извлекается путь до файла процесса, в который будет внедряться шелл-код. Имя может содержать переменные окружения. Предусмотрено до четырех имен, каждое из которых проверяется последовательно до первого ненулевого, после чего создается процесс с флагом CREATE_SUSPENDED, в который внедряется шелл-код.

#drweb

В случае успешного внедрения процесс завершается, в противном случае управление переходит на основной функционал.

Установка хуков "Wininet.dll" (op_mode==4)

Предположительно, данный режим предусмотрен после внедрения в процесс Internet Explorer.

Хуки устанавливаются на функции:

HttpSendRequestA
HttpSendRequestW
HttpSendRequestExA
HttpSendRequestExW

Их назначение состоит в перехвате HTTP-запросов для извлечения логинов и паролей для подключения к прокси-серверу. Полученные реквизиты записываются в структуру:

struct proxy_info
{
  WORD type;
  WORD port;
  BYTE serv_addr_str[64];
  BYTE username_str[64];
  BYTE password[64];
};

где параметр type может принимать следующие значения:

  • 1 — socks4
  • 2 — socks5
  • 3 — http
  • 5 — https
  • 6 — ftp

В формате этой структуры данные сохраняются в глобальной переменной и в файле в каталоге бэкдора. Имя файла генерируется с инициализирующим значением 0x485A ("HZ").

Внедрение в процесс IE (op_mode==3)

BackDoor.PlugX28 внедряет шелл-код через функцию CreateRemoteThread в процесс IE. Поиск процесса выполняется через поиск окна IEFrame. Перед этим происходит инициализация плагинов бэкдора. Генерируется имя пайпа \\.\PIPE\<rndname>. Инициализатором для <rndname> является PID текущего процесса. Затем происходит повторная инициализация конфигурации.

Создается объект, реализующий интерфейс асинхронного взаимодействия с пайпом, затем создается и инициализируется сам пайп. В отдельном потоке создается обработчик, который в качестве параметра принимает указатель на экземпляр объекта подключения к пайпу. Обработчик через интерфейс объекта читает команды, предназначенные для выполнения плагинами. Результаты их исполнения возвращает в пайп.

Основной фукнционал (op_mode==2 или op_mode==4 после закрепления)

Проверяет наличие административных привилегий у пользователя, от имени которого запущен текущий процесс. Затем проверяет в конфигурации флаг config.hide_service. Если флаг установлен, и пользователь не является локальным администратором, то ищет %WINDIR%\SYSTEM32\SERVICES.EXE среди запущенных процессов, после чего перечисляет его модули. Обращается к первому модулю в списке, читает адрес первой секции и копирует ее в свой буфер. Затем ищет в этом буфере последовательность инструкций, которую можно представить в виде следующего регулярного выражения:

\xA3.{4}\xA3.{4}\xA3.{4}\xA3.{4}\xE8

Это соответствует последовательности в функции ScInitDatabase()

#drweb

Далее считывается адрес ServiceDatabase — связный список структур, описывающих работающие службы. Затем ищет запись, соответствующую имени службы бэкдора, и «удаляет» ее, изменяя указатели предыдущей и следующей записи в списке.

После сокрытия службы создается мьютекс с именем, указанным в конфигурации в параметре config.mutex_name.

Создает RAW-сокет, прослушивающий все IP-пакеты на локальном хосте. Разбирает входящие пакеты, выбирает из них TCP, а затем проверяет на соответствие пакетам протоколов SOCKS4, SOCKS5 и HTTP. Затем извлекает из них реквизиты прокси-серверов, после чего формирует структуры proxy_info и сохраняет их в файл, аналогично алгоритму перехвата функций Wininet.

В конфигурации проверяется флаг config.elevated_process_injection_flag. Если флаг установлен, то запускается поток, в котором последовательно перебираются запущенные процессы в поисках запущенного от имени локального администратора. У этого процесса клонируется маркер доступа, и дубликату маркера присваивается HighIntegrity класс. Затем создается блок окружения от имени локального администратора, который используется для создания процесса с маркером доступа класса HighIntegrity. Имя процесса также извлекается из параметра конфигурации config.elevated_inject_target_dummy_proc_<n>", n 1..4. Проверяются все четыре варианта до первого ненулевого. Процесс создается с флагом CREATE_SUSPENDED, и в него внедряется шелл-код. Информация о каждом процессе сохраняется в специальной структуре:

struct injected_proc
{
  DWORD session_ID;
  DWORD pid;
  DWORD hProcess;
  BYTE admin_account_name[40];
};
 
struct injected_elevated__procs
{
  injected_proc injected_process_info[32];
  DWORD hThread;
  DWORD hEvent;
};

Далее инициализируются плагины, запускается цикл приема и обработки команд от управляющего сервера. Перед подключением к серверу извлекаются и сохраняются глобальные настройки прокси, используемые функциями WIninet, и записанные в конфигурации браузера Firefox.

Следует отметить, что серверы хранятся в конфигурации в виде структур:

struct srv
{
  WORD type;
  WORD port;
  BYTE address[64];
};

Для взаимодействия с сервером создается объект соединения, тип которого определяется значением srv.type. Возможные типы соединений:

1, 2 — pipe-соединение;
3 — TCP-сокет (подразумевает возможность использования SOCKS4, SOCKS5, HTTP-прокси);
4 — HTTP-соединение;
5 — открытие UDP-сокета для прослушивания, работа в режиме DNS-сервера;
6, 7, 8 — RAW-сокет.

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

Первая попытка подключения к управляющему серверу из конфигурации выполняется без использования прокси. В случае неудачи используются данные прокси, которые хранятся в глобальной переменной. Конфигурация предусматривает слоты для 16 серверов. Если ни к одному из них не удалось подключиться, то из поля config.url_1 извлекается URL, который сначала разбирается на составляющие (такие как хост, URI, параметры), а затем по этим данным формируется и отправляется GET-запрос. В теле ответа на этот запрос выполняется поиск закодированной строки, заключенной между тегами DZKS и DZJS. После декодирования строка представляет собой тип, порт и адрес управляющего сервера в виде структуры srv. Предусмотрено до 16 таких URL-указателей, при помощи которых можно получить новый адрес управляющего сервера.

Алгоритм декодирования адреса управляющего сервера:

int __usercall find_and_decode_string@(BYTE *decoded_response@, BYTE *response_data@, int response_data_len@)
{
  int v3; // edx
  int i; // ecx
  int v6; // esi
  int j; // edi
  int v8; // ecx
  char v9; // dl
  BYTE *v10; // edx
  int v11; // eax
  int v12; // esi
  v3 = response_data_len - 4;
  for ( i = 0; i < v3; ++i )
  {
    if ( response_data[i] == 'D'
      && response_data[i + 1] == 'Z'
      && response_data[i + 2] == 'K'
      && response_data[i + 3] == 'S' )
    {
      break;
    }
  }
  if ( i >= v3 )
    return 1168;
  v6 = i + 4;
  for ( j = i + 4;
        j < v3
     && (response_data[j] != 'D'
      || response_data[j + 1] != 'Z'
      || response_data[j + 2] != 'J'
      || response_data[j + 3] != 'S');
        ++j )
  {
    ;
  }
  if ( j > v3 )
    return 1168;
  v8 = 0;
  while ( v6 < j )
  {
    v9 = response_data[v6] + 16 * (response_data[v6 + 1] - 65);
    response_data[v8 + 1] = 0;
    response_data[v8++] = v9 - 65;
    v6 += 2;
  }
  *(_WORD *)decoded_response = *response_data + (response_data[1] << 8);
  *((_WORD *)decoded_response + 1) = response_data[2] + (response_data[3] << 8);
  if ( v8 > 0 )
  {
    v10 = decoded_response + 4;
    v11 = response_data - decoded_response;
    v12 = v8;
    do
    {
      *v10 = v10[v11];
      ++v10;
      --v12;
    }
    while ( v12 );
  }
  return 0;
}

Первичное обращение к управляющему серверу

BackDoor.PlugX28 получает текущие время и дату при помощи функции GetLocalTime. Затем проверяет день недели: если это воскресенье (0), то в структуре SYSTEMTIME меняет его на субботу (6), в ином случае уменьшает значение на 1. Далее обращается к массиву config.timetable, чтобы проверить значение элемента под индексом, зависящим от текущего времени. Размер массива составляет _BYTE[672]. Каждый элемент представляет собой флаг каждой четверти часа в неделе (24 * 7 * 4 = 672). Если значение элемента ненулевое, то выполнение продолжается, в противном случае троян переходит в режим ожидания.

Проверка флага расписания работы:

while ( 1 )
  {
    GetLocalTime(&local_time);
    if ( local_time.wDayOfWeek )
      --local_time.wDayOfWeek;
    else
      local_time.wDayOfWeek = 6;
    if ( config.timetable[4 * (local_time.wHour + 24 * local_time.wDayOfWeek) + local_time.wMinute / 15] )
      break;
    Sleep(1000);
  }

В конфигурации рассмотренного образца все элементы массива равны 1. При подготовке конфигурации по умолчанию массив также заполняется единицами. После проверки расписания троян читает значение поля config.timestamp, определяемого следующим образом:

struct config_timestamp
{
  BYTE days;
  BYTE hours;
  BYTE minutes;
  BYTE seconds;
};

Затем переводит его значение в секунды, умножает на 0x10000000 и складывает с текущим значением системного времени в формате FILETIME. Затем проверяет наличие параметра <config.service_name> в ключе реестра HKCU\Software\<config.service_name>. Если параметр существует, то сравнивает его значение с системной временной меткой. Если значение метки больше хранимого, то выполнение продолжается, в противном случае происходит ожидание в течение секунды, после чего производится повторная проверка. Если значение в реестре отсутствует, то вычисленная временная метка помещается в этот параметр и сравнивается с системной временной меткой. В итоге режим ожидания остается активным до тех пор, пока системная временная метка не окажется больше метки, вычисленной в начале проверки, либо метки, хранимой в параметре.

#drweb

result_ts помещается в реестр при необходимости.

Перемножение значений временных меток представлено на иллюстрации:

#drweb

После временны́х проверок создается объект соединения, соответствующий типу, указанному для текущего сервера. В случае использования протокола HTTP для взаимодействия с управляющим сервером обработка соединения (прием и передача данных) выполняется в отдельном потоке. На первом этапе устанавливается соединение в режиме keep-alive, и отправляется первый GET-запрос. URL формируется по формату /%p%p%p из трех случайных значений DWORD. Затем готовится структура следующего формата:

struct prefix
{
  DWORD unknown;
  DWORD sync_ctr;
  DWORD conn_state;
  DWORD available_buffer_size;
};

Данная структура используется только при передаче по протоколу HTTP и выполняет служебную функцию синхронизации и поддержания соединения. При установке соединения поля структуры заполняются следующими значениями из внутренних полей объекта соединения:

  • unknown = 0;
  • sync_ctr = 1 — представляет собой некий счетчик, при каждой отправке увеличивающийся на единицу;
  • conn_state = 20130923 — представляет собой флаг состояния соединения. В данном случае начальное значение 20130923 используется клиентом для запроса на установку соединения;
  • available_buffer_size = 0xF010 — начальный размер внутреннего буфера объекта для хранения входящих данных.

Данная структура шифруется тем же алгоритмом, что используется для шифрования строк. Структура на выходе имеет следующий вид:

struct http_encrypted_data
{
  DWORD key;
  BYTE  data[0x10];
}

После шифрования данные кодируются в Base64 и помещаются в заголовок Cookie:, затем запрос отправляется на управляющий сервер. В теле ответа приходит структура http_encrypted_data, после расшифровки которой получается структура prefix. Проверяется значение prefix.conn_state, которое должно быть равно 20130924. Данное значение может сообщать о готовности сервера к приему данных. Также предусмотрено значение 20130926, которое обозначает окончание соединения.

Проверяется поле prefix.sync_ctr, значение которого должно быть на единицу больше значения prefix.sync_ctr, отправленного клиентом. Такой формат диалога с сервером используется и при отправке реальных данных. Они помещаются после структуры prefix.

После того как соединение с сервером установлено, подготавливается непосредственный запрос команды. Для этого троян генерирует от 0 до 0x1F случайных байт и формирует структуру пакета из заголовка и тела:

struct packet_hdr
{
  DWORD key;
 DWORD command_id;
 DWORD len;
 DWORD errc;
};
struct packet
{
  packet_hdr header;
  BYTE data[61440] //0xF000;
};

Данная структура используется для отправки данных на сервер и обработки команд. Значения полей заголовка ("packet_hdr"):

  • "key" — ключ, использованный для шифрования данных;
  • "command_id" — идентификатор команды или ответа на команду. При ответе идентификатор не меняется;
  • "len" — длина данных без учета заголовка;
  • "errc" — код ошибки выполнения команды. В большинстве случаев это поле содержит код ошибки (GetLastError), если не удалось полностью выполнить команду, либо содержит 0, если команда выполнена успешно. В ряде случаев содержит дополнительные параметры для выполнения команды клиентом.

При первой отправке значения command_id и errc приравниваются к 0, а значение len приравнивается к длине случайной последовательности (0-0x1F). В packet.data помещается сама случайная последовательность. Затем данные пакета ("data") сжимаются алгоритмом LZNT1 через RtlCompressBuffer и шифруются алгоритмом шифрования строк со случайным ключом. В поле packet.header.len помещается значение (uncompressed_len << 0x10) | compressed_len, где uncompressed_len и comressed_len содержат размер данных до сжатия и после сжатия соответственно (без учета длины заголовка). Далее шифруется заголовок, и в поле packet.header.key помещается случайный ключ.

Полученные шифрованные данные отправляются на сервер в поле Cookie: HTTP-запроса. Перед данными помещается структура prefix, вся полученная последовательность шифруется, затем кодируется по стандарту Base64 и отправляется в запросе. В ответ приходит команда от сервера. Пакет с командой представляет собой структуру, аналогичную packet, при этом формат data и, в ряде случаев, назначение header.errc может меняться в зависимости от команды.

Обработка команд управляющего сервера

После получения пакет расшифровывается и распаковывается. Троян проверяет значение идентификатора команды packet.header.command_id. Предусмотрены следующие значения команд:

  • 1 — сбор и отправка сведений о системе;
  • 3 — работа с плагинами;
  • 4 — сброс соединения;
  • 5 — самоудаление;
  • 6 — отправка имеющейся конфигурации на управляющий сервер;
  • 7 — получить новую конфигурацию;
  • 8 — отправить информацию о процессах с внедренным шелл-кодом;
  • 2, 9, 10 —действий не предусмотрено;
  • >10 — работа с плагинами.

В поле packet.header.command_id принятых ответов проставляется то же значение, что получено в команде.

Команда 1 (информация о системе)

Троян сравнивает строку в поле packet.data со строкой из конфигурации config.campaign_id (TEST в конфигурации по умолчанию). Если строки равны, то начинается сбор информации о системе, в противном случае возникает ошибка. После этого троян пытается прочитать в своем каталоге файл с именем, которое сгенерировано с инициализатором 0x4343 ("CC"). Если файл существует — его содержимое считывается и кодируется.

#drweb

Если файла нет, то таковой создается, и в него записывается последовательность из 8 случайных байтов. После чего эта случайная последовательность кодируется таким же образом. Получившаяся закодированная строка будет помещена в ответ на команду. Затем программа выполняет сбор следующей информации:

  • имя компьютера;
  • имя пользователя;
  • частота процессора (из HKLM\HARDWARE\DESCRIPTION\SYSTEM\CENTRALPROCESSOR\0);
  • является ли процесс Wow64;
  • информация о домене;
  • наличие у текущего пользователя привилегий локального администратора;
  • IP-адрес компьютера;
  • общий объем оперативной памяти в килобайтах;
  • информация о версии ОС;
  • системное время;
  • разрешение экрана;
  • региональные настройки;
  • количество процессоров.

Ответ с результатами отправляется на сервер в виде структуры:

struct command_1_response
{
  packet_hdr header;
  sysinfo data;
};

где sysinfo представляет собой структуру с информацией о системе:

struct sysinfo
{
  DWORD date_stamp; //20150202
  DWORD zero_0;
  DWORD self_IP;
  DWORD total_PhysMem;
  DWORD cpu_MHz;
  DWORD screen_width;
  DWORD screen_height;
  DWORD winserv2003_build_num;
  DWORD default_LCID;
  DWORD tick_count;
  DWORD systeminfo_processor_architecture;
  DWORD systeminfo_number_of_processors;
  DWORD systeminfo_processor_type;
  DWORD zero_1;
  DWORD os_MajorVersion;
  DWORD os_MinorVersion;
  DWORD os_BuildNumber;
  DWORD os_PlatformId;
  WORD os_ServicePackMajor;
  WORD os_ServicePackMinor;
  WORD os_SuiteMask;
  WORD os_ProductType;
  DWORD isWow64Process;
  DWORD if_domain;
  DWORD if_admin;
  DWORD process_run_as_admin;
  WORD systime_Year;
  WORD systime_Month;
  WORD systime_Day;
  WORD systime_Hour;
  WORD systime_Minute;
  WORD systime_Second;
  DWORD server_type;
  WORD off_CCseed_file_data;  //offset from 0
  WORD off_compname_string; 
  WORD off_username_string;
  WORD off_verinfo_szCSDVersion;
  WORD off_str_X_4_from_config;
  BYTE string_CCseed_file_data[16];
  .......
  //strings
};

Члены структуры off_CCseed_file_data", "off_compname_string", "off_username_string", "off_verinfo_szCSDVersion", "off_str_X_4_from_config" являются смещениями относительно начала структуры sysinfo. off_str_X_4_from_config — смещение до строки, скопированной из config.str_X_4 (в конфигурации по умолчанию — X). Затем подготавливается пакет для отправки информации на сервер. В заголовке указывается идентификатор пакета, равный 1. Затем пакет сжимается, шифруется и отправляется на сервер.

command_id == 3 (работа с плагинами)

При получении пакета с command_id 3 в отдельном потоке запускается обработчик задач для плагинов, в котором создается новое соединение с управляющим сервером. Входящий пакет с командой имеет следующий вид:

struct command_3_packet
{
  packet_hdr header;
  DWORD dword_0;
  DWORD index;
};

Если значение index равно 0xFFFFFFFF, то в этом случае обработка задач для плагинов будет производиться в этом же процессе. В ином случае это значение используется как индекс в массиве структуры injected_elevated_procs. Из массива по заданному индексу получается нужная структура, из нее извлекается идентификатор процесса, который служит в качестве инициализирующего значения для генерации имени пайпа. Затем создается объект соединения с пайпом, реализующий интерфейс пересылки команд для плагинов. Эти команды будут исполняться в контексте другого процесса (например, Internet Explorer), внедрение в который будет выполнено при "shellarg.op_mode" == 3, или же в контексте одного из процессов, заданных в конфигурации и запускаемых с повышенными привилегиями ("config.elevated_inject_target_dummy_proc_<n>", n 1..4). После инициализации пайпа на сервер отправляется ответ, который представляет собой тот же пакет, что и команда. После этого запускается пересылка пакетов, содержащих задачи для плагинов, между двумя объектами — HTTP-соединением и пайпом.

Если значение index задано как 0xFFFFFFFF, то полученный пакет отправляется обратно, и выполняется запуск цикла обработки задач для плагинов.

command_id == 4 — сброс соединения. Никаких специальных действий не совершается; производится выход из цикла обработки команд для дальнейшего подключения к другим серверам.

command_id == 5 — самоудаление. Удаляет из реестра ключ своей службы и удаляет все файлы в своем каталоге.

command_id == 6 — отправка конфигурации. Шифрует имеющуюся конфигурацию и отправляет ее в теле пакета.

command_id == 7 — получение новой конфигурации. В теле пакета содержится новая конфигурация. Троян сжимает ее, шифрует и сохраняет в файл, присваивая имя с инициализирующим значением 0x4358 ("CX"). Затем считывает ее и заменяет старую конфигурацию.

command_id == 8 — отправка информации и процессах с внедрениями. Подготавливает пакет с информацией о процессах, в которые был внедрен шелл-код, затем шифрует его и отравляет на сервер. Структура пакета:

struct command_8_response
{
  packet_hdr header;
  DWORD number_of_procs;
  injected_proc injected_processes_info[number_of_procs];
};

command_id > 10 — работа с плагинами. В отличие от режима "command_id" == 3, в этом случае предусмотрена работа только в контексте текущего процесса.

Работа с плагинами

После того как была получена команда с id 3 или >10, и полученный пакет был отправлен обратно, в ответ от сервера приходит пакет с задачей для какого-либо плагина. Команда для плагина обрабатывается отдельно от основного цикла обработки команд и в отдельном соединении.

BackDoor.PlugX28 имеет следующие плагины:

  • DISK (2 вида);
  • Keylogger;
  • Nethood;
  • Netstat;
  • Option;
  • PortMap;
  • Process;
  • Regedit;
  • Screen;
  • Service;
  • Shell;
  • SQL;
  • Telnet.

Имена плагинов зашиты в зашифрованном виде и используются при инициализации соответствующих объектов.

Каждый плагин представлен объектом pluginfo:

struct pluginfo
{
  wchar_t name[64];
  DWORD timestamp;
  PROC pfnInit;
  PROC pfnJob;
  PROC pfnFree;
};

Временная метка timestamp для всех плагинов равна 20130707.

Объекты плагинов объединены в глобальный объект, через который осуществляется доступ к функциям плагинов.

Во время инициализации для каждого плагина последовательно вызываются функции pluginfo.pfnInit. Инициализация заключается в создании таблицы вспомогательных функций. Кроме того, для плагинов Keylogger и Screen выполняются некоторые дополнительные действия.

Инициализация плагина "Keylogger"

После инициализации таблицы вспомогательных функций троян создает отдельный поток для функции pluginfo.pfnJob, которая устанавливает хук типа WH_KEYBOARD_LL. Имя файла для журнала событий генерируется с инициализатором 0x4B4C ("KL"). Временные атрибуты файла подделываются после каждой записи. Формат строчки записи журнала имеет следующий вид:

<yyyy-mm-dd hh:mm:ss> <username> <process_path> <window_title> <event></event></window_title>

Записи в журнал событий записываются последовательно. Каждая запись имеет формат:

struct keylog_rec
{
  DWORD recsize;
  BYTE encdata[recsize];
};

Инициализация плагина "Screen"

Во время инициализации плагина Screen в отдельном потоке запускается функция создания скриншота. В потоке сначала инициализируется библиотека gdiplus.dll, затем в конфигурации проверяется флаг config.make_screenshot_flag. Если флаг не установлен, то поток переходит в режим ожидания, периодически проверяя флаг. Если флаг установлен, то из конфигурации извлекается значение config.screen_age, которое задает максимальный срок хранения скриншотов в днях. При этом из каталога config.screenshots_path (в конфигурации по умолчанию %AUTO>%\\XS) рекурсивно удаляются все JPEG-файлы, даты создания которых меньше заданной. Очистка происходит раз в день. Далее выполняется создание скриншота, кодирование его в JPEG-формат и сохранение в директорию <config.screenshots_path>\<username>\<screen_filename>.jpg. Имя созданного скриншота записывается в формате < ГГГГ-ММ-ДД ЧЧ:ММ:СС >.

Параметры кодирования JPEG заданы в конфигурации в параметрах "config.screen_scale_coefficient", "config.encoder_quality", "config.bits_per_pixel".

Для каждого плагина предусмотрен отдельный набор command_id. При ответе на команду в заголовке проставляется тот же command_id. Строки передаются в теле пакета, смещение указывается явно, отсчитывается от начала тела пакета, при этом пропускается заголовок packet_hdr.

Плагин DISK

command_id для плагина DISK имеет формат 0x300X, X - 0,1,2,4,7,0xA,0xC,0xD,0xE.

Команда Описание Ввод Вывод
0x3000 Собирает информацию о логических дисках по буквам A-Z, заполняет массив структур disk_info и отправляет на сервер. -
struct disk_info
  {
    int drive_type;
    LARGE_INTEGER total_bytes;
    LARGE_INTEGER free_bytes_available;
    LARGE_INTEGER free_bytes;
    WORD off_volume_name;
    WORD off_filesystem_name;
  }
  struct command_3000h_response
  {
    packet_hdr header;
    disk_info info[26]'
  };
0x3001 Формирует список файлов и поддиректорий в заданной директории, которая указывается в параметре target_dir команды; по каждому файлу отправляет отдельный пакет.
struct command_3001h_request
  {
    packet_hdr header;
    BYTE target_dir[];
  };
  
struct command_3001h_response
  {
    packet_hdr header;
    BOOL has_subdir; //if is dir
    DWORD file_attributes;
    DWORD filesize_high;
    DWORD filesize_low;
    FILETIME creation_time;
    FILETIME last_access_time;
    FILETIME last_write_time;
    WORD off_file_name;
    WORD off_alternate_file_name;
    ...
    //strings
  };
  
0x3002 Формирует список файлов из директории, заданной в параметре target_dir команды. Имена файлов задаются маской, которая может использовать символы ? и * для замещения одного или нескольких любых символов; по каждому файлу отправляет отдельный пакет.
struct command_3002h_request
{
  packet_hdr header;
  WORD off_target_dir;
  WORD off_filename_mask;
  ...
  //target_dir,filename_mask
};
struct command_3002h_response
{
  packet_hdr header;
  DWORD file_attributes;
  DWORD file_size_high;
  DWORD file_size_low;
  FILETIME creation_time;
  FILETIME last_access_time;
  FILETIME last_write_time;
  WORD target_path_offset;
  WORD file_name_offset;
  WORD alternate_file_name_offset;
}; 
0x3004 Читает запрашиваемый файл блоками по 0x1000 байт с заданного смещения от начала файла. Имя файла и смещение определяются в команде. Сначала отправляет информацию о файле (временные атрибуты, размер файла) со значением поля command_id, равным 0x3004, в заголовке ответа, затем начинает читать файл и отправляет блоками с "command_id"==0x3005. Блоки содержимого файла помещает в тело пакета. По завершении отправляет пакет нулевой длины с 0x3005 в заголовке.
struct command_3004h_request
{
  packet_hdr header;
  BYTE pad_0[28];
  DWORD file_pointer_offset_low;
  DWORD file_pointer_offset_high;
  BYTE pad_1[8];
  BYTE target_file_name[];
};
struct command_3004h_response
{
  packet_hdr header;
  FILETIME creation_time;
  FILETIME last_access_time;
  FILETIME last_write_time;
  DWORD dword_0;
  DWORD returned_file_pointer;
  DWORD file_pointer_offset_high;
  DWORD file_size_low;
  DWORD file_size_high;
  WORD target_file_name_beg;
};
0x3007 Создает новый или открывает существующий файл с конца для записи и записывает в него данные, начиная с указанного смещения. Подменяет временны́е атрибуты. В команде с "command_id" 0x3007 задается имя файла и смещение, в команде с command_id 0x3008 — буфер для записи.
struct command_3007h_request
{
  packet_hdr header;
  FILETIME creation_time;
  FILETIME last_access_time;
  FILETIME last_write_time;
  DWORD dword_0;
  DWORD file_pointer_offset_low;
  DWORD file_pointer_offset_high;
  DWORD dword_1;
  DWORD dword_2;
  BYTE target_file_path[];
}; 
-
0x300A Создает папку, путь к которой указывается в теле пакета. Отвечает пакетом с нулевой длиной и "command_id" == 0x300A. - -
0x300C Создает процесс с использованием командной строки, переданной в теле команды. При этом, если в заголовке пакета значение поля «errc» ненулевое, создает рабочий стол HH и использует его в STARTUP_INFO создаваемого процесса. В ответ возвращает PROCESS_INFORMATION созданного процесса.
struct command_300Сh_request
{
  packet_hdr header;
  BYTE cmdline[]
};
struct command_300Сh_response
{
  packet_hdr header;
  PROCESS_INFORMATION proc_info;
};
0x300D Выполнение функции SHFileOperationW с заданными в команде параметрами. В ответ — пакет с нулевой длиной.
struct c2_command_300Dh_disk_srv2cli
{
  packet_hdr header;
  DWORD FO_wFunc;
  WORD FOF_flags;
  WORD word_0;
  WORD source_file_name_offset;
  WORD dest_file_name_offset;
  ...
  //strings
;
-
0x300E Разворачивает переменную среды и отправляет на сервер результат. Переменная содержится в теле команды, результат содержится в теле ответа. - -

Плагин DISK (2)

Второй плагин также называется DISK, однако ничего общего с системными дисками не имеет. Предусмотрены следующие номера команд: 0xF010, 0xF011, 0xF012, 0xF013.

В команде получает структуру srv, в соответствии с которой создает объект подключения и начинает ретрансляцию пакетов из одного соединения во вновь созданное.

Плагин KeyLogger

Включает команду 0xE000. Читает файл с журналом событий плагина, затем отправляет его на сервер в теле ответа.

Плагин Nethood

Плагин для работы с сетевым окружением.

Команда Описание Ввод Вывод
0xA000 Перечисляет все доступные ресурсы сети. По каждому ресурсу заполняет структуру и отправляет на сервер. В команде содержатся параметры структуры NETRESOURCE, используемой в качестве аргумента при вызове функции WNetOpenEnumW.
struct command_A000h_request
{
  packet_hdr header;
  WORD netres_scope;
  WORD netres_type;
  WORD netres_display_type;
  WORD netres_usage;
  WORD off_netres_localname;
  WORD off_netres_remotename;
  WORD off_etres_comment;
  WORD off_netres_provider;
};
struct command_A000h_response
{
  packet_hdr header;
  WORD netres_scope;
  WORD netres_type;
  WORD netres_display_type;
  WORD netres_usage;
  WORD off_netres_localname;
  WORD off_netres_remotename;
  WORD off_etres_comment;
  WORD off_netres_provider;
  BYTE res_comment_str[1000];
  NETRESOURCEW net_res_struct;
};
0xA001 Отключает заданный в команде сетевой ресурс с флагом Force, затем заново подключает. В ответ отправляет пакет с нулевой длиной.
struct command_A001h_request
{
  packet_hdr header;
  DWORD netres_scope;
  DWORD netres_type;
  DWORD netres_display_type;
  DWORD netres_usage;
  WORD netres_localname_offset;
  WORD netres_remotename_offset;
  WORD netres_comment_offset;
  WORD netres_provider_offset;
  WORD add_conn_username;
  WORD add_conn_password_offset;
  DWORD add_conn_flags;
  ...
  //strings
};
-

Плагин Netstat

Плагин собирает и отправляет сведения о сетевых соединениях.

Команда Описание Ввод Вывод
0xD000 Собирает и отправляет информацию о TCP-соединениях. В зависимости от версии ОС вызывает одну из функций для получения сведений о соединениях: AllocateAndGetTcpExTableFromStack (Windows XP); GetTcpTable (Windows 2000); GetExtendedTcpTable (Windows Vista-Windows 7). -
struct command_D000h_response
{
  packet_hdr header;
  DWORD conn_state;
  DWORD local_addr;
  DWORD local_port;
  DWORD remote_addr;
  DWORD remote_port;
  DWORD owner_pid;
  BYTE proc_name[];
};
0xD001 Собирает информацию о UDP-соединениях. Аналогична предыдущей команде. -
struct udp_listener_table
{
  DWORD local_addr;
  DWORD local_port;
  DWORD owner_port;
};
struct command_D001h_response
{
  packet_hdr header;
  udp_listener_table udp_tab;
  BYTE proc_name[];
};
0xD002 Меняет состояние TCP-соединения. В теле команды содержится аргумент для функции SetTcpEntry (MIB_TCPROW).
struct command_D002h_request
{
  packet_hdr header;
  MIB_TCPROW tcp_row
}
-

Плагин Option

Плагин может принимать следующие команды:

  • 0x2000 — заблокировать систему через функцию LockWorkstation;
  • 0x2001 — принудительно завершить сеанс пользователя;
  • 0x2002 — перезагрузка;
  • 0x2003 — завершение работы;
  • 0x2005 — показать в отдельном потоке MessageBox с заданными параметрами:
    struct command_0x2004_request
    {
      packet_hdr header;
      DWORD uType;
      WORD off_lpCaption;
      WORD off_lpText;
    }
    

Плагин Portmap

Содержит одну команду — 0xB000. Получает от управляющего сервера его адрес и порт:

 struct command_0xB000_request
{
  packet_hdr header;
  WORD port;
  BYTE srv_addr[40];
}
Затем создает объект TCP-соединения и подключается к полученному серверу, после чего работает в режиме туннельного соединения, передавая данные от управляющего сервера тому серверу, с которым установил соединение.

Плагин Process

Команда Описание Вывод
0x5000 Получить список работающих процессов. Каждому процессу соответствует отдельный отправляемый пакет.
struct command_5000h_response
{
  packet_hdr header;
  BOOL if_sfc_protected;
  BOOL is_wow64;
  DWORD pid;
  WORD off_username;
  WORD off_user_domain;
  WORD off_proc_path;
  WORD off_CompanyName;
  WORD off_FileDescription;
  WORD off_FileVersion;
  WORD off_ProductName;
  WORD off_ProductVersion;
  WORD off_icon_bitmask_bitmap;
  WORD off_icon_color_bm;
  ...
  //strings
};
0x5001 Получить список модулей заданного процесса; идентификатор целевого процесса задан в поле header.errc команды.
struct command_5001h_response
{
  packet_hdr header;
  BOOL if_sfc_protected;
  DWORD dll_base;
  DWORD size_of_image;
  FILETIME creation_time;
  FILETIME last_access_time;
  FILETIME last_write_time;
  WORD off_module_path;
  WORD off_CompanyInfo;
  WORD off_FileDescription;
  WORD off_FileVersion;
  WORD off_ProductName;
  WORD off_ProductVersion;
  ...
  //strings
};
0x5002 Завершить процесс; идентификатор задан в поле header.errc команды. -

Плагин Regedit

Плагин, предназначенный для работы с реестром.

Команда Описание Ввод Вывод
0x9000 Получить вложенные ключи реестра в заданном ключе. Дескриптор раздела содержится в поле header.errc, имя ключа содержится в теле команды. Отправляет по одному вложенному ключу. -
struct command_0x9000_response
{
  packet_hdr header;
  BOOL if_has_subkeys;
  BYTE subkey_name[];
}
0x9001 Создает вложенный ключ с заданным в теле команды именем. Дескриптор ключа содержится в поле header.errc. - -
0x9002 Удаляет заданный в теле команды вложенный ключ. Дескриптор ключа содержится в поле header.errc. - -
0x9003 Создает ключ с заданным именем, затем рекурсивно копирует в него значения из другого ключа, также заданного в команде. В случае успеха исходный ключ удаляет. В ином случае удаляет вновь созданный ключ. Дескриптор содержится в поле header.errc.
struct command_0x9003_request
{
  packet_hdr header;
  WORD off_src_subkey;
  WORD off_dst_subkey;
  ...
  //strings
}
-
0x9004 Получает значения заданного ключа. Имя ключа содержится в теле; дескриптор содержится в поле header.errc. -
struct command_9004h_response
{
  packet_hdr header;
  DWORD dword_0_zero;
  DWORD value_data_type;
  DWORD value_data_len;
  WORD word_0_zero;
  WORD off_value_name;
  WORD off_value_data;
  ...
  //strings
};
0x9005 Создает вложенный ключ и значение в нем. В зависимости от флага в команде может проверить, существует ли значение. Дескриптор содержится в поле header.errc.
struct command_9005h_request
{
  packet_0_hdr header;
  BOOL check_if_val_exists;
  DWORD value_data_type;
  DWORD value_data_size;
  WORD off_subkey_name;
  WORD off_value_name;
  WORD off_value_data;
  ...
  //strings
};
-
0x9006 Удаляет значение из ключа.
struct command_9006h_request
{
  packet_hdr header;
  WORD off_subkey_name;
  WORD off_value_name;
  ...
  //strings
}
-
0x9007 Проверяет, существует ли значение 1. Если его нет, то проверяет значение 2. Если оно существует, то создается значение 1, которое заменяется значением 2. После этого значение 2 удаляется.
struct command_9007h_request
{
  packet_hdr header;
  WORD off_subkey_name;
  WORD off_value_2_name;
  WORD off_value_1_name;
  ...
  //strings
}
-

Плагин Screen

Создает и отправляет скриншоты рабочего стола, имитирует работу по протоколу RDP.

Команда Описание Ввод Вывод
0x4000 Команда запускает 2 отдельных потока, которые имитируют работу по протоколу RDP. В одном потоке происходит отправка скриншотов интерактивного рабочего стола. Во втором — прием и выполнение команд, связанных с регистрацией событий мыши и клавиатуры. Изначально с командой 0x4000 приходит пакет с указанием на требуемое разрешение снимков экрана (бит на пиксель). Второй поток может получить одну из команд:
  • 0x4004 — установка фокуса на окне по заданным в команде координатам и (опционально) клик мышкой;
  • 0x4005 — отправка события клавиатуры;
  • 0x4006 — отправка HWND_BROADCAST сообщения с комбинацией клавиш Ctrl+Alt+Del.
struct command_4000h_request
{
  packet_hdr header;
  WORD bits_per_pixel;
}
struct command_4004h_request
{
  packet_hdr header;
  DWORD mouse_event_flags;
  DWORD mouse_event_data;
  DWORD x;
  DWORD y;
};
struct command_4005h_request
{
  packet_0_hdr header;
  BYTE vkey_code;
  BYTE key_scan_code;
  WORD reserved_0;
  BYTE keybd_event_flags;
};
struct command_4000h_screen_attr
{
  packet_hdr header;
  WORD bits_per_pixel;
  WORD horiz_res;
  WORD ver_res;
  BYTE bitmap_colos[];
}
0x4100 Делает снимок экрана с заданными параметрами и отправляет на сервер.
struct command_4100h_request
{
  packet_0_hdr header;
  BYTE bFlag;
  BYTE scale_or_resolution;
  WORD horz; //if flag -> resolutione, else scale coeff
  WORD vert; //as horz
};
-
0x4200 Отправляет заранее сделанный снимок экрана в формате JPEG из каталога config.screenshots_path. Сначала отправляет его имя, затем блоками по 0xE000 байт сам снимок. По окончании — пакет с нулевой длиной. - -

Плагин Service

Плагин предназначен для работы со службами.

Команда Описание Ввод Вывод
0x6000 Получает информацию о сервисах и их файлах. -
struct command_6000h_response
{
  packet_hdr header;
  DWORD if_sfc_protected;
  DWORD current_state;
  DWORD start_type;
  DWORD controls_accepted;
  DWORD pid;
  WORD offset_service_name;
  WORD offset_display_name;
  WORD offset_service_start_name;
  WORD offset_description;
  WORD offset_binpath;
  WORD offset_CompanyName;
  WORD offset_FileDescription;
  WORD offset_FileVersion;
  WORD offset_ProductName;
  WORD offset_ProductVersion;
  ...
  //strings
};
0x6001 Изменяет способ запуска заданной службы struct command_6000h_response. Имя целевой службы содержится в теле команды; новый параметр способа запуска содержится в поле header.errc. - -
0x6002 Запускает заданную службу, имя службы содержится в теле команды. - -
0x6003 Отправляет код управления заданной службе. Имя содержится в теле; код управления содержится в поле header.errc. - -
0x6004 Удаляет заданную в теле команды службу. - -

Плагин Shell

Плагин предназначен для создания оболочки командного процессора cmd.exe; идентификатор команды плагина — command_id — 0x7002. В двух отдельных потоках создает пайпы для чтения и записи, затем создает процесс cmd.exe с перенаправлением ввода-вывода на пайпы. Ввод получает от объекта соединения с управляющим сервером, а вывод отправляет в ответ.

Плагин SQL

Плагин предназначен для работы с SQL-запросами.

Команда Описание Ввод Вывод
0xC000 Получает доступные источники SQL-данных через функцию odbc32!SQLDataSourcesW. -
struct command_C000h_response
{
  packet_hdr header;
  BYTE server_name[4096];
  BYTE descriptions[];
}
0xC001 Перечисляет доступные SQL-драйверы через функцию odbc32!SQLDriversW. -
struct command_C001h_response
{
  packet_0_hdr header;
  BYTE driver_description[4096];
  BYTE driver_attributes[];
};
0xC002 Исполняет произвольный SQL-запрос. В теле первого пакета содержится строка подключения, используемая в качестве аргумента при вызове функции odbc32!SQLDriverConnect. Далее в пакетах с header.command_id, равным 0xC003, содержатся сами запросы. В ответ в пакетах с header.command_id, равным 0xC008, отправляются диагностические данные, полученные с помощью вызова функции SQLGetDiagRecW; в пакетах с header.command_id, равным 0xC004, отправляются результаты SQL-запроса. - -

Плагин Telnet

Плагин предназначен для полной имитации работы по протоколу Telnet. Запускается при получении команды 0x7100. По этой команде создается процесс "cmd.exe /Q", на сервер отправляется пакет нулевой длины, затем в отдельных потоках запускаются 2 обработчика. Первый принимает пакеты с id 0x7101 и 0x7102:

  • 0x7101 — открывает консоль по идентификатору CONIN$ и пишет в нее данные, полученные из команды. В теле пакета находится массив структур INPUT_RECORD;
  • 0x7102 — отправляет идентификатор управляющего события (CtrlEvent) в консоль, открытую по идентификатору CONIN$. Код события находится в поле header.errc.

Второй дескриптор в пакетах с id 0x7103 отправляет информацию о консоли:

struct c2_command_7103h_telnet_cli2srv
{
  packet_hdr header;
  DWORD console_CP;
  DWORD consoleOutput_CP;
  DWORD console_input_mode;
  DWORD console_output_mode;
  DWORD console_display_mode;
  CONSOLE_CURSOR_INFO console_cursor_info;
  COORD console_position;
  COORD console_size;
};

В пакетах с id 0x7104 отправляет считанный буфер консоли.

Рекомендации по лечению

  1. В случае если операционная система способна загрузиться (в штатном режиме или режиме защиты от сбоев), скачайте лечащую утилиту Dr.Web CureIt! и выполните с ее помощью полную проверку вашего компьютера, а также используемых вами переносных носителей информации.
  2. Если загрузка операционной системы невозможна, измените настройки BIOS вашего компьютера, чтобы обеспечить возможность загрузки ПК с компакт-диска или USB-накопителя. Скачайте образ аварийного диска восстановления системы Dr.Web® LiveDisk или утилиту записи Dr.Web® LiveDisk на USB-накопитель, подготовьте соответствующий носитель. Загрузив компьютер с использованием данного носителя, выполните его полную проверку и лечение обнаруженных угроз.
Скачать Dr.Web

По серийному номеру

Выполните полную проверку системы с использованием Антивируса Dr.Web Light для macOS. Данный продукт можно загрузить с официального сайта Apple App Store.

На загруженной ОС выполните полную проверку всех дисковых разделов с использованием продукта Антивирус Dr.Web для Linux.

Скачать Dr.Web

По серийному номеру

  1. Если мобильное устройство функционирует в штатном режиме, загрузите и установите на него бесплатный антивирусный продукт Dr.Web для Android Light. Выполните полную проверку системы и используйте рекомендации по нейтрализации обнаруженных угроз.
  2. Если мобильное устройство заблокировано троянцем-вымогателем семейства Android.Locker (на экране отображается обвинение в нарушении закона, требование выплаты определенной денежной суммы или иное сообщение, мешающее нормальной работе с устройством), выполните следующие действия:
    • загрузите свой смартфон или планшет в безопасном режиме (в зависимости от версии операционной системы и особенностей конкретного мобильного устройства эта процедура может быть выполнена различными способами; обратитесь за уточнением к инструкции, поставляемой вместе с приобретенным аппаратом, или напрямую к его производителю);
    • после активации безопасного режима установите на зараженное устройство бесплатный антивирусный продукт Dr.Web для Android Light и произведите полную проверку системы, выполнив рекомендации по нейтрализации обнаруженных угроз;
    • выключите устройство и включите его в обычном режиме.

Подробнее о Dr.Web для Android

Демо бесплатно на 14 дней

Выдаётся при установке

Российский разработчик антивирусов Dr.Web с 1992 года
Dr.Web в Реестре Отечественного ПО
Dr.Web совместим с российскими ОС и оборудованием
Dr.Web пользуются в 200+ странах мира
Техническая поддержка 24х7х365 Рус | En

Dr.Web © «Доктор Веб»
2003 — 2021

«Доктор Веб» — российский производитель антивирусных средств защиты информации под маркой Dr.Web. Продукты Dr.Web разрабатываются с 1992 года.

125124, Россия, Москва, 3-я улица Ямского поля, вл.2, корп.12А