-1

我正在尝试获取位于 dll 中特定地址的函数。

我试过查看 dll 的反汇编,但没有调试符号。

auto lib = LoadLibrary("lib.dll");
auto proc = GetProcAddress(lib, "proc1"); // Getting the address of the function.

如何在不为 dll 中的每个函数调用 GetProcAddress 的情况下从 proc(地址)中获取“proc1”(函数名)?似乎没有用于此目的的功能。有没有其他方法可以获取函数名?

4

2 回答 2

2

首先,我们需要找到包含指定内存地址的映像的基地址。这可以通过RtlPcToFileHeader函数来​​完成。

然后我们需要通过说ImageDirectoryEntryToDataDbghelp.dll或通过RtlImageDirectoryEntryToDatantdll.dll获取它的导出目录并枚举所有导出函数。先看名字。如果没有此类地址的名称 - 查找序号。

void FromAddress(LPCVOID Address)
{
    PVOID BaseOfImage = RtlPcToFileHeader(Address, &BaseOfImage);

    if (!BaseOfImage)
    {
        return;
    }

    ULONG Size;
    PIMAGE_EXPORT_DIRECTORY pied = (PIMAGE_EXPORT_DIRECTORY)
    RtlImageDirectoryEntryToData(BaseOfImage, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &Size);

    ULONG NumberOfFunctions, NumberOfNames;

    if (!pied || !(NumberOfFunctions = pied->NumberOfFunctions))
    {
        return;
    }

    NumberOfNames = pied->NumberOfNames;

    PULONG AddressOfFunctions = (PULONG)RtlOffsetToPointer(BaseOfImage, pied->AddressOfFunctions);
    PULONG AddressOfNames = (PULONG)RtlOffsetToPointer(BaseOfImage, pied->AddressOfNames); 
    PUSHORT AddressOfNameOrdinals = (PUSHORT)RtlOffsetToPointer(BaseOfImage, pied->AddressOfNameOrdinals);

    bool bFound = false;

    if (NumberOfNames)
    {
        do 
        {
            ULONG rva = *AddressOfNames++;

            if (RtlOffsetToPointer(BaseOfImage, AddressOfFunctions[*AddressOfNameOrdinals++]) == Address)
            {
                DbgPrint("%s\n", RtlOffsetToPointer(BaseOfImage, rva));
                bFound = true;
            }
        } while (--NumberOfNames);
    }

    if (!bFound)
    {
        DWORD Base = pied->Base;

        do 
        {
            if (Address == RtlOffsetToPointer(BaseOfImage, *AddressOfFunctions++))
            {
                DbgPrint("#%u\n", Base);
            }
        } while (Base++, --NumberOfFunctions);
    }
}
于 2019-04-19T00:59:42.500 回答
1

如果您想查看 DLL 中的函数列表,可以使用工具。 http://www.dependencywalker.com/

但我不确定为什么你需要在运行时这样做。大多数情况下,您需要从 DLL 中使用的函数您已经知道名称和参数,并且已经准备好与之交互的标头。

但是如果你真的需要做相反的过程检查那个开源项目,你可能会在源代码中找到你需要的东西。它在 C# 中,但可能会给您一些提示。 https://github.com/lucasg/Dependencies

于 2019-04-19T00:50:17.147 回答