如何判断Windows模块句柄是否仍然有效?

hfwmuf9z  于 2023-06-07  发布在  Windows
关注(0)|答案(3)|浏览(269)

一个模块可以被卸载,那么我如何确定它是否还在内存中?我有一个句柄,从GetModuleHandle获得。当我尝试调用GetHandleInformation时,我看到错误0xc 0000008-“指定了一个无效的HANDLE”。

67up9zun

67up9zun1#

术语“句柄”在这里有点多了--Win32 API中的许多不同类的对象都被称为“句柄”。
GetHandleInformation用于内核对象的句柄-文件、注册表项、互斥锁等。
GetModuleHandle返回的HMODULE由加载程序使用,并且不是实际的内核对象,因此GetHandleInformation失败。不过,GetHandleInformation中的两个标志对HMODULE都没有意义。
如果你想检查HMODULE是否仍然加载在内存中,你可以调用GetModuleHandle --这个API应该足够快,可以调用很多次。然而,GetModuleHandle的结果在返回时可能是无效的--另一个线程可能已经调用了FreeLibrary。最好确保DLL保持加载状态。您可以通过自己调用LoadLibrary或调用GetModuleHandleEx来实现此操作,后者将递增DLL的引用计数。

xqnpmsa8

xqnpmsa82#

两种解决方案:

1

在HMODULE上调用GetModuleFileName()。如果加载了模块,您将获得一个有效的文件名。如果它没有被加载,你将不会得到一个有效的文件名。请确保在调用GetModuleFileName()之前将返回的文件名数组的第一个字节设置为“\0”,或者检查返回值。如果在调用前设置第一个字节,则可以有效地忽略返回值,并将零长度字符串视为“未加载”信号。

TCHAR szModName[MAX_PATH + 1];

szModName[0] = _T('\0');
GetModuleFileName(hMod, szModName, MAX_PATH);

// zero length string if not loaded, valid DLL name if still loaded

2

调用VirtualQuery(),传递HMODULE作为查询地址。作为一个实验,在一个已加载的库和一个您知道要释放的库上执行此操作。您会发现它们对于返回的MEMORY_BASIC_INFORMATION有非常不同的结果。我把它留给你来制定一个合适的算法来确定两者之间的差异。

注意事项

当然,在您运行这些测试的同时,另一个线程可能会卸载库的警告也适用。根据我的经验,这是极不可能发生的,但这在很大程度上取决于你在做什么,为什么要这样做,以及当你这样做时,程序的执行路径。小心使用。

t8e9dugd

t8e9dugd3#

这是一个非常简单的API。

PIMAGE_NT_HEADERS (NTAPI* _RtlImageNtHeader)

示例程序:

(PVOID)typedef PIMAGE_NT_HEADERS (NTAPI *RTLIMAGENTHEADER)(PVOID);
RTLIMAGENTHEADER RtlImageNtHeader;
HMODULE hDll = GetModuleHandle("ntdll.dll");
HMODULE hDllTmp = LoadLibrary("ws2_32.dll");
RtlImageNtHeader = (RTLIMAGENTHEADER)GetProcAddress(hDll,"RtlImageNtHeader");

struct _IMAGE_NT_HEADERS *r,*r2;
r= RtlImageNtHeader(hDllTmp); 
FreeLibrary(hDllTmp);
r2= RtlImageNtHeader(hDllTmp);

//r = NULL
//r2 = return ws2_32 PE Header address

相关问题