如未特殊说明均在以下机器测试
Windows 7 Professional with Service Pack 1 (x86) - DVD (Chinese-Simplified)
Windows 10 (business edition), version 1903 (updated June 2019) (x64) - DVD (Chinese-Simplified)
下面代码仅在win7下测试
句柄表 https://bbs.kanxue.com/thread-272049.htm
全局句柄表 全局句柄表是以线程和进程id为索引
对于32位操作系统的句柄表,一项为8字节,存放内核对象地址和一些属性,每一项都是一个_HANDLE_TABLE_ENTRY结构体类型
对于全局句柄表地址如果最后为0结尾(如0x123450),则该地址就是全局句柄表(大小为4096)
如果以1结尾如(0x123451)则该地址指向一个全局句柄表的指针数组,每一个数组元素指向一个全局句柄表
2结尾递推,类似与页表这样的形式
全局句柄表地址存放在nt!PspCidTable
处指向的一个nt!_HANDLE_TABLE
结构体(**CID句柄表(Client ID handle table)**)
kd> dd nt!PspCidTable83f5dd94 89001080 00000000 80000020 00000101 83f5dda4 80000328 80000024 00000000 00000000 83f5ddb4 00000000 00000000 00000000 00000113 83f5ddc4 00000000 00000000 83f0c4be 00000000 83f5ddd4 00000000 00000000 00000000 00000008 83f5dde4 00000000 83f5dde8 83f5dde8 00000000 83f5ddf4 00000000 00000000 00000000 00000000 83f5de04 00000000 807cec28 807cac28 00000000 kd> dt _handle_table 89001080 nt!_HANDLE_TABLE +0x000 TableCode : 0x9168b001 +0x004 QuotaProcess : (null) +0x008 UniqueProcessId : (null) +0x00c HandleLock : _EX_PUSH_LOCK +0x010 HandleTableList : _LIST_ENTRY [ 0x89001090 - 0x89001090 ] +0x018 HandleContentionEvent : _EX_PUSH_LOCK +0x01c DebugInfo : (null) +0x020 ExtraInfoPages : 0n0 +0x024 Flags : 1 +0x024 StrictFIFO : 0y1 +0x028 FirstFreeHandle : 0xf20 +0x02c LastFreeHandleEntry : 0x89004808 _HANDLE_TABLE_ENTRY +0x030 HandleCount : 0x20f +0x034 NextHandleNeedingPool : 0x1000 +0x038 HandleCountHighWatermark : 0x2f4
句柄表里的项需要把后三位清零才能的到eprocess或者ethread地址(即&0xfffffff8)
通过对象头nt!_OBJECT_HEADER结构体中的TypeIndex成员来判断是进程还是线程,该成员数值是nt!ObTypeIndexTable表的索引,ObTypeIndexTable是结构体_OBJECT_TYPE,其中的Name为Process就为进程,反之
全局句柄表抹除保护进程 利用未导出函数PVOID ExpLookupHandleTableEntry(pspCidTable,id)
第一个参数为pspCidTable的位置,第二参数为句柄id
返回值为所到的_HANDLE_TABLE_ENTRY的地址
好处就是win10的句柄表是加密的,利用该函数就不用我们自己去解析和解密了
clearhandle.h
#pragma once #include "search.h" #include "drivercommon.h" typedef struct _HANDLE_TABLE_ENTRY { union { VOID* Object; ULONG ObAttributes; struct _HANDLE_TABLE_ENTRY_INFO * InfoTable ; ULONG Value; }; union { ULONG GrantedAccess; struct { USHORT GrantedAccessIndex; USHORT CreatorBackTraceIndex; }; ULONG NextFreeTableEntry; }; }HANDLE_TABLE_ENTRY, * PHANDLE_TABLE_ENTRY; PHANDLE_TABLE_ENTRY MyExpLookupHandleTableEntry (HANDLE id) ; BOOLEAN ProtectProcess (HANDLE id) ;
clearhandle.c
#include "clearhandle.h" PVOID GetPspCidTable () { static PVOID tableAd = NULL ; if (tableAd) { return tableAd; } FindCode fc[2 ] = { 0 }; UNICODE_STRING name = { 0 }; initFindCodeStruct(&fc[0 ], "FF ?? ?? 8B ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 8B F8 85 FF" , 0 , +5 ); initFindCodeStruct(&fc[1 ], "75 ?? 8B D3 E8 ?? ?? ?? ?? 84 C0 75 ??" , 0x1C , 0 ); RtlInitUnicodeString(&name, L"PsLookupProcessByProcessId" ); PUCHAR startAd = (PUCHAR)MmGetSystemRoutineAddress(&name); ULONG_PTR PspCidTableOffset = findAddressByCode(startAd, startAd + 0x200 , fc, 2 ); if (PspCidTableOffset) { tableAd = **(PVOID**)(PspCidTableOffset); } return tableAd; } PVOID GetExpLookupHandleTableEntryAd () { static PVOID funcAd = NULL ; if (funcAd) { return funcAd; } FindCode fc[2 ] = { 0 }; UNICODE_STRING name = { 0 }; initFindCodeStruct(&fc[0 ], "FF ?? ?? 8B 4D ?? E8 ?? ?? ?? ?? 8B F0 85 F6 75 ?? EB ??" , 0 , +7 ); initFindCodeStruct(&fc[1 ], "8B 4D ?? 56 E8 ?? ?? ?? ?? EB ??" , 0x17 , 0 ); RtlInitUnicodeString(&name, L"ExEnumHandleTable" ); PUCHAR startAd = (PUCHAR)MmGetSystemRoutineAddress(&name); ULONG_PTR funcOffset = findAddressByCode(startAd, startAd + 0x400 , fc, 1 ); if (funcOffset) { funcAd = (PVOID)((*(PULONG_PTR)funcOffset) + funcOffset + 4 ); } return funcAd; } PHANDLE_TABLE_ENTRY MyExpLookupHandleTableEntry (HANDLE id) { typedef PVOID (__fastcall* ExpLookupHandleTableEntry) (PVOID, PVOID, HANDLE) ; PVOID pspCidTable = GetPspCidTable(); ExpLookupHandleTableEntry func = (ExpLookupHandleTableEntry)GetExpLookupHandleTableEntryAd(); if (!pspCidTable || !func) { return NULL ; } return (PHANDLE_TABLE_ENTRY)func(pspCidTable, 0 , id); } ULONG32 GetIdOffset () { FindCode fc[1 ] = { 0 }; UNICODE_STRING name = { 0 }; #ifdef _WIN64 initFindCodeStruct(&fc[0 ], "48 8B ?? ?? ?? ?? ?? C3" , 0 , 3 ); #else initFindCodeStruct(&fc[0 ], "8B EC 8B 45 ?? 8B 80 ?? ?? ?? ??" , 0 , 7 ); #endif RtlInitUnicodeString(&name, L"PsGetProcessId" ); PUCHAR startAd = (PUCHAR)MmGetSystemRoutineAddress(&name); ULONG_PTR funcOffset = findAddressByCode(startAd, startAd + 0x400 , fc, 1 ); if (!funcOffset) { return -1 ; } return *(PULONG32)(funcOffset); } BOOLEAN ClearProcessId (HANDLE id) { PEPROCESS process = NULL ; NTSTATUS status = PsLookupProcessByProcessId(id, &process); if (!NT_SUCCESS(status)) { LOG("%x" , status); return FALSE; } ObDereferenceObject(process); ULONG offset = GetIdOffset(); *(VOID**)((PCHAR)process + offset) = 0 ; return TRUE; } BOOLEAN ProtectProcess (HANDLE id) { PHANDLE_TABLE_ENTRY entry = MyExpLookupHandleTableEntry(id); if (!entry) { LOG("Myexplookuphandletableentry fail" ); return FALSE; } if (!ClearProcessId(id)) { return FALSE; } memset (entry, 0 , sizeof (HANDLE_TABLE_ENTRY)); return TRUE; }
私有句柄表 句柄表位置信息存在Eprocess.ObjectTable,也是_HANDLE_TABLE结构,句柄表里项依旧是_HANDLE_TABLE_ENTRY结构 但是_HANDLE_TABLE_ENTRY结构里的Object存的是对象头_OBJECT_HEADER位置
句柄表权限问题看https://bbs.kanxue.com/thread-272049.htm
摘抄:
64位分为:
划分
含义
(56-64bit)8位
该位的前四位始终为0,后四位标志比如写成函数SetHandleInformation()函数是否设定了HANDLE_FLAG_PROTECT_FROM_CLOSE标志位,如果设定了这四位的值为0x2
(32-55bit)24位
通过获得句柄的函数得到的访问掩码,在进程中就是OpenProcess(dwDesiredAccess,BInheritHandle,dwProcessId)中的dwDesiredAccess
(3-31bit)29位
内核对象的首地址,后三位用0填充
(0-3bit)3位
分别表示三种权限句柄通用权限。
保护之句柄降权 ExEnumHandleTable来遍历所有进程私有句柄表,发现我们想保护的进程句柄相同就把他的读写权限抹除
#include "drivercommon.h" #define PROCESS_VM_READ (0x0010) #define PROCESS_VM_WRITE (0x0020) BOOLEAN g_bWorking = FALSE; HANDLE g_thread = NULL ; typedef struct _HANDLE_TABLE_ENTRY { union { VOID* Object; ULONG ObAttributes; struct _HANDLE_TABLE_ENTRY_INFO * InfoTable ; ULONG Value; }; union { ULONG GrantedAccess; struct { USHORT GrantedAccessIndex; USHORT CreatorBackTraceIndex; }; ULONG NextFreeTableEntry; }; }HANDLE_TABLE_ENTRY, * PHANDLE_TABLE_ENTRY; typedef BOOLEAN (NTAPI* EX_ENUMERATE_HANDLE_ROUTINE) ( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN PVOID EnumParameter ) ;BOOLEAN ExEnumHandleTable ( __in PVOID HandleTable, __in EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, __in PVOID EnumParameter, __out_opt PHANDLE Handle ) ;BOOLEAN NTAPI enumRoutine ( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN PVOID EnumParameter ) { if (HandleTableEntry) { ULONG_PTR obj = (HandleTableEntry->Value & ~7 ) + 0x18 ; if (obj == (ULONG_PTR)EnumParameter) { HandleTableEntry->GrantedAccess &= ~(PROCESS_VM_READ | PROCESS_VM_WRITE); } } return FALSE; } PEPROCESS FindProcessByName (PWCH name) { PEPROCESS process = NULL ; NTSTATUS status = NULL ; for (size_t i = 0 ; i < 0x100000 ; i += 4 ) { status = PsLookupProcessByProcessId((HANDLE)i, &process); if (!NT_SUCCESS(status) || !process) { continue ; } PUNICODE_STRING ProcessName = NULL ; status = SeLocateProcessImageName(process, &ProcessName); if (!NT_SUCCESS(status) || !ProcessName->Length) { ObDereferenceObject(process); continue ; } _wcsupr(ProcessName->Buffer); if (wcsstr(ProcessName->Buffer, name) != 0 ) { ExFreePoolWithTag(ProcessName, 0 ); ObDereferenceObject(process); LOG("%S" , ProcessName->Buffer); return process; } ExFreePoolWithTag(ProcessName, 0 ); ObDereferenceObject(process); } LOG("not find" ); return NULL ; } VOID ProcessHandleResetPrivilege (PEPROCESS ep) { PEPROCESS curprocess = NULL ; NTSTATUS status = NULL ; while (g_bWorking) { for (size_t i = 4 ; i < 0x10000 ; i += 4 ) { status = PsLookupProcessByProcessId((HANDLE)i, &curprocess); if (!NT_SUCCESS(status)) { continue ; } if (PsGetProcessExitStatus(curprocess) == 0x103 ) ExEnumHandleTable(*(PULONG)((PUCHAR)curprocess + 0xf4 ), enumRoutine, ep, NULL ); if (PsGetProcessExitStatus(curprocess) == 0x103 ) ObDereferenceObject(curprocess); } LARGE_INTEGER tin = { 0 }; tin.QuadPart = 8 * DELAY_ONE_SECOND; KeDelayExecutionThread(KernelMode, FALSE, &tin); } } VOID DriverUnload (_In_ struct _DRIVER_OBJECT* DriverObject) { UNREFERENCED_PARAMETER(DriverObject); LOG("%s" , __FUNCTION__); g_bWorking = FALSE; if (g_thread) { LOG("wait" ); ZwWaitForSingleObject(g_thread, FALSE, NULL ); ZwClose(g_thread); } } NTSTATUS DriverEntry ( __in struct _DRIVER_OBJECT* DriverObject, __in PUNICODE_STRING RegistryPath ) { UNREFERENCED_PARAMETER(RegistryPath); DriverObject->DriverUnload = DriverUnload; PEPROCESS process = FindProcessByName(L"DBGVIEW.EXE" ); if (!process) { return STATUS_UNSUCCESSFUL; } if (PsGetProcessExitStatus(process) != STATUS_PENDING) { LOG("process teminaled ,but someone still own his handle" ); return STATUS_UNSUCCESSFUL; } NTSTATUS status = PsCreateSystemThread(&g_thread, THREAD_ALL_ACCESS, NULL , NULL , NULL , ProcessHandleResetPrivilege, process); if (!NT_SUCCESS(status)) { return status; } g_bWorking = TRUE; LOG("%s" , __FUNCTION__); return STATUS_SUCCESS; }
效果对于ce来说就是正常显示一下后全部变???????
反保护之防止句柄降权(提权) 上面的保护遍历是通过对比私有句柄表里的eprocess是否是他的进程来的,我们可以伪造他的eprocess并进一步eprocess里的一些特征改掉(id name cr3等),用伪造的eprocess覆盖私有句柄表来逃避检测
#include "drivercommon.h" #include <intrin.h> PVOID g_fakeObj = NULL ; typedef struct _HANDLE_TABLE_ENTRY { union { VOID* Object; ULONG ObAttributes; struct _HANDLE_TABLE_ENTRY_INFO * InfoTable ; ULONG Value; }; union { ULONG GrantedAccess; struct { USHORT GrantedAccessIndex; USHORT CreatorBackTraceIndex; }; ULONG NextFreeTableEntry; }; }HANDLE_TABLE_ENTRY, * PHANDLE_TABLE_ENTRY; typedef BOOLEAN (NTAPI* EX_ENUMERATE_HANDLE_ROUTINE) ( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN PVOID EnumParameter ) ;BOOLEAN ExEnumHandleTable ( __in PVOID HandleTable, __in EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure, __in PVOID EnumParameter, __out_opt PHANDLE Handle ) ;BOOLEAN NTAPI enumRoutine ( IN PHANDLE_TABLE_ENTRY HandleTableEntry, IN HANDLE Handle, IN PVOID EnumParameter ) { if (HandleTableEntry) { ULONG process = (HandleTableEntry->Value & ~7 ) + 0x18 ; if (process == (ULONG)EnumParameter) { HandleTableEntry->Value = (ULONG)g_fakeObj | 1 ; HandleTableEntry->GrantedAccess |= PROCESS_ALL_ACCESS; } } return FALSE; } ULONG GetIdOffset () { UNICODE_STRING name = { 0 }; RtlInitUnicodeString(&name, L"PsGetProcessId" ); PUCHAR startAd = (PUCHAR)MmGetSystemRoutineAddress(&name); return *(PULONG)(startAd + 10 ); } PEPROCESS FindProcessByName (PWCH name) { PEPROCESS process = NULL ; NTSTATUS status = NULL ; for (size_t i = 0 ; i < 0x100000 ; i += 4 ) { status = PsLookupProcessByProcessId((HANDLE)i, &process); if (!NT_SUCCESS(status) || !process) { continue ; } PUNICODE_STRING ProcessName = NULL ; status = SeLocateProcessImageName(process, &ProcessName); if (!NT_SUCCESS(status) || !ProcessName->Length) { ObDereferenceObject(process); continue ; } _wcsupr(ProcessName->Buffer); if (wcsstr(ProcessName->Buffer, name) != 0 ) { ExFreePoolWithTag(ProcessName, 0 ); ObDereferenceObject(process); LOG("%S" , ProcessName->Buffer); return process; } ExFreePoolWithTag(ProcessName, 0 ); ObDereferenceObject(process); } LOG("not find" ); return NULL ; } VOID DriverUnload (_In_ struct _DRIVER_OBJECT* DriverObject) { UNREFERENCED_PARAMETER(DriverObject); LOG("%s" , __FUNCTION__); } NTSTATUS DriverEntry ( __in struct _DRIVER_OBJECT* DriverObject, __in PUNICODE_STRING RegistryPath ) { UNREFERENCED_PARAMETER(RegistryPath); PEPROCESS targetProcess = FindProcessByName(L"DBGVIEW.EXE" ); if (!targetProcess) { return STATUS_UNSUCCESSFUL; } PVOID targetObj = (PUCHAR)targetProcess - 0x18 ; g_fakeObj = ExAllocatePool(NonPagedPool, PAGE_SIZE); if (!g_fakeObj) { return STATUS_UNSUCCESSFUL; } PUCHAR fakeProcess = (PUCHAR)g_fakeObj + 0x18 ; memset (g_fakeObj, 0 , PAGE_SIZE); memcpy (g_fakeObj, targetObj, 0x350 ); *(PHANDLE)((PUCHAR)fakeProcess + GetIdOffset()) = 0 ; ULONG_PTR cr4 = __readcr4(); ULONG srcCr3 = *(PULONG)((PUCHAR)targetProcess + 0x18 ); PVOID fakeCr3 = ExAllocatePool(NonPagedPool, PAGE_SIZE); if (NULL == fakeCr3) { ExFreePool(g_fakeObj); return STATUS_UNSUCCESSFUL; } memset (fakeCr3, 0 , PAGE_SIZE); int size = PAGE_SIZE; if (cr4 & (0x20 )) { size = 4 * 8 ; } PHYSICAL_ADDRESS phySrcCr3 = { 0 }; phySrcCr3.QuadPart = srcCr3; PVOID virtualCr3 = MmMapIoSpace(phySrcCr3, size, MmNonCached); memcpy (fakeCr3, virtualCr3, size); PHYSICAL_ADDRESS phyFakeCr3 = MmGetPhysicalAddress(fakeCr3); *(PULONG)((PUCHAR)fakeProcess + 0x18 ) = phyFakeCr3.QuadPart; PEPROCESS hackProcess = FindProcessByName(L"CHEATENGINE-I386.EXE" ); if (NULL == hackProcess) { ExFreePool(g_fakeObj); ExFreePool(fakeCr3); return STATUS_UNSUCCESSFUL; } ExEnumHandleTable(*(PULONG_PTR)((PUCHAR)hackProcess + 0xf4 ), enumRoutine, targetProcess, NULL ); DriverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; }
句柄回调保护 ObRegisterCallbacks注册回调拦截对句柄的操作,进行降权处理
仅在win10下测试
ExportFunc.h
#pragma once #include <ntifs.h> NTSTATUS MmCopyVirtualMemory ( IN PEPROCESS FromProcess, IN CONST VOID* FromAddress, IN PEPROCESS ToProcess, OUT PVOID ToAddress, IN SIZE_T BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PSIZE_T NumberOfBytesCopied ) ;PPEB PsGetProcessPeb (__in PEPROCESS Process) ; PVOID PsGetCurrentProcessWow64Process () ; EXTERN_C void * NTAPI PsGetProcessWow64Process (PEPROCESS Process) ; EXTERN_C void * NTAPI PsGetThreadTeb (PETHREAD Thread) ;
protect.h
#pragma once #include "../drivercommon.h" #include "../ExportFunc.h" NTSTATUS InitObRegister () ; VOID DestoryObRegister () ; NTSTATUS InitObRegisterUnProtect () ; VOID DestoryObRegisterUnprotect () ; NTSTATUS SetProtectPid (HANDLE pid) ; NTSTATUS UnProtectPid (HANDLE pid) ;
protect.c
#include "protect.h" #include "../SearchCode.h" HANDLE gRegProtectHandle = NULL ; HANDLE gProtectId=-1 ; HANDLE gRegUnProtectHandle = NULL ; HANDLE gUnProtectId = -1 ; OB_PREOP_CALLBACK_STATUS PobPreOperationCallbackProtect ( PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation ) { if (-1 == gProtectId) { return OB_PREOP_SUCCESS; } PEPROCESS Process = OperationInformation->Object; if (!Process) return OB_PREOP_SUCCESS; HANDLE currentPid = PsGetCurrentProcessId(); HANDLE targetPid = PsGetProcessId(Process); if (currentPid == gProtectId) return OB_PREOP_SUCCESS; if (targetPid != gProtectId) return OB_PREOP_SUCCESS; LOG("protect targetpid:%x\r\n" , targetPid); if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0 ; OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess = 0 ; } else { OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0 ; OperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess = 0 ; } return OB_PREOP_SUCCESS; } OB_PREOP_CALLBACK_STATUS PobPreOperationCallbackUnProtect ( PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation ) { if (-1 == gUnProtectId) { return OB_PREOP_SUCCESS; } PEPROCESS Process = OperationInformation->Object; if (!Process) return OB_PREOP_SUCCESS; HANDLE currentPid = PsGetCurrentProcessId(); HANDLE targetPid = PsGetProcessId(Process); if (currentPid == gUnProtectId) return OB_PREOP_SUCCESS; if (targetPid != gUnProtectId) return OB_PREOP_SUCCESS; LOG("unprotect targetpid:%x\r\n" ,targetPid); if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = PROCESS_ALL_ACCESS; OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess = PROCESS_ALL_ACCESS; } else { OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = PROCESS_ALL_ACCESS; OperationInformation->Parameters->DuplicateHandleInformation.OriginalDesiredAccess = PROCESS_ALL_ACCESS; } return OB_PREOP_SUCCESS; } NTSTATUS InitObRegister () { NTSTATUS status = STATUS_UNSUCCESSFUL; ULONG_PTR MmVerifyCallbackFunctionCheckFlagsAd = searchCode("ntoskrnl.exe" , ".text" , "48 ?? ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 D2 48 8B CE E8 ?? ?? ?? ?? 48 85 C0 74 ?? 85 FF 74 ??" , -0x37 ); if (!MmVerifyCallbackFunctionCheckFlagsAd) { return STATUS_UNSUCCESSFUL; } ULONG64 jmpRcx = searchCode("ntoskrnl.exe" , ".text" , "FFE1" , 0 ); if (!jmpRcx) return STATUS_UNSUCCESSFUL; OB_OPERATION_REGISTRATION operationRegRation = { 0 }; operationRegRation.ObjectType = PsProcessType; operationRegRation.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; operationRegRation.PreOperation = jmpRcx; OB_CALLBACK_REGISTRATION callBackRegRation = { 0 }; callBackRegRation.Version = ObGetFilterVersion(); callBackRegRation.OperationRegistrationCount = 1 ; RtlInitUnicodeString(&callBackRegRation.Altitude, L"456340" ); callBackRegRation.RegistrationContext = PobPreOperationCallbackProtect; callBackRegRation.OperationRegistration = &operationRegRation; UCHAR bufCode[10 ] = { 0 }; UCHAR patch[] = { 0xB8 ,0x01 ,0x00 ,0x00 ,0x00 ,0x90 ,0xc3 }; PHYSICAL_ADDRESS phyAddress = MmGetPhysicalAddress(MmVerifyCallbackFunctionCheckFlagsAd); if (!phyAddress.QuadPart) { return STATUS_UNSUCCESSFUL; } PVOID mapMmVerifyCallbackFunctionCheckFlagsAd = MmMapIoSpace(phyAddress, 10 , MmNonCached); if (!mapMmVerifyCallbackFunctionCheckFlagsAd) { return STATUS_UNSUCCESSFUL; } memcpy (bufCode, mapMmVerifyCallbackFunctionCheckFlagsAd, 10 ); memcpy (mapMmVerifyCallbackFunctionCheckFlagsAd, patch, sizeof (patch)); status = ObRegisterCallbacks(&callBackRegRation, &gRegProtectHandle); memcpy (mapMmVerifyCallbackFunctionCheckFlagsAd, bufCode, 10 ); return status; } VOID DestoryObRegister () { if (gRegProtectHandle) ObUnRegisterCallbacks(gRegProtectHandle); } NTSTATUS SetProtectPid (HANDLE pid) { NTSTATUS status; if (!gRegProtectHandle) { status = InitObRegister(); } else { status = STATUS_SUCCESS; } if (NT_SUCCESS(status)) { LOG("sucess protect" ); gProtectId = pid; } else { LOG("fail %x" ,status); } return status; } NTSTATUS InitObRegisterUnProtect () { NTSTATUS status = STATUS_UNSUCCESSFUL; ULONG_PTR MmVerifyCallbackFunctionCheckFlagsAd = searchCode("ntoskrnl.exe" , ".text" , "48 ?? ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 D2 48 8B CE E8 ?? ?? ?? ?? 48 85 C0 74 ?? 85 FF 74 ??" , -0x37 ); if (!MmVerifyCallbackFunctionCheckFlagsAd) { return STATUS_UNSUCCESSFUL; } ULONG64 jmpRcx = searchCode("ntoskrnl.exe" , ".text" , "FFE1" , 0 ); if (!jmpRcx) return STATUS_UNSUCCESSFUL; OB_OPERATION_REGISTRATION operationRegRation = { 0 }; operationRegRation.ObjectType = PsProcessType; operationRegRation.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; operationRegRation.PreOperation = jmpRcx; OB_CALLBACK_REGISTRATION callBackRegRation = { 0 }; callBackRegRation.Version = ObGetFilterVersion(); callBackRegRation.OperationRegistrationCount = 1 ; RtlInitUnicodeString(&callBackRegRation.Altitude, L"456100" ); callBackRegRation.RegistrationContext = PobPreOperationCallbackUnProtect; callBackRegRation.OperationRegistration = &operationRegRation; UCHAR bufCode[10 ] = { 0 }; UCHAR patch[] = { 0xB8 ,0x01 ,0x00 ,0x00 ,0x00 ,0x90 ,0xc3 }; PHYSICAL_ADDRESS phyAddress = MmGetPhysicalAddress(MmVerifyCallbackFunctionCheckFlagsAd); if (!phyAddress.QuadPart) { return STATUS_UNSUCCESSFUL; } PVOID mapMmVerifyCallbackFunctionCheckFlagsAd = MmMapIoSpace(phyAddress, 10 , MmNonCached); if (!mapMmVerifyCallbackFunctionCheckFlagsAd) { return STATUS_UNSUCCESSFUL; } memcpy (bufCode, mapMmVerifyCallbackFunctionCheckFlagsAd, 10 ); memcpy (mapMmVerifyCallbackFunctionCheckFlagsAd, patch, sizeof (patch)); status = ObRegisterCallbacks(&callBackRegRation, &gRegUnProtectHandle); memcpy (mapMmVerifyCallbackFunctionCheckFlagsAd, bufCode, 10 ); return status; } VOID DestoryObRegisterUnprotect () { if (gRegUnProtectHandle) ObUnRegisterCallbacks(gRegUnProtectHandle); } NTSTATUS UnProtectPid (HANDLE pid) { NTSTATUS status; if (!gRegUnProtectHandle) { status = InitObRegisterUnProtect(); } else { status = STATUS_SUCCESS; } if (NT_SUCCESS(status)) { LOG("sucess unprotect" ); gUnProtectId = pid; } else { LOG("fail %x" , status); } return status; }