隐式库链接和GetModuleHandle / GetProcAdress

时间:2016-10-09 08:47:27

标签: windows winapi dll symbols loadlibrary

我们试图了解在运行时定位符号的一些更精细的细节。我已经审核了Jeffrey Richter的Programming Applications for Microsoft Windows,第19章( DLL Basics )和20( DLL Advanced )。 Richter比MSDN更全面,更有凝聚力。

我们正在尝试将隐式库链接与动态符号位置相结合。由于某些潜在的安全隐患,我们希望避免拨打LoadLibrary。我们还试图避免加载器锁定问题如果用户在DllMain函数中徘徊太多。

#include <windows.h>
#pragma comment(lib, "kernel32")

extern "C" {
  typedef BOOL (WINAPI * PFN_GOR)(HANDLE, LPOVERLAPPED, LPDWORD, BOOL);
  typedef BOOL (WINAPI * PFN_GORX)(HANDLE, LPOVERLAPPED, LPDWORD, DWORD, BOOL);
}
int main(int argc, char* argv[])
{
    HINSTANCE hInst = GetModuleHandle("kernel32");
    PFN_GOR pfn1 = hInst ? (PFN_GOR)GetProcAddress(hInst, "GetOverlappedResult") : NULL;
    PFN_GORX pfn2 = hInst ? (PFN_GORX)GetProcAddress(hInst, "GetOverlappedResultEx") : NULL;

    std::cout << "kernel32: " << std::hex << (void*)hInst << std::endl;
    std::cout << "GetOverlappedResult: " << std::hex << (void*)pfn1 << std::endl;
    std::cout << "GetOverlappedResultEx: " << std::hex << (void*)pfn2 << std::endl;

    return 0;
}

我们很幸运GetOverlappedResultGetOverlappedResultEx,因为无论平台如何,kernel32.dll都提供了这两者。 kernel32.dll有另一个不错的属性,因为每个Windows应用程序都链接到它,并且无法将其删除。

平台上的随机数似乎有点麻烦。在Windows 7及更低版本中,我们CryptGenRandom来自advapi32.dll; Windows 10及更高版本使用BCryptGenRandom中的bcrypt.dll。 Windows 8是一个灰色区域,因为某些版本(如Windows Phone 8)不提供任何功能。我们相信我们可以根据WINVER_WINNT_VER保留对图书馆的加入。

我觉得隐式库链接的模式与GetModuleHandleGetProcAdress相结合是不寻常的,但它符合我们的要求。它不寻常,因为它使用隐式链接和GetModuleHandle而不是LoadLibrary。我也找不到禁止隐式链接的文本和GetModuleHandle

它符合我们的要求,因为由于二进制种植和其他DLL重定向技巧,我们不负责不安全的库加载。我们还会通过在DLLmain中做太多来避免因意外误用而致DoS。

我的问题是,代码是合法的组合还是模式。如果它是一个有缺陷的模式,那么缺陷是什么?

我们使用Visual Studio 2015通过Windows 10 / Phone 10 / Store 10支持Windows XP和Visual Studio .Net。

在Windows XP上,代码产生以下结果:

>cl.exe /TP /EHsc test.cxx /Fetest.exe
...
>.\test.exe
kernel32: 7D4C0000
GetOverlappedResult: 7D52E12C
GetOverlappedResultEx: 00000000

在Windows 7上,代码产生以下结果:

>cl.exe /TP /EHsc test.cxx /Fetest.exe
...
>.\test.exe
kernel32: 772A0000
GetOverlappedResult: 772CCC69
GetOverlappedResultEx: 00000000

在Windows 8上,代码产生以下结果(Windows 10类似):

>cl.exe /TP /EHsc test.cxx /Fetest.exe
...
>.\test.exe
kernel32: 74FD0000
GetOverlappedResult: 74FEF8C0
GetOverlappedResultEx: 7675C4D0

在Windows 8和10上,我们只能测试交叉编译并与ARM Developer Prompt链接。我们使用以下附加CXXFLAGS测试桌面,电话和商店的编译:

  • 要测试桌面应用,请添加以下CXXFLAGS
    • /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
  • 要测试Windows应用商店应用,请添加以下CXXFLAGS
    • /DWINAPI_FAMILY=WINAPI_FAMILY_APP
  • 要测试Windows Phone,请添加以下CXXFLAGS
    • /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
  • 要测试Surface RT(ARM平板电脑),请添加以下CXXFLAGS
    • /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP

我发现很多点击次数如Implicit vs. Explicit linking to a DLL,但我找不到能够检查LoadLibrary可以施加的一些安全问题,以及如何避免{{}} {{}} 1}}完全。

1 个答案:

答案 0 :(得分:3)

这里不多说。将GetProcAddress与通过调用GetModuleHandle获得的模块句柄一起使用是完全合法的。

更新:我是根据问题的原始形式写的,但没有说清楚这个问题是为了涵盖移动平台还是桌面。