PIMAGE_EXPORT_DIRECTORY-内存访问错误

PIMAGE_EXPORT_DIRECTORY - Memory Access Error

本文关键字:访问 错误 内存 DIRECTORY- EXPORT PIMAGE      更新时间:2023-10-16

我正在kernel32.dll中查找加载库的RVA。我已经阅读了一些关于解析PE标头的文档,但似乎找不到为什么我指向导出目录的指针无效。

hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        err = GetLastError();
        return err;
    }
    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if (hFileMapping == 0)
    {
        err = GetLastError();
        CloseHandle(fileName);
        return err;
    }
    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if (lpFileBase == 0)
    {
        err = GetLastError();
        CloseHandle(fileName);
        CloseHandle(hFileMapping);
        return err;
    }
    dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
    pNTHeader = (PIMAGE_NT_HEADERS)((BYTE*)dosHeader + dosHeader->e_lfanew);
    base = (DWORD64)dosHeader;

在这里我打开文件,当我用调试器运行这里时,一切似乎都很好。

    exportsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    exportsEndRVA = exportsStartRVA + pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;

在这里,我成功地访问了DataDirectory以获取导出目录的VirtualAddress和Size。

PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
unsigned i;
for (i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++)
{
    // Is the RVA within this section?
    if ((exportsStartRVA >= section->VirtualAddress) &&
        (exportsStartRVA < (section->VirtualAddress + section->Misc.VirtualSize)))
        break;
}

我浏览了所有的节,直到得到一个包含exportsStartRVA的节头。现在"section"指针指向导出目录的section Header。

exportDir = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)base + exportsStartRVA + section->PointerToRawData - section->VirtualAddress);

在这里我得到一个指向导出目录的指针。

PDWORD pfunctions = (PDWORD)((PBYTE)base + (DWORD64)exportDir->AddressOfFunctions + header->PointerToRawData - header->VirtualAddress);
PDWORD ordinals = (PDWORD)((PBYTE)base + (DWORD64)exportDir->AddressOfNameOrdinals + header->PointerToRawData - header->VirtualAddress);
PSTR* name = (PSTR*)((PBYTE)base + (DWORD64)exportDir->AddressOfNames + header->PointerToRawData - header->VirtualAddress);
PSTR funcName;
for (unsigned i = 0; i < (DWORD64)exportDir->NumberOfNames; i++)
{
    funcName = name[i];
}

edit:问题在于我的取消引用。我认为,funcName实际上除了内存访问错误之外,没有给我任何其他信息。

AddressOfNames是字符串名称的RVA列表,而不是字符串列表的RVA。