PE导出目录表的OrdinalBase字段被忽略了吗?

时间:2011-04-13 17:43:07

标签: dll reverse-engineering dllexport portable-executable

根据我和其他人的经验(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条目。

3 个答案:

答案 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!