7

根据我和其他人的经验 (http://webster.cs.ucr.edu/Page_TechDocs/pe.txt),PE/COFF 规范文档错误地声称序数表中包含的导出地址表索引是相对的到序数基数,甚至给出了一个不正确的例子(第 5.3 节)。实际上,在 Ordinal Base = 1 的正常情况下,Ordinal Table 中的索引是地址表中基于 0 的索引。我在 VS Studio 生成的 PE 库和 Kernel32.dll 等系统库中看到了这一点。

我的问题是,你有没有观察过序数基数不等于 1 的二进制文件?我想知道这是否是一个错误,或者序数基数是否从未应用于序数表条目。

4

3 回答 3

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

于 2011-04-13T19:24:39.810 回答
4

这不是一个错误的错误,Ordinal Base 不应用于序数表条目,而是应用于序数本身的计算。是的,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
于 2013-12-08T11:43:13.507 回答
1

不,PE 导出目录表的 OrdinalBase 字段不会被忽略!

上面提供的示例 (mfc42.dll) 是一个很好的示例(因为它的 Ordinal Base 不是 1)。

这里有两个关于这个问题的评论:

. 就序数字段而言,转储工具的输出是正确的。它显示,Base 字段为 5。这意味着,当按名称从 mfc42.dll 导入导出函数时,导出地址表中计算的偏移量将为 x-5。Microsoft 规范第 5.3 节是正确的。

. 就提示而言,转储工具的输出不正确。导出表没有提示字段,只有导入表有提示字段。

事实上,Ordinal Base 不是在 Ordinal Table 中应用,而是在检索地址表的索引时应用!

于 2012-06-20T14:17:38.040 回答