如何使用导出函数交叉编译 DLL

How to cross-compile DLL with exported functions

我正在完成 DLL 劫持练习,并且编写了一个 DLL,在 Visual Studio 中编译时按预期工作。本质上,当加载 DLL 时,它会执行 shell 命令并传递合法功能(在本例中,CheckEvenOddPrintAMessage 函数)到最初的 DLL(在本例中,GetEvenOdd.dll)。工作代码如下;

#include "stdafx.h"
#include <windows.h>

#pragma comment(linker, "/export:CheckEvenOdd=GetEvenOdd.dll.original.CheckEvenOdd")
#pragma comment(linker, "/export:PrintAMessage=GetEvenOdd.dll.original.PrintAMessage")

extern "C" __declspec(dllexport)
DWORD WINAPI ExecuteCmd(LPVOID lpParam) {
    WinExec("c:\Users\Public\execute.bat", 0);
    return 0;
}

extern "C" __declspec(dllexport)
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, NULL, ExecuteCmd, NULL, NULL, NULL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

虽然它在 Visual Studio (Windows) 中编译时按预期工作,但我想在 Linux 中生成 DLL(用于 Windows 程序).在 Linux 内,我可以交叉编译 CPP 文件 (injector.cpp),并使用这些命令创建 DLL;

i686-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL injector.cpp
i686-w64-mingw32-g++ -shared -o GetEvenOdd.dll injector.o -Wl,--out-implib,injector.a

这将成功创建 DLL。但是,当我的 "victim application"(Windows 上的 运行)加载 DLL 时,尽管执行了 "ExecuteCmd" 函数,但导出的函数(来自 "pragma comment"线)不可用。即,加载此 DLL 的程序试图找到导出的函数,但无法找到(即执行 DLL 导入应用程序的以下 if 分支)。

FNPTR fn = (FNPTR)GetProcAddress(hInst, "CheckEvenOdd");
if (!fn)
{
    std::cout << "\nCould not locate the function CheckEvenOdd";
    std::cout << "\n\nPress Enter to Continue...";
    getch();
    return EXIT_FAILURE;
} 

这告诉我,当我在 Linux 中生成 DLL 时,"pragma comment" 行没有按预期工作。

从一些阅读中我了解到这些 "pragma commands" 是特定于编译器的。有没有我可以给 "i686-w64-mingw32-g++" 的标志(或者我可以做的一些代码更改),以便在 Linux 中编译 DLL 时导出的函数可用?

编译指示特定于每个编译器,您的编译指示可以在 Visual C++ 中运行,但不能在 MingW 中运行。相反,您可以使用 Visual C++ 和 MinGW 支持的 .def 文件。

在您的案例中,injector.def 可能是这样的:

EXPORTS
    CheckEvenOdd = GetEvenOdd.dll.original.CheckEvenOdd
    PrintAMessage = GetEvenOdd.dll.original.PrintAMessage

编译命令:

$ i686-w64-mingw32-g++ -o GetEvenOdd.dll --shared injector.cpp injector.def