首页
社区
课程
招聘
[分享]目录树枚举内核模块
发表于: 2018-8-29 17:08 4833

[分享]目录树枚举内核模块

2018-8-29 17:08
4833
//功能:根据目录对象来获取内核模块列表
//参数:
//		pArray 非递归遍历目录对象数的目录对象存放指针,0位置已经存放了要检测\\目录对象地址
//		uArrayMaxCount pArray里最大许可容纳对象数量
//		pBuf 存放结果地址
//		nBufLen 存放结果长度(单位字节)
//返回:无
VOID list_kernel_module_use_DirectoryObject(POBJECT_DIRECTORY_ *pArray, LONG uArrayMaxCount, PVOID pBuf, ULONG nBufLen)
{
	POBJECT_TYPE _IoDriverObjectType;
	POBJECT_TYPE _IoDeviceObjectType;
	pMmIsAddressValid nMmIsAddressValid;

	ULONG nArrayForIndex;
	ULONG nN1Index;
	ULONG nN2Index;

	POBJECT_DIRECTORY_ objectDirectory;
	LONG nArrayIndex;

	POBJECT_HEADER_ objectHeader;
	PWIN7_OBJECT_HEADER_ pWin7objectHeader;
	PVOID pObjectDirectoryType;		//目录对象的Type
	ULONG nIndex;
	POBJECT_DIRECTORY_ENTRY_ pObjectDirectoryEntry;
	PVOID pSubObject;
	POBJECT_HEADER_ pSubObjectHeader;
	PWIN7_OBJECT_HEADER_ pWin7SubObjectHeader;

	BOOLEAN bGotoTarget;

	PDEVICE_OBJECT deviceObject;
	PDRIVER_OBJECT driverObject;

	PKernelModuleInformation pModules;
	PKernelModuleItem pItem;
	ULONG nSize;

	_IoDriverObjectType = (POBJECT_TYPE)get_init_array_one_value(IO_DRIVER_OBJECT_TYPE_ADD);
	_IoDeviceObjectType = (POBJECT_TYPE)get_init_array_one_value(IO_DEVICE_OBJECT_TYPE_ADD);
	nMmIsAddressValid = (pMmIsAddressValid)get_init_array_one_value(MM_IS_ADDRESS_VALID_ADD);

	if(NULL != _IoDeviceObjectType && NULL != _IoDriverObjectType && NULL != nMmIsAddressValid && uArrayMaxCount > 1)
	{
		for(objectDirectory = pArray[0], nArrayIndex = -1, nArrayForIndex = 0; NULL != objectDirectory && TRUE == TheARK_MmIsAddressValid(objectDirectory, TRUE) && nArrayForIndex < 0x100000; nArrayForIndex++) //设置是-1表示当前pArray没有一项
		{
			pModules = (PKernelModuleInformation)pBuf;

			nSize = sizeof(KernelModuleInformation) + sizeof(KernelModuleItem) * pModules->nModuleCount;

			objectHeader = (POBJECT_HEADER_)((PCHAR)objectDirectory - sizeof(OBJECT_HEADER_));
			pWin7objectHeader = (PWIN7_OBJECT_HEADER_)((PCHAR)objectDirectory - sizeof(WIN7_OBJECT_HEADER_));
			if(*NtBuildNumber <= 6002)
			{
				pObjectDirectoryType = objectHeader->Type;
			}
			else
			{
				pObjectDirectoryType = (PVOID)(ULONG)pWin7objectHeader->TypeIndex;
			}

			/*
			2k xp 2k3 vista 2k8
			lkd> dt _OBJECT_DIRECTORY
			nt!_OBJECT_DIRECTORY
			+0x000 HashBuckets      : [37] Ptr32 _OBJECT_DIRECTORY_ENTRY
			+0x094 Lock             : _EX_PUSH_LOCK
			+0x098 DeviceMap        : Ptr32 _DEVICE_MAP
			+0x09c SessionId        : Uint4B
			+0x0a0 Reserved         : Uint2B
			+0x0a2 SymbolicLinkUsageCount : Uint2B

			win7:
			nt!_OBJECT_DIRECTORY
			+0x000 HashBuckets      : [37] Ptr32 _OBJECT_DIRECTORY_ENTRY
			+0x094 Lock             : _EX_PUSH_LOCK
			+0x098 DeviceMap        : Ptr32 _DEVICE_MAP
			+0x09c SessionId        : Uint4B
			+0x0a0 NamespaceEntry   : Ptr32 Void
			+0x0a4 Flags            : Uint4B
			*/

			for(nIndex = 0; nIndex < 37 && nSize < nBufLen; nIndex++)
			{
				pObjectDirectoryEntry = objectDirectory->HashBuckets[nIndex];

				for(nN1Index = 0; NULL != pObjectDirectoryEntry && nSize < nBufLen && nN1Index < 0x10000; pObjectDirectoryEntry = pObjectDirectoryEntry->ChainLink, nN1Index++)
				{
					pItem = &pModules->item[pModules->nModuleCount];

					pSubObject = pObjectDirectoryEntry->Object;
					pSubObjectHeader = (POBJECT_HEADER_)((PCHAR)pSubObject - sizeof(OBJECT_HEADER_));
					pWin7SubObjectHeader = (PWIN7_OBJECT_HEADER_)((PCHAR)pSubObject - sizeof(WIN7_OBJECT_HEADER_));

					//开始判定是不是子OBJECT_DIRECTORY
					bGotoTarget = FALSE;
					if(*NtBuildNumber <= 6002)
					{
						if(pObjectDirectoryType == pSubObjectHeader->Type) bGotoTarget = TRUE;
					}
					else
					{
						if(pObjectDirectoryType == (PVOID)(ULONG)pWin7SubObjectHeader->TypeIndex) bGotoTarget = TRUE;
					}

					if(TRUE == bGotoTarget)
					{
						//list_kernel_module_use_DirectoryObject((POBJECT_DIRECTORY_)pSubObject, pBuf, nBufLen); //原来的递归算法
						if(nArrayIndex < uArrayMaxCount - 1)
						{
							nArrayIndex++;
							pArray[nArrayIndex] = (POBJECT_DIRECTORY_)pSubObject;
						}
					}
					else
					{
						//判定是是不是DEVICE_OBJECT
						bGotoTarget = FALSE;
						if(*NtBuildNumber <= 6002)
						{
							if((PVOID)*(POBJECT_TYPE*)_IoDeviceObjectType == pSubObjectHeader->Type) bGotoTarget = TRUE;
						}
						else
						{
							if((UCHAR)get_init_array_one_value(WIN7_WIN8_DEVICE_TYPE_INDEX) == pWin7SubObjectHeader->TypeIndex && 0 != pWin7SubObjectHeader->TypeIndex) bGotoTarget = TRUE;
						}

						deviceObject = NULL;
						if(TRUE == bGotoTarget)
						{
							deviceObject = (PDEVICE_OBJECT)pSubObject;
						}
						else
						{
							//判定是是不是DRIVER_OBJECT
							bGotoTarget = FALSE;
							if(*NtBuildNumber <= 6002)
							{
								if((PVOID)*(POBJECT_TYPE*)_IoDriverObjectType == pSubObjectHeader->Type) bGotoTarget = TRUE;
							}
							else
							{
								if((UCHAR)get_init_array_one_value(WIN7_WIN8_DRIVER_TYPE_INDEX) == pWin7SubObjectHeader->TypeIndex && 0 != pWin7SubObjectHeader->TypeIndex) bGotoTarget = TRUE;
							}

							if(TRUE == bGotoTarget)
							{
								driverObject = (PDRIVER_OBJECT)pSubObject;

								//试图插入对象的信息
								if(TRUE == try_to_insert_driverObject_to_kernel_module_list(driverObject, TRUE, pBuf, nBufLen, pItem))
								{
									nSize += sizeof(KernelModuleItem);
									pItem++;

									pModules->nModuleCount++;
								}

								deviceObject = driverObject->DeviceObject;
							}
						}

						//扫描设备栈
						for(nN2Index = 0; NULL != deviceObject && TRUE == nMmIsAddressValid(deviceObject) && nSize < nBufLen && nN2Index < 0x10000; deviceObject = deviceObject->AttachedDevice, nN2Index++)
						{
							driverObject = deviceObject->DriverObject;

							if(TRUE == try_to_insert_driverObject_to_kernel_module_list(driverObject, TRUE, pBuf, nBufLen, pItem))
							{
								nSize += sizeof(KernelModuleItem);
								pItem++;

								pModules->nModuleCount++;
							}
						}
					}

					nSize = sizeof(KernelModuleInformation) + sizeof(KernelModuleItem) * pModules->nModuleCount;
				}

				nSize = sizeof(KernelModuleInformation) + sizeof(KernelModuleItem) * pModules->nModuleCount;
			}

			//取下一个目录对象节点
			if(nArrayIndex >= 0) //不是负数就说明还有目录对象节点
			{
				objectDirectory = pArray[nArrayIndex];
				nArrayIndex--;
			}
			else
			{
				break;
			}
			if(!(nSize < nBufLen)) break;	//无足够空间来容纳检测结果了
		}
	}
}


