返回顶部
扩大
缩小

Zhang_derek

五、句柄表

5.1.全局句柄

1.全局句柄表中只存储进程和线程对象,把PID/CID当作索引在全局句柄表中查找对应对象结构.

2全局句柄表有三张表:

  • 0表:共4096字节,每个元素占8个字节,总共可以存512个元素,每个元素指向的就是object本身

  • 1表:共4096字节,每个元素(占4字节)存的是表的索引,可以存512*1024个

  • 2表:共4096个字节,每个元素(占4字节)存的是表目录的索引,可以存51210241024个

3.通过进程PID,在全局句柄表中查到进程对象

#Dbgview.exe进程id:2264

2264/4 =566   大于512说明在第二张表里面

566-512 = 54 转换成16进制位 0x36

#第二张表的位置
dq 99f8a000+36*8

#计算进程对象地址
85eb8939 & FFFFFFF8 = 85EB8938 

#查看进程对象
dt _EPROCESS 85EB8938
kd> dd PsPCidTable
83f8dca4  8aa010a8 00000000 80000020 00000101
83f8dcb4  800002d4 80000024 00000000 00000113
83f8dcc4  00000000 00000000 83f3e3d0 00000000
83f8dcd4  00000000 00000000 00000000 00000008
83f8dce4  00000000 83f8dce8 83f8dce8 00000000
83f8dcf4  00000000 00000000 00000000 00000000
83f8dd04  00000000 807d1c38 807cdc38 00000000
83f8dd14  00000000 00000000 00000000 00000001
kd> dt _HANDLE_TABLE 8aa010a8
ntdll!_HANDLE_TABLE
   +0x000 TableCode        : 0x99f89001
   +0x004 QuotaProcess     : (null) 
   +0x008 UniqueProcessId  : (null) 
   +0x00c HandleLock       : _EX_PUSH_LOCK
   +0x010 HandleTableList  : _LIST_ENTRY [ 0x8aa010b8 - 0x8aa010b8 ]
   +0x018 HandleContentionEvent : _EX_PUSH_LOCK
   +0x01c DebugInfo        : (null) 
   +0x020 ExtraInfoPages   : 0n0
   +0x024 Flags            : 1
   +0x024 StrictFIFO       : 0y1
   +0x028 FirstFreeHandle  : 0x920
   +0x02c LastFreeHandleEntry : 0x99f8ae80 _HANDLE_TABLE_ENTRY
   +0x030 HandleCount      : 0x27c
   +0x034 NextHandleNeedingPool : 0x1000
   +0x038 HandleCountHighWatermark : 0x2ea
kd> dd 0x99f89000
99f89000  8aa04000 99f8a000 00000000 00000000    //两个句柄表
99f89010  00000000 00000000 00000000 00000000
99f89020  00000000 00000000 00000000 00000000
99f89030  00000000 00000000 00000000 00000000
99f89040  00000000 00000000 00000000 00000000
99f89050  00000000 00000000 00000000 00000000
99f89060  00000000 00000000 00000000 00000000
99f89070  00000000 00000000 00000000 00000000
kd> dq 99f8a000+36*8
99f8a1b0  00000000`85eb8939 000003d8`00000000
99f8a1c0  00000000`87eb2651 00000000`87dfb681
99f8a1d0  00000000`87e62631 00000000`87e9fd19
99f8a1e0  00000f68`00000000 00000000`86040289
99f8a1f0  00000000`87e56811 00000000`876e1261
99f8a200  00000c24`00000000 00000000`87ea8661
99f8a210  00000d1c`00000000 00000000`87eaa251
99f8a220  00000e9c`00000000 00000000`85f56709
kd> dt _EPROCESS 85EB8938
ntdll!_EPROCESS
   +0x16c ImageFileName    : [15]  "Dbgview.exe"

4.查看对象类型

#可以看到TypeIndex的索引为7
dt _OBJECT_HEADER 85eb8938-0X18   

#去对象类型表里面查看是什么类型的对象
dd ObTypeIndexTable

#可以看到Name位“Process”对象
dt _OBJECT_TYPE 85cd1eb0   
kd> dt _OBJECT_HEADER 85eb8938-0X18
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n62
   +0x004 HandleCount      : 0n4
   +0x004 NextToFree       : 0x00000004 Void
   +0x008 Lock             : _EX_PUSH_LOCK
   +0x00c TypeIndex        : 0x7 ''     //对象类型
   +0x00d TraceFlags       : 0 ''
   +0x00e InfoMask         : 0x8 ''
   +0x00f Flags            : 0 ''
   +0x010 ObjectCreateInfo : 0x83f81a00 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : 0x83f81a00 Void
   +0x014 SecurityDescriptor : 0xa44d4b66 Void
   +0x018 Body             : _QUAD
