好的,我正在编写一个旨在枚举给定进程中的线程的应用程序,就像Process Explorer一样。我很清楚,这可能会在不同的Windows版本之间中断,因为它依赖于“非官方”API,如NtQuerySystemInformation
,我完全可以使用它。
我已经有了获取给定线程基址的代码。我现在想把它变成类似于进程资源管理器的东西,即“ntdll.dll!EtwDeliverDataBlock + 0x453”。我实际上并不需要函数名称或偏移量,只需要模块名称。
我该怎么做?
答案 0 :(得分:4)
如果您只需要模块名称,最简单的方法是使用EnumProcessModules获取所有已加载模块的列表,然后在每个模块上使用GetModuleInformation。 GetModuleInformation
返回的内容之一是加载该模块的基址。从技术上讲,HMODULE
本身的整数值与基地址相同,但这对我来说似乎有点脆弱......
然后,只需在线程的当前(或开始)地址下方找到具有基址的模块即可。
哦,为了得到模块的实际名称,有GetModuleBaseName。
答案 1 :(得分:1)
您可以使用GetModuleHandleEx和GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
标志来获取给定地址的模块的句柄。然后,您可以使用GetModuleBaseName获取模块的名称。
编辑:您可能也想使用GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
标志,因此不会增加模块的引用次数。
答案 2 :(得分:0)
您可以使用该代码获取模块句柄(比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;
}