In my experience and that of others (http://webster.cs.ucr.edu/Page_TechDocs/pe.txt), the PE/COFF specification document incorrectly claims that the Export Address Table indices that are contained in the Ordinal Table are relative to the Ordinal Base, and even gives an incorrect example (Section 5.3). In actuality, the indices in the Ordinal Table are 0-based indices into the Address Table for the normal case in which Ordinal Base = 1. I have seen this in VS Studio generated PE libraries and in system libraries like Kernel32.dll.
My question is, have you ever observed a binary with an Ordinal Base that was not equal to 1? I want to know if this an off-by-one error, or if the Ordinal Base is never applied to Ordinal Table entries.
Here's a dump for mfc42.dll, version 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]
Here's how it looks in the binary:
;
; 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
So yes, it seems you're right and the indexes in the ordinal table are 0-based.