x64回调监控注册表
发布日期:2021-06-29 01:11:26 浏览次数:3 分类:技术文章

本文共 8169 字,大约阅读时间需要 27 分钟。

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

 

转载地址:https://blog.csdn.net/youyou519/article/details/96454731 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:通过GetProcessNameByProcessId得到进程路径
下一篇:自己的HIPS开发记录

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月17日 19时19分39秒