繁体   English   中英

MFC 应用程序和共享库

[英]MFC app and shared libs

我有一个似乎是用 MFC 编写的应用程序(进程黑客和 DependencyWalker 显示指向 MFC90 的链接)。

另外,安装路径中有一个库(FTD2XX)。 但是 DependencyWalker 不会显示库的 MFC90 链接并显示:

SetupAPI.dll
KERNEL32.dll
USER32.dll
ADVAPI32.dll

lib是在什么框架中构建的? 我没有 MFC 的经验。 我的编译器中没有信息,以及是否可以使用 VC++ 库与 MFC 应用程序链接。

如果要记录对 dll 的调用,最好的方法是编写代理 dll(dll 重定向)。 但是为此,您必须知道要覆盖的函数的签名(语法) ,即参数的确切数量、它们的类型和返回类型等。如果我可以假设您可以以某种方式找出所有函数的签名ftd2xx.dll,那么完成它就很简单了。

获取 dll 函数和序数:为此只需使用 Visual Studio 附带的 dumpbin.exe(通过运行 Visual Studio 命令提示符使用它)

dumpbin.exe /exports {你的路径}\\ftd2xx.dll > ftd2xx.txt

现在您的 ftd2xx.txt 包含 ftd2xx.dll 的所有函数名称和序号。 您甚至可以使用您的依赖项walker 导出并获取此列表。

创建名为 ftd2xx.dll 的 dll:打开 Visual Studio,选择 VC++ >> Win32 >> Win32 Project >> Dll(带导出符号选项),最后使用 #pragma 指令在 dll 代码中声明所有导出的原始 dll 函数,例如以下,

//#pragma comment (linker, "/export:<function>=<origdll_name>.<function>,@<ordinal_number>")

#pragma comment (linker, "/export:FT_Open=ftd2xx_.FT_Open,@1")
#pragma comment (linker, "/export:FT_Close=ftd2xx_.FT_Close,@2")
// :
// :
// :
// delcare all your exported functions here with ordinal number
// :
// :
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
}

现在,您需要编写自己的函数,该函数可以伪装成 ftd2xx.dll 的原始函数,当应用程序调用 ftd2xx.dll 的原始函数时会调用该函数。 下面的代码只是为了解释它是如何工作的。 正如我之前所说,您需要知道要覆盖(重定向)的 dll 函数的确切签名。 还要记住,无论你想做什么,你都需要调用原始函数,否则你的应用程序最终可能会出现意外行为。

假设 FT_Close() 函数不接受参数并返回 void,我只是将其作为示例,其中我使用代理 NewFT_Close() 函数覆盖 ftd2xx.dll 的 FT_Close() 函数。 请注意,如果您覆盖一个函数,则从 #pragma 指令中删除它并将其添加到 .def 文件中(将新的 ftd2xx.def 文件添加到您的项目并声明您的新函数,如下所示)。

DEF 文件示例

LIBRARY ftd2xx.dll
EXPORTS
FT_Close = NewFT_Close @2

dll代码示例

HINSTANCE   hInstance = NULL;        // handle to ftd2xx.dll
FARPROC     fpFTClose = {NULL};      // function pointer to hold original function address

extern "C" void __stdcall NewFT_Close()
{
    // This is our proxy function for FT_Close()
    // Do whatever you want to do here and the 
    // finally call the original FT_Close() using 
    // the function pointer we got from GetProcAddress()
    typedef void (__stdcall *PFTCLOSE)();
    PFTCLOSE pFc = (PFTCLOSE)fpFTClose;
    if(pFc) pFc();
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            // Load the original dll in to the memory and get the handle
            hInstance = LoadLibraryA("ftd2xx_.dll");
            if(!hInstance) return FALSE;
            // Get the address of the function to be overriden
            fpFTClose = GetProcAddress(hInstance,"FT_Close");
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            // Our dll is getting unloaded from the application, unload original as well
            FreeLibrary(hInstance);
            break;
    }
    return TRUE;
}

请注意,原始 dll 在 LoadLibraryA() 调用中称为 ftd2xx_.dll。 因此,将原始 dll 重命名为 ftd2xx_.dll 或随意命名。 构建您的代理 dll 代码并将您的代理 dll (ftd2xx.dll) 带到原始 ftd2xx.dll 所在的路径。 现在,您的应用程序将像往常一样调用 ftd2xx.dll(代理),但 ftd2xx.dll 将在内部调用原始 dll ftd2xx_.dll。

更新 #1:我一直提到你需要知道你试图覆盖的函数的签名,幸运的是我刚刚在 linux 版本的驱动程序中找到了 ftd2xx.h 文件。

ftd2xx 的 Linux 版本

从上面的链接下载 libftd2xx-i386-1.3.6.tgz 文件并将其解压缩到一个文件夹(我使用 7zip),进一步解压缩 .tar 文件以获取发布文件夹,您将在“释放”文件夹。 好了,现在您获得了 dll 的完整函数签名,并且您知道如何编写代理 dll。 祝你好运。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM