Files
PYAS/Plugins/Filter/ProtectRegistry.cpp
T
2026-04-29 18:09:24 +08:00

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;
}
}