директория экспорта...кто слажал?

Тема в разделе "WASM.WIN32", создана пользователем IceFire, 3 апр 2007.

  1. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    Читаю Bernd Luevelsmeyer'a. Вижу следующее:

    Пишу код, который делает именно это. Экспериментирую над ntoskrnl.exe WIN XP SP 2.

    В моем случае i=1. Если все делать по мануалу Brend'a, то получаем следующие данные:
    FuncName: CcCanIWrite
    Ordinal: 003C
    RVA EP: 0x47В5

    А если мы запустим LordPE или PE Tools, то увидим, что это значение RVA EP для функции с ординалом 1 и именем ExAcquireFastMutexUnsafe.

    Кто прав? Кому верить?
     
  2. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    смотри сорцы pedump Питрека
     
  3. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    IceFire
    Вместо адреса публичного символа там может оказаться адрес цепочки форвардов (forwarder chain). Если адрес попадает в диапазон секции экспорта, то там должен быть форвард.

    Нельзя так делать, ведь по индексам совпадают только 2 последние таблицы (names и ordinals), а первую (EAT) нужно индексировать по ординалу из 3ей. Т.е. сначала читаем н-ный ординал из таблицы ординалов (и параллельно имя функции из таблицы имён), вычитаем базу ординалов и прибавляем 1 - получаем индекс для RVA адреса данной функции в таблице адресов (или форвард вместо адреса).

    PECOFF v8: Visual Studio, Microsoft Portable Executable and Common Object File Format Specification
    Хотя и в нём есть некоторые ошибки.
     
  4. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    А поподробнее можно? Интересненько...
    //хотя даже в мануалах от интела последних несколько ошибок нашёл сам (fsincos - гон в хедере таблицы).
     
  5. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    asmfan
    Формат библиотек импорта описан неправильно вообще (есть там 2-3 серьёзных ошибки) и про @compid'ы ни слова.

    Ординалы в импорте/экспорте не zero-based, а 1-based, т.е. с 1 начинаются. Поэтому в своём парсере после длительной отладки пришлось добавить +1 и всё заработало.
     
  6. IceFire

    IceFire New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2006
    Сообщения:
    244
    Quantum

    Спасибо! Очень подробно и понятно.
     
  7. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    6.3.1. Export Directory Table
    об этом речь?
    [added]
    Всё-таки 0 то мы получим при вычитании. Да это и логично имхо, т.к. доступ до первой экспортируемой ф-ии - нулевой индекс.
     
  8. bers

    bers New Member

    Публикаций:
    0
    Регистрация:
    16 сен 2005
    Сообщения:
    139
    Адрес:
    Russia
    Кстати, очень много примеров разбора таблицы экспорта написаны с учетом того, что ординалы, как вы тут выразились, zero-based. Я тоже в свое время разобрался в этом деле, но мне непонятны постоянные ошибки в статьях - они что там свои примеры не тестят чтоли?
     
  9. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    asmfan
    Нет, Ordinal Base - это само собой. Я имел в виду, что к ординалу из таблицы ординалов, из которого нужно вычесть базу, необходимо ещё прибавить 1, чтобы проиндексировать таблицу адресов. Короче, так:
    function_RVA = RVA_table[ordinal - base + 1]

    Ну, вот простой пример из kernel32.dll:

    Address of name ordinals: 000043EC (RVA) -> 000037EC (file offset)
    Base: 1

    В хексредакторе по адресу 000037EC имеем следующее: 0000 0100 0200 0300 0400 0500 0600 0700 ...

    Таким образом, первый ординал = 0. После вычитания базы получаю: 0 - 1 = -1, а вовсе не ноль! Поэтому нужно прибавить ещё 1.
     
  10. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    А ведь и вправду... с нуля. Выходит мелкомягкие заметаютъ следы к знаниям о формате. Прескорбно.
     
  11. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    мне кажется что у Ицзелиона этот момент вполне прозрачно описан, + исходники
    pedump, и не надо запутывать :)

    я вот так ищу указатели на RVA(в памяти)

    Код (Text):
    1. for ( unsigned int i = 0; i < pExportDir->NumberOfNames; i++ )
    2. {
    3.     if ( 0 == strcmp(lpProcName, (char*)(pszFuncNames[i] + (char*)ImageBase)) )
    4.         return (void*)(&pdwFunctions[(unsigned int)pwOrdinals[i]]);
    5. }
    и надеюсь что все правильно ;)
     
  12. bers

    bers New Member

    Публикаций:
    0
    Регистрация:
    16 сен 2005
    Сообщения:
    139
    Адрес:
    Russia
    Зря, что надеешься...
    Во-первых, не учитываешь OrdinalBase, во-вторых - забыл вычесть 1 из индекса при поиске адреса точки входа функции. Короче, смотри последний пост Quantum
     
  13. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    bers
    т.е. ты утверждаешь что код нерабочий?
     
  14. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    у дядьки Ицзелиона написано:
    "Заметьте, что nBase не влияет на значения в массиве AddressOfNameOrdinals.
    Hесмотpя на имя "AddressOfNameOrdinals", этот массив содеpжит индесы в массиве,
    а не оpдиналы."

    оттуда же:
    Если у нас есть имя экспоpтиpуемой функции и нам тpебуется получить ее адpес в модуле, мы должны сделать следующее.

     
  15. bers

    bers New Member

    Публикаций:
    0
    Регистрация:
    16 сен 2005
    Сообщения:
    139
    Адрес:
    Russia
    Смотри, тут получается интересная вещь - (кстати у меня ошибочка вышла в предыдущем посте: не отнять 1, а прибавить 1 к индексу )), извиняюсь за дизинформацию) если ты не будешь учитывать эти вещи о которых я написал, у тебя все БУДЕТ РАБОТАТЬ при OrdinalBase == 1 (в большинстве случаев линкер в такое значение его и выставляет). А вот если OrdilnalBase != 1, то тогда ты будешь получать адреса каких-то следующих функций.
     
  16. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    чтоб показать что код работает корректно набросал примерчик,
    реализован поиск по имени в таблице экспорта указателя на RVA
     
  17. bers

    bers New Member

    Публикаций:
    0
    Регистрация:
    16 сен 2005
    Сообщения:
    139
    Адрес:
    Russia
    читай мой предыдущий пост
     
  18. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    А что именно чиать то?

    если вот это
    "у тебя все БУДЕТ РАБОТАТЬ при OrdinalBase == 1 (в большинстве случаев линкер в такое значение его и выставляет). А вот если OrdilnalBase != 1, то тогда ты будешь получать адреса каких-то следующих функций."

    то я спецом сделал две dll'ки разные для теста, как видишь все работает
     
  19. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Asterix
    Во-первых твой код показывает адрес, по которому хранится RVA функции MyProc2, а не сам RVA.

    Во-вторых, что гораздо интереснее, в обоих DLL таблицы ординалов идентичны - они содержат 0000 0100. Получается, что база вообще учитывается только лишь при импорте по ординалу. Получается, что дока по PE формату врёт ещё больше, чем я думал ;) А в моей формуле нужно не 1 прибавлять, а просто не вычитать базу...
     
  20. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Quantum
    Почитай что Ицзелион пишет...
    что это не ординалы а индексы.
    А ординалы само собой, и при поиске по имени они как таковые не учитываются.
    Вот когда нужен поиск по ординалу, тогда и базу учитывать придется.

    а функции в имеют ординалы 1 и 2 в первой длл, и 200, 201 во второй,
    значит во втором случае база 200