1

dliNotePreLoadLibrary在我自己的延迟加载钩子中使用它来验证要在实际加载之前加载的 DLL 的代码签名。为了避免它执行任何代码,我通过LoadLibraryExA(...,...,LOAD_LIBRARY_AS_DATAFILE)(钩子只提供ANSI名称,所以没关系)加载它并在验证后卸载它,以便它可以作为带有代码的DLL加载。

单步调试调试器中的代码,我可以看到我收到了一个句柄,并且该句柄<baseaddress>+1与“数据模块”的预期一致。但是,一旦我尝试将此句柄传递到GetModuleFileName库函数内部(这也是我不能传递名称的原因,只能传递模块句柄),函数返回0并且 GetLastError 给了我ERROR_MOD_NOT_FOUND. 但是,该模块已加载,因此肯定找到了。此外,这是在当前进程中,因此访问“目标进程”在这里没有问题。

所以我想为什么不使用VirtualQuery检索MEMORY_BASIC_INFORMATION::BaseAddress我刚刚加载的 DLL 的实际基地址 ( )(以防万一<baseaddress>+1出现问题),但结果保持不变ERROR_MOD_NOT_FOUND

我没主意了。有谁知道这里发生了什么?

测试平台:Windows 7 SP1,x64(最新补丁)

这是以下代码:

FARPROC WINAPI MyDliHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
    switch(dliNotify)
    {
    case dliNotePreLoadLibrary:
        if(0 == lstrcmpiA(pdli->szDll, "DLLNAME.dll"))
        {
            HMODULE hVerifiedDll = LoadLibraryExA(pdli->szDll, NULL, LOAD_LIBRARY_AS_DATAFILE);
            if(hVerifiedDll)
            {
                MEMORY_BASIC_INFORMATION mbi;
                if(0 != VirtualQuery(hVerifiedDll, &mbi, sizeof(mbi)));
                {
                    VerifyModuleSignature((HMODULE)mbi.BaseAddress, pdli->szDll);
                }
                FreeLibrary(hVerifiedDll);
            }
        }
        break;
    default:
        break;
    }
    return NULL;
}
PfnDliHook __pfnDliNotifyHook2 = MyDliHook;

该函数VerifyModuleSignature首先调用GetModuleFileName以检索文件名,但在该步骤失败。我验证了.exe创建过程的代码签名验证工作正常。

旁注:我已经验证了ERROR_MOD_NOT_FOUND错误来自GetModuleFileName而不是,例如,来自之前对LoadLibraryExA. 为了确保SetLastError(ERROR_SUCCESS)在调用GetModuleFileName.

4

1 回答 1

3

MSDN中所述,当使用 LOAD_LIBRARY_AS_DATAFILE 时,您无法使用 GetModuleHandle 检索模块:

如果使用此值,系统会将文件映射到调用进程的虚拟地址空间,就好像它是一个数据文件一样。没有做任何事情来执行或准备执行映射的文件。因此,您不能使用此 DLL 调用 GetModuleFileName、GetModuleHandle 或 GetProcAddress 等函数。

编辑:实际上 Hans Passant 比这个答案更接近原因。虽然这个答案重申了 MS 所说的,但它没有给出理由。然而,原因是它GetModuleFileName基本上遍历了LDR_MODULE列表PEB,并且仅在您“加载代码”时填充了详细信息。

于 2012-08-21T06:56:37.627 回答