Registry Operations
Protecting a registry key or value from deleting using a CmRegistryCallback
. This feature is not enabled when the driver is loaded reflectively.
NTSTATUS RegistryUtils::RegNtPreDeleteKeyHandler(REG_DELETE_KEY_INFORMATION* info)
info [REG_DELETE_KEY_INFORMATION*] -- Contains important information such as key path, key object, etc.
NTSTATUS RegistryUtils::RegNtPreDeleteValueKeyHandler(REG_DELETE_VALUE_KEY_INFORMATION* info)
info [REG_DELETE_VALUE_KEY_INFORMATION*] -- Contains important information such as key path, value name, key object, etc.
# Protecting a registry key
NidhoggClient.exe reg add <PATH>
# Unprotecting registry key
NidhoggClient.exe reg remove <PATH>
# Protecting a registry value
NidhoggClient.exe reg add <PATH> <VALUE NAME>
# Unprotecting registry value
NidhoggClient.exe reg remove <PATH> <VALUE NAME>
The function begins by checking if the Object
in the info
structure is valid kernel-mode memory. If it is not, it returns STATUS_SUCCESS
.
Next, it gets the key object ID and the registry path of the key object. If this operation fails, it returns STATUS_SUCCESS
.
The function then checks if the Buffer
in the regPath
structure is NULL
, if the Length
of the regPath
is zero, or if the Buffer
is not valid kernel-mode memory. If any of these conditions are true, it returns STATUS_SUCCESS
.
The function then copies the Buffer from the regPath
to a RegItem
structure, and sets the type of the RegItem
to RegProtectedKey
.
It checks if the RegItem
is in the list of protected registry items. If it is, it sets the status to STATUS_ACCESS_DENIED
.
Finally, it releases the key object ID and returns the status of the operation. If the operation was successful, it means that the registry key was not protected and was allowed to be deleted. If the status is STATUS_ACCESS_DENIED
, it means that the registry key was protected and the deletion was blocked.
The function begins by checking if the Object
in the info structure is valid kernel-mode memory. If it isn't, it returns STATUS_SUCCESS
.
Next, it gets the key object ID and the registry path of the key object. If this operation fails, it returns STATUS_SUCCESS
.
The function then checks if the Buffer
in the regPath
structure is NULL
, if the Length
of the regPath
is zero, or if the Buffer
is not valid kernel-mode memory. If any of these conditions are true, it returns STATUS_SUCCESS
.
The function then copies the Buffer
from the regPath
and the ValueName
from the info structure to a RegItem
structure, and sets the Type
of the RegItem
to RegProtectedValue
.
It checks if the RegItem
is in the list of protected registry items. If it is, it sets the status to STATUS_ACCESS_DENIED
.
Finally, it releases the key object ID and returns the status of the operation. If the operation was successful, it means that the registry value was not protected and was allowed to be deleted. If the status is STATUS_ACCESS_DENIED
, it means that the registry value was protected and the deletion was blocked.
Protecting a registry value from overwriting using a CmRegistryCallback
. This feature is not enabled when the driver is loaded reflectively.
NTSTATUS RegistryUtils::RegNtPreSetValueKeyHandler(REG_SET_VALUE_KEY_INFORMATION* info)
info [REG_SET_VALUE_KEY_INFORMATION*] -- Contains important information such as key path, value name, key object, etc.
# Protecting a registry value
NidhoggClient.exe reg add <PATH> <VALUE NAME>
# Unprotecting registry value
NidhoggClient.exe reg remove <PATH> <VALUE NAME>
The function begins by checking if the Object
in the info
structure is valid kernel-mode memory. If it is not, it returns STATUS_SUCCESS
.
Next, it gets the key object ID and the registry path of the key object. If this operation fails, it returns STATUS_SUCCESS
.
The function then checks if the Buffer
in the regPath
structure is NULL
, if the Length
of the regPath
is zero, or if the Buffer
is not valid kernel-mode memory. If any of these conditions are true, it returns STATUS_SUCCESS
.
The function then copies the Buffer
from the regPath
and the ValueName
from the info structure to a RegItem
structure, and sets the type of the RegItem
to RegProtectedValue
.
It checks if the RegItem
is in the list of protected registry items. If it is, it sets the status to STATUS_ACCESS_DENIED
.
Finally, it releases the key object ID and returns the status of the operation. If the operation was successful, it means that the registry value was not protected and was allowed to be modified. If the status is STATUS_ACCESS_DENIED
, it means that the registry value was protected and the modification was blocked.
Hiding a registry key or value from querying using a CmRegistryCallback
. This feature is not enabled when the driver is loaded reflectively.
The documentation below is for RegNtPostEnumerateKey
and RegNtPostEnumerateValueKey
only because RegNtPreQueryKey
and RegNtPreQueryValueKey
works the same as the functions mentioned above.
NTSTATUS RegistryUtils::RegNtPostEnumerateKeyHandler(REG_POST_OPERATION_INFORMATION* info)
info [REG_POST_OPERATION_INFORMATION*] -- Contains important information such as keys list, keys objects, etc.
NTSTATUS RegistryUtils::RegNtPostEnumerateValueKeyHandler(REG_POST_OPERATION_INFORMATION* info)
info [REG_POST_OPERATION_INFORMATION*] -- Contains important information such as keys list, keys objects, etc.
# Protecting a registry key
NidhoggClient.exe reg hide <PATH>
# Unprotecting registry key
NidhoggClient.exe reg unhide <PATH>
# Protecting a registry value
NidhoggClient.exe reg hide <PATH> <VALUE NAME>
# Unprotecting registry value
NidhoggClient.exe reg unhide <PATH> <VALUE NAME>
The function begins by checking if the operation status in the info structure is successful. If it is not, it returns the status.
Next, it gets the key object ID and the registry path of the key object. If this operation fails, it returns STATUS_SUCCESS
.
The function then checks if the registry key contains any protected registry value. If it does not, it releases the key object ID and returns STATUS_SUCCESS
.
The function then gets the name from the value enumeration pre-information. If this operation fails, it releases the key object ID and returns STATUS_SUCCESS
.
The function then opens the object by pointer with tag. If this operation fails, it releases the key object ID and returns STATUS_SUCCESS
.
The function then allocates memory for tempValueInformation
.
If tempValueInformation
is not NULL
, it sets the type of the item to RegHiddenValue
and copies the Buffer
from the regPath
to the KeyPath
of the item.
The function then enters a loop where it enumerates the value key and checks if the item is in the list of protected registry items. If it is not, it copies the tempValueInformation
to the KeyValueInformation
in the preInfo
structure and breaks the loop. If it is, it increments the counter and continues the loop.
Finally, it sets the ReturnStatus
in the info structure to the status of the operation, closes the key, releases the key object ID, and returns STATUS_SUCCESS.
The function begins by checking if the operation status in the info
structure is successful. If it is not, it returns the status.
Next, it gets the key object ID and the registry path of the key object. If this operation fails, it returns STATUS_SUCCESS
.
The function then checks if the registry key contains any protected registry value. If it does not, it releases the key object ID and returns STATUS_SUCCESS
.
The function then gets the name from the value enumeration pre-information. If this operation fails, it releases the key object ID and returns STATUS_SUCCESS
.
The function then opens the object by pointer with tag. If this operation fails, it releases the key object ID and returns STATUS_SUCCESS
.
The function then allocates memory for tempValueInformation
.
If tempValueInformation
is not NULL, it sets the Type of the item to RegHiddenValue
and copies the Buffer
from the regPath
to the KeyPath
of the item.
The function then enters a loop where it enumerates the value key and checks if the item is in the list of protected registry items. If it is not, it copies the tempValueInformation
to the KeyValueInformation
in the preInfo
structure and breaks the loop. If it is, it increments the counter and continues the loop.
Finally, it sets the ReturnStatus
in the info structure to the status of the operation, closes the key, releases the key object ID, and returns STATUS_SUCCESS
.