如何从外部访问内部 DLL 函数或数据?

逆向工程 C++ dll
2021-06-16 21:02:03

我正在用 C++ 编写并做一个练习来熟悉 DLL 和共享对象 (.so)。如何在不导出内部结构的情况下访问内部结构?GetProcAddress在调用未导出的函数时返回 null。我编写了 DLL,所以我知道所有的函数和变量名称。

2个回答

如果您知道 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 中调用私有函数的一般机制。

GetProcAddrWindows API的用于为检索地址导出功能。它将始终返回null未导出的函数,因为它无法在 PE 文件中找到它。

导出函数使其可用于其他可执行文件。如果不导出函数驻留在可执行文件中的位置的数据,则不可用(这并不完全正确,因为符号可能仍会显示该信息,但它们不会被 使用GetProcAddr)。

如果您仍然希望找到指向非导出函数的函数指针,则需要遵循导出的引用链。例如,如果func1使用func2func1 导出,你可以得到的地址func1,然后拆解func1,直到找到调用func2内它。识别正确的调用可能有点棘手,但这绝对是可行的。