Exported DLL functions not ordered lexically?

▼魔方 西西 提交于 2019-12-10 16:16:34

问题


Well, today I ran into an oddity. I wrote my own version of GetProcAddress a while ago to get function addresses from remote processes. I obviously spent quite a lot of time reading up on the PE architecture to figure out the best way to approach this.

From the PECOFF v8 specification (which, as I take it is the most up-to-date official specification), there is the following notation about the Export Name Pointer Table:

The export name pointer table is an array of addresses (RVAs) into the export name table. The pointers are 32 bits each and are relative to the image base. The pointers are ordered lexically to allow binary searches.

So I took this into account when writing my version of GetProcAddress. Obviously there would be a nice efficiency improvement in walking the export table in say...KERNEL32.dll (1300+ exported functions) using a binary search over a linear search.

This worked for a while until today when I ran into a weird issue. It appears that some of the exported functions in Kernel32 aren't actually ordered lexically and this was throwing off my binary search. The following is an excerpt from a Exported Dll dump using the function I'll post below:

Ordinal: 810    Name: K32QueryWorkingSetEx
Ordinal: 811    Name: LCIDToLocaleName
Ordinal: 812    Name: LCMapStringA
Ordinal: 813    Name: LCMapStringEx
Ordinal: 814    Name: LCMapStringW
Ordinal: 815    Name: LZClose
Ordinal: 816    Name: LZCloseFile
Ordinal: 817    Name: LZCopy
Ordinal: 818    Name: LZCreateFileW
Ordinal: 819    Name: LZDone
Ordinal: 820    Name: LZInit
Ordinal: 821    Name: LZOpenFileA
Ordinal: 822    Name: LZOpenFileW
Ordinal: 823    Name: LZRead
Ordinal: 824    Name: LZSeek
Ordinal: 825    Name: LZStart
Ordinal: 826    Name: LeaveCriticalSection
Ordinal: 827    Name: LeaveCriticalSectionWhenCallbackReturns
Ordinal: 828    Name: LoadAppInitDlls
Ordinal: 829    Name: LoadLibraryA
Ordinal: 830    Name: LoadLibraryExA

Anyone spot the issue here? Despite the documentation claiming that the export table is ordered lexically, LZRead is listed before LeaveCriticalSection.

I've always taken lexical ordering to be synonymous with alphabetical ordering when dealing with strings, am I wrong here or is there some weird issue with Kernel32's export table?

Function used to dump exports:

void DumpExports(PBYTE pBase)
{
    freopen("B:\\PeDump.txt", "wb", stdout);
    IMAGE_DOS_HEADER *pDosHd = (IMAGE_DOS_HEADER*)pBase;
    IMAGE_NT_HEADERS *pNtHd = (IMAGE_NT_HEADERS*)(pBase + pDosHd->e_lfanew);
    IMAGE_DATA_DIRECTORY expDir = pNtHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    if (expDir.Size)
    {
        IMAGE_EXPORT_DIRECTORY *pExpDir = (IMAGE_EXPORT_DIRECTORY*)(pBase + expDir.VirtualAddress);
        WORD *pOrds = (WORD*)(pBase + pExpDir->AddressOfNameOrdinals);
        DWORD *pNames = (DWORD*)(pBase + pExpDir->AddressOfNames);

        for(unsigned long i = 0; i < pExpDir->NumberOfNames; i++, pOrds++, pNames++)
            printf("Ordinal: %d\tName: %s\n", *pOrds, (char*)(pBase + *pNames));
    }
    else
    {
        printf("No functions are exported from this image.\n");
    }
    fflush(stdout);
    freopen("CON", "w", stdout);
}

EDIT: I'm an idiot. Of course 'Z' is before 'o', It's 3am and my brain isn't functioning. Very sorry.

EDIT EDIT: Okay, I'm not totally insane. Half of the problem was that apparently C#'s string.CompareTo extension doesn't compare lexically.

For example

"LoadLibraryW".CompareTo("LZRead");

Returns "-1". This was the source of my confusion.


回答1:


LZRead is lexicographically before LeaveCriticalSection using ascii. Don't use case insensitivity and it looks like it will work.


An interesting observation about the documentation.

The pointers are 32 bits each ... are ordered lexically to allow binary searches.

It is hard to understand why one would do a binary search for a pointer (rather than a symbol name) but that is what is says.




回答2:


The character ordinals for upper case come before the ordinals for lower case.



来源:https://stackoverflow.com/questions/11107095/exported-dll-functions-not-ordered-lexically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!