如何使用导出函数交叉编译 DLL
How to cross-compile DLL with exported functions
我正在完成 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 文件 (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
我正在完成 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 文件 (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