我正在用 C++ 编写并做一个练习来熟悉 DLL 和共享对象 (.so)。如何在不导出内部结构的情况下访问内部结构?GetProcAddress在调用未导出的函数时返回 null。我编写了 DLL,所以我知道所有的函数和变量名称。
如何从外部访问内部 DLL 函数或数据?
如果您知道 DLL 中函数的地址,您可以通过函数指针以“C”语言调用。让我们举个例子:
假设您有一个函数驻留在名为“notExportedFunc”的 DLL 中,并带有签名
int notExportedFunc(int a, int b);
您可以在以下主程序中调用它:
typedef int notExportedFunc(int a, int b);
int main() {
HANDLE h = LoadLibrary(L"mydll.dll"); //Image base address, might change on every call
if (h == 0)
{
printf("Cannot load mydll.dll\n");
return -1;
}
int funcOffset = 0x11560; //from the linker map
int funcAddress = (int)h + funcOffset;
notExportedFunc* f = (notExportedFunc*)(funcAddress);
int result = f(3, 4);
printf("Result = %d\n", result);
}
在链接器映射中,相关条目如下所示:
0000:00000000 ___ImageBase 10000000 <===链接器建议
0001:00000000 __enc$textbss$begin 10001000此处不相关
0001:00010000 __enc$textbss$end 10011000此处不相关
0002:00000560 ?notExportedFunc@@YAHHH@Z 10011560 f dllmain.obj
ImageBase 地址由“LoadLibrary("mydll.dll")”调用返回。您应该知道,由于 ASLR(地址空间布局随机化),此地址通常在每次调用 LoadLibrary 时都会更改。因此,notExportedFunc 的地址不能直接从链接器映射中获取,而必须进行计算。在我们的示例中,偏移量为 0x11560,必须将其添加到 LoadLibrary 返回的地址中。
程序的其余部分通常是通过函数指针调用“C”函数。
有可能进一步自动化,但该示例希望展示在 DLL 中调用私有函数的一般机制。
在GetProcAddr
Windows API的用于为检索地址导出功能。它将始终返回null
未导出的函数,因为它无法在 PE 文件中找到它。
导出函数使其可用于其他可执行文件。如果不导出函数驻留在可执行文件中的位置的数据,则不可用(这并不完全正确,因为符号可能仍会显示该信息,但它们不会被 使用GetProcAddr
)。
如果您仍然希望找到指向非导出函数的函数指针,则需要遵循导出的引用链。例如,如果func1
使用func2
和func1
被导出,你可以得到的地址func1
,然后拆解func1
,直到找到调用func2
内它。识别正确的调用可能有点棘手,但这绝对是可行的。