与DLL Get Symbols From Its Parent (Loader)相关但不等同于
是否有一种方法可以说服Windows加载程序从加载的可执行文件或中间dll中解析A.dll引用的特定符号,而无需指定文件来解析A.dll中的符号?
如果正在加载的.exe具有已知名称,但如果没有已知名称,该怎么办呢?
这是您实际上想要执行此操作的充分理由:https://www.gnu.org/software/libc/manual/html_node/Replacing-malloc.html
如果可以做到这一点,一个很好的答案就是说如何以某种方式做到这一点。
我半信半疑,答案是做不到。在这种情况下,一个好的答案将表明为什么这是不可能的。 “构建工具不支持此功能。”是一个错误的答案。
答案 0 :(得分:2)
当我们使用import时,我们需要准确指出模块名称和函数名称。而且我们不能使用复杂的算法。同样对于 exe 来说,它不存在众所周知的别名,我们可以在确切的位置使用exe名称。进行比较:如果获取GetModuleHandle
,我们可以使用NULL
获取用于创建调用进程的文件(.exe文件)的句柄。但是如果LoadLibraryExW
不能使用0或空字符串(L""
)或其他别名来表示-我们需要处理 exe 。当加载程序加载我们的模块时-他从IMAGE_IMPORT_DESCRIPTOR
中读取dll名称,并尝试通过LoadLibraryExW
的低级,私有,核心尝试找到或加载具有该名称的模块。这里需要确切的名字。或加载失败。结果使用import-如果我们在构建时不知道exe名称,则这里不是解决方案
可能的变体-在运行时自行解析函数指针。在这里我们可以通过HMODULE
获取exe GetModuleHandle(0)
。如果需要,我们不仅可以在 exe 中搜索功能,还可以在其他地方搜索功能。可以实现任何搜索算法。
这里存在几种方式。对于具体示例,我们需要获取带有签名的函数的指针:
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);
在这种情况下, CL 自己生成名称为__imp_ ## __FUNCDNAME__
的函数的指针。因此,实际上,当我们自己声明指针时,与第一个变体相同。语法和符号名称的唯一区别。看起来像__imp_?fn2@@YAXH@Z
。这里的问题是__imp_?fn2@@YAXH@Z
不是 c / c ++ 的有效名称-我们无法从 c / c ++ 直接为其赋值。即使我们用extern "C"
声明函数-函数名称将包含@
和__stdcall
函数的__fastcall
符号(对于 c ++ 而言是非法的),对于 x86 。对于不同的平台( x86 , x64 等),名称也将有所不同。访问此类名称-需要或使用外部 asm 文件(名称中有效的asm ?
和@
符号)或使用/alternatename
链接器选项-设置别名这样的名称和访问符号。说
__pragma(comment(linker, "/alternatename:__imp_?fn@@YAXH@Z=__imp_fn"))
并通过
初始化*(void**)&__imp_fn = GetProcAddress(GetModuleHandle(0), "fn");
另一种选择是在函数声明中使用__declspec(dllimport)
+添加导入库,其中定义了所有__imp___FUNCDNAME__
(例如__imp_?fn2@@YAXH@Z
)。 (即使我们没有这样的库,我们也可以轻松地自己创建它-所需的所有内容-使用空实现纠正函数声明)。在将这样的导入库添加到链接器输入中之后,添加/DELAYLOAD:dllname
,其中dllname
-从导入库中准确命名。认为此dllname
将(<)可能与 exe 不匹配-所需要的-它必须是唯一的。并且我们需要自己处理延迟负载(在我们首次调用fn
时调用)。对于工具延迟负载,我们需要implement
extern "C" FARPROC WINAPI __delayLoadHelper2(
PCImgDelayDescr pidd,
FARPROC * ppfnIATEntry
);
我们可以自己实现它,或将delayimp.lib
添加到我们的项目中。 delayimp.lib
(在delayLoadHelper2
中)并已实现。但是,我们必须自定义此过程(默认实现(在/include/DelayHlp.cpp
中查看)将与LoadLibraryExA
一起使用dllname
和__pfnDliNotifyHook2
,在我们的情况下不排除这种情况,否则我们可以直接使用import) 。因此我们需要强制实施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);
使用<i>
获取 exe 的基础。
此处的“ unique_exe_alias”(链接程序从导入库中获取)扮演的角色不是真正的 exe 名称(未知),而是exe的唯一标记(别名)