Как я понял из вашего описания, вы хотите изменить поведение определенного API.Однако вы не указали, хотите ли вы изменить данные, передаваемые в такой API, или просто проигнорировали запрос.В любом случае, для такого требования самое простое и простое решение - написать драйвер ядра мини-фильтра.При таком подходе вы будете использовать CmRegisterCallbackEx
, а не CmRegisterCallback
(так как этот устарел) для регистрации обратного вызова для фильтрации событий реестра.И тогда вы можете написать свои собственные функции обратного вызова, которые заботятся о каждом событии реестра, которое вы хотите изменить.Вот простой фрагмент о том, как написать такой драйвер ядра для мини-фильтра.Помните, что вам все еще необходимо написать логику для изменения API, просто отклоняя запрос или изменяя его содержимое.
#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
LARGE_INTEGER g_Cookie = { 0 };
NTSTATUS DriverRegistryCallback(
_In_ PVOID CallbackContext,
_In_ PVOID Argument1,
_In_ PVOID Argument2
) {
UNREFERENCED_PARAMETER(CallbackContext);
PREG_POST_OPERATION_INFORMATION PreInfo;
PREG_OPEN_KEY_INFORMATION_V1 OpenKey;
PREG_CREATE_KEY_INFORMATION_V1 CreateKey;
REG_NOTIFY_CLASS RegOp = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
switch (RegOp) {
case RegNtPreCreateKeyEx:
PreInfo = (PREG_POST_OPERATION_INFORMATION)Argument2;
CreateKey = (PREG_CREATE_KEY_INFORMATION_V1)PreInfo->PreInformation;
if (PreInfo->Status == STATUS_SUCCESS) {
// do something here
}
break;
case RegNtPreOpenKeyEx:
PreInfo = (PREG_POST_OPERATION_INFORMATION)Argument2;
OpenKey = (PREG_OPEN_KEY_INFORMATION_V1)PreInfo->PreInformation;
if (PreInfo->Status == STATUS_SUCCESS) {
// do something here
}
break;
default:
break;
}
return STATUS_SUCCESS;
}
VOID
DriverUnload(
_In_ PDRIVER_OBJECT pDriverObject
) {
UNREFERENCED_PARAMETER(pDriverObject);
PAGED_CODE();
NTSTATUS status = CmUnRegisterCallback(g_Cookie);
if (!NT_SUCCESS(status)) {
DbgPrint("[RegistryFilter] Failed to unregister callback\n");
}
DbgPrint("[RegistryFilter] Driver unloaded successfully\n");
}
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT pDriverObject,
_In_ PUNICODE_STRING pRegistryPath
) {
UNREFERENCED_PARAMETER(pRegistryPath);
pDriverObject->DriverUnload = DriverUnload;
UNICODE_STRING AltitudeString = RTL_CONSTANT_STRING(L"360000");
NTSTATUS status = CmRegisterCallbackEx(DriverRegistryCallback, &AltitudeString, pDriverObject, NULL, &g_Cookie, NULL);
if (!NT_SUCCESS(status)) {
DbgPrint("[RegistryFilter] Failed to register callback\n");
return status;
}
DbgPrint("[RegistryFilter] Driver loaded successfully\n");
return status;
}
Помните, что это не ваше окончательное решение.Вы должны написать свою собственную логику, как я упоминал ранее, либо для отказа в доступе к определенному вызову, сравнивая данные, возвращенные к вашим собственным статическим данным, а затем возвращая STATUS_ACCESS_DENIED
, либо изменяя структуру данных, содержащую значения, и затем передавая ее обратно.Вы должны знать, что если вы хотите изменить какое-либо событие Open*
, вам нужно сначала обработать событие Create*
.Поскольку любому событию Open*
должен предшествовать, а первым должно быть событие Create*
.
Кстати, SSDT не является предпочтительным решением, поскольку индексы изменяются с версии Windows на другую и с одного пакета обновления надругой.Это ненадежно, в общем и не рекомендуется, по крайней мере, для этой простой задачи.Не говоря уже о том, что у вас могут возникнуть проблемы с его настройкой для архитектуры x64.
РЕДАКТИРОВАТЬ: я забыл упомянуть, что это будет работать только начиная с Vista +, поэтому для работы в Windows XP необходимо внести определенные изменения, какизменятся имена структуры реестра и имена событий реестра.
Вот несколько ссылок, с которых можно начать:
- CmRegisterCallbackEx (https://msdn.microsoft.com/en-us/library/windows/hardware/ff541921(v=vs.85).aspx)
- пример кода Windows WDK CmRegisterCallbackEx(https://github.com/Microsoft/Windows-driver-samples/tree/master/general/registry)