kd> dd ObTypeIndexTable
83f8f660  00000000 bad0b0b0 85c3c808 85c3c740
83f8f670  85c3c678 85cd1040 85cd1f78 85cd1eb0
83f8f680  85cd1de8 85cd1d20 85cd1c58 85cd15a0
83f8f690  85ced418 85ced350 85cf8418 85cf8350
83f8f6a0  85cf8288 85cec588 85cec4c0 85cec3f8
83f8f6b0  85ceec90 85ceebc8 85ceeb00 85ceea38
83f8f6c0  85cee970 85cee8a8 85cee7e0 85cee718
83f8f6d0  85cee650 85cf5f78 85cf5eb0 85cf5de8
kd> dt _OBJECT_TYPE 85cd1eb0
ntdll!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0x85cd1eb0 - 0x85cd1eb0 ]
   +0x008 Name             : _UNICODE_STRING "Process"     //类型位进程
   +0x010 DefaultObject    : (null) 
   +0x014 Index            : 0x7 ''
   +0x018 TotalNumberOfObjects : 0x29
   +0x01c TotalNumberOfHandles : 0xe4
   +0x020 HighWaterNumberOfObjects : 0x33
   +0x024 HighWaterNumberOfHandles : 0x12b
   +0x028 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x078 TypeLock         : _EX_PUSH_LOCK
   +0x07c Key              : 0x636f7250
   +0x080 CallbackList     : _LIST_ENTRY [ 0x85cd1f30 - 0x85cd1f30 ]

5.2.保护进程

在虚拟机里面要先删除掉这个内核钩子,关闭进程的时候才不会蓝屏。

特征码定位PspCidTable函数地址

特征码定位ExpLookupHandleTableEntry函数地址

 

Search.h

 

#pragma once
#include <ntifs.h>


typedef enum _SYSTEM_INFORMATION_CLASS {
	SystemBasicInformation,
	SystemProcessorInformation,             // obsolete...delete
	SystemPerformanceInformation,
	SystemTimeOfDayInformation,
	SystemPathInformation,
	SystemProcessInformation,
	SystemCallCountInformation,
	SystemDeviceInformation,
	SystemProcessorPerformanceInformation,
	SystemFlagsInformation,
	SystemCallTimeInformation,
	SystemModuleInformation,
	SystemLocksInformation,
	SystemStackTraceInformation,
	SystemPagedPoolInformation,
	SystemNonPagedPoolInformation,
	SystemHandleInformation,
	SystemObjectInformation,
	SystemPageFileInformation,
	SystemVdmInstemulInformation,
	SystemVdmBopInformation,
	SystemFileCacheInformation,
	SystemPoolTagInformation,
	SystemInterruptInformation,
	SystemDpcBehaviorInformation,
	SystemFullMemoryInformation,
	SystemLoadGdiDriverInformation,
	SystemUnloadGdiDriverInformation,
	SystemTimeAdjustmentInformation,
	SystemSummaryMemoryInformation,
	SystemMirrorMemoryInformation,
	SystemPerformanceTraceInformation,
	SystemObsolete0,
	SystemExceptionInformation,
	SystemCrashDumpStateInformation,
	SystemKernelDebuggerInformation,
	SystemContextSwitchInformation,
	SystemRegistryQuotaInformation,
	SystemExtendServiceTableInformation,
	SystemPrioritySeperation,
	SystemVerifierAddDriverInformation,
	SystemVerifierRemoveDriverInformation,
	SystemProcessorIdleInformation,
	SystemLegacyDriverInformation,
	SystemCurrentTimeZoneInformation,
	SystemLookasideInformation,
	SystemTimeSlipNotification,
	SystemSessionCreate,
	SystemSessionDetach,
	SystemSessionInformation,
	SystemRangeStartInformation,
	SystemVerifierInformation,
	SystemVerifierThunkExtend,
	SystemSessionProcessInformation,
	SystemLoadGdiDriverInSystemSpace,
	SystemNumaProcessorMap,
	SystemPrefetcherInformation,
	SystemExtendedProcessInformation,
	SystemRecommendedSharedDataAlignment,
	SystemComPlusPackage,
	SystemNumaAvailableMemory,
	SystemProcessorPowerInformation,
	SystemEmulationBasicInformation,
	SystemEmulationProcessorInformation,
	SystemExtendedHandleInformation,
	SystemLostDelayedWriteInformation,
	SystemBigPoolInformation,
	SystemSessionPoolTagInformation,
	SystemSessionMappedViewInformation,
	SystemHotpatchInformation,
	SystemObjectSecurityMode,
	SystemWatchdogTimerHandler,
	SystemWatchdogTimerInformation,
	SystemLogicalProcessorInformation,
	SystemWow64SharedInformation,
	SystemRegisterFirmwareTableInformationHandler,
	SystemFirmwareTableInformation,
	SystemModuleInformationEx,
	SystemVerifierTriageInformation,
	SystemSuperfetchInformation,
	SystemMemoryListInformation,
	SystemFileCacheInformationEx,
	MaxSystemInfoClass  // MaxSystemInfoClass should always be the last enum
} SYSTEM_INFORMATION_CLASS;

