⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regmon.c

📁 注册表监控驱动程序(以拦截ObReferenceObjectByHandle函数为主)
💻 C
字号:
#include <ntddk.h>
#include "Reg.h"
#include <windef.h>
#include <stdio.h>

UNICODE_STRING 				DeviceNameString;
UNICODE_STRING 				LinkDeviceNameString;

/////////////////变量定义////////////////////////////

BYTE		g_HookCode[5] = { 0xE9,0x00,0x00,0x00,0x00 };	//定义原始代码
BYTE		g_OrigCode[5] = { 0x8B,0xFF,0x55,0x8B,0xEC };
BYTE		jmp_orig_code[7] = { 0xEA,0x00,0x00,0x00,0x00,0x08,0x00 };

ULONG		Addr_ObReferenceObjectByHandle = 0;

PVOID			pRootControlBlock = 0;
POBJECT_TYPE	CmpKeyObjectType;	//注册表类型的数据

//////////////////////////////////////////////////////

//====================================================
NTSTATUS DetourFunctionHook_ObOpenObjectByHandle(IN ULONG FunAddr)
{ 
	KIRQL	oldIrql;
	PMDL	g_pmdlFunc = NULL;
	PMDL	g_pmdlReold = NULL;
	PVOID	*MappedPointer_OldFuc = NULL;
	PVOID	*MappedPointer_ToOld = NULL;
	PUCHAR	ori_Function = NULL;
	PUCHAR	re_Function  = NULL;
	PUCHAR	inlineAdd	 = NULL;
	ULONG	Offset = 0;
	ULONG	ulDetourAddress  = 0;
	ULONG	ulReEntryAddress = 0;
	ori_Function = (PUCHAR)FunAddr;
	re_Function = (PUCHAR)Re_Old_Function;
	ulDetourAddress = (ULONG)Proxy_Function;
	ulReEntryAddress = FunAddr + 5;
	
	//初始化全局变量:
	*( (PULONG)(g_HookCode+1) ) = (ULONG)Proxy_Function - FunAddr - 5;
	*( (PULONG)(jmp_orig_code+1) ) = ulReEntryAddress;

	//(1)映射内存,填写Re_Ori_NTFuntion函数机器码
	g_pmdlReold = MmCreateMdl(NULL,re_Function,20);
	if( !g_pmdlReold )
	{
		return STATUS_UNSUCCESSFUL;
	}
	MmBuildMdlForNonPagedPool(g_pmdlReold);
	g_pmdlReold->MdlFlags = g_pmdlReold->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
	MappedPointer_ToOld = MmMapLockedPages(g_pmdlReold, KernelMode);
	inlineAdd = (PUCHAR)MappedPointer_ToOld;
	RtlCopyMemory ( inlineAdd,g_OrigCode,5 );	//头五字节,补全原函数机器码(标准堆栈帧)
	RtlCopyMemory ( (PUCHAR)inlineAdd + 5, jmp_orig_code, 7);	//后七字节jmp_orig_code[7] (跳转回原函数)
	MmUnmapLockedPages(MappedPointer_ToOld,g_pmdlReold);
	IoFreeMdl(g_pmdlReold);
	
	//(2)映射内存,对内核中原始函数打Detour补丁:
	g_pmdlFunc = MmCreateMdl(NULL,ori_Function,10);
	if(!g_pmdlFunc)
	{
		return STATUS_UNSUCCESSFUL; 
	}
	MmBuildMdlForNonPagedPool(g_pmdlFunc);
	g_pmdlFunc->MdlFlags = g_pmdlFunc->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
	MappedPointer_OldFuc= MmMapLockedPages(g_pmdlFunc,KernelMode);
	ori_Function = (PUCHAR)MappedPointer_OldFuc;
	//对所要inline hook的函数头填充跳转指令,即打Detour补丁
	KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); 
    RtlCopyMemory ( ori_Function,g_HookCode,5 );
	KeLowerIrql(oldIrql);
	
	MmUnmapLockedPages(MappedPointer_OldFuc,g_pmdlReold);
	IoFreeMdl(g_pmdlReold);
	return STATUS_SUCCESS;
}


