How can `kernel32.dll` export an ordinal of 0, when its `OrdinalBase` field is set to 1?

狂风中的少年 提交于 2020-01-01 07:22:05

问题


Looking at kernel32.dll as it is loaded into memory, I see the following export ordinal table:

(gdb) x /400hd $eax

0x776334b0 <Wow64Transition+71576>:     3       4       5       6       7       8       9       10
0x776334c0 <Wow64Transition+71592>:     11      12      13      14      15      16      17      18
0x776334d0 <Wow64Transition+71608>:     19      20      21      22      23      24      25      26
0x776334e0 <Wow64Transition+71624>:     27      28      29      30      31      32      33      34
0x776334f0 <Wow64Transition+71640>:     35      36      37      38      39      40      41      42
0x77633500 <Wow64Transition+71656>:     43      44      45      46      47      48      49      50
0x77633510 <Wow64Transition+71672>:     51      52      53      54      55      56      57      58
0x77633520 <Wow64Transition+71688>:     59      60      61      62      63      64      65      66
0x77633530 <Wow64Transition+71704>:     67      68      69      70      0       71      72      73
0x77633540 <Wow64Transition+71720>:     74      75      76      77      78      79      80      81
0x77633550 <Wow64Transition+71736>:     82      83      84      85      86      87      88      89
0x77633560 <Wow64Transition+71752>:     90      91      92      93      94      95      96      97

As can be verified, an ordinal of 0 is exported.

But given that the OrdinalBase field of the export directory table is set to 1, how can an ordinal be less than 1?:

Ordinal Base: The starting ordinal number for exports in this image. This field specifies the starting ordinal number for the export address table. It is usually set to 1.

The documentation says that the ordinals are biased, i.e.:

The export ordinal table is an array of 16-bit indexes into the export address table. The ordinals are biased by the Ordinal Base field of the export directory table. In other words, the ordinal base must be subtracted from the ordinals to obtain true indexes into the export address table.

Now, this implies that an ordinal of 0 gives rise to an index of -1 into the export address table?

From my point of view, it seems like the ordinals are pre-adjusted (i.e. 1 is subtracted from each), but then the "official" algorithm (also stated in the PE-docs) fails:

Thus, when the export name pointer table is searched and a matching string is found at position i, the algorithm for finding the symbol’s address is:

i = Search_ExportNamePointerTable (ExportName); 
ordinal =
ExportOrdinalTable [i]; 
SymbolRVA = ExportAddressTable [ordinal - OrdinalBase];

The only idea that comes to mind is the following: The loader has adjusted the ordinals within the export ordinal table when it loaded the DLL into memory.

Can anyone give an explanation?


回答1:


This is a known error in the PE/COFF specification. The algorithm specified is plain wrong, and it should be

ordinal = ExportOrdinalTable [i] + OrdinalBase;

not

ordinal = ExportOrdinalTable [i];

as the ordinal table actually contains unbiased ordinals.



来源:https://stackoverflow.com/questions/39996742/how-can-kernel32-dll-export-an-ordinal-of-0-when-its-ordinalbase-field-is-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!