typedef struct _RTL_PROCESS_MODULE_INFORMATION {
	HANDLE Section;                 // Not filled in
	PVOID MappedBase;
	PVOID ImageBase;
	ULONG ImageSize;
	ULONG Flags;
	USHORT LoadOrderIndex;
	USHORT InitOrderIndex;
	USHORT LoadCount;
	USHORT OffsetToFileName;
	UCHAR  FullPathName[256];
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
	ULONG NumberOfModules;
	RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;


NTSTATUS NTAPI ZwQuerySystemInformation(
	__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
	__out_bcount_opt(SystemInformationLength) PVOID SystemInformation,
	__in ULONG SystemInformationLength,
	__out_opt PULONG ReturnLength
);



typedef struct _FindCode
{
	UCHAR code[0x200];
	ULONG len;
	int offset;
	ULONG lastAddressOffset;
}FindCode, *PFindCode;


void initFindCodeStruct(PFindCode findCode, PCHAR code, ULONG_PTR offset, ULONG_PTR lastAddrOffset);

ULONG_PTR findAddressByCode(ULONG_PTR beginAddr, ULONG_PTR endAddr, PFindCode  findCode, ULONG numbers);

ULONG_PTR QuerySysModule(char * MoudleName, _Out_opt_ ULONG_PTR * module);

ULONG searchNtCode(char * code, int offset);

ULONG searchCode(char * moduleName, char * segmentName, char * code, int offset);


ULONG searchOtherCode(ULONG_PTR startAdd, ULONG_PTR endAddr, char * code, int offset);

Search.c

#include "Search.h"
#include <ntimage.h>

UCHAR charToHex(UCHAR * ch)
{
	unsigned char temps[2] = { 0 };
	for (int i = 0; i < 2; i++)
	{
		if (ch[i] >= '0' && ch[i] <= '9')
		{
			temps[i] = (ch[i] - '0');
		}
		else if (ch[i] >= 'A' && ch[i] <= 'F')
		{
			temps[i] = (ch[i] - 'A') + 0xA;
		}
		else if (ch[i] >= 'a' && ch[i] <= 'f')
		{
			temps[i] = (ch[i] - 'a') + 0xA;
		}
	}
	return ((temps[0] << 4) & 0xf0) | (temps[1] & 0xf);
}



void initFindCodeStruct(PFindCode findCode, PCHAR code, ULONG_PTR offset, ULONG_PTR lastAddrOffset)
{

	memset(findCode, 0, sizeof(FindCode));

	findCode->lastAddressOffset = lastAddrOffset;
	findCode->offset = offset;

	PCHAR pTemp = code;
	ULONG_PTR i = 0;
	for (i = 0; *pTemp != '\0'; i++)
	{
		if (*pTemp == '*' || *pTemp == '?')
		{
			findCode->code[i] = *pTemp;
			pTemp++;
			continue;
		}

		findCode->code[i] = charToHex(pTemp);
		pTemp += 2;

	}

	findCode->len = i;
}


ULONG_PTR findAddressByCode(ULONG_PTR beginAddr, ULONG_PTR endAddr, PFindCode  findCode, ULONG numbers)
{
	ULONG64 j = 0;
	LARGE_INTEGER rtna = { 0 };

	for (ULONG_PTR i = beginAddr; i <= endAddr; i++)
	{
		if (!MmIsAddressValid((PVOID)i))
		{
			i = i & (~0xfff) + PAGE_SIZE - 1;
			continue;
		}

		

		for (j = 0; j < numbers; j++)
		{
			FindCode  fc = findCode[j];
			ULONG_PTR tempAddress = i;

			UCHAR * code = (UCHAR *)(tempAddress + fc.offset);
			BOOLEAN isFlags = FALSE;

			for (ULONG_PTR k = 0; k < fc.len; k++)
			{
				if (!MmIsAddressValid((PVOID)(code + k)))
				{
					isFlags = TRUE;
					break;
				}

				if (fc.code[k] == '*' || fc.code[k] == '?') continue;

				if (code[k] != fc.code[k])
				{
					isFlags = TRUE;
					break;
				}
			}

			if (isFlags) break;

		}

		//找到了
		if (j == numbers)
		{
			rtna.QuadPart = i;
			rtna.LowPart += findCode[0].lastAddressOffset;
			break;
		}

	}

	return rtna.QuadPart;
}

char * CharToUper(char * wstr, BOOLEAN isAllocateMemory)
{
	char * ret = NULL;

	if (isAllocateMemory)
	{
		int len = strlen(wstr) + 2;
		ret = ExAllocatePool(PagedPool, len);
		memset(ret, 0, len);
		memcpy(ret, wstr, len - 2);
	}
	else
	{
		ret = wstr;
	}

	_strupr(ret);

	return ret;
}

//返回值为模块的大小
ULONG_PTR QuerySysModule(char * MoudleName, _Out_opt_ ULONG_PTR * module)
{
	RTL_PROCESS_MODULES info;
	ULONG retPro = NULL;
	ULONG_PTR moduleSize = 0;



	NTSTATUS ststas = ZwQuerySystemInformation(SystemModuleInformation, &info, sizeof(info), &retPro);
	char * moduleUper = CharToUper(MoudleName, TRUE);

	if (ststas == STATUS_INFO_LENGTH_MISMATCH)
	{
		//申请长度
		ULONG len = retPro + sizeof(RTL_PROCESS_MODULES);
		PRTL_PROCESS_MODULES mem = (PRTL_PROCESS_MODULES)ExAllocatePool(PagedPool, len);
		memset(mem, 0, len);
		ststas = ZwQuerySystemInformation(SystemModuleInformation, mem, len, &retPro);

		if (!NT_SUCCESS(ststas))
		{
			ExFreePool(moduleUper);
			ExFreePool(mem);
			return 0;
		}

		//开始查询

		if (strstr(MoudleName, "ntkrnlpa.exe") || strstr(MoudleName, "ntoskrnl.exe"))
		{
			PRTL_PROCESS_MODULE_INFORMATION ModuleInfo = &(mem->Modules[0]);
			*module = ModuleInfo->ImageBase;
			moduleSize = ModuleInfo->ImageSize;
		}
		else
		{
			for (int i = 0; i < mem->NumberOfModules; i++)
			{
				PRTL_PROCESS_MODULE_INFORMATION processModule = &mem->Modules[i];
				CharToUper(processModule->FullPathName, FALSE);
				if (strstr(processModule->FullPathName, moduleUper))
				{
					if (module)
					{
						*module = processModule->ImageBase;

					}

					moduleSize = processModule->ImageSize;

					break;
				}

			}
		}




		ExFreePool(mem);
	}


	ExFreePool(moduleUper);
	return moduleSize;
}


ULONG searchOtherCode(ULONG_PTR startAdd, ULONG_PTR endAddr,char * code, int offset)
{
	FindCode fs[1] = { 0 };
	initFindCodeStruct(&fs[0], code, 0, offset);


	ULONG_PTR func = findAddressByCode(startAdd, endAddr, fs, 1);

	return func;
}

ULONG searchNtCode(char * code,int offset)
{
	FindCode fs[1] = { 0 };
	initFindCodeStruct(&fs[0], code, 0, offset);


	SIZE_T moduleBase = 0;
	ULONG size = QuerySysModule("ntoskrnl.exe", &moduleBase);

	ULONG_PTR func = findAddressByCode(moduleBase, size + moduleBase, fs, 1);

	return func;
}

ULONG searchCode(char * moduleName, char * segmentName, char * code, int offset)
{
	FindCode fs[1] = { 0 };
	initFindCodeStruct(&fs[0], code, 0, offset);
	SIZE_T moduleBase = 0;
	ULONG size = QuerySysModule(moduleName, &moduleBase);

	if (!moduleBase)
	{
		return 0;
	}


	PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)moduleBase;

	PIMAGE_NT_HEADERS pNts = (PIMAGE_NT_HEADERS)((PUCHAR)moduleBase + pDos->e_lfanew);

	PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNts);

	PIMAGE_SECTION_HEADER pTemp = NULL;

	for (int i = 0; i < pNts->FileHeader.NumberOfSections; i++)
	{
		char bufName[9] = {0};
		memcpy(bufName, pSection->Name, 8);
		if (_stricmp(bufName, segmentName) == 0)
		{
			pTemp = pSection;
			break;
		}
		pSection++;
	}

	if (pTemp)
	{
		moduleBase = pSection->VirtualAddress + moduleBase;
		size = pSection->SizeOfRawData;
	}

	ULONG_PTR func = findAddressByCode(moduleBase, size + moduleBase, fs, 1);

	return func;
}

