248 lines
9.7 KiB
C++
248 lines
9.7 KiB
C++
#include "DriverCommon.h"
|
|
|
|
static LARGE_INTEGER Cookie;
|
|
|
|
static BOOLEAN IsBamRegistryPath(PCUNICODE_STRING KeyName) {
|
|
if (!KeyName || !KeyName->Buffer) return FALSE;
|
|
if (WildcardMatch(L"*\\Services\\bam\\*", KeyName->Buffer, KeyName->Length)) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOLEAN IsWriteAccess(ACCESS_MASK Access) {
|
|
if (Access & (KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_CREATE_LINK |
|
|
DELETE | WRITE_DAC | WRITE_OWNER | GENERIC_WRITE)) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static PWCHAR GetFullPath(PVOID RootObject, PUNICODE_STRING CompleteName, PULONG OutLength) {
|
|
PWCHAR Buffer = NULL;
|
|
ULONG TotalSize = 0;
|
|
PCUNICODE_STRING RootName = NULL;
|
|
BOOLEAN NeedFreeRootName = FALSE;
|
|
|
|
if (RootObject) {
|
|
NTSTATUS status = CmCallbackGetKeyObjectIDEx(&Cookie, RootObject, NULL, &RootName, 0);
|
|
if (NT_SUCCESS(status) && RootName) {
|
|
NeedFreeRootName = TRUE;
|
|
}
|
|
}
|
|
|
|
ULONG RootLen = (RootName && RootName->Buffer) ? RootName->Length : 0;
|
|
ULONG RelLen = (CompleteName && CompleteName->Buffer) ? CompleteName->Length : 0;
|
|
|
|
TotalSize = RootLen + sizeof(WCHAR) + RelLen + sizeof(WCHAR);
|
|
|
|
Buffer = (PWCHAR)PyasAllocate(TotalSize);
|
|
if (!Buffer) {
|
|
if (NeedFreeRootName) CmCallbackReleaseKeyObjectIDEx(RootName);
|
|
return NULL;
|
|
}
|
|
|
|
RtlZeroMemory(Buffer, TotalSize);
|
|
|
|
PWCHAR Current = Buffer;
|
|
if (RootLen > 0) {
|
|
RtlCopyMemory(Current, RootName->Buffer, RootLen);
|
|
Current += (RootLen / sizeof(WCHAR));
|
|
if (Current > Buffer && *(Current - 1) != L'\\') {
|
|
*Current = L'\\';
|
|
Current++;
|
|
}
|
|
}
|
|
|
|
if (RelLen > 0) {
|
|
if (RootLen > 0 && CompleteName->Buffer[0] == L'\\') {
|
|
RtlCopyMemory(Current, CompleteName->Buffer + 1, RelLen - sizeof(WCHAR));
|
|
}
|
|
else {
|
|
RtlCopyMemory(Current, CompleteName->Buffer, RelLen);
|
|
}
|
|
}
|
|
|
|
if (NeedFreeRootName) CmCallbackReleaseKeyObjectIDEx(RootName);
|
|
|
|
if (OutLength) *OutLength = (ULONG)wcslen(Buffer) * sizeof(WCHAR);
|
|
return Buffer;
|
|
}
|
|
|
|
static NTSTATUS RegistryCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2) {
|
|
UNREFERENCED_PARAMETER(CallbackContext);
|
|
|
|
if (KeGetCurrentIrql() > APC_LEVEL) return STATUS_SUCCESS;
|
|
|
|
REG_NOTIFY_CLASS Class = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
if (Class == RegNtPreCreateKey || Class == RegNtPreOpenKey || Class == RegNtPreOpenKeyEx) {
|
|
PVOID RootObject = NULL;
|
|
PUNICODE_STRING CompleteName = NULL;
|
|
ACCESS_MASK DesiredAccess = 0;
|
|
|
|
if (Class == RegNtPreCreateKey) {
|
|
REG_CREATE_KEY_INFORMATION* Info = (REG_CREATE_KEY_INFORMATION*)Argument2;
|
|
RootObject = Info->RootObject;
|
|
CompleteName = Info->CompleteName;
|
|
DesiredAccess = Info->DesiredAccess;
|
|
}
|
|
else {
|
|
REG_OPEN_KEY_INFORMATION* Info = (REG_OPEN_KEY_INFORMATION*)Argument2;
|
|
RootObject = Info->RootObject;
|
|
CompleteName = Info->CompleteName;
|
|
DesiredAccess = Info->DesiredAccess;
|
|
}
|
|
|
|
if (!IsWriteAccess(DesiredAccess)) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ULONG PathLen = 0;
|
|
PWCHAR FullPathBuffer = GetFullPath(RootObject, CompleteName, &PathLen);
|
|
|
|
if (FullPathBuffer) {
|
|
UNICODE_STRING FullPath;
|
|
RtlInitUnicodeString(&FullPath, FullPathBuffer);
|
|
|
|
if (CheckRegistryRule(&FullPath)) {
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
if (!IsProcessTrusted(Pid)) {
|
|
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, FullPath.Buffer, FullPath.Length);
|
|
status = STATUS_ACCESS_DENIED;
|
|
}
|
|
}
|
|
PyasFree(FullPathBuffer);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
if (Class == RegNtPreDeleteKey) {
|
|
REG_DELETE_KEY_INFORMATION* Info = (REG_DELETE_KEY_INFORMATION*)Argument2;
|
|
PCUNICODE_STRING KeyName = NULL;
|
|
|
|
if (NT_SUCCESS(CmCallbackGetKeyObjectIDEx(&Cookie, Info->Object, NULL, &KeyName, 0))) {
|
|
if (KeyName) {
|
|
if (CheckRegistryRule(KeyName)) {
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
if (!IsProcessTrusted(Pid)) {
|
|
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, KeyName->Buffer, KeyName->Length);
|
|
status = STATUS_ACCESS_DENIED;
|
|
}
|
|
}
|
|
CmCallbackReleaseKeyObjectIDEx(KeyName);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
if (Class == RegNtPreSetValueKey) {
|
|
REG_SET_VALUE_KEY_INFORMATION* Info = (REG_SET_VALUE_KEY_INFORMATION*)Argument2;
|
|
PCUNICODE_STRING KeyName = NULL;
|
|
|
|
if (NT_SUCCESS(CmCallbackGetKeyObjectIDEx(&Cookie, Info->Object, NULL, &KeyName, 0))) {
|
|
if (KeyName) {
|
|
if (KeyName->Buffer) {
|
|
if (!IsBamRegistryPath(KeyName)) {
|
|
ULONG FullSize = KeyName->Length + sizeof(WCHAR) +
|
|
(Info->ValueName ? Info->ValueName->Length : 0) +
|
|
sizeof(WCHAR);
|
|
|
|
if (FullSize <= 0xFFFF) {
|
|
PWCHAR Buffer = (PWCHAR)PyasAllocate(FullSize);
|
|
if (Buffer) {
|
|
UNICODE_STRING FullPath;
|
|
FullPath.Buffer = Buffer;
|
|
FullPath.Length = 0;
|
|
FullPath.MaximumLength = (USHORT)FullSize;
|
|
|
|
RtlCopyUnicodeString(&FullPath, KeyName);
|
|
|
|
if (Info->ValueName && Info->ValueName->Length > 0) {
|
|
if (FullPath.Length > 0 && FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] != L'\\') {
|
|
RtlAppendUnicodeToString(&FullPath, L"\\");
|
|
}
|
|
RtlAppendUnicodeStringToString(&FullPath, Info->ValueName);
|
|
}
|
|
|
|
if (CheckRegistryRule(&FullPath)) {
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
if (!IsProcessTrusted(Pid)) {
|
|
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, FullPath.Buffer, FullPath.Length);
|
|
status = STATUS_ACCESS_DENIED;
|
|
}
|
|
}
|
|
PyasFree(Buffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CmCallbackReleaseKeyObjectIDEx(KeyName);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
if (Class == RegNtPreDeleteValueKey) {
|
|
REG_DELETE_VALUE_KEY_INFORMATION* Info = (REG_DELETE_VALUE_KEY_INFORMATION*)Argument2;
|
|
PCUNICODE_STRING KeyName = NULL;
|
|
|
|
if (NT_SUCCESS(CmCallbackGetKeyObjectIDEx(&Cookie, Info->Object, NULL, &KeyName, 0))) {
|
|
if (KeyName) {
|
|
if (KeyName->Buffer) {
|
|
if (!IsBamRegistryPath(KeyName)) {
|
|
ULONG FullSize = KeyName->Length + sizeof(WCHAR) +
|
|
(Info->ValueName ? Info->ValueName->Length : 0) +
|
|
sizeof(WCHAR);
|
|
|
|
if (FullSize <= 0xFFFF) {
|
|
PWCHAR Buffer = (PWCHAR)PyasAllocate(FullSize);
|
|
if (Buffer) {
|
|
UNICODE_STRING FullPath;
|
|
FullPath.Buffer = Buffer;
|
|
FullPath.Length = 0;
|
|
FullPath.MaximumLength = (USHORT)FullSize;
|
|
|
|
RtlCopyUnicodeString(&FullPath, KeyName);
|
|
|
|
if (Info->ValueName && Info->ValueName->Length > 0) {
|
|
if (FullPath.Length > 0 && FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] != L'\\') {
|
|
RtlAppendUnicodeToString(&FullPath, L"\\");
|
|
}
|
|
RtlAppendUnicodeStringToString(&FullPath, Info->ValueName);
|
|
}
|
|
|
|
if (CheckRegistryRule(&FullPath)) {
|
|
HANDLE Pid = PsGetCurrentProcessId();
|
|
if (!IsProcessTrusted(Pid)) {
|
|
SendMessageToUser(3001, (ULONG)(ULONG_PTR)Pid, FullPath.Buffer, FullPath.Length);
|
|
status = STATUS_ACCESS_DENIED;
|
|
}
|
|
}
|
|
PyasFree(Buffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CmCallbackReleaseKeyObjectIDEx(KeyName);
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS InitializeRegistryProtection(PDRIVER_OBJECT DriverObject) {
|
|
UNICODE_STRING Altitude;
|
|
RtlInitUnicodeString(&Altitude, L"320000");
|
|
return CmRegisterCallbackEx(RegistryCallback, &Altitude, DriverObject, NULL, &Cookie, NULL);
|
|
}
|
|
|
|
VOID UninitializeRegistryProtection() {
|
|
if (Cookie.QuadPart != 0) {
|
|
CmUnRegisterCallback(Cookie);
|
|
Cookie.QuadPart = 0;
|
|
}
|
|
} |