最近看一些关于内核方面的资料,碰到未公开函数,未能在微软官方找到答案,从网上了解到一些信息,摘录下来备用。
我看到驱动程序在ring0调用的一段代码的使用:
ULONG GetModuleBase(PCHAR szModuleName)
{
ULONG uSize = 0x10000;
PVOID pModuleInfo = ExAllocatePoolWithTag(NonPagedPool,
uSize,
'GetB');
if (pModuleInfo == NULL)
{
KdPrint(("ExAllocatePoolWithTag failed\n"));
return 0;
}
RtlZeroMemory(pModuleInfo, uSize);
NTSTATUS status = ZwQuerySystemInformation(SystemModuleInformation,
pModuleInfo,
uSize,
NULL);
if(!NT_SUCCESS(status))
{
KdPrint(("FindModuleByAddress query failed\n"));
KdPrint(("FindModuleByAddress status: 0x%x\n", status));
if (pModuleInfo != NULL)
{
ExFreePool(pModuleInfo);
pModuleInfo = NULL;
}
return 0;
}
ULONG uNumberOfModules = *(PULONG)pModuleInfo;
if (uNumberOfModules == 0)
{
return 0;
}
PRTL_PROCESS_MODULE_INFORMATION pStart =
(PRTL_PROCESS_MODULE_INFORMATION)((ULONG)pModuleInfo + sizeof(ULONG));
for (ULONG uCount = 0; uCount < uNumberOfModules; uCount++)
{
PUCHAR pszFullPathName = (PUCHAR)pStart->FullPathName;
ULONG uOffsetName = pStart->OffsetToFileName;
PUCHAR pszName = (PUCHAR)(pszFullPathName + uOffsetName);
if (_stricmp((const char *)pszName, szModuleName) == 0)
{
ULONG uImageBase = (ULONG)pStart->ImageBase;
if (pModuleInfo != NULL)
{
ExFreePool(pModuleInfo);
pModuleInfo = NULL;
}
return uImageBase;
}
pStart++;
}
if (pModuleInfo != NULL)
{
ExFreePool(pModuleInfo);
pModuleInfo = NULL;
}
return 0;
}
上面代码GetModuleBase功能是获取指定名字的模块的内存中的基址。
其中ZwQuerySystemInformation函数微软官方链接:ZwQuerySystemInformation并未能提供足够的信息,SystemModuleInformation并没有在官方链接中找到描述的使用方法。我想官方不可能会漏掉这个使用,故意不公开一定是有原因的,传统上的原因是这块内容很可能在后面的版本改变不公开给用户使用。我不管是什么原因,能弄清楚这块内容,就是我的目标。
函数原型:
NTSTATUS WINAPI ZwQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Inout_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength );
在网上找到一段利用在ring3中利用ZwQuerySystemInformation来获取进程模块信息的代码,稍加修改,就可以正常编译运行,功能类似于ddk提供的drivers.exe的功能