ProcessProtect.h

#pragma once
#include <ntifs.h>

PVOID MyExpLookupHandleTableEntry(HANDLE pid);

BOOLEAN ProtectProcess(HANDLE pid);

ProcessProtect.c

#include "ProcessProtect.h"
#include "Search.h"

PVOID GetPspCidTable()
{
	static PVOID scidTable = NULL;
	if (scidTable) return scidTable;

	UNICODE_STRING unName = {0};
	RtlInitUnicodeString(&unName, L"PsLookupProcessByProcessId");
	PUCHAR startFunc = MmGetSystemRoutineAddress(&unName);

	scidTable = (PVOID)searchOtherCode(startFunc, startFunc+0x100,"8B*****E8****8BF885FF74*8B1F",2);
	
	if (scidTable)
	{
		scidTable = **(PVOID ***)scidTable;
	}
	
	return scidTable;
}

ULONG_PTR GetExpLookupHandleTableEntry()
{
	static PVOID sExpLookupHandleTableEn = NULL;
	if (sExpLookupHandleTableEn) return sExpLookupHandleTableEn;

	UNICODE_STRING unName = { 0 };
	RtlInitUnicodeString(&unName, L"ExEnumHandleTable");
	PUCHAR startFunc = MmGetSystemRoutineAddress(&unName);

	PUCHAR searchFunc = (PUCHAR)searchOtherCode(startFunc, startFunc + 0x200, "FF75*8B4D*E8****8BF085F675*EB", 6);

	if (searchFunc)
	{
		sExpLookupHandleTableEn = (searchFunc + 5) + *(PULONG)(searchFunc+1);
	}

	return sExpLookupHandleTableEn;
}


