1
votes

I'm trying to find the RVA for loadlibrary in kernel32.dll. I've read a couple documents on parsing PE Headers but I can't seem to find out why my pointer to the export directory seems invalid.

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;

Here I open the file, everything seems fine, when I run through here wit the debugger.

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

Here I successfully access the DataDirectory to get the VirtualAddress and Size of the Export Directory.

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;
}

I go through all the sections till I get a section header that encloses the exportsStartRVA. Now "section" pointer to the Section Header for the export directory.

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

Here I get a pointer to the Export Directory.

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: Problem lies within my dereferencing I think, the funcName doesn't actually give me anything other than a Memory Access Error.

1
For what it's worth, your logic looks okay to me at first glance. Have you tried dereferencing any of the pointers within the export directory to see if that gets you to anywhere that looks valid? - 500 - Internal Server Error
I added a section of code above. funcName is always "Memory Read Error at Address". I guess there may be a problem with my dereferencing. I just assumed that the exportDir was wrong because WinDBG gives me "Memory Access Errors" - Informat
Yeah, the pointer to the ExportDir works, it just doesn't update from Memory Access Error till I actually read from it my bad. So the problem lies within my dereferencing. I'll update this. - Informat

1 Answers

1
votes

AddressOfNames is a RVA to a list of RVAs to string names not a RVA to a list of strings.