根据PECOFF v8规范(我认为它是最新的官方规范),有Export Name Pointer Table
的以下符号:
导出名称指针表是一个地址数组(RVAs) 导出名称表。指针各32位,相对于 形象基础。指针是词法排序的,以允许二进制 搜索。
所以我在编写GetProcAddress版本时考虑到了这一点。显然,通过线性搜索使用二进制搜索,在导出表格中可以有很好的效率提升... KERNEL32.dll(1300多个导出函数)。
直到今天,我遇到了一个奇怪的问题。看起来Kernel32中的一些导出函数实际上并没有在词汇上排序,这就是我的二进制搜索。以下是使用我在下面发布的函数导出的Dll转储的摘录:
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
有人在这里发现了这个问题吗?尽管文档声称导出表是按词汇顺序排序的,但LZRead在LeaveCriticalSection之前列出。
在处理字符串时,我一直采用词法排序作为字母排序的同义词,我在这里是错的还是Kernel32的导出表有一些奇怪的问题?
用于转储导出的函数:
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);
}
编辑:我是个白痴。当然&#39; Z&#39;在凌晨3点之前,凌晨3点,我的大脑无法正常运转。很抱歉。
编辑编辑:好的,我并非完全疯了。问题的一半是显然是C#的字符串。比较扩展并不能用词汇进行比较。
例如
"LoadLibraryW".CompareTo("LZRead");
返回&#34; -1&#34;。这是我混乱的根源。
答案 0 :(得分:5)
LZRead
在使用ascii LeaveCriticalSection
之前按字典顺序排列。不要使用不区分大小写,看起来它会起作用。
关于文档的有趣观察。
指针各为32位......以词汇方式排序以允许二进制搜索。
很难理解为什么人们会对指针进行二进制搜索(而不是符号名称),但这就是所说的。
答案 1 :(得分:3)
大写的字符序号出现在小写的序号之前。