根据我和其他人的经验(http://webster.cs.ucr.edu/Page_TechDocs/pe.txt),PE / COFF规范文档错误地声明了序号中包含的导出地址表索引表是相对于序数基数,甚至给出了一个不正确的例子(第5.3节)。实际上,Ordinal Table中的索引是基于0的索引到正常情况下的Ordinal Base = 1的地址表中。我在VS Studio生成的PE库和系统库(如Kernel32.dll)中看到了这一点。
我的问题是,你有没有观察过一个不等于1的Ordinal Base的二进制文件?我想知道这是一个off-by-one错误,还是Ordinal Base从未应用于Ordinal Table条目。
答案 0 :(得分:4)
这是mfc42.dll版本6.06.8064.0的转储。
Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file mfc42.dll
File Type: DLL
Section contains the following exports for MFC42.dll
00000000 characteristics
4D79A4A3 time date stamp Fri Mar 11 05:27:15 2011
0.00 version
5 ordinal base
6939 number of functions
6 number of names
ordinal hint RVA name
5 0 0000ED7C ?classCCachedDataPathProperty@CCachedDataPathProperty@@2UCRuntimeClass@@B
6 1 0000ED44 ?classCDataPathProperty@CDataPathProperty@@2UCRuntimeClass@@B
7 2 000DEEAC DllCanUnloadNow
8 3 000DEE6C DllGetClassObject
9 4 000DED0A DllRegisterServer
10 5 000DEEDE DllUnregisterServer
256 0004F84F [NONAME]
[...]
6943 0003B412 [NONAME]
以下是它在二进制文件中的显示方式:
;
; Export directory for MFC42.dll
;
dd 0 ; Characteristics
dd 4D79A4A3h ; TimeDateStamp: Fri Mar 11 05:27:15 2011
dw 0 ; MajorVersion
dw 0 ; MinorVersion
dd rva aMfc42_dll ; Name
dd 5 ; Base
dd 1B1Bh ; NumberOfFunctions
dd 6 ; NumberOfNames
dd rva functbl ; AddressOfFunctions
dd rva nametbl ; AddressOfNames
dd rva nameordtbl ; AddressOfNameOrdinals
;
; Export Address Table for MFC42.dll
;
functbl dd rva ?classCCachedDataPathProperty@CCachedDataPathProperty@@2UCRuntimeClass@@B; 0
dd rva ?classCDataPathProperty@CDataPathProperty@@2UCRuntimeClass@@B; 1
dd rva DllCanUnloadNow ; 2
dd rva DllGetClassObject; 3
dd rva DllRegisterServer; 4
dd rva DllUnregisterServer; 5
dd 0F5h dup(rva __ImageBase); 6
dd rva ??0_AFX_CHECKLIST_STATE@@QAE@XZ; 251
[...]
;
; Export Names Table for MFC42.dll
;
nametbl dd rva a?classccachedd, rva a?classcdatapat, rva aDllcanunloadno
dd rva aDllgetclassobj, rva aDllregisterser, rva aDllunregisters
;
; Export Ordinals Table for MFC42.dll
;
nameordtbl dw 0, 1, 2, 3, 4, 5
所以是的,似乎你是对的,序数表中的索引是 0-based 。
答案 1 :(得分:3)
这不是一个一个一个错误,Ordinal Base不会应用于Ordinal Table条目,而是应用于序数本身的计算。是的,Microsoft PE规范(http://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx,第5.3.4节)是错误的。这就是计算的方式:
i = Search_ExportNamePointerTable(ExportName);
ordinal = ExportOrdinalTable[i] + OrdinalBase; // The "+ OrdinalBase" is missing in the official PE specification
SymbolRVA = ExportAddressTable[ordinal - OrdinalBase];
或者,以不同的方式表达:
i = Search_ExportNamePointerTable(ExportName);
offset = ExportOrdinalTable[i];
SymbolRVA = ExportAddressTable[offset];
ordinal = OrdinalBase + offset;
如果我转储我的mfc42.dll ...
dumpbin mfc42.dll /exports |more
......这就是我得到的:
Microsoft (R) COFF/PE Dumper Version 12.00.20827.3
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file mfc42.dll
File Type: DLL
Section contains the following exports for MFC42.dll
00000000 characteristics
4D798B26 time date stamp Fri Mar 11 03:38:30 2011
0.00 version
5 ordinal base
6888 number of functions
8 number of names
ordinal hint RVA name
1452 0 000EF5D8 ?AfxFreeLibrary@@YAHPEAUHINSTANCE__@@@Z
1494 1 000EF5A4 ?AfxLoadLibrary@@YAPEAUHINSTANCE__@@PEBD@Z
1497 2 000F8344 ?AfxLockGlobals@@YAXH@Z
1587 3 000F83DC ?AfxUnlockGlobals@@YAXH@Z
7 4 000FC83C DllCanUnloadNow
8 5 000FC7E0 DllGetClassObject
9 6 000FC870 DllRegisterServer
10 7 000FC87C DllUnregisterServer
5 0001C910 [NONAME]
6 0001C8E8 [NONAME]
256 0005DEC0 [NONAME]
257 000423C0 [NONAME]
258 00042400 [NONAME]
259 00042440 [NONAME]
[...]
上面的第7个函数(例如)是DllRegisterServer,它对应于mfc42.dll下面的十六进制转储中的导出序号表中的第7个字(0x0004)。开头是A7 05
。
59 CC 12 00 6B CC 12 00 A7 05 D1 05 D4 05 2E 06
02 00 03 00 04 00 05 00 4D 46 43 34 32 2E 64 6C
计算:
i = Search_ExportNamePointerTable("DllRegisterServer") = 7 - 1 = 6 // zero-based
offset = ExportOrdinalTable[6] = 4
SymbolRVA = ExportAddressTable[4] = ...
ordinal = OrdinalBase + offset = 5 + 4 = 9
答案 2 :(得分:1)
否,PE导出目录表的OrdinalBase字段不被忽略!
上面提供的示例(mfc42.dll)很好(因为它的Ordinal Base不是1)。
这里有两个关于这个问题的评论:
。就序数字段而言,转储工具的输出是正确的。它显示Base字段为5.这意味着,当按名称从mfc42.dll导入导出的函数时,导出地址表中的计算偏移量将为x-5。 Microsoft规范第5.3节是正确的。
。就提示而言,转储工具的输出不正确。导出表具有NO提示字段,仅导入表具有提示字段。
事实上,在检索地址表的索引时,Ordinal Base不应用于Ordinal Table BUT!