//功能:根据目录对象来获取内核模块列表
//参数:
// 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);
}
}
}