代码之家  ›  专栏  ›  技术社区  ›  Joshua

让dll从其调用的.exe导入符号

  •  0
  • Joshua  · 技术社区  · 6 年前

    有关但不等同于 DLL Get Symbols From Its Parent (Loader)

    如果加载的.exe有一个已知的名称,那么很明显该怎么做,但是如果没有。。。

    下面是一个很好的理由让你这么做: https://www.gnu.org/software/libc/manual/html_node/Replacing-malloc.html

    我有一半的期望答案是这是做不到的。在这种情况下,一个好的答案将说明为什么这是不可能的。”构建工具不支持这个。

    1 回复  |  直到 6 年前
        1
  •  2
  •   RbMm    6 年前

    当我们使用import时,我们需要准确地指示模块名和函数名。我们不能使用复杂的算法。也适用于 执行 GetModuleHandle 我们可以用 NULL 用于获取用于创建调用进程的文件的句柄(.exe文件)。但万一 LoadLibraryExW 不能使用0或空字符串( L"" 执行 . 当加载程序加载我们的模块时,他从 IMAGE_IMPORT_DESCRIPTOR 并尝试先通过低级别、私有、核心找到或加载具有此名称的模块 加载库EXW . 这里需要确切的名字。或负载故障。因此,如果我们在构建时不知道exe名称,请使用导入-这里不是解决方案

    可能的变量-在运行时自己解析函数指针。在这里我们可以得到exe HMODULE GetModuleHandle(0) . 如果需要的话我们不仅可以在搜索功能 执行 但在别的地方。可以实现任何搜索算法。

    void WINAPI fn(int i);
    

    我们可以声明指向这个函数的指针并在运行时解析它

    void (WINAPI *fn)(int);
    
    *(void**)&fn = GetProcAddress(GetModuleHandleW(0), "fn");
    

    说上 DLL_PROCESS_ATTACH

    一个稍微不同的解决方案(尽管在二进制级别上它是完全等效的)声明函数 __declspec(dllimport) 属性。这是给你的 CL.EXE (更被称为 MSVC公司 )仅编译器。所以

    __declspec(dllimport) void fn(int i);
    

    在这种情况下 __FUNCDNAME__ 姓名。所以事实上和第一个变量一样,当我们自己声明指针时。只是语法和。。符号名称。它看起来像 __imp_?fn2@@YAXH@Z 不是的有效名称 信用证++ -我们不能直接给它赋值 . 即使我们用 extern "C" @ 符号(非法用于 )为了 __stdcall __fastcall 功能,用于 . 不同平台的名称也不同( x86个 , 等)。对于访问这些名称-需要或使用外部 asm公司 文件(用于asm) ? 符号(名称有效)或使用 /alternatename 链接器选项-用于为此类名称和访问符号设置别名。说喜欢

    __pragma(comment(linker, "/alternatename:__imp_?fn@@YAXH@Z=__imp_fn"))
    

    初始化通过

    *(void**)&__imp_fn = GetProcAddress(GetModuleHandle(0), "fn");
    

    另一种选择使用 __declspec(dllimport) __imp___FUNCDNAME__ (如 __进口?fn2@@YAXH@Z )已定义(即使我们没有这样的库,我们也可以自己轻松地创建它(所有需要的都是空实现的正确函数声明)。在我们将这样的import lib添加到链接器input-add之后 /DELAYLOAD:dllname dllname -导入库中的确切名称。感觉到这个 执行 fn ). 对于我们需要的负载 implement

    extern "C" FARPROC WINAPI __delayLoadHelper2(   
       PCImgDelayDescr pidd,  
       FARPROC * ppfnIATEntry  
    ); 
    

    delayimp.lib delayimp.lib delayLoadHelper2 并付诸实施。但是,我们必须自定义这个过程(默认实现(look in /include/DelayHlp.cpp LoadLibraryExA 具有 __pfnDliNotifyHook2 :

    例如:

    FARPROC WINAPI MyDliHook(
                                 unsigned        dliNotify,
                                 PDelayLoadInfo  pdli
                                 )
    {
        switch (dliNotify)
        {
        case dliNotePreLoadLibrary:
            if (!strcmp(pdli->szDll, "unique_exe_alias"))
            {
                return (FARPROC)GetModuleHandle(0);
            }
        }
    
        return 0;
    }
    
    const PfnDliHook  __pfnDliNotifyHook2 = MyDliHook;
    

    dliNotePreLoadLibrary 通知,而不是默认值 LoadLibraryEx(dli.szDll, NULL, 0); 使用 GetModuleHandle(0); 执行 . 执行 名称,未知,但exe的唯一标记(别名)