VOID UnHook_Function(IN ULONG FunAddr)
{
	KIRQL	oldIrql;
	PUCHAR	ori_Function   = NULL;
	PMDL  	g_pmdlPointer  = NULL;
	PVOID 	*MappedPointer = NULL;
	__try
	{
		ori_Function = (PUCHAR)FunAddr;
		g_pmdlPointer = MmCreateMdl(NULL,ori_Function,10);
		if(!g_pmdlPointer)
		{
			return;
		}
		MmBuildMdlForNonPagedPool(g_pmdlPointer);
		g_pmdlPointer->MdlFlags = g_pmdlPointer->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
		MappedPointer= MmMapLockedPages(g_pmdlPointer, KernelMode);
		ori_Function=(PUCHAR)MappedPointer;
		
		KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
		RtlCopyMemory ( ori_Function, g_OrigCode, 5 );
		KeLowerIrql(oldIrql);
		
		MmUnmapLockedPages(MappedPointer,g_pmdlPointer);
		IoFreeMdl(g_pmdlPointer);
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		DbgPrint("UnHook Unsuccessful!\n");
	}
}

ULONG GetFunctionAddr(IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,IN PUNICODE_STRING theRegistryPath)
{
	NTSTATUS status;
	
	PFILE_OBJECT 	FileObject;
	UNICODE_STRING 	FilePath;
	UNICODE_STRING 	DosName;
	NTSTATUS 		Status;
	STRING 			AnsiString;
	
	theDriverObject->DriverUnload  = UnloadDriver;
	DbgPrint("Driver Loaded!");
	Addr_ObReferenceObjectByHandle = (ULONG)GetFunctionAddr(L"ObReferenceObjectByHandle");
	DbgPrint("ObReferenceObjectByHandle Address 0x%0.8X",Addr_ObReferenceObjectByHandle);	
	if( Addr_ObReferenceObjectByHandle == 0 )
		return STATUS_UNSUCCESSFUL;

	status = GetCmpKeyObjectTypeByInstance();
	if( !NT_SUCCESS(status)||CmpKeyObjectType==0 )
		return STATUS_UNSUCCESSFUL;
	
	DbgPrint("CmpKeyObjectType 0x%0.8X",CmpKeyObjectType);

	DetourFunctionHook_ObOpenObjectByHandle(Addr_ObReferenceObjectByHandle);
	return STATUS_SUCCESS;
}

VOID UnloadDriver(IN PDRIVER_OBJECT DriverObject)
{
	UnHook_Function(Addr_ObReferenceObjectByHandle);
	DbgPrint("\nDriver Unload OK!\n");
}

__declspec(naked)
BOOLEAN 
Proxy_Function()
{
_asm{
	push	ebp
	mov		ebp,esp		//构建标准堆栈帧
	pushad				
	pushfd				//保护现场
	
	push	[ebp+0x1C]
	push	[ebp+0x18]
	push	[ebp+0x14]
	push	[ebp+0x10]
	push	[ebp+0x0C]
	push	[ebp+0x08]
	call	Check_Parameter
	cmp		eax,1
	je		DenyRunning	//返回值为1,运行DenyRunning
	
	popfd
	popad				//恢复现场
	mov		esp,ebp		
	pop 	ebp			//恢复原本堆栈帧
	jmp		Re_Old_Function
	
DenyRunning:
	popfd
	popad
	mov		eax,0xC0000022
	mov		esp,ebp
	pop 	ebp
	ret 	18h
	}
}