//功能:根据目录对象树来获取内核模块列表
//参数:
//		pBuf 存放结果地址
//		nBufLen 存放结果长度(单位字节)
//返回:无
VOID list_kernel_module_use_OpenDirectoryObject(PVOID pBuf, ULONG nBufLen)
{
	NTSTATUS ntStatus;

	pRtlInitUnicodeString nRtlInitUnicodeString;
	pZwOpenDirectoryObject nZwOpenDirectoryObject;
	pObReferenceObjectByHandle nObReferenceObjectByHandle;
	pObfDereferenceObject nObfDereferenceObject;
	pZwClose nZwClose;

	ULONG nRoot;
	UNICODE_STRING unicodeRoot;
	OBJECT_ATTRIBUTES objectAttributes;
	HANDLE hRoot;
	POBJECT_DIRECTORY_ objectDirectory;

	POBJECT_DIRECTORY_ *pArray;

	/*
	lkd> dt _OBJECT_DIRECTORY
		nt!_OBJECT_DIRECTORY
		+0x000 HashBuckets      : [37] Ptr32 _OBJECT_DIRECTORY_ENTRY
		+0x094 Lock             : _EX_PUSH_LOCK
		+0x098 DeviceMap        : Ptr32 _DEVICE_MAP
		+0x09c SessionId        : Uint4B
		+0x0a0 Reserved         : Uint2B
		+0x0a2 SymbolicLinkUsageCount : Uint2B
	*/

	nRtlInitUnicodeString = (pRtlInitUnicodeString)get_init_array_one_value(RTL_INIT_UNICODE_STRING_ADD);
	nZwOpenDirectoryObject = (pZwOpenDirectoryObject)get_init_array_one_value(ZW_OPEN_DIRECTORY_OBJECT_ADD);
	nObReferenceObjectByHandle = (pObReferenceObjectByHandle)get_init_array_one_value(OB_REFERENCE_OBJECT_BY_HANDLE_ADD);
	nObfDereferenceObject = (pObfDereferenceObject)get_init_array_one_value(OBF_DEREFERENCE_OBJECT_ADD);
	nZwClose = (pZwClose)get_init_array_one_value(ZW_CLOSE_ADD);

	if(NULL != nRtlInitUnicodeString && NULL != nZwOpenDirectoryObject && NULL != nObReferenceObjectByHandle && \
		NULL != nObfDereferenceObject && NULL != nZwClose)
	{
		nRoot = 0x0000005c;		//L"\\"
		nRtlInitUnicodeString(&unicodeRoot, (PWCHAR)&nRoot);
		InitializeObjectAttributes(&objectAttributes, &unicodeRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
		
		ntStatus = nZwOpenDirectoryObject(&hRoot, DIRECTORY_QUERY, &objectAttributes);	//打开对象目录
		if(NT_SUCCESS(ntStatus))
		{
			ntStatus = nObReferenceObjectByHandle(hRoot, DIRECTORY_ALL_ACCESS, NULL, KernelMode, (PVOID)&objectDirectory, NULL);
			if(NT_SUCCESS(ntStatus))
			{
				pArray = (POBJECT_DIRECTORY_ *)TheARK_ExAllocatePoolWithTag(PagedPool, UNRE_MAX_DIRECTORY_OBJECT_COUNT * sizeof(PVOID));
				if(NULL != pArray)
				{
					pArray[0] = objectDirectory;
					__try
					{
						list_kernel_module_use_DirectoryObject(pArray, UNRE_MAX_DIRECTORY_OBJECT_COUNT, pBuf, nBufLen);
					}
					__except(EXCEPTION_EXECUTE_HANDLER)
					{
					}

					TheARK_ExFreePoolWithTag(pArray);
				}
				
				nObfDereferenceObject(objectDirectory);
			}
			
			nZwClose(hRoot);
		}
	}
}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 12848
活跃值: (9147)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
2
记得加锁
2018-8-29 18:37
0
雪    币: 182
活跃值: (43)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢分享
2018-8-29 21:18
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
感谢分享!
2019-7-29 23:08
0
游客
登录 | 注册 方可回帖
返回
//