2016-10-12 12 views
1

Глядя на kernel32.dll, как он будет загружен в память, я вижу следующее экспортное порядковое таблицу:Как `kernel32.dll` экспортирует порядковый номер 0, если для поля` OrdinalBase` установлено значение 1?

(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 

Как можно проверить, порядковый 0 экспортируются.

Но учитывая, что OrdinalBase поле таблицы каталога экспорта устанавливаются в 1, как может порядковый быть меньше 1 ?:

Порядкового Основание: Исходный порядковый номер для экспорта в этом изображения. Это поле указывает начальный порядковый номер для таблицы адресов экспорта . Это, как правило, устанавливаются в 1.

В документации сказано, что порядковые пристрастны, т.е .:

Экспорта порядковая таблица представляет собой массив из 16-битовых индексов в таблицу адресов экспорта . Ординалы смещены с помощью поля «Оринальная база» таблицы каталога экспорта. Другими словами, порядковая база должна быть вычтена из ординалов, чтобы получить истинные индексы в таблице адресов экспорта .

Теперь это означает, что порядковый номер 0 порождает индекс -1 в таблицу экспортных адресов?

С моей точки зрения, похоже, ординалы предварительно скорректированы (т.е. 1 вычитается из каждого), а затем «официальный» алгоритм (также указывается в PE-документы) не:

Таким образом, когда таблица указателя имя экспорта ищется и соответствие строка найдена в позиции я, алгоритм для нахождения адреса символа является:

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

Единственная мысль, которая приходит на ум, я s следующее: загрузчик скорректировал ординалы в пределах экспортной таблицы ордеров при загрузке DLL в память.

Может ли кто-нибудь дать объяснение?

+0

А как насчет алгоритма в документации PE для поиска символа RVA? Тогда этот алгоритм некорректен? Он использует ординалы как часть поиска RVA. Кроме того, каковы числа в порядковой таблице, если не правильные ординалы (соответствующие тем, которые видны с использованием самосвала)? – Shuzheng

+0

Кроме того, вы говорите, что запись 0 является порядковым номером 4, но почему она отображает 3? – Shuzheng

+0

@HansPassant: Кроме того, почему 1 (OrdinalBase) вычитается из каждого порядкового номера?Если бы вы могли ответить на эти вопросы, вы бы сделали Рождество в начале этого года :) – Shuzheng

ответ

2

Это известная ошибка в спецификации PE/COFF. Алгоритм указан совершенно неправильно, и это должно быть

ordinal = ExportOrdinalTable [i] + OrdinalBase; 

не

ordinal = ExportOrdinalTable [i]; 

как порядковое таблица фактически содержит беспристрастные порядковые.

+0

Спасибо, у вас есть источник или просто личный опыт? – Shuzheng

+0

Опыт написания парсера и загрузчика PE для предыдущего проекта :) –

+0

Я пришел к мысли о следующем: алгоритм работает для проверки DLL статически? Кажется, что загрузка DLL в память изменяет ординалы, например. изменяется с 348 (проверено с использованием DUMPBIN) до 347 (проверено во время выполнения). Ваша личность кажется абсурдной: ordinal = ExportOrdinalTable [i] + OrdinalBase; - Зачем добавлять OrdinalBase только для того, чтобы сразу же вычесть его? – Shuzheng