zoukankan      html  css  js  c++  java
  • Win64 驱动内核编程-11.回调监控进线程句柄操作

    HOOK监控进线程句柄操作

             

            在 NT5 平台下,要监控进线程句柄的操作。

      通常要挂钩三个APINtOpenProcessNtOpenThreadNtDuplicateObject。但是在 VISTA SP1 以及之后的系统中,我们可以完全抛弃 HOOK 方案了,转而使用一个标准的 APIObRegisterCallbacks。下面做一个监视进线程句柄操作的程序,并实现保护名为 CALC.EXE 的进程不被结束。


        首先介绍一下 ObRegisterCallbacks 这个函数。此函数的前缀是Ob,看得出它是属于对象管理器的函数,Register 是注册,Callbacks 是回调(复数)。

        因此从字面意思上看,它是注册一个对象回调的意思。现在它只能监控进程对象和线程对象。但微软承诺会给此函数增加功能,实现对其它内核对象的监控。这个函数在不能合法进行内核挂钩的 WIN64 上特别有用,但是微软做了一个很扯淡的限制: 驱动程序必须有数字签名才能使用 此函数。不过国外的黑客对此限制很不爽,他们通过逆向 ObRegisterCallbacks,找到了破解这个限制的方法。经研究,内核通过 MmVerifyCallbackFunction 验证此回调是否合法,但此函数只是简单的验证了一下 DriverObject->DriverSection->Flags 的值是不是为 0x20所以可以简单破解掉这个限制:

    X32
    	typedef struct _LDR_DATA_TABLE_ENTRY32
    	{
    		LIST_ENTRY32 InLoadOrderLinks;
    		LIST_ENTRY32 InMemoryOrderLinks;
    		LIST_ENTRY32 InInitializationOrderLinks;
    		ULONG DllBase;
    		ULONG EntryPoint;
    		ULONG SizeOfImage;
    		UNICODE_STRING32 FullDllName;
    		UNICODE_STRING32 BaseDllName;
    		ULONG Flags;
    		USHORT LoadCount;
    		USHORT TlsIndex;
    		union {
    			LIST_ENTRY32 HashLinks;
    			struct {
    				ULONG SectionPointer;
    				ULONG  CheckSum;
    			};
    		};
    		union {
    			struct {
    				ULONG  TimeDateStamp;
    			};
    			struct {
    				ULONG LoadedImports;
    			};
    		};
    	} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;
    
    	PLDR_DATA_TABLE_ENTRY32 ldr;
    	ldr = (PLDR_DATA_TABLE_ENTRY32)(pDriverObj->DriverSection);
    	ldr->Flags |= 0x20;
    X64
    	typedef struct _LDR_DATA_TABLE_ENTRY64
    	{
    		LIST_ENTRY64    InLoadOrderLinks;
    		LIST_ENTRY64    InMemoryOrderLinks;
    		LIST_ENTRY64    InInitializationOrderLinks;
    		PVOID            DllBase;
    		PVOID            EntryPoint;
    		ULONG            SizeOfImage;
    		UNICODE_STRING    FullDllName;
    		UNICODE_STRING     BaseDllName;
    		ULONG            Flags;
    		USHORT            LoadCount;
    		USHORT            TlsIndex;
    		PVOID            SectionPointer;
    		ULONG            CheckSum;
    		PVOID            LoadedImports;
    		PVOID            EntryPointActivationContext;
    		PVOID            PatchInformation;
    		LIST_ENTRY64    ForwarderLinks;
    		LIST_ENTRY64    ServiceTagLinks;
    		LIST_ENTRY64    StaticLinks;
    		PVOID            ContextInformation;
    		ULONG64            OriginalBase;
    		LARGE_INTEGER    LoadTime;
    	} LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
    
    	PLDR_DATA_TABLE_ENTRY64 ldr;
    	ldr = (PLDR_DATA_TABLE_ENTRY64)(pDriverObj->DriverSection);
    	ldr->Flags |= 0x20;

        上面代码如果是用于商业或者其他正当场合,注意要好好测试下,我是在网上找了到了那个结构体定义,然后自己在win7 32win764位机器上测试了一下,没问题。小伙伴记得好好测试其他系统再用。然后就是来两个回调函数,一个是进程回调,一个是线程回调:

    NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
    NTKERNELAPI char* PsGetProcessImageFileName(PEPROCESS Process);
    
    
    BOOLEAN IsProtectedProcessName(PEPROCESS eprocess)
    {
    	char *Name=PsGetProcessImageFileName(eprocess);
    	if(!_stricmp("calc.exe",Name))
    		return TRUE;
    	else
    		return FALSE;
    }
    
    PVOID obHandle=NULL,obHandle2=NULL;
    
    OB_PREOP_CALLBACK_STATUS preCall(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
    {
    	#define PROCESS_TERMINATE 0x1
    	HANDLE pid;
    	if(pOperationInformation->ObjectType!=*PsProcessType)
    		goto exit_sub;
    	pid = PsGetProcessId((PEPROCESS)pOperationInformation->Object);
    	DbgPrint("[OBCALLBACK][Process]PID=%ld
    ",pid);
    	UNREFERENCED_PARAMETER(RegistrationContext);
    	if( IsProtectedProcessName((PEPROCESS)pOperationInformation->Object) )
    	{
    		if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
    		{
    			//pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
    			if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
                {
                    pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
                }
    		}
    		if(pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
    		{
    			//pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;
    			if ((pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & PROCESS_TERMINATE) == PROCESS_TERMINATE)
                {
                    pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE;
                }
    		}
    	}
    exit_sub:
    	return OB_PREOP_SUCCESS;
    }
    
    OB_PREOP_CALLBACK_STATUS preCall2(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION pOperationInformation)
    {
    	#define THREAD_TERMINATE2 0x1
    	PEPROCESS ep;
    	PETHREAD et;
    	HANDLE pid;
    	if(pOperationInformation->ObjectType!=*PsThreadType)
    		goto exit_sub;
    	et=(PETHREAD)pOperationInformation->Object;
    	ep=IoThreadToProcess(et);
    	pid = PsGetProcessId(ep);
    	DbgPrint("[OBCALLBACK][Thread]PID=%ld; TID=%ld
    ",pid,PsGetThreadId(et));
    	UNREFERENCED_PARAMETER(RegistrationContext);
    	if( IsProtectedProcessName(ep) )
    	{
    		if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
    		{
    			//pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess=0;
    			if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE2) == THREAD_TERMINATE2)
                {
                    pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE2;
                }
    		}
    		if(pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
    		{
    			//pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess=0;
    			if ((pOperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess & THREAD_TERMINATE2) == THREAD_TERMINATE2)
                {
                    pOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess &= ~THREAD_TERMINATE2;
                }
    		}
    	}
    exit_sub:
    	return OB_PREOP_SUCCESS;
    }
    
    然后就是在驱动里注册/卸载这两个回调函数:
    NTSTATUS ObProtectProcess(BOOLEAN Enable)
    {
    	if(Enable==TRUE)
    	{
    		NTSTATUS obst1=0,obst2=0;
    		OB_CALLBACK_REGISTRATION obReg,obReg2;
    		OB_OPERATION_REGISTRATION opReg,opReg2;
    		//reg ob callback 1
    		memset(&obReg, 0, sizeof(obReg));
    		obReg.Version = ObGetFilterVersion();
    		obReg.OperationRegistrationCount = 1;
    		obReg.RegistrationContext = NULL;
    		RtlInitUnicodeString(&obReg.Altitude, L"321124");
    		obReg.OperationRegistration = &opReg;
    		memset(&opReg, 0, sizeof(opReg));
    		opReg.ObjectType = PsProcessType;
    		opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
    		opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall;
    		obst1=ObRegisterCallbacks(&obReg, &obHandle);
    		//reg ob callback 2
    		memset(&obReg2, 0, sizeof(obReg2));
    		obReg2.Version = ObGetFilterVersion();
    		obReg2.OperationRegistrationCount = 1;
    		obReg2.RegistrationContext = NULL;
    		RtlInitUnicodeString(&obReg2.Altitude, L"321125");
    		obReg2.OperationRegistration = &opReg2;
    		memset(&opReg2, 0, sizeof(opReg2));
    		opReg2.ObjectType = PsThreadType;
    		opReg2.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
    		opReg2.PreOperation = (POB_PRE_OPERATION_CALLBACK)&preCall2;
    		obst1=ObRegisterCallbacks(&obReg2, &obHandle2);
    		return NT_SUCCESS(obst1) & NT_SUCCESS(obst2);
    	}
    	else
    	{
    		if(obHandle!=NULL)
    			ObUnRegisterCallbacks(obHandle);
    		if(obHandle2!=NULL)
    			ObUnRegisterCallbacks(obHandle2);
    		return TRUE;
    	}
    }
    执行结果:





  • 相关阅读:
    silverlight中path对象使用总结
    推荐一款Silverlight数据列表控件AgDataGrid
    在silverlight中实现Marquee效果
    在silverlight中使用IsolateStore隔离存储(下)
    在silverlight中使用IsolateStore隔离存储(上)
    在Silverlight中使用DynamicMethod(动态方法)
    使用createObject(createObjectEx)创建silverlight对象
    在Silverlight中使用Json
    怎么这两天总能看到刺激我的好东西
    使silverlight适应IE窗口大小的方法
  • 原文地址:https://www.cnblogs.com/csnd/p/12062027.html
Copyright © 2011-2022 走看看