ULONG GetProcessIdOffset()
{
	
	UNICODE_STRING unName = { 0 };
	RtlInitUnicodeString(&unName, L"PsGetProcessId");
	PUCHAR startFunc = MmGetSystemRoutineAddress(&unName);

	return *(PULONG)(startFunc + 8);
}

PVOID MyExpLookupHandleTableEntry(HANDLE pid)
{
	//x64 不需要这么来定义调用堆栈 原因模拟x86 this call 所以用的fastcall来模拟,参数定义为3个
	//本质参数只有2个 
	typedef  PVOID (__fastcall *ExpLookupHandleTableEntryProc)(PVOID handleTable, ULONG xxx,HANDLE id);
	PVOID pspTable = GetPspCidTable();
	ExpLookupHandleTableEntryProc func = (ExpLookupHandleTableEntryProc)GetExpLookupHandleTableEntry();

	if (!pspTable || !func) return NULL;

	return func(pspTable,0, pid);
}

BOOLEAN ProtectProcess(HANDLE pid)
{
	PEPROCESS Process = NULL;
	NTSTATUS status = PsLookupProcessByProcessId(pid, &Process);
	if (!NT_SUCCESS(status)) return FALSE;

	ObDereferenceObject(Process);
	
	PVOID hanldeEntry = MyExpLookupHandleTableEntry(pid);
	memset(hanldeEntry, 0, 8);
	//ULONG offset = GetProcessIdOffset();
    //把进程pid = 0
	*(PHANDLE)((PUCHAR)Process + 0xb4) = 0;  

	return TRUE;
}

DriverEntry.c

#include <ntifs.h>
#include "ProcessProtect.h"

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	ProtectProcess(2612);
	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

5.3.私有句柄

全局句柄表中存储的是所有进程和线程的句柄表。每个进程还存储自己的私有句柄表

1.EPROCESS的f4位置存的就是进程的私有句柄表

PROCESS 887d8030  SessionId: 1  Cid: 0ed0    Peb: 7ffdf000  ParentCid: 0564
    DirBase: 7ea01280  ObjectTable: 8b5346d0  HandleCount: 199.
    Image: Çý¶¯¹ÜÀí.exe