int __stdcall
Check_Parameter(
__in 		HANDLE 			Handle,
__in 		ACCESS_MASK 	DesiredAccess,
__in_opt 	POBJECT_TYPE 	ObjectType,
__in 		KPROCESSOR_MODE AccessMode,
__out 		PVOID 			*Object,
__out_opt 	POBJECT_HANDLE_INFORMATION HandleInformation)
{
	NTSTATUS		status;
	PEPROCESS 		Caller;
	PCM_KEY_BODY	KeyBody;
	char			CallerName[20] = {0};
	char			keyname[256];
	
	Caller	=	PsGetThreadProcess( PsGetCurrentThread() );

	//监控注册表
	if( CmpKeyObjectType == ObjectType )
	{
	status = Re_Old_Function(Handle,DesiredAccess,ObjectType,
		AccessMode,&KeyBody,NULL);
	if( !NT_SUCCESS(status) )
		return 1;
	
		memcpy(CallerName,PsGetProcessImageFileName(Caller),16);
		if( _stricmp(CallerName,"regedit.exe")==0 )
		{
		switch(DesiredAccess)
		{
			case KEY_QUERY_VALUE:
				DbgPrint("KEY_QUERY_VALUE 0x%0.8X",DesiredAccess);break;
			case KEY_SET_VALUE:
				DbgPrint("KEY_SET_VALUE 0x%0.8X",DesiredAccess);break;
			case KEY_CREATE_SUB_KEY:
				DbgPrint("KEY_CREATE_SUB_KEY 0x%0.8X",DesiredAccess);break;
			case KEY_ENUMERATE_SUB_KEYS:
				DbgPrint("KEY_ENUMERATE_SUB_KEYS 0x%0.8X",DesiredAccess);break;
			case KEY_ALL_ACCESS:
				DbgPrint("KEY_ALL_ACCESS 0x%0.8X",DesiredAccess);break;
			case DELETE:
				DbgPrint("DELETE 0x%0.8X",DesiredAccess);break;				
			default: 
				DbgPrint("UnKnown 0x%0.8X",DesiredAccess);break;
		}
		DbgPrint("[Reg Called] %s ",PsGetProcessImageFileName(Caller));
		memset(keyname,'\0',256);
		GetRegNameByKeyObject(KeyBody,keyname);
		DbgPrint("%s\n\n",keyname);
		ObDereferenceObject(KeyBody);
		if( _stricmp(keyname,"\\Registry\\Machine\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run")==0 )
			return 1;	//与指定键值相等时进行筛出
		}
	}
	return 0;
}

//Re_Old_NTFuntion跳转回原函数
__declspec(naked) 
BOOLEAN
Re_Old_Function(
__in 		HANDLE 			Handle,
__in 		ACCESS_MASK 	DesiredAccess,
__in_opt 	POBJECT_TYPE 	ObjectType,
__in 		KPROCESSOR_MODE AccessMode,
__out 		PVOID 			*Object,
__out_opt 	POBJECT_HANDLE_INFORMATION HandleInformation)
{
    __asm {  
            _emit 0x90	//头五字节,补全原函数机器码(g_OrigCode[5])
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  
            _emit 0x90	//后七字节,jmp_orig_code[7]
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90 	//	jmp     0008:ulReEntryAddress
    }
}


NTSTATUS
GetRegNameByKeyObject(PCM_KEY_BODY pKeyObject,PCHAR RegKeyName)
{
	char		KeyName[256] = {0};
	char		KeyTmp[256] = {0};
	PVOID		pControlBlock = 0;
	PVOID		pParentControlBlock = 0;
	PCM_NAME_CONTROL_BLOCK	pNameControlBlock;
	ULONG		strLength;

	if(	!MmIsAddressValid(pKeyObject) || 
	!MmIsAddressValid( (PULONG)((ULONG)pKeyObject->KeyControlBlock+NameBlock) ) )
	{
		return STATUS_ACCESS_DENIED;
	}
	
	pControlBlock = (PULONG)pKeyObject->KeyControlBlock;

	for( pParentControlBlock = GetNextRegNameByControlBlock(pControlBlock,KeyTmp);
		 pParentControlBlock != 0;
		 pParentControlBlock = GetNextRegNameByControlBlock(pParentControlBlock,KeyTmp)	)
	{
		strcat(KeyName,"\\");
		strcat(KeyName,KeyTmp);
	}

	GetTheOriName(KeyName,KeyTmp);//逆序转为顺序的模块

	pNameControlBlock = *(PCM_NAME_CONTROL_BLOCK *)((ULONG)pRootControlBlock+NameBlock);
	strcat(RegKeyName,"\\");
	memcpy(RegKeyName+1,pNameControlBlock->Name,pNameControlBlock->NameLength);
	
	strLength = strlen(RegKeyName) + strlen(KeyTmp);
	
	if( strLength < 256 )
	{
		strcat(RegKeyName,KeyTmp);
		RegKeyName[strLength] = 0;
	}	
		
	if( strLength >=256 )
	{
		memcpy(RegKeyName+1+pNameControlBlock->NameLength,KeyTmp,256-1-pNameControlBlock->NameLength);
		*(RegKeyName+255) = 0;
	}
	
	return STATUS_SUCCESS;	
}

