В августе этого года мы публиковали информацию о новом state-sponsored вредоносном ПО под названием Cremes (aka Remsec). Антивирусные продукты ESET обнаруживают его компоненты как Win32/Cremes и Win64/Cremes. Cremes является сложным трояном со множеством компонентов, которые используются для кибершпионажа. Информация о Cremes также была опубликована специалистами Федеральной Службы Безопасности (ФСБ), поскольку Cremes использовался для кибершпионажа за сотрудниками государственных учреждений.
![](https://habrastorage.org/files/b56/9e7/612/b569e761297f48358cf6552aded01aed.jpeg)
Cremes включает в себя и Ring 0 компонент (руткит), который используется злоумышленниками как LPE-шлюз (kernel gate) для исполнения своего кода в режиме ядра. В отличие от уже таких хорошо известных руткитов и буткитов как ZeroAccess, TDL4, Mebroot, Gapz и др., Cremes не обременяет себя сложными процедурами компрометации MBR и ранних стадий загрузки ядра NT для исполнения своего Ring 0 кода в системе в обход DSE, вместо этого он использует для этого легитимные драйверы.
Авторы Cremes прибегли к использованию двух плагинов с названиями kgate и xkgate для размещения там Ring 0 кода. Нам удалось обнаружить внутри обоих плагинов временные метки, которые свидетельствуют о дате разработки плагинов и использовались авторами в отладочных целях. Согласно этим меткам, авторы прибегли к разработке xkgate позднее чем kgate. Валидность даты в xkgate подтверждается также временной меткой из заголовка PE-файла (хотя они и различаются на один день).
![](https://habrastorage.org/files/b89/5e9/173/b895e91731ba48e1bd3a679af0f7e0e4.png)
Рис. Временные метки внутри обоих плагинов
Плагин kgate используется в качестве установщика в систему Ring 0 кода как на 32-х, так и на 64-битных версиях Windows. Для 32-битной системы, kgate прибегает к использованию функций драйвера Agnitum Sandbox.sys, который позволяет с использованием специального IOCTL запроса загрузить драйвер руткита в систему. Для этого плагин извлекает из своего тела (секции .rdata) драйвер Sandbox.sys и записывает его на диск, после чего налету формирует PE-файл для своего вредоносного Ring 0 кода и записывает его в файл aswfilt.dll. Ниже приведены свойства этого драйвера.
![](https://habrastorage.org/files/617/006/7be/6170067bea4d42b48757729673dda4bd.png)
Рис. Плагин сбрасывает в файловую систему драйвер Agnitum Sandbox.sys, создает его сервис в системном реестре и загружает его в память для последующей эксплуатации.
![](https://habrastorage.org/files/8d5/f65/12d/8d5f6512da6e49df90b22f9c4908483b.png)
Рис. Плагин генерирует файл руткита, прописывает его в реестре и указывает Sandbox.sys загрузить драйвер.
Ответ на вопрос, зачем авторам понадобилось записывать содержимое руткита в файл aswfilt.dll кроется в драйвере Sandbox.sys. Если мы посмотрим на его код, то увидим ссылку на него внутри драйвера.
![](https://habrastorage.org/files/dcc/c07/cf4/dccc07cf47974ee9b7854a49f804f859.png)
Рис. Ссылка на aswfilt.dll внутри легитимного драйвера Sandbox.sys.
После небольшого анализа кода Sandbox.sys, нам удалось обнаружить, что ссылка на данный файл внутри драйвера связана с тем IOCTL-кодом, который плагин отправляет драйверу. Особенность заключается в том, что aswfilt.dll является названием плагина Agnitum, который драйвер Sandbox.sys может загрузить в память после того, как ему отправлен данный IOCTL код.
![](https://habrastorage.org/files/5d8/c18/1ee/5d8c181ee5f4480794578a8ce3c924b5.png)
![](https://habrastorage.org/files/761/55c/e1e/76155ce1ee0f4e71a0b868be81b75cd8.png)
![](https://habrastorage.org/files/a4d/0a5/016/a4d0a5016b724629990532580ce2fbdb.png)
Рис. При обработке драйвером IOCTL-кода, он проверяет название файла и загружает его в системную память с использованием API ядра ZwLoadDriver.
Руткит используется плагином kgate лишь для одной цели — исполнение указанной ему из пользовательского режима функции в режиме ядра с обходом SMEP. Для коммуникации с клиентом, руткит создает объект-устройство \Device\rwx, при этом клиент использует путь \\.\GLOBALROOT\Device\rwx для открытия устройства. Для отключения SMEP и исполнения функции, клиент отправляет Ring 0 коду IOCTL с кодом 0x1173000C.
![](https://habrastorage.org/files/b5c/c61/732/b5cc6173237a4ba0a1925e07982cd7f3.png)
Рис. Руткит отключает SMEP для исполнения функции из user mode, при этом, предварительно, привязав поток к текущему процессору.
Следующая структура используется руткитом в качестве контекста (DeviceObject->DeviceExtension).
Драйвер использует интересную процедуру выгрузки по таймеру и позволяет клиенту из пользовательского режима задавать интервал ожидания. Для этого драйвер создает отдельный системный поток, который ждет на таймере и в случае истечения времени вызывает функцию ZwUnloadDriver. Выгрузка драйвера из своего же кода может быть выполнена некорректно, поскольку поток может вернуться уже на несуществующую страницу памяти.
![](https://habrastorage.org/files/88a/5ab/097/88a5ab0976cb4311981da243e288e9d4.png)
Рис. Функция fnCreateDriverRegKeyOrRemoveIt выполняет удаление сервиса драйвера и выгружает его с помощью ZwLoadDriver.
Ниже приведена структура исполняемого файла плагина.
![](https://habrastorage.org/files/029/963/66c/02996366c6ac43fdb465714b64902935.png)
Рис. Структура PE-файла плагина kgate.
Название плагина xkgate можно интерпретировать как extended kgate, т. е. расширенный kgate. В отличие от своего предшественника, он не имеет на борту 32-х разрядной версии, а рассчитан только на 64-битную версию Windows. Ниже в таблице указаны сравнения возможностей обоих плагинов.
![](https://habrastorage.org/files/0ab/c14/6d1/0abc146d1b0b48d8bcc7e16ee3f93a77.png)
![](https://habrastorage.org/files/a58/70d/fd3/a5870dfd381446ef995eff75018d943b.png)
Ниже приведена информация о цифровых подписях используемых драйверов AV продуктов авторами Cremes.
![](https://habrastorage.org/files/4de/8e9/363/4de8e9363544471eab83e95cdc4f22b0.png)
Рис. Цифровые подписи драйверов Avast и Agnitum.
Как видно, оба плагина содержат идентичный код в секциях с 64-битным кодом krwkr64 и krdrv64. Для загрузки этого Ring 0 кода авторы Cremes выбрали еще одну жертву — драйвер Avast. Эксплуатация этого драйвера сложнее чем драйвера Agnitum, рассмотрим его более подробно.
Первое что делает xkgate для загрузки Ring 0 кода, это создает специальный мьютекс для предотвращения повторной загрузки драйвера Avast в память (функция).
![](https://habrastorage.org/files/c32/053/88e/c3205388e86c429eb65b82bbe0a6da23.png)
Рис. Код открытия/создания мьютекса.
После этого код вызывает функцию fnDropAvastDriverAndPrepareEnv, которая выполняет следующие действия.
![](https://habrastorage.org/files/da0/8ca/426/da08ca426f9843ed847424d6ba63b797.png)
Рис. Вызов функции fnDropAvastDriverAndPrepareEnv внутри fnLoadAvast.
После этого fnLoadAvast вызывает fnCreateAvastServiceAndLoadDriver для создания раздела реестра для Avast. Ниже указаны предпринимаемые действия.
После того как aswSnx.sys загружен, fnLoadAvast удаляет файлы snxhk.dll и snxhk64.dll с помощью NtSetInformationFile. Далее функция создает процесс с названием aswSnx.exe, который представляет из себя notepad.exe. После этого создается дескриптор на устройство Avast с названием \Device\aswSnx.
![](https://habrastorage.org/files/2ae/40a/93c/2ae40a93cd8a4e95a4af329a9c84773d.png)
Рис. Функция создания псевдо — aswSnx.exe.
После создания процесса aswSnx.exe с остановленным стартовым потоком, функция дублирует открытый дескриптор на устройство \Device\aswSnx из процесса плагина в новый процесс aswSnx.exe. Далее туда же копируется специальный код из секции плагина .avit, которая отвечает за взаимодействие с драйвером Avast. Он выполняет функцию DeviceIoControl, которая приводит к исполнению вредоносного Ring 0 кода.
![](https://habrastorage.org/files/261/599/6de/2615996de9b64fe0b7b25a97e22121be.png)
Рис. Функция эксплуатации драйвера Avast.
Ниже указаны характеристики загружаемого Ring 0 кода.
Для упрощения анализа рассмотрим идентичную 32-битную версию Ring 0 кода, которая хранится в плагине kgate.
Так как код режима ядра не загружается самим ядром Windows и не представляет из себя полноценный файл драйвера, для загруженного кода не создан объект драйвера, который должен передаваться ему через DriverEntry. Поэтому, первое что делает руткит, это создает для себя объект драйвера с помощью ObCreateObject.
![](https://habrastorage.org/files/dc7/f33/34a/dc7f3334a5dd45849ff25dc15bc482d7.png)
![](https://habrastorage.org/files/9d1/78b/ab6/9d178bab653c4d0e96a474da424e9d5f.png)
Рис. Функция создания объекта драйвера и вставки его в системную очередь Windows через недокументированную функцию ObInsertObject.
Для обработки запроса DeviceControl, драйвер регистрирует не стандартный в таких случаях обработчик IRP_MJ_DEVICE_CONTROL, а использует вместо этого функцию быстрого ввода-вывода DriverObject->FastIoDispatch.FastIoDeviceControl.
![](https://habrastorage.org/files/9b8/f0a/b17/9b8f0ab174e94a70af195f045e906a8f.png)
Рис. Функция регистрации DriverObject->FastIoDispatch.FastIoDeviceControl.
Эта функция-обработчик используется только для исполнения кода требуемого клиентом кода в режиме ядра.
![](https://habrastorage.org/files/e4f/417/4d0/e4f4174d09044e3995dcbf3dbcb10a1a.png)
Рис. Обработчик Fast I/O руткита.
Применяемые авторами Cremes методы для загрузки руткита в память являются действительно интересными, так как для этого используются легитимные драйверы режима ядра антивирусных продуктов. В отличие от прочих известных руткитов, Cremes не заинтересован в перехвате каких-либо API-вызовов или системных операций для сокрытия своей активности в системе. Вместо этого, авторов просто интересовала возможность гарантированного исполнения своего кода в режима ядра, т. е. повышение своих привилегий в системе. С помощью используемого ими подхода такая методика является достаточно успешной.
![](https://habrastorage.org/files/b56/9e7/612/b569e761297f48358cf6552aded01aed.jpeg)
Cremes включает в себя и Ring 0 компонент (руткит), который используется злоумышленниками как LPE-шлюз (kernel gate) для исполнения своего кода в режиме ядра. В отличие от уже таких хорошо известных руткитов и буткитов как ZeroAccess, TDL4, Mebroot, Gapz и др., Cremes не обременяет себя сложными процедурами компрометации MBR и ранних стадий загрузки ядра NT для исполнения своего Ring 0 кода в системе в обход DSE, вместо этого он использует для этого легитимные драйверы.
Авторы Cremes прибегли к использованию двух плагинов с названиями kgate и xkgate для размещения там Ring 0 кода. Нам удалось обнаружить внутри обоих плагинов временные метки, которые свидетельствуют о дате разработки плагинов и использовались авторами в отладочных целях. Согласно этим меткам, авторы прибегли к разработке xkgate позднее чем kgate. Валидность даты в xkgate подтверждается также временной меткой из заголовка PE-файла (хотя они и различаются на один день).
![](https://habrastorage.org/files/b89/5e9/173/b895e91731ba48e1bd3a679af0f7e0e4.png)
Рис. Временные метки внутри обоих плагинов
Плагин kgate
Плагин kgate используется в качестве установщика в систему Ring 0 кода как на 32-х, так и на 64-битных версиях Windows. Для 32-битной системы, kgate прибегает к использованию функций драйвера Agnitum Sandbox.sys, который позволяет с использованием специального IOCTL запроса загрузить драйвер руткита в систему. Для этого плагин извлекает из своего тела (секции .rdata) драйвер Sandbox.sys и записывает его на диск, после чего налету формирует PE-файл для своего вредоносного Ring 0 кода и записывает его в файл aswfilt.dll. Ниже приведены свойства этого драйвера.
- Имеет компактный размер и может уместиться на одну страницу виртуальной памяти (4КБ).
- Так как сам PE-файл генерируется на лету, он не имеет временной метки в PE-заголовке. Он также имеет одну безымянную NONPAGED-секцию с кодом и данными драйвера.
- Драйвер использует динамически подгружаемые импорты и хранит их в специальной структуре DeviceObject->DeviceExtension.
- Драйвер использует обфускацию смещений внутри кода.
- С точки зрения кодинга, драйвер написан квалифицированными авторами
![](https://habrastorage.org/files/617/006/7be/6170067bea4d42b48757729673dda4bd.png)
Рис. Плагин сбрасывает в файловую систему драйвер Agnitum Sandbox.sys, создает его сервис в системном реестре и загружает его в память для последующей эксплуатации.
![](https://habrastorage.org/files/8d5/f65/12d/8d5f6512da6e49df90b22f9c4908483b.png)
Рис. Плагин генерирует файл руткита, прописывает его в реестре и указывает Sandbox.sys загрузить драйвер.
Ответ на вопрос, зачем авторам понадобилось записывать содержимое руткита в файл aswfilt.dll кроется в драйвере Sandbox.sys. Если мы посмотрим на его код, то увидим ссылку на него внутри драйвера.
![](https://habrastorage.org/files/dcc/c07/cf4/dccc07cf47974ee9b7854a49f804f859.png)
Рис. Ссылка на aswfilt.dll внутри легитимного драйвера Sandbox.sys.
После небольшого анализа кода Sandbox.sys, нам удалось обнаружить, что ссылка на данный файл внутри драйвера связана с тем IOCTL-кодом, который плагин отправляет драйверу. Особенность заключается в том, что aswfilt.dll является названием плагина Agnitum, который драйвер Sandbox.sys может загрузить в память после того, как ему отправлен данный IOCTL код.
![](https://habrastorage.org/files/5d8/c18/1ee/5d8c181ee5f4480794578a8ce3c924b5.png)
![](https://habrastorage.org/files/761/55c/e1e/76155ce1ee0f4e71a0b868be81b75cd8.png)
![](https://habrastorage.org/files/a4d/0a5/016/a4d0a5016b724629990532580ce2fbdb.png)
Рис. При обработке драйвером IOCTL-кода, он проверяет название файла и загружает его в системную память с использованием API ядра ZwLoadDriver.
Руткит используется плагином kgate лишь для одной цели — исполнение указанной ему из пользовательского режима функции в режиме ядра с обходом SMEP. Для коммуникации с клиентом, руткит создает объект-устройство \Device\rwx, при этом клиент использует путь \\.\GLOBALROOT\Device\rwx для открытия устройства. Для отключения SMEP и исполнения функции, клиент отправляет Ring 0 коду IOCTL с кодом 0x1173000C.
![](https://habrastorage.org/files/b5c/c61/732/b5cc6173237a4ba0a1925e07982cd7f3.png)
Рис. Руткит отключает SMEP для исполнения функции из user mode, при этом, предварительно, привязав поток к текущему процессору.
Следующая структура используется руткитом в качестве контекста (DeviceObject->DeviceExtension).
struct RootkitStruct {
PVOID ExAllocatePool;
PVOID ExFreePool;
PVOID IoCompleteRequest;
PVOID IoCreateDevice;
PVOID IoDeleteDevice;
PVOID KeAcquireSpinLock;
PVOID KeCancelTimer;
PVOID KeInitializeEvent;
PVOID KeInitializeSpinLock;
PVOID KeInitializeTimer;
PVOID KeQueryInterruptTime;
PVOID KeReleaseSpinLock;
PVOID KeSetEvent;
PVOID KeSetTimer;
PVOID KeWaitForMultipleObjects;
PVOID ObfReferenceObject;
PVOID ObDereferenceObject;
PVOID PsCreateSystemThread;
PVOID PsGetVersion;
PVOID PsTerminateSystemThread;
PVOID ZwClose;
PVOID ZwCreateKey;
PVOID ZwDeleteKey;
PVOID ZwEnumerateKey;
PVOID ZwOpenKey;
PVOID ZwSetValueKey;
PVOID ZwUnloadDriver;
PVOID KeQueryActiveProcessors;
PVOID KeSetSystemAffinityThread;
PVOID KeRevertToUserAffinityThread;
ULONG Flag;
KEVENT Event;
ULONG dwField1;
KTIMER Timer;
KSPIN_LOCK SpinLock;
ULONG dwField2;
LARGE_INTEGER IntervalTime;
UNICODE_STRING unDriverRegistryPath;
};
Драйвер использует интересную процедуру выгрузки по таймеру и позволяет клиенту из пользовательского режима задавать интервал ожидания. Для этого драйвер создает отдельный системный поток, который ждет на таймере и в случае истечения времени вызывает функцию ZwUnloadDriver. Выгрузка драйвера из своего же кода может быть выполнена некорректно, поскольку поток может вернуться уже на несуществующую страницу памяти.
![](https://habrastorage.org/files/88a/5ab/097/88a5ab0976cb4311981da243e288e9d4.png)
Рис. Функция fnCreateDriverRegKeyOrRemoveIt выполняет удаление сервиса драйвера и выгружает его с помощью ZwLoadDriver.
Ниже приведена структура исполняемого файла плагина.
![](https://habrastorage.org/files/029/963/66c/02996366c6ac43fdb465714b64902935.png)
Рис. Структура PE-файла плагина kgate.
Плагин xkgate
Название плагина xkgate можно интерпретировать как extended kgate, т. е. расширенный kgate. В отличие от своего предшественника, он не имеет на борту 32-х разрядной версии, а рассчитан только на 64-битную версию Windows. Ниже в таблице указаны сравнения возможностей обоих плагинов.
![](https://habrastorage.org/files/0ab/c14/6d1/0abc146d1b0b48d8bcc7e16ee3f93a77.png)
![](https://habrastorage.org/files/a58/70d/fd3/a5870dfd381446ef995eff75018d943b.png)
Ниже приведена информация о цифровых подписях используемых драйверов AV продуктов авторами Cremes.
![](https://habrastorage.org/files/4de/8e9/363/4de8e9363544471eab83e95cdc4f22b0.png)
Рис. Цифровые подписи драйверов Avast и Agnitum.
Как видно, оба плагина содержат идентичный код в секциях с 64-битным кодом krwkr64 и krdrv64. Для загрузки этого Ring 0 кода авторы Cremes выбрали еще одну жертву — драйвер Avast. Эксплуатация этого драйвера сложнее чем драйвера Agnitum, рассмотрим его более подробно.
Первое что делает xkgate для загрузки Ring 0 кода, это создает специальный мьютекс для предотвращения повторной загрузки драйвера Avast в память (функция).
![](https://habrastorage.org/files/c32/053/88e/c3205388e86c429eb65b82bbe0a6da23.png)
Рис. Код открытия/создания мьютекса.
После этого код вызывает функцию fnDropAvastDriverAndPrepareEnv, которая выполняет следующие действия.
- Создает директорию \SystemRoot\Temp\aswSnx, куда записывает файлы Avast.
- Сбрасывает в файловую систему файл aswSnx.sys.
- Сбрасывает в файловую систему snx_lconfig.xml
- Также извлекает из себя snx_gconfig.xml.
- Создает пустой файл snxhk.dll.
- Создает файл aswSnx.exe и записывает в него содержимое notepad.exe.
![](https://habrastorage.org/files/da0/8ca/426/da08ca426f9843ed847424d6ba63b797.png)
Рис. Вызов функции fnDropAvastDriverAndPrepareEnv внутри fnLoadAvast.
После этого fnLoadAvast вызывает fnCreateAvastServiceAndLoadDriver для создания раздела реестра для Avast. Ниже указаны предпринимаемые действия.
- Создает раздел реестра System\CurrentControlSet\Services\aswSnx.
- Создает в нем параметр ImagePath со значением \SystemRoot\Temp\aswSnx\aswSnx.sys.
- Создает параметр Type.
- Создает подраздел Parameters.
- Создает в нем параметр DataFolder со значением \??\Global\GLOBALROOT\SystemRoot\Temp\aswSnx.
- Создает параметр ProgramFolder со значением \??\Global\GLOBALROOT\SystemRoot\Temp\aswSnx.
- Создает подраздел Instances.
- Создает в нем подраздел DefaultInstance.
- Создает в нем параметры Altitude и Flags.
- Загружает aswSnx.sys с использованием NtLoadDriver.
После того как aswSnx.sys загружен, fnLoadAvast удаляет файлы snxhk.dll и snxhk64.dll с помощью NtSetInformationFile. Далее функция создает процесс с названием aswSnx.exe, который представляет из себя notepad.exe. После этого создается дескриптор на устройство Avast с названием \Device\aswSnx.
![](https://habrastorage.org/files/2ae/40a/93c/2ae40a93cd8a4e95a4af329a9c84773d.png)
Рис. Функция создания псевдо — aswSnx.exe.
После создания процесса aswSnx.exe с остановленным стартовым потоком, функция дублирует открытый дескриптор на устройство \Device\aswSnx из процесса плагина в новый процесс aswSnx.exe. Далее туда же копируется специальный код из секции плагина .avit, которая отвечает за взаимодействие с драйвером Avast. Он выполняет функцию DeviceIoControl, которая приводит к исполнению вредоносного Ring 0 кода.
![](https://habrastorage.org/files/261/599/6de/2615996de9b64fe0b7b25a97e22121be.png)
Рис. Функция эксплуатации драйвера Avast.
Ниже указаны характеристики загружаемого Ring 0 кода.
- Имеет компактный размер и умещается в одну страницу виртуальной памяти.
- Использует динамические импорты, которые также хранятся в контексте устройства.
- Плагин kgate имеет 32-битный аналог этого кода.
- Не содержит функцию DriverEntry.
- Исполняет требуемый клиентом код через механизм быстрого DeviceControl (Fast I/O) FastIoDeviceControl.
- Использует недокументированные функции ядра Windows.
Для упрощения анализа рассмотрим идентичную 32-битную версию Ring 0 кода, которая хранится в плагине kgate.
Так как код режима ядра не загружается самим ядром Windows и не представляет из себя полноценный файл драйвера, для загруженного кода не создан объект драйвера, который должен передаваться ему через DriverEntry. Поэтому, первое что делает руткит, это создает для себя объект драйвера с помощью ObCreateObject.
![](https://habrastorage.org/files/dc7/f33/34a/dc7f3334a5dd45849ff25dc15bc482d7.png)
![](https://habrastorage.org/files/9d1/78b/ab6/9d178bab653c4d0e96a474da424e9d5f.png)
Рис. Функция создания объекта драйвера и вставки его в системную очередь Windows через недокументированную функцию ObInsertObject.
Для обработки запроса DeviceControl, драйвер регистрирует не стандартный в таких случаях обработчик IRP_MJ_DEVICE_CONTROL, а использует вместо этого функцию быстрого ввода-вывода DriverObject->FastIoDispatch.FastIoDeviceControl.
![](https://habrastorage.org/files/9b8/f0a/b17/9b8f0ab174e94a70af195f045e906a8f.png)
Рис. Функция регистрации DriverObject->FastIoDispatch.FastIoDeviceControl.
Эта функция-обработчик используется только для исполнения кода требуемого клиентом кода в режиме ядра.
![](https://habrastorage.org/files/e4f/417/4d0/e4f4174d09044e3995dcbf3dbcb10a1a.png)
Рис. Обработчик Fast I/O руткита.
Заключение
Применяемые авторами Cremes методы для загрузки руткита в память являются действительно интересными, так как для этого используются легитимные драйверы режима ядра антивирусных продуктов. В отличие от прочих известных руткитов, Cremes не заинтересован в перехвате каких-либо API-вызовов или системных операций для сокрытия своей активности в системе. Вместо этого, авторов просто интересовала возможность гарантированного исполнения своего кода в режима ядра, т. е. повышение своих привилегий в системе. С помощью используемого ими подхода такая методика является достаточно успешной.
Поделиться с друзьями
VANSCoder
<сарказм>Зато аваст бесплатный</сарказм>