kd> dt _EPROCESS 887d8030  
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x098 ProcessLock      : _EX_PUSH_LOCK
   +0x0a0 CreateTime       : _LARGE_INTEGER 0x01d88ebb`5fa1fd0b
   +0x0a8 ExitTime         : _LARGE_INTEGER 0x0
   +0x0b0 RundownProtect   : _EX_RUNDOWN_REF
   +0x0b4 UniqueProcessId  : 0x00000ed0 Void
   +0x0b8 ActiveProcessLinks : _LIST_ENTRY [ 0x83f89c88 - 0x880d0738 ]
   +0x0c0 ProcessQuotaUsage : [2] 0x35fc
   +0x0c8 ProcessQuotaPeak : [2] 0x3674
   +0x0d0 CommitCharge     : 0x5b3
   +0x0d4 QuotaBlock       : 0x87b2a240 _EPROCESS_QUOTA_BLOCK
   +0x0d8 CpuQuotaBlock    : (null) 
   +0x0dc PeakVirtualSize  : 0x7f57000
   +0x0e0 VirtualSize      : 0x7e57000
   +0x0e4 SessionProcessLinks : _LIST_ENTRY [ 0x8d2d6010 - 0x87e6b80c ]
   +0x0ec DebugPort        : (null) 
   +0x0f0 ExceptionPortData : 0x879d9968 Void
   +0x0f0 ExceptionPortValue : 0x879d9968
   +0x0f0 ExceptionPortState : 0y000
   +0x0f4 ObjectTable      : 0x8b5346d0 _HANDLE_TABLE
   +0x0f8 Token            : _EX_FAST_REF

2.查看私有句柄表结构

kd> dt 0x8b5346d0 _HANDLE_TABLE
ntdll!_HANDLE_TABLE
   +0x000 TableCode        : 0x8b536000     //最后以为位0,表示只有一张表
   +0x004 QuotaProcess     : 0x887d8030 _EPROCESS     //该私有句柄表所属的进程
   +0x008 UniqueProcessId  : 0x00000ed0 Void
   +0x00c HandleLock       : _EX_PUSH_LOCK
   +0x010 HandleTableList  : _LIST_ENTRY [ 0x83f834e8 - 0x9a3d5950 ] 
   +0x018 HandleContentionEvent : _EX_PUSH_LOCK
   +0x01c DebugInfo        : (null) 
   +0x020 ExtraInfoPages   : 0n0
   +0x024 Flags            : 0
   +0x024 StrictFIFO       : 0y0
   +0x028 FirstFreeHandle  : 0x208
   +0x02c LastFreeHandleEntry : 0x8b536ff8 _HANDLE_TABLE_ENTRY
   +0x030 HandleCount      : 0xc7
   +0x034 NextHandleNeedingPool : 0x800
   +0x038 HandleCountHighWatermark : 0xca
kd> dq 0x8b536000
8b536000  fffffffe`00000000 00000003`9792d301     //-2表示当前线程,-1表示当前进程
8b536010  00100020`880cf491 00100020`87bfc6a1
8b536020  00020019`90fba199 001f0001`87ffb379
8b536030  00000001`8b513571 00000804`87ea87d1
8b536040  021f0003`87af1fd9 000f037f`8799dcc1
8b536050  000f01ff`8799eac1 000f037f`8799dcc1
8b536060  000f003f`8be81471 001f0001`86f0dbb9
8b536070  001f0003`8799e1f9 00000804`875c45d9
kd> dt _HANDLE_TABLE_ENTRY 0x8b536000+8
ntdll!_HANDLE_TABLE_ENTRY
   +0x000 Object           : 0x9792d301 Void   //ObjectHeader结构体,实际结构体需要 +0x18
   +0x000 ObAttributes     : 0x9792d301
   +0x000 InfoTable        : 0x9792d301 _HANDLE_TABLE_ENTRY_INFO
   +0x000 Value            : 0x9792d301
   +0x004 GrantedAccess    : 3                 //访问权限
   +0x004 GrantedAccessIndex : 3
   +0x006 CreatorBackTraceIndex : 0
   +0x004 NextFreeTableEntry : 3

5.4.句柄降权

DriverMain.c

#include <ntifs.h>


#define PROCESS_VM_READ           (0x0010)  // winnt
#define PROCESS_VM_WRITE          (0x0020)  // winnt


BOOLEAN isThreadWork = TRUE;

struct _HANDLE_TABLE_ENTRY_INFO
{
	ULONG AuditMask;                                                        //0x0
};

typedef struct _HANDLE_TABLE_ENTRY
{
	union
	{
		VOID* Object;                                                       //0x0
		ULONG ObAttributes;                                                 //0x0
		struct _HANDLE_TABLE_ENTRY_INFO* InfoTable;                         //0x0
		ULONG Value;                                                        //0x0
	};
	union
	{
		ULONG GrantedAccess;                                                //0x4
		struct
		{
			USHORT GrantedAccessIndex;                                      //0x4
			USHORT CreatorBackTraceIndex;                                   //0x6
		};
		ULONG NextFreeTableEntry;                                           //0x4
	};
}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)
	{
		
		PUCHAR x = (HandleTableEntry->Value & ~7);
		ULONG_PTR object = (HandleTableEntry->Value & ~7) + 0x18; //0xfffffff8
		UCHAR tindex = *(x + 0xc);
		DbgPrintEx(77, 0, "[db]:index = %x EnumParameter=%x,object=%x\r\n", tindex, EnumParameter, object);
		if (tindex == 0x7)
		{
			
			if (object == (ULONG_PTR)EnumParameter)
			{
				HandleTableEntry->GrantedAccess &= ~(PROCESS_VM_READ | PROCESS_VM_WRITE);

			}
		}

	
	}

	return FALSE;
}

VOID ProcessHandleResetPrivilege(PEPROCESS ep)
{
	while (isThreadWork)
	{
		PEPROCESS Process = NULL;
		for (int i = 8; i < 0x1000000; i += 4)
		{
			NTSTATUS status = PsLookupProcessByProcessId((HANDLE)i, &Process);
			if (!NT_SUCCESS(status))
			{
				continue;
			}

			//if (PsGetProcessExitStatus(Process) == 0x103)
			{
				if (PsGetProcessId(Process) == 3088)   //CE进程pid
				{
					ExEnumHandleTable(*(PULONG)((PUCHAR)Process + 0xf4), enumRoutine, ep, NULL);
				}
				

				if (PsGetProcessExitStatus(Process) == 0x103) ObDereferenceObject(Process);
			}

			
		}

		LARGE_INTEGER tin = {0};
		tin.QuadPart = -10000 * 10000;
		KeDelayExecutionThread(KernelMode, FALSE, &tin);
	}
	

}

PEPROCESS FindProcessByName(PWCH name)
{

	PEPROCESS Process = NULL;
	PEPROCESS findProcess = NULL;
	for (int i = 8; i < 0x1000000; i += 4)
	{
		NTSTATUS status = PsLookupProcessByProcessId((HANDLE)i, &Process);
		if (!NT_SUCCESS(status))
		{
			continue;
		}

		PUNICODE_STRING ProcessName = NULL;
		status = SeLocateProcessImageName(Process, &ProcessName);

		if (!NT_SUCCESS(status))
		{
			ObDereferenceObject(Process);
			continue;
		}



		if (ProcessName->Length)
		{
			_wcsupr(ProcessName->Buffer);

			if (wcsstr(ProcessName->Buffer, name) != 0)
			{
				findProcess = Process;
				ExFreePoolWithTag(ProcessName, 0);
				break;
			}
		}

		ExFreePoolWithTag(ProcessName, 0);
		ObDereferenceObject(Process);
	}

	return findProcess;
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	isThreadWork = FALSE;
	LARGE_INTEGER tin = { 0 };
	tin.QuadPart = -10000 * 15000;
	KeDelayExecutionThread(KernelMode, FALSE, &tin);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	PEPROCESS Process = FindProcessByName(L"DBGVIEW.EXE");
	HANDLE hThread = NULL;
	PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, ProcessHandleResetPrivilege, Process);
	if (hThread) NtClose(hThread);

	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

5.5.句柄提权

句柄提权步骤

1.我们自己创建一个EPROCESS结构,ExAllocatePool
2.找到要打开的进程把EPROCESS复制一份到我们申请的内存里
3.把PID改了,把进程名字改成NULL
4.创建一个页,把游戏进程的CR3里面的第一层界面复制过来
5.拿到这个页的物理地址,挂到我们进程CR3上
6.修改句柄表进程对象地址

DriverMain.c

#include <ntifs.h>
#include <intrin.h>

#define PROCESS_VM_READ           (0x0010)  // winnt
#define PROCESS_VM_WRITE          (0x0020)  // winnt


BOOLEAN isThreadWork = TRUE;

struct _HANDLE_TABLE_ENTRY_INFO
{
	ULONG AuditMask;                                                        //0x0
};

typedef struct _HANDLE_TABLE_ENTRY
{
	union
	{
		VOID* Object;                                                       //0x0
		ULONG ObAttributes;                                                 //0x0
		struct _HANDLE_TABLE_ENTRY_INFO* InfoTable;                         //0x0
		ULONG Value;                                                        //0x0
	};
	union
	{
		ULONG GrantedAccess;                                                //0x4
		struct
		{
			USHORT GrantedAccessIndex;                                      //0x4
			USHORT CreatorBackTraceIndex;                                   //0x6
		};
		ULONG NextFreeTableEntry;                                           //0x4
	};
}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
);

PVOID gObject = NULL;

BOOLEAN NTAPI enumRoutine(
	IN PHANDLE_TABLE_ENTRY HandleTableEntry,
	IN HANDLE Handle,
	IN PVOID EnumParameter
)
{
	if (HandleTableEntry)
	{
		
		ULONG_PTR object = (HandleTableEntry->Value & ~7) + 0x18;
		if (object == (ULONG_PTR)EnumParameter)
		{
			
			HandleTableEntry->Value = (ULONG_PTR)gObject | 1;
			HandleTableEntry->GrantedAccess |= PROCESS_ALL_ACCESS;

		}
	}

	return FALSE;
}

PEPROCESS FindProcessByName(PWCH name)
{

	PEPROCESS Process = NULL;
	PEPROCESS findProcess = NULL;
	for (int i = 8; i < 0x1000000; i += 4)
	{
		NTSTATUS status = PsLookupProcessByProcessId((HANDLE)i, &Process);
		if (!NT_SUCCESS(status))
		{
			continue;
		}

		PUNICODE_STRING ProcessName = NULL;
		status = SeLocateProcessImageName(Process, &ProcessName);

		if (!NT_SUCCESS(status))
		{
			ObDereferenceObject(Process);
			continue;
		}



		if (ProcessName->Length)
		{
			_wcsupr(ProcessName->Buffer);

			if (wcsstr(ProcessName->Buffer, name) != 0)
			{
				findProcess = Process;
				ExFreePoolWithTag(ProcessName, 0);
				break;
			}
		}

		ExFreePoolWithTag(ProcessName, 0);
		ObDereferenceObject(Process);
	}

	return findProcess;
}


ULONG GetProcessIdOffset()
{

	UNICODE_STRING unName = { 0 };
	RtlInitUnicodeString(&unName, L"PsGetProcessId");
	PUCHAR startFunc = MmGetSystemRoutineAddress(&unName);

	return *(PULONG)(startFunc + 8);
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
	gObject = ExAllocatePool(NonPagedPool, PAGE_SIZE);
	PEPROCESS srcProcess = (PUCHAR)gObject + 0x18;
	memset(gObject, 0, PAGE_SIZE);

	//复制进程
	PEPROCESS TargetProcess = FindProcessByName(L"DBGVIEW.EXE");
	memcpy(gObject, (PUCHAR)TargetProcess - 0x18, 0x300);

	//干掉PID
	*(PHANDLE)((PUCHAR)srcProcess + GetProcessIdOffset()) = 0;

	

	ULONG cr3 = *(PULONG)((PUCHAR)TargetProcess + 0x18);

	PHYSICAL_ADDRESS cr3Phy = {0};
	cr3Phy.QuadPart = cr3;
	ULONG msize = 0x20;  // 29912分页

	if ((cr3  % 0x1000 ) == 0)
	{
		//101012分页
		msize = PAGE_SIZE;
	}

	// WIN10 1803以上,不能映射页表
	//有弊端  如果是小页。在一次映射多页时候 不一定成功,如果是大页一次映射2M 或者4M 必须是页开头,跨页就有问题
	PVOID mem = MmMapIoSpace(cr3Phy, msize, MmNonCached);

	//复制CR3	
	PVOID srcCr3 = (PVOID)ExAllocatePool(NonPagedPool, PAGE_SIZE);
	memset(srcCr3, 0, PAGE_SIZE);
	memcpy(srcCr3, mem, msize);

	//如果不替换CR3 进程退出,或者在某些API的情况会卡死,蓝屏
	PHYSICAL_ADDRESS srcphyCr3 =  MmGetPhysicalAddress(srcCr3);
	//给它一个新的CR3
	*(PULONG)((PUCHAR)srcProcess + 0x18) = srcphyCr3.LowPart;

	PEPROCESS ceProcess = NULL;
	NTSTATUS status  = PsLookupProcessByProcessId(3088, &ceProcess);   //ce进程PID
	if (NT_SUCCESS(status))
	{
		ExEnumHandleTable(*(PULONG)((PUCHAR)ceProcess + 0xf4), enumRoutine, TargetProcess, NULL);
	}

	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

 

posted on 2022-09-18 22:45  zhang_derek  阅读(189)  评论(0编辑  收藏  举报

导航