void GetTheOriName(PCHAR inName,PCHAR outName)
{
	ULONG	length = 0;
	ULONG	iCnt = 0;
	ULONG	iTmp = 0;
	length = strlen(inName);
	for( iCnt=0;iCnt<length;iCnt++ )
	{		
		if( *(inName+iCnt)==0x5c||*(inName+iCnt)==0x00 )
		{
			for(iTmp=1;iTmp<length;iTmp++)
			{
				if( *(inName+iCnt+iTmp)==0x5c||*(inName+iCnt+iTmp)==0x00 )
				{
				memcpy(outName+length-iTmp-iCnt,inName+iCnt,iTmp);
				break;
				}
			}
		}
	}
}

PVOID
GetNextRegNameByControlBlock(PVOID pControlBlock,char* Name)
{	
	PVOID 					pParentControlBlock;
	PCM_NAME_CONTROL_BLOCK	pNameControlBlock;

	if(pControlBlock ==0 || !MmIsAddressValid(pControlBlock) )
		return 0;
		
	pParentControlBlock = *(PVOID *)((ULONG)pControlBlock+ParentKcb);
	pNameControlBlock =
		*(PCM_NAME_CONTROL_BLOCK *)((ULONG)pControlBlock+NameBlock);
	memcpy(Name,pNameControlBlock->Name,pNameControlBlock->NameLength);
	Name[pNameControlBlock->NameLength]=0;
	
	if( pParentControlBlock ==0  )
		pRootControlBlock = pControlBlock;
	return pParentControlBlock;
}

NTSTATUS
GetCmpKeyObjectTypeByInstance()
{
    NTSTATUS				ntStatus;
    UNICODE_STRING			keyName;
    OBJECT_ATTRIBUTES		objAttr;
    HANDLE					hKey;
    PCM_KEY_BODY			KeyBody;
    char					Type[30] = {0};
    
    CmpKeyObjectType = 0;
    
    RtlInitUnicodeString(&keyName,L"\\Registry\\Machine");
    InitializeObjectAttributes(&objAttr,&keyName,
    OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,NULL,NULL);
    
    ntStatus = ZwOpenKey(&hKey,KEY_READ,&objAttr);
    if(! NT_SUCCESS(ntStatus))
	{	DbgPrint("OpenKey Unsuccessful");
		return STATUS_UNSUCCESSFUL;	}
		
    ntStatus = ObReferenceObjectByHandle(hKey,KEY_READ,NULL,KernelMode,&KeyBody,NULL);
    if(! NT_SUCCESS(ntStatus))
    {
		DbgPrint("Object Initial Unsuccessful");
		ZwClose(hKey);
		return STATUS_UNSUCCESSFUL;
    }
    
    //验证KeyType的UNICODE_STRING是否为Key
	ntStatus = GetObjectType(KeyBody,Type);
	if( !NT_SUCCESS(ntStatus) )
		return STATUS_UNSUCCESSFUL;
	
	if( _stricmp(Type,"Key")==0 )
	CmpKeyObjectType = OBJECT_TO_OBJECT_HEADER(KeyBody)->Type;

    return STATUS_SUCCESS;
}

NTSTATUS
GetObjectType(PVOID Object,PUCHAR TypeName)
{
	ANSI_STRING		ANSI_TypeName;
	PUNICODE_STRING	pUNI_String;
	*TypeName = 0;	
	pUNI_String = (PUNICODE_STRING)((ULONG)OBJECT_TO_OBJECT_HEADER(Object)->Type+type_Name);

	if( !MmIsAddressValid(pUNI_String) )
		return STATUS_ACCESS_DENIED;

	if( !MmIsAddressValid(pUNI_String->Buffer) )
		return STATUS_ACCESS_DENIED;

	RtlUnicodeStringToAnsiString(&ANSI_TypeName,pUNI_String,TRUE);
	
	memcpy(TypeName,ANSI_TypeName.Buffer,ANSI_TypeName.Length); 
	TypeName[ANSI_TypeName.Length] = 0; 
	RtlFreeAnsiString(&ANSI_TypeName);
	
	return STATUS_SUCCESS;
}

BOOL IceSleep(int time)
{
	LARGE_INTEGER 	Interval;
	NTSTATUS 		status;
	Interval.QuadPart = -10000 * time;
	status=KeDelayExecutionThread(0, 0, &Interval);
	return NT_SUCCESS(status);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -