好的,我正在编写一个应用程序,旨在枚举给定进程中的线程,就像Process Explorer一样。我很清楚这可能会因为依赖于“非正式”API(如NtQuerySystemInformation
)而在不同的Windows版本之间出现问题,但我完全可以接受。
我已经有了获取给定线程基地址的代码。我现在想把它变成像进程资源管理器那样的东西,也就是“ntdll.dll!EtwDeliverDataBlock+0x453”。我实际上并不需要函数名称或偏移量,只需要模块名称。
我该怎么做?
好的,我正在编写一个应用程序,旨在枚举给定进程中的线程,就像Process Explorer一样。我很清楚这可能会因为依赖于“非正式”API(如NtQuerySystemInformation
)而在不同的Windows版本之间出现问题,但我完全可以接受。
我已经有了获取给定线程基地址的代码。我现在想把它变成像进程资源管理器那样的东西,也就是“ntdll.dll!EtwDeliverDataBlock+0x453”。我实际上并不需要函数名称或偏移量,只需要模块名称。
我该怎么做?
GetModuleInformation
返回的其中一项是该模块加载的基地址。从技术上讲,HMODULE
本身的整数值与基地址相同,但我觉得这似乎有点脆弱...
然后,只需找到基地址略低于线程当前(或起始)地址的模块即可。
哦,要获取模块的实际名称,可以使用GetModuleBaseName。
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
标识来获取给定地址的模块句柄。之后,您可以使用 GetModuleBaseName 函数获取模块名称。
编辑: 您可能还需要使用 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
标识,以避免增加模块的引用计数。UNCHANGED_REFCOUNT
标志也是无关紧要的... - wj32您可以使用该代码获取模块句柄(它比GetModuleHandleEx更快),然后调用GetModuleBaseName。
HMODULE GetCallingModule( LPCVOID pCaller ) const
{
HMODULE hModule = NULL;
MEMORY_BASIC_INFORMATION mbi;
if ( VirtualQuery(pCaller, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION) )
{
// the allocation base is the beginning of a PE file
hModule = (HMODULE) mbi.AllocationBase;
}
return hModule;
}
VirtualQueryEx
。不过,通过查找您自己进程中静态变量的MEMORY_BASIC_INFORMATION::AllocationBase
来获取HINSTANCE hInstance
是一个很棒的技巧。但是,只有在避免样板CRT代码等情况下才需要这样做... - 0xC0000022L
SystemModuleInformation
调用NtQuerySystemInformation来解决这个问题 - 我会回复你我想到的方案。 - Billy ONeal