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

C++ 如何使用导出函数交叉编译DLL,c++,linux,mingw,cross-compiling,mingw32,C++,Linux,Mingw,Cross Compiling,Mingw32,我正在进行一个DLL劫持练习,并编写了一个DLL,在VisualStudio中编译时可以正常工作。实际上,加载DLL时,它会执行一个shell命令,并将合法功能(在本例中为checkenOdd和PrintAMessage函数)传递给最初想要的DLL(在本例中为GetEvenOdd.DLL)。工作代码如下: #include "stdafx.h" #include <windows.h> #pragma comment(linker, "/export:CheckEvenOdd=Ge

我正在进行一个DLL劫持练习,并编写了一个DLL,在VisualStudio中编译时可以正常工作。实际上,加载DLL时,它会执行一个shell命令,并将合法功能(在本例中为checkenOdd和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;
}
这将成功创建DLL。但是,当DLL由我的“受害者应用程序”(在Windows上运行)加载时,尽管执行了“ExecuteCmd”函数,但导出的函数(从“pragma comment”行)不可用。也就是说,加载此DLL的程序尝试查找导出的函数,但无法找到(即,如果执行DLL导入应用程序的以下分支,则无法找到)

FNPTR fn=(FNPTR)GetProcAddress(hInst,“CheckEvenOdd”);
如果(!fn)
{

STD::CUT> P>语法是每个编译器特有的,你的语法将在Visual C++中工作,而不是在明文中。你可以使用VisualC++和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

对否决票有何评论?我不理解你的问题…你如何在linux上使用WIN32函数???我只想在linux上编译DLL。我计划在Windows上使用它。交叉编译DLL(第一个代码块)与显示的命令,可以工作(DLL被创建,我可以在另一个程序中导入),但“链接”函数(pragma)行似乎不可用(也就是说,在使用新编译的DLL的程序中,CheckEvenOdd和PrintAMessage函数不可用)。请注意,当我编译相同的DLL(相同的代码)时,这些函数可用使用Visual Studio。我认为使用GCC进行编译只需提供
-fPIC
编译器选项……感谢您的回复。这种方法很有效(我的客户端程序显然能够获得指向dll函数的指针)但是现在,当函数实际被调用时,我得到了某种内存转储。--有什么想法吗?右边的代码是驱动程序代码(checkevenodd函数就是被调用的函数)问题是,使用mingw编译的dll使用的标准库与实际调用该dll的应用程序不同。因此,dll和应用程序具有不同的字符串实现,这会导致应用程序错误地解释返回的数据。关于跨dll边界传递数据的许多问答也是如此最有效的修复方法是将
checkenOdd
更改为使用基元类型,这样就可以不返回字符串,而是返回字符数组或指向字符的指针。问题是,作为DLL劫持的一部分,我通常不会控制该DLL(任何函数)也不是客户端应用程序。我所控制的,就是我在linux中编译的这个中间驱动程序(我问题的第一个代码块中所示的那个),有什么我可以在那里更改以获得预期的行为吗?没有简单的解决方案。大多数DLL API将使用、和类型。如果它们不是这两种类型,则需要使用兼容的标准库(即使用VC++),或对类型的语义进行反向工程,这将非常困难。不将自身限制为某些类型的代码在不同的库之间根本不兼容。的情况就是这样。请注意,只要使用VC++编译GetEvenOdd.dll.original,GetEvenOdd.dll就可以使用MinGW进行编译,因为在这种情况下,应用程序ion从原始dll获取兼容字符串。只有在使用MinGW编译原始dll时,才会出现问题,因为MinGW的字符串与VC++的字符串不兼容。
EXPORTS
    CheckEvenOdd = GetEvenOdd.dll.original.CheckEvenOdd
    PrintAMessage = GetEvenOdd.dll.original.PrintAMessage
$ i686-w64-mingw32-g++ -o GetEvenOdd.dll --shared injector.cpp injector.def