Где-то примерно неделю назад один мой коллега приметил одну замечательную вещь: Kaspersky интересным образом протянул свои ручки к Kernel Shim Engine.
В итоге мы собрались где-то вчера разгребать и смотреть, что он там забыл. Также попытались распилить и отловить шим Касперского, но об этом чуть позже.
Вводные
Начнем с понимания, что это вообще за зверь такой - Kernel Shim Engine.
Технически Kernel Shim Engine (далее KSE) предоставляет "обертки" для драйверов устройств, а также обеспечивает дополнительную поддержку и обработку ошибок драйверов устройств. У него есть своя специальная база данных, мы затронем её позже.
Также стоит поговорить о кое чем еще.
Инициализация шимов
Если говорить в кратце и не вдаваться в подробности работы, то шимы инициализируются на этапе загрузки системы, где-то сразу после того, как инциализировался HAL (Hardware Abstraction Layer) и WMI (Windows Management Instrumentation) с ETW (Event Tracing for Windows). После прогрузки HAL, WMI и ETW вызывается функция KseInitialize(), а после нее KseRegisterShim(). Эти функции официально не документированы, но находятся в некоторых заголовочных файлах WDK.
Инициализация "Built-in" шимов драйверов
В конце инициализации HAL происходит инициализация шима DriverScope, этот шим преоставляется по стандарту системой:
Затем, во время инициализации WMI/ETW также инициализируется функция KseVersionLieInitialize(). Данная функция инициализирует шимы KmWin7VersionLie, KmWin8VersionLie и KmWin81VersionLie (хоть тесты и производились на десятке, но подобный шим с версией "10" я не обнаружил):
Потом вызывается функция KseSkipDriverUnloadInitialize(), которая инициализирует шим SkipDriverUnload.
Функции Касперского в ядре
Окей, вроде +- разобрались. Теперь, какие функции были найдены мной, затрагивающие шимы:
Доступ был только к функции к KseKasperskyInitialize():
Сперва мы решили посмотреть, как поведет себя Касперский при манипуляции с реестром, а конкретнее:
- HKEY_LOCAL_MACHINE\System\CurrentControlSet\Policies\Microsoft\Compatibility
С ключами DisableDeviceFlags и DisableDriverShims (REG_DWORD), их значения равны единицы, очевидно по названиям ключей, что они делают при значении 0x01. - HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Compatibility
С ключем DisableFlags (REG_DWORD) со значением 0x01 (отключает функциональность драйвера).
В нашем случае Касперский никак себя не повел, тем более он спокойно дал изменить значения регистров, т.е эти ключи реестра не мониторятся Касперским.
Как поломать KSE
Можно сломать KSE двумя путями: мониторинг драйвера через Verifier и с помощью удаления drvmain.sdb.
Мы вполне имеем право поставить Verifier на драйвер Касперского, ну или удалить сам drvmain.sdb, но скорее всего это вызовет BSOD.
drvmain.sdb
Мы все же решили для начала порыться в drvmain.sdb. Стоит сказать, что до мониторинга и удаления мы не дошли, а почему - вы поймете позже.
drvmain.sdb - стандартная база данных "легальных" драйверов и не только. Помимо драйверов, там также находится информация о шимах и других вещах.
Этот файл находится в "%systemroot%/apppatch/". Файлы с расширением sdb можно открыть, к примеру, через SDBExplorer.
Видим в drvmain вот такую картину:
Да, список драйверов Касперского, ничего удивительного. Можно было бы ставить Verifier на klhk.sys и идти отлавливать шим Касперского, но не все так просто.
KSHIM и почему все печально закончилось
В drvmain, как и упоминалось выше, есть не только перечисление драйверов, а также некоторые шимы.
Представляются они в виде структуры KSHIM, которая по сути является структурой KSE_SHIM, только слегка измененной:
typedef struct _KSE_SHIM { _In_ ULONG Size; _In_ PGUID ShimGuid; _In_ PWCHAR ShimName; _Out_ PVOID KseCallbackRoutines; _Inopt_ PVOID ShimmedDriverTargetedNotification; _Inopt_ PVOID ShimmedDriverUntargetedNotification; _In_ PVOID HookCollectionsArray; } KSE_SHIM, *PKSE_SHIM;
Вот как выглядит KSHIM Касперского:
Заметьте, что поле MODULE несет значение "NT kernel component". А теперь можем посмотреть на ndis шимы:
Да, тут поле MODULE со значением "ndis". Думаю, можно догадаться, в чем проблема.
Ага, это значит, что шим Касперского существует в пространстве самого ядра системы. А это значит, что кроме как накидывая Verifier на ядро мы отследить шим Касперского не сможем. Вот, только если накидывать его на ядро, сломается не только Касперский, но и сама система. Прикольно, правда?
Возможный путь отлова шима Касперского
В мою голову лезет только анализ дампа системы. Т.е мы должны завершить систему аварийно, при этом сгенерировав дамп системы, где был запущен Касперский. Команда ".crash" (если не ошибаюсь) из windbg вполне решит эту проблему. Я, правда, не уверен, что мы сможем вытащить что-то дельное, но попытка не пытка, как говорится.
Послесловие и догадки
Теоретически, _KSE_SHIM - пользовательский ввод. Есть смысл посидеть над драйвером ndis.sys (сама структура оттуда). Однако, стучать туда через непривелегированного пользователя мы не сможем, но вполне вероятно, что до туда сможет достать TrustedInstaller.