当它的“OrdinalBase”字段设置为1时,“kernel32.dll”如何导出序数为0? [英] How can `kernel32.dll` export an ordinal of 0, when its `OrdinalBase` field is set to 1?

查看:273
本文介绍了当它的“OrdinalBase”字段设置为1时,“kernel32.dll”如何导出序数为0?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看到kernel32.dll被加载到内存中,我看到以下导出序数表:

 (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 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

可以验证,导出0的序数。



但是,由于导出目录的OrdinalBase字段表格设置为1,序数如何小于1?:


Ordinal Base:此$ $中的出口起始序号b $ b图像。此字段指定导出
地址表的起始序号。它通常设置为1。


文档说,这些序号有偏见,即:


导出序数表是导出
地址表中的16位索引数组。序数由导出目录表
的Ordinal Base字段偏置。换句话说,序数基数必须从序数中减去
,以获取导出
地址表中的真实索引。


现在,这意味着0的序数在出口地址表中产生了-1的索引?



从我的角度来看,似乎像序号被预先调整(即从每个减去1),然后官方算法(也在PE文档中说明)失败:


因此,当搜索出口名称指针表并且在位置i找到匹配的
字符串时,用于查找符号的
地址的算法是:




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

想到的唯一想法如下:加载器已经调整了导出序数中的序数


$ b

任何人都可以给出解释?

解决方案

div>

这是PE / COFF规范中已知的错误。指定的算法是明文错误的,它应该是

  ordinal = ExportOrdinalTable [i] + OrdinalBase; 

  ordinal = ExportOrdinalTable [i]; 

作为序数表实际包含无偏见的序号。


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?

解决方案

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.

这篇关于当它的“OrdinalBase”字段设置为1时,“kernel32.dll”如何导出序数为0?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