x64回调监控注册表

85 篇文章 6 订阅
83 篇文章 9 订阅

x86下可以使用hook技术,x64下使用回调监控。

主要函数CmRegisterCallback(RegistryCallback, NULL, &CmHandle);

原型

NTSTATUS CmRegisterCallback(
  PEX_CALLBACK_FUNCTION Function,
  PVOID                 Context,
  PLARGE_INTEGER        Cookie
);

第一个参数就是我们的回调函数,自己想实现的逻辑就是在这里写,中间这个微软的解释是A driver-defined value that the configuration manager will pass as the CallbackContext parameter to the RegistryCallback routine,配置管理器将作为CallbackContext参数传递给RegistryCallback例程的驱动程序定义的值,我目前没用到过,最后一个是指向LARGE_INTEGER变量的指针,该变量接收标识回调例程的值。取消注册回调例程时,将此值作为Cookie参数传递给CmUnRegisterCallback。关闭注册表回调会用到。

第一个参数也就是我们实现的函数申明如下

NTSTATUS RegistryCallback
(
	IN PVOID CallbackContext,
	IN PVOID Argument1,//操作类型,
	IN PVOID Argument2//操作的结构体指针
)

也就是第二个参数是操作注册表的类型,然后操作内容等可以通过第三个参数拿到,下面是我进行操作的监控代码demo片段

NTSTATUS RegistryCallback
(
	IN PVOID CallbackContext,
	IN PVOID Argument1,//操作类型,
	IN PVOID Argument2//操作的结构体指针
)
{
	if (!isOpenReg)
	{
		return STATUS_SUCCESS;
	}
	ULONG Options = 0;//记录操作类型 4创建,5删除,6设置键值,7删除键值,8重命名键
	BOOLEAN isAllow = TRUE;//是否放行
	PFQDRV_NOTIFICATION notification = NULL;
	ULONG replyLength = 0;
	BOOLEAN SafeToOpen;
	SafeToOpen = TRUE;
	NTSTATUS status = STATUS_SUCCESS;

	long type;
	NTSTATUS CallbackStatus = STATUS_SUCCESS;
	UNICODE_STRING registryPath;
	registryPath.Length = 0;
	registryPath.MaximumLength = 2048 * sizeof(WCHAR);
	registryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, registryPath.MaximumLength, REGISTRY_POOL_TAG);


	notification = ExAllocatePoolWithTag(NonPagedPool,
		sizeof(FQDRV_NOTIFICATION),
		'nacS');

	if (NULL == notification)
	{
		CallbackStatus = STATUS_INSUFFICIENT_RESOURCES;
		return CallbackStatus;
	}


	if (registryPath.Buffer == NULL)
		return STATUS_SUCCESS;
	type = (REG_NOTIFY_CLASS)Argument1;
	switch (type)
	{
	case RegNtPreCreateKeyEx:	//出现两次是因为一次是OpenKey,一次是createKey
	{
		if (IsProcessName("regedit.exe", PsGetCurrentProcess()))
		{
			GetRegistryObjectCompleteName(&registryPath, NULL, ((PREG_CREATE_KEY_INFORMATION)Argument2)->RootObject);
			DbgPrint("[RegNtPreCreateKeyEx]KeyPath: %wZ", &registryPath);	//新键的路径
			DbgPrint("[RegNtPreCreateKeyEx]KeyName: %wZ",
				((PREG_CREATE_KEY_INFORMATION)Argument2)->CompleteName);//新键的名称

			notification->Operation = 4;
			char newPath[MAX_PATH] = { 0 };
			WCHAR newPath1[MAX_PATH] = { 0 };
			UnicodeToChar(&registryPath, newPath);
			CharToWchar(newPath, newPath1);
			wcscpy_s(notification->ProcessPath, MAX_PATH, newPath1);
			
			char newName[MAX_PATH] = { 0 };
			WCHAR newName1[MAX_PATH] = { 0 };
			UnicodeToChar(((PREG_CREATE_KEY_INFORMATION)Argument2)->CompleteName, newName);
			CharToWchar(newName, newName1);
			wcscpy_s(notification->TargetPath, MAX_PATH, newName1);
			replyLength = sizeof(FQDRV_REPLY);
			status = FltSendMessage(FQDRVData.Filter,
				&FQDRVData.ClientPort,
				notification,
				sizeof(FQDRV_NOTIFICATION),
				notification,
				&replyLength,
				NULL);
			if (STATUS_SUCCESS == status) {
			
				SafeToOpen = ((PFQDRV_REPLY)notification)->SafeToOpen;
				if (SafeToOpen)
				{
					CallbackStatus = STATUS_SUCCESS;
				}
				else {
					CallbackStatus = STATUS_ACCESS_DENIED;
				}
			}

			//CallbackStatus = STATUS_ACCESS_DENIED;
		}
		break;
	}
	case RegNtPreDeleteKey:
	{
		if (IsProcessName("regedit.exe", PsGetCurrentProcess()))
		{
			GetRegistryObjectCompleteName(&registryPath, NULL, ((PREG_DELETE_KEY_INFORMATION)Argument2)->Object);
			DbgPrint("[RegNtPreDeleteKey]%wZ", &registryPath);				//新键的路径

			notification->Operation = 5;
			char newPath[MAX_PATH] = { 0 };
			WCHAR newPath1[MAX_PATH] = { 0 };
			UnicodeToChar(&registryPath, newPath);
			CharToWchar(newPath, newPath1);
			wcscpy_s(notification->ProcessPath, MAX_PATH, newPath1);

			replyLength = sizeof(FQDRV_REPLY);
			status = FltSendMessage(FQDRVData.Filter,
				&FQDRVData.ClientPort,
				notification,
				sizeof(FQDRV_NOTIFICATION),
				notification,
				&replyLength,
				NULL);
			if (STATUS_SUCCESS == status) {

				SafeToOpen = ((PFQDRV_REPLY)notification)->SafeToOpen;
				if (SafeToOpen)
				{
					CallbackStatus = STATUS_SUCCESS;
				}
				else {
					CallbackStatus = STATUS_ACCESS_DENIED;
				}
			}

			//CallbackStatus = STATUS_ACCESS_DENIED;
		}
		break;
	}
	case RegNtPreSetValueKey:
	{
		if (IsProcessName("regedit.exe", PsGetCurrentProcess()))
		{
			GetRegistryObjectCompleteName(&registryPath, NULL, ((PREG_SET_VALUE_KEY_INFORMATION)Argument2)->Object);
			DbgPrint("[RegNtPreSetValueKey]KeyPath: %wZ", &registryPath);
			DbgPrint("[RegNtPreSetValueKey]ValName: %wZ", ((PREG_SET_VALUE_KEY_INFORMATION)Argument2)->ValueName);
			
			notification->Operation = 6;
			char newPath[MAX_PATH] = { 0 };
			WCHAR newPath1[MAX_PATH] = { 0 };
			UnicodeToChar(&registryPath, newPath);
			CharToWchar(newPath, newPath1);
			wcscpy_s(notification->ProcessPath, MAX_PATH, newPath1);

			char newName[MAX_PATH] = { 0 };
			WCHAR newName1[MAX_PATH] = { 0 };
			UnicodeToChar(((PREG_SET_VALUE_KEY_INFORMATION)Argument2)->ValueName, newName);
			CharToWchar(newName, newName1);
			wcscpy_s(notification->TargetPath, MAX_PATH, newName1);
			replyLength = sizeof(FQDRV_REPLY);
			status = FltSendMessage(FQDRVData.Filter,
				&FQDRVData.ClientPort,
				notification,
				sizeof(FQDRV_NOTIFICATION),
				notification,
				&replyLength,
				NULL);
			if (STATUS_SUCCESS == status) {

				SafeToOpen = ((PFQDRV_REPLY)notification)->SafeToOpen;
				if (SafeToOpen)
				{
					CallbackStatus = STATUS_SUCCESS;
				}
				else {
					CallbackStatus = STATUS_ACCESS_DENIED;
				}
			}

			//CallbackStatus = STATUS_ACCESS_DENIED;
		}
		break;
	}
	case RegNtPreDeleteValueKey:
	{
		if (IsProcessName("regedit.exe", PsGetCurrentProcess()))
		{
			GetRegistryObjectCompleteName(&registryPath, NULL, ((PREG_DELETE_VALUE_KEY_INFORMATION)Argument2)->Object);
			DbgPrint("[RegNtPreDeleteValueKey]KeyPath: %wZ", &registryPath);
			DbgPrint("[RegNtPreDeleteValueKey]ValName: %wZ", ((PREG_DELETE_VALUE_KEY_INFORMATION)Argument2)->ValueName);

			notification->Operation = 7;
			char newPath[MAX_PATH] = { 0 };
			WCHAR newPath1[MAX_PATH] = { 0 };
			UnicodeToChar(&registryPath, newPath);
			CharToWchar(newPath, newPath1);
			wcscpy_s(notification->ProcessPath, MAX_PATH, newPath1);

			char newName[MAX_PATH] = { 0 };
			WCHAR newName1[MAX_PATH] = { 0 };
			UnicodeToChar(((PREG_DELETE_VALUE_KEY_INFORMATION)Argument2)->ValueName, newName);
			CharToWchar(newName, newName1);
			wcscpy_s(notification->TargetPath, MAX_PATH, newName1);
			replyLength = sizeof(FQDRV_REPLY);
			status = FltSendMessage(FQDRVData.Filter,
				&FQDRVData.ClientPort,
				notification,
				sizeof(FQDRV_NOTIFICATION),
				notification,
				&replyLength,
				NULL);
			if (STATUS_SUCCESS == status) {

				SafeToOpen = ((PFQDRV_REPLY)notification)->SafeToOpen;
				if (SafeToOpen)
				{
					CallbackStatus = STATUS_SUCCESS;
				}
				else {
					CallbackStatus = STATUS_ACCESS_DENIED;
				}
			}

			//CallbackStatus = STATUS_ACCESS_DENIED;
		}
		break;
	}
	case RegNtPreRenameKey:
	{
		if (IsProcessName("regedit.exe", PsGetCurrentProcess()))
		{
			GetRegistryObjectCompleteName(&registryPath, NULL, ((PREG_RENAME_KEY_INFORMATION)Argument2)->Object);
			DbgPrint("[RegNtPreRenameKey]KeyPath: %wZ", &registryPath);
			DbgPrint("[RegNtPreRenameKey]NewName: %wZ", ((PREG_RENAME_KEY_INFORMATION)Argument2)->NewName);

			notification->Operation = 8;
			char newPath[MAX_PATH] = { 0 };
			WCHAR newPath1[MAX_PATH] = { 0 };
			UnicodeToChar(&registryPath, newPath);
			CharToWchar(newPath, newPath1);
			wcscpy_s(notification->ProcessPath, MAX_PATH, newPath1);

			char newName[MAX_PATH] = { 0 };
			WCHAR newName1[MAX_PATH] = { 0 };
			UnicodeToChar(((PREG_RENAME_KEY_INFORMATION)Argument2)->NewName, newName);
			CharToWchar(newName, newName1);
			wcscpy_s(notification->TargetPath, MAX_PATH, newName1);
			replyLength = sizeof(FQDRV_REPLY);
			status = FltSendMessage(FQDRVData.Filter,
				&FQDRVData.ClientPort,
				notification,
				sizeof(FQDRV_NOTIFICATION),
				notification,
				&replyLength,
				NULL);
			if (STATUS_SUCCESS == status) {

				SafeToOpen = ((PFQDRV_REPLY)notification)->SafeToOpen;
				if (SafeToOpen)
				{
					CallbackStatus = STATUS_SUCCESS;
				}
				else {
					CallbackStatus = STATUS_ACCESS_DENIED;
				}
			}

			//CallbackStatus = STATUS_ACCESS_DENIED;
		}
		break;
	}
	//『注册表编辑器』里的“重命名键值”是没有直接函数的,是先SetValueKey再DeleteValueKey
	default:
		break;
	}
	

	if (registryPath.Buffer != NULL)
		ExFreePoolWithTag(registryPath.Buffer, REGISTRY_POOL_TAG);
	return CallbackStatus;
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值