From 79cec65cf2a6f1d7a98c412599f675065e6fde1c Mon Sep 17 00:00:00 2001 From: JKornev <8bit.dosninja@gmail.com> Date: Sun, 18 Dec 2016 21:11:10 +0300 Subject: [PATCH] Driver loads configs from registry --- Hidden/Configs.c | 281 ++++++++++++++++++++++++++++++++++ Hidden/Configs.h | 23 +++ Hidden/Driver.c | 8 +- Hidden/FsFilter.c | 19 +++ Hidden/Hidden.vcxproj | 2 + Hidden/Hidden.vcxproj.filters | 6 + Hidden/PsMonitor.c | 72 ++++++++- Hidden/RegFilter.c | 19 +++ 8 files changed, 427 insertions(+), 3 deletions(-) create mode 100644 Hidden/Configs.c create mode 100644 Hidden/Configs.h diff --git a/Hidden/Configs.c b/Hidden/Configs.c new file mode 100644 index 0000000..1354326 --- /dev/null +++ b/Hidden/Configs.c @@ -0,0 +1,281 @@ +#include "Configs.h" + +#define CONFIG_ALLOC_TAG 'gfnC' + +typedef struct _HidConfigContext { + BOOLEAN state; + BOOLEAN stealth; + UNICODE_STRING hideFSDirs; + UNICODE_STRING hideFSFiles; + UNICODE_STRING hideRegKeys; + UNICODE_STRING hideRegValues; + UNICODE_STRING ignoreImages; + UNICODE_STRING protectImages; +} HidConfigContext, *PHidConfigContext; + +PHidConfigContext g_configContext = NULL; + +NTSTATUS ReleaseConfigContext(PHidConfigContext context); + +NTSTATUS GetRegistryDWORD(HANDLE hKey, LPCWSTR Value, PULONG Data, ULONG Default); +NTSTATUS QueryAndAllocRegistryData(HANDLE hKey, LPCWSTR Value, ULONG Type, PUNICODE_STRING Data, PUNICODE_STRING Default); +VOID ReleaseRegistryData(PUNICODE_STRING Data); + +// ========================================================================================= + +NTSTATUS InitializeConfigs(PUNICODE_STRING RegistryPath) +{ + HidConfigContext config; + OBJECT_ATTRIBUTES attribs; + NTSTATUS status; + HANDLE hkey; + ULONG value; + + if (g_configContext) + return STATUS_ALREADY_REGISTERED; + + RtlZeroMemory(&config, sizeof(config)); + + InitializeObjectAttributes(&attribs, RegistryPath, 0, NULL, NULL); + + status = ZwOpenKey(&hkey, KEY_ALL_ACCESS, &attribs); + if (!NT_SUCCESS(status)) + { + DbgPrint("FsFilter1!" __FUNCTION__ ": can't open config registry key, code:%08x\n", status); + return status; + } + + GetRegistryDWORD(hkey, L"Hid_State", &value, 1); + config.state = (value ? TRUE : FALSE); + + GetRegistryDWORD(hkey, L"Hid_StealthMode", &value, 0); + config.stealth = (value ? TRUE : FALSE); + + QueryAndAllocRegistryData(hkey, L"Hid_HideFsDirs", REG_MULTI_SZ, &config.hideFSDirs, NULL); + QueryAndAllocRegistryData(hkey, L"Hid_HideFsFiles", REG_MULTI_SZ, &config.hideFSFiles, NULL); + QueryAndAllocRegistryData(hkey, L"Hid_HideRegKeys", REG_MULTI_SZ, &config.hideRegKeys, NULL); + QueryAndAllocRegistryData(hkey, L"Hid_HideRegValues", REG_MULTI_SZ, &config.hideRegValues, NULL); + + QueryAndAllocRegistryData(hkey, L"Hid_IgnoredImages", REG_MULTI_SZ, &config.ignoreImages, NULL); + QueryAndAllocRegistryData(hkey, L"Hid_ProtectedImages", REG_MULTI_SZ, &config.protectImages, NULL); + + ZwClose(hkey); + + g_configContext = (PHidConfigContext)ExAllocatePoolWithTag(NonPagedPool, sizeof(config), CONFIG_ALLOC_TAG); + if (!g_configContext) + { + DbgPrint("FsFilter1!" __FUNCTION__ ": can't allocate memory for the config context\n"); + ReleaseConfigContext(&config); + return STATUS_NO_MEMORY; + } + + RtlCopyMemory(g_configContext, &config, sizeof(config)); + + return STATUS_SUCCESS; +} + +NTSTATUS DestroyConfigs() +{ + if (!g_configContext) + return STATUS_NOT_FOUND; + + return ReleaseConfigContext(g_configContext); +} + +// ========================================================================================= + +BOOLEAN CfgGetDriverState() +{ + if (!g_configContext) + return TRUE; // Enable by default + + return g_configContext->state; +} + +BOOLEAN CfgGetStealthState() +{ + if (!g_configContext) + return FALSE; // Disable by default + + return g_configContext->stealth; +} + +NTSTATUS CfgEnumConfigsTable(enum CfgMultiStringTables Table, CfgMultiStringCallback Callback, PVOID Params) +{ + PUNICODE_STRING table; + LPWSTR buffer; + ULONG length; + + if (!g_configContext) + return STATUS_NOT_FOUND; + + switch (Table) + { + case HideFilesTable: + table = &g_configContext->hideFSFiles; + break; + case HideDirsTable: + table = &g_configContext->hideFSDirs; + break; + case HideRegKeysTable: + table = &g_configContext->hideRegKeys; + break; + case HideRegValuesTable: + table = &g_configContext->hideRegValues; + break; + case IgnoreImagesTable: + table = &g_configContext->ignoreImages; + break; + case ProtectImagesTable: + table = &g_configContext->protectImages; + break; + default: + return STATUS_INVALID_VARIANT; + } + + if (table->Length == 0) + return STATUS_SUCCESS; + + buffer = table->Buffer; + length = table->Length; + while (length > 0) + { + UNICODE_STRING entry; + ULONG inx, delta = 0; + + for (inx = 0; inx < length / sizeof(WCHAR); inx++) + { + if (buffer[inx] == L'\0') + { + delta = 1; + break; + } + } + + entry.Buffer = buffer; + entry.Length = (USHORT)(inx * sizeof(WCHAR)); + entry.MaximumLength = entry.Length; + + length -= (inx + delta) * sizeof(WCHAR); + buffer += (inx + delta); + + if (entry.Length) + Callback(&entry, Params); + } + + return STATUS_SUCCESS; +} + +// ========================================================================================= + +NTSTATUS ReleaseConfigContext(PHidConfigContext context) +{ + ReleaseRegistryData(&context->hideFSDirs); + ReleaseRegistryData(&context->hideFSFiles); + ReleaseRegistryData(&context->hideRegKeys); + ReleaseRegistryData(&context->hideRegValues); + ReleaseRegistryData(&context->ignoreImages); + ReleaseRegistryData(&context->protectImages); + + return STATUS_SUCCESS; +} + +NTSTATUS GetRegistryDWORD(HANDLE hKey, LPCWSTR Value, PULONG Data, ULONG Default) +{ + UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + NTSTATUS status; + UNICODE_STRING valueName; + ULONG length; + + RtlInitUnicodeString(&valueName, Value); + + status = ZwQueryValueKey(hKey, &valueName, KeyValuePartialInformation, buffer, sizeof(buffer), &length); + if (NT_SUCCESS(status) && length <= sizeof(buffer)) + { + PKEY_VALUE_PARTIAL_INFORMATION info = (PKEY_VALUE_PARTIAL_INFORMATION)buffer; + if (info->Type == REG_DWORD && info->DataLength == sizeof(ULONG)) + *Data = *(ULONG*)(info->Data); + else + *Data = Default; + } + else + { + *Data = Default; + } + + return STATUS_SUCCESS; +} + +NTSTATUS QueryAndAllocRegistryData(HANDLE hKey, LPCWSTR Value, ULONG Type, PUNICODE_STRING Data, PUNICODE_STRING Default) +{ + PKEY_VALUE_PARTIAL_INFORMATION info = NULL; + UNICODE_STRING valueName; + ULONG length, dataLength; + NTSTATUS status; + PVOID dataBuffer; + + if (Default) + { + dataLength = Default->Length; + dataBuffer = ExAllocatePoolWithTag(NonPagedPool, dataLength, CONFIG_ALLOC_TAG); + if (!dataBuffer) + return STATUS_NO_MEMORY; + + RtlCopyMemory(dataBuffer, Default->Buffer, dataLength); + } + else + { + dataLength = 0; + dataBuffer = NULL; + } + + RtlInitUnicodeString(&valueName, Value); + + status = ZwQueryValueKey(hKey, &valueName, KeyValuePartialInformation, NULL, 0, &length); + if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) + goto end_proc; + + if (length < sizeof(KEY_VALUE_PARTIAL_INFORMATION)) + goto end_proc; + + info = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, length, CONFIG_ALLOC_TAG); + if (!info) + goto end_proc; + + status = ZwQueryValueKey(hKey, &valueName, KeyValuePartialInformation, info, length, &length); + if (!NT_SUCCESS(status)) + goto end_proc; + + if (info->Type != Type) + goto end_proc; + + if (info->DataLength == 0 || info->DataLength > 0xFFFF) + goto end_proc; + + if (dataBuffer) + ExFreePoolWithTag(dataBuffer, CONFIG_ALLOC_TAG); + + dataLength = info->DataLength; + dataBuffer = ExAllocatePoolWithTag(NonPagedPool, dataLength, CONFIG_ALLOC_TAG); + if (!dataBuffer) + return STATUS_NO_MEMORY; + + RtlCopyMemory(dataBuffer, info->Data, dataLength); + +end_proc: + + if (info) + ExFreePoolWithTag(info, CONFIG_ALLOC_TAG); + + Data->Buffer = (PWCH)dataBuffer; + Data->Length = (USHORT)dataLength; + Data->MaximumLength = (USHORT)dataLength; + + return STATUS_SUCCESS; +} + +VOID ReleaseRegistryData(PUNICODE_STRING Data) +{ + if (Data->Length) + ExFreePoolWithTag(Data->Buffer, CONFIG_ALLOC_TAG); +} diff --git a/Hidden/Configs.h b/Hidden/Configs.h new file mode 100644 index 0000000..72a0aab --- /dev/null +++ b/Hidden/Configs.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +NTSTATUS InitializeConfigs(PUNICODE_STRING RegistryPath); +NTSTATUS DestroyConfigs(); + +BOOLEAN CfgGetDriverState(); +BOOLEAN CfgGetStealthState(); + +enum CfgMultiStringTables { + HideFilesTable, + HideDirsTable, + HideRegKeysTable, + HideRegValuesTable, + IgnoreImagesTable, + ProtectImagesTable, + MaxTableEntries, +}; + +typedef VOID(NTAPI*CfgMultiStringCallback)(PUNICODE_STRING str, PVOID Params); + +NTSTATUS CfgEnumConfigsTable(enum CfgMultiStringTables Table, CfgMultiStringCallback Callback, PVOID Params); diff --git a/Hidden/Driver.c b/Hidden/Driver.c index c587bd2..2aa141e 100644 --- a/Hidden/Driver.c +++ b/Hidden/Driver.c @@ -7,7 +7,7 @@ #include "PsMonitor.h" #include "Device.h" #include "Driver.h" - +#include "Configs.h" PDRIVER_OBJECT g_driverObject = NULL; @@ -45,6 +45,10 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) EnableDisableDriver(TRUE); + status = InitializeConfigs(RegistryPath); + if (!NT_SUCCESS(status)) + DbgPrint("FsFilter1!" __FUNCTION__ ": can't initialize configs\n"); + status = InitializePsMonitor(DriverObject); if (!NT_SUCCESS(status)) DbgPrint("FsFilter1!" __FUNCTION__ ": object monitor didn't start\n"); @@ -61,6 +65,8 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) if (!NT_SUCCESS(status)) DbgPrint("FsFilter1!" __FUNCTION__ ": can't create device\n"); + DestroyConfigs(); + DriverObject->DriverUnload = DriverUnload; g_driverObject = DriverObject; diff --git a/Hidden/FsFilter.c b/Hidden/FsFilter.c index 76b5a75..0748297 100644 --- a/Hidden/FsFilter.c +++ b/Hidden/FsFilter.c @@ -8,6 +8,7 @@ #include "Helper.h" #include "PsMonitor.h" #include "Driver.h" +#include "Configs.h" NTSTATUS FilterSetup(PCFLT_RELATED_OBJECTS FltObjects, FLT_INSTANCE_SETUP_FLAGS Flags, DEVICE_TYPE VolumeDeviceType, FLT_FILESYSTEM_TYPE VolumeFilesystemType); @@ -751,6 +752,20 @@ NTSTATUS CleanFileNamesInformation(PFILE_NAMES_INFORMATION info, PFLT_FILE_NAME_ return STATUS_SUCCESS; } +VOID LoadConfigFilesCallback(PUNICODE_STRING Str, PVOID Params) +{ + ExcludeContext context = (ExcludeContext)Params; + ExcludeEntryId id; + AddExcludeListFile(context, Str, &id); +} + +VOID LoadConfigDirsCallback(PUNICODE_STRING Str, PVOID Params) +{ + ExcludeContext context = (ExcludeContext)Params; + ExcludeEntryId id; + AddExcludeListDirectory(context, Str, &id); +} + NTSTATUS InitializeFSMiniFilter(PDRIVER_OBJECT DriverObject) { NTSTATUS status; @@ -775,6 +790,8 @@ NTSTATUS InitializeFSMiniFilter(PDRIVER_OBJECT DriverObject) AddExcludeListFile(g_excludeFileContext, &str, &id); } + CfgEnumConfigsTable(HideFilesTable, &LoadConfigFilesCallback, g_excludeFileContext); + status = InitializeExcludeListContext(&g_excludeDirectoryContext, ExcludeDirectory); if (!NT_SUCCESS(status)) { @@ -789,6 +806,8 @@ NTSTATUS InitializeFSMiniFilter(PDRIVER_OBJECT DriverObject) AddExcludeListDirectory(g_excludeDirectoryContext, &str, &id); } + CfgEnumConfigsTable(HideDirsTable, &LoadConfigDirsCallback, g_excludeDirectoryContext); + // Filesystem mini-filter initialization status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle); diff --git a/Hidden/Hidden.vcxproj b/Hidden/Hidden.vcxproj index 28a2a99..1f6f3dc 100644 --- a/Hidden/Hidden.vcxproj +++ b/Hidden/Hidden.vcxproj @@ -67,6 +67,7 @@ + @@ -352,6 +353,7 @@ + diff --git a/Hidden/Hidden.vcxproj.filters b/Hidden/Hidden.vcxproj.filters index 687992e..f2f3bf0 100644 --- a/Hidden/Hidden.vcxproj.filters +++ b/Hidden/Hidden.vcxproj.filters @@ -46,6 +46,9 @@ Source Files + + Source Files + @@ -87,6 +90,9 @@ Header Files + + Header Files + diff --git a/Hidden/PsMonitor.c b/Hidden/PsMonitor.c index 1792d97..62e501b 100644 --- a/Hidden/PsMonitor.c +++ b/Hidden/PsMonitor.c @@ -4,6 +4,7 @@ #include "PsTable.h" #include "PsRules.h" #include "Driver.h" +#include "Configs.h" #define PROCESS_QUERY_LIMITED_INFORMATION 0x1000 #define SYSTEM_PROCESS_ID (HANDLE)4 @@ -28,14 +29,14 @@ typedef struct _ProcessListEntry { // For instance: L"\\Device\\HarddiskVolume1\\Windows\\System32\\calc.exe", // Notice: this array should be NULL terminated CONST ProcessListEntry g_excludeProcesses[] = { - { NULL, 0 } + { NULL, PsRuleTypeWithoutInherit } }; // Use this variable for hard code full path to applications that will be protected // For instance: L"\\Device\\HarddiskVolume1\\Windows\\System32\\cmd.exe", // Notice: this array should be NULL terminated CONST ProcessListEntry g_protectProcesses[] = { - { NULL, 0 } + { NULL, PsRuleTypeWithoutInherit } }; #define CSRSS_PAHT_BUFFER_SIZE 256 @@ -357,6 +358,67 @@ BOOLEAN IsProcessProtected(HANDLE ProcessId) return entry.protected; } +NTSTATUS ParsePsConfigEntry(PUNICODE_STRING Entry, PUNICODE_STRING Path, PULONG Inherit) +{ + USHORT inx, length = Entry->Length / sizeof(WCHAR); + LPWSTR str = Entry->Buffer; + UNICODE_STRING command, template; + + RtlZeroMemory(&command, sizeof(command)); + + for (inx = 0; inx < length; inx++) + { + if (str[inx] == L';') + { + command.Buffer = str + inx + 1; + command.Length = (length - inx - 1) * sizeof(WCHAR); + command.MaximumLength = command.Length; + break; + } + } + + if (inx == 0) + return STATUS_NO_DATA_DETECTED; + + Path->Buffer = Entry->Buffer; + Path->Length = inx * sizeof(WCHAR); + Path->MaximumLength = Path->Length; + + RtlInitUnicodeString(&template, L"none"); + if (RtlCompareUnicodeString(&command, &template, TRUE) == 0) + { + *Inherit = PsRuleTypeWithoutInherit; + return STATUS_SUCCESS; + } + + RtlInitUnicodeString(&template, L"always"); + if (RtlCompareUnicodeString(&command, &template, TRUE) == 0) + { + *Inherit = PsRuleTypeInherit; + return STATUS_SUCCESS; + } + + RtlInitUnicodeString(&template, L"once"); + if (RtlCompareUnicodeString(&command, &template, TRUE) == 0) + { + *Inherit = PsRuleTypeInheritOnce; + return STATUS_SUCCESS; + } + + return STATUS_NOT_FOUND; +} + +VOID LoadConfigRulesCallback(PUNICODE_STRING Str, PVOID Params) +{ + PsRulesContext context = (PsRulesContext)Params; + UNICODE_STRING path; + ULONG inherit; + PsRuleEntryId ruleId; + + if (NT_SUCCESS(ParsePsConfigEntry(Str, &path, &inherit))) + AddRuleToPsRuleList(context, &path, inherit, &ruleId); +} + NTSTATUS InitializePsMonitor(PDRIVER_OBJECT DriverObject) { const USHORT maxBufSize = 512; @@ -422,6 +484,9 @@ NTSTATUS InitializePsMonitor(PDRIVER_OBJECT DriverObject) AddRuleToPsRuleList(g_excludeProcessRules, &normalized, g_excludeProcesses[i].inherit, &ruleId); } + // Load entries from the config + CfgEnumConfigsTable(IgnoreImagesTable, &LoadConfigRulesCallback, g_excludeProcessRules); + // protected status = InitializePsRuleListContext(&g_protectProcessRules); @@ -448,6 +513,9 @@ NTSTATUS InitializePsMonitor(PDRIVER_OBJECT DriverObject) AddRuleToPsRuleList(g_protectProcessRules, &normalized, g_protectProcesses[i].inherit, &ruleId); } + // Load entries from the config + CfgEnumConfigsTable(ProtectImagesTable, &LoadConfigRulesCallback, g_protectProcessRules); + // Process table KeInitializeSpinLock(&g_processTableLock); diff --git a/Hidden/RegFilter.c b/Hidden/RegFilter.c index 5ea0466..ba0e4ec 100644 --- a/Hidden/RegFilter.c +++ b/Hidden/RegFilter.c @@ -5,6 +5,7 @@ #include "RegFilter.h" #include "ExcludeList.h" #include "PsMonitor.h" +#include "Configs.h" #define FILTER_ALLOC_TAG 'FRlF' @@ -555,6 +556,20 @@ NTSTATUS RegistryFilterCallback(PVOID CallbackContext, PVOID Argument1, PVOID Ar return status; } +VOID LoadConfigRegKeysCallback(PUNICODE_STRING Str, PVOID Params) +{ + ExcludeContext context = (ExcludeContext)Params; + ExcludeEntryId id; + AddExcludeListRegistryKey(context, Str, &id); +} + +VOID LoadConfigRegValuesCallback(PUNICODE_STRING Str, PVOID Params) +{ + ExcludeContext context = (ExcludeContext)Params; + ExcludeEntryId id; + AddExcludeListRegistryValue(context, Str, &id); +} + NTSTATUS InitializeRegistryFilter(PDRIVER_OBJECT DriverObject) { NTSTATUS status; @@ -577,6 +592,8 @@ NTSTATUS InitializeRegistryFilter(PDRIVER_OBJECT DriverObject) AddExcludeListRegistryKey(g_excludeRegKeyContext, &str, &id); } + CfgEnumConfigsTable(HideRegKeysTable, &LoadConfigRegKeysCallback, g_excludeRegKeyContext); + status = InitializeExcludeListContext(&g_excludeRegValueContext, ExcludeRegValue); if (!NT_SUCCESS(status)) { @@ -591,6 +608,8 @@ NTSTATUS InitializeRegistryFilter(PDRIVER_OBJECT DriverObject) AddExcludeListRegistryValue(g_excludeRegValueContext, &str, &id); } + CfgEnumConfigsTable(HideRegValuesTable, &LoadConfigRegValuesCallback, g_excludeRegValueContext); + // Register registry filter RtlInitUnicodeString(&altitude, L"320000");