Не линкуется ndis.lib

Тема в разделе "WASM.NT.KERNEL", создана пользователем neutronion, 5 фев 2011.

  1. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    на стадии компиляции есть возможность проверить ошибки в студии, доходим до линковки получаем ошибку,запускаем вышеописанный скрипт все компилиться без проблем, вот такая двух-тактная система получилась.
     
  2. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    а в свойства проекта залезть религия не позволяет чтоле? написал же куда.
    раз компилируется build'ом как плоский Си, то и в студии скомпилируется.
     
  3. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Естественно опробованы все вышеуказанные советы, результат тот же. Студия отказывается линковать. Могу дать проект, можете попробовать, если есть желание.
    И еще, сборка экзешника двухтактный процесс, сначала компиляция затем линковка.
    Студия компили проект без проблем т.е. создает .obj файл. Проблема возникает при линковке .obj файла с файлом ndis.lib. Линковка с hal.lib Тоже происходит без проблем.
     
  4. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Не забываем, что студия использует свой cl.exe и Link.exe, а утилита
    бильд свою версию cl.exe и link.exe. link.exe билдера отличается от линкера студии.
    Замена линкера студии на линкер билдера ни к чему хорошему не привела, говорит ошибка
    в линковщике, дальше я не разбирался.
     
  5. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    Так именно и говорит, что ошибка в линковщике? Ну если студия 2008, то не удивлюсь.
    link.exe может конечо и разный, но я ещё пока разницы в поведении не замечал. Вот только дрова студией не пытался собирать. Хз, может чисто с ними какие новые затупы.

    А если ошибка та, которая была в первом посте - то тут link.exe ни при чём. Это просто несоответствие имён.
     
  6. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    ок. Делаем очень просто, смотрим какое имя сформировала студия в .obj файле и сравниваем есть ли такое
    в ndis.lib. Я одного только не пойму, если линковщику нужно всего лишь прописать имя импортируемой функции в таблице импорта, то на кой ей ляд нужен ndis.lib? Если бы код импортируемой функции встраивался в мой экзешник, тогда другое дело.
     
  7. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    упс, вот он и косяк нашелся.
    Вот что у меня получилось, в .obj файле видим символ, который мой компилятор из студии сформировал
    NdisInitializeEvent@@YGXPAU_NDIS_EVENT@@@Z, в то время как импортируемый символ в этом же .obj файле функции RtlInitUnicodeString
    такой: _imp_RtlInitUnicodeString@8, теперь смотрим, что в ndis.lib
    такого символа NdisInitializeEvent@@YGXPAU_NDIS_EVENT@@@Z не наблюдается. Зато есть такой: _imp_NdisInitializeEvent@4!!!

    Следует вопрос, почему компилятор студии формирует символ функции RtlInitUnicodeString правильный, а символ функции NdisInitializeEvent неправльный?

    В то время как билдовский компилятор формирует правильный символ в .obj файле: _imp_NdisInitializeEvent@4


    Спасибо krabs натолкнул на идею, сравнить импортируемые функции. Вывод, как говорил Гете дьявол в деталях.
    Зря я на линкер грешил, виноват компилятор.
     
  8. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Теперь бы понять, почему компилятор студии ведет себя подобным образом.
     
  9. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    Да всё дело опять в разнице между C и C++.

    _imp_NdisInitializeEvent@4 - это обычный сишный stdcall. такие функции и составляют всё API в винде.
    а вот это:
    NdisInitializeEvent@@YGXPAU_NDIS_EVENT@@@Z - это та же функция, но в формате C++, где вся инфа о параметрах включается в декорированное имя, за счёт чего линкер видит различия между функциями с одинаковыми именами но разными параметрами. естественно такой функции в .lib нет.

    поэтому, очевидно Вы всё же не настроили студию на компиляцию плоского Си. попробуйте задать это для каждого файла отдельно чтоле - щелчком правой кнопкой по файлу в дереве проекта. ну или переименуйте файлы в *.c на худой конец.

    а .lib - это по сути контейнер для множества .obj и линкер хавает одновременно Ваши .obj и внешние .lib и собирает из них исполняемый модуль. и уже из этих входных файлов он смотрит надо ли искать код в этих файлах, либо выводить его на динамический импорт.
     
  10. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Переведено все файлы в .с и настройки сделаны как
    Compile as C Code (/TC) для всех файлов.
    Я вижу единственный способ разобраться:
    1) Определяем в коде компилятора место, где разветвляется генерация
    символов.
    2) Сравнить почему генерация для _imp_RtlInitUnicodeString@8 идет по одному пути, а генерация для NdisInitializeEvent@@YGXPAU_NDIS_EVENT@@@Z идет по другому пути.
    Это все равно, что взломать серийник, только проще, потому что никто специально не прячет этот алгоритм. Ладно будет время попробую это сделать, потом напишу. Может даже на статью в wasm потянет.
    Для опытного кракера - это пол-часа работы. :)
     
  11. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    Итак, смотрим в wdm.h:
    Код (Text):
    1. NTSYSAPI
    2. VOID
    3. NTAPI
    4. RtlInitUnicodeString(
    5.     __out PUNICODE_STRING DestinationString,
    6.     __in_z_opt __drv_aliasesMem PCWSTR SourceString
    7.     );
    смотрим в ndis.h

    Код (Text):
    1. EXPORT
    2. VOID
    3. NdisInitializeEvent(
    4.     __out  PNDIS_EVENT             Event
    5. );
    NTSYSAPI == DECLSPEC_IMPORT
    EXPORT == DECLSPEC_IMPORT

    видим разницу в отсутствии NTAPI. NTAPI == __stdcall
    build по дефолту использует __stdcall. студия по дефолту использует __cdecl. это тоже настраивается в свойствах проекта.
    однако указанное Вами выше имя не относится и к __cdecl по идее. там должно просто одно "_" добавляться спереди. оно указывает на С++. а посмотрите на DriverEntry в .obj файле - как оно выглядит? если не _DriverEntry@8, то Вас обманули и продолжают компилировать как С++.

    я не думаю что имеет смысл реверсить студию. Вы потом её и патчить будете чтобы работала? ведь пишут же на ней дрова все кому не лень. значит она работает, просто надо понять что происходит.
     
  12. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Вот так выглядит: DriverEntr@@YGJPAU_DRIVER_OBJECT_@@PAU_UNICODE_STRING@@@Z

    Попробовал поставить перед DriverEntry _stdcall результат тот же.
    Создал другую функцию
    Код (Text):
    1. #include "StdAfx.h"
    2.  
    3.  
    4. PDRIVER_OBJECT g_DriverObject;
    5.  
    6. //object which was top before we connected to it
    7. PDEVICE_OBJECT g_topDeviceObj;
    8.  
    9. int _stdcall MyTest();
    10.  
    11. NTSTATUS
    12. _stdcall
    13. DriverEntry(
    14.     IN PDRIVER_OBJECT pDriverObject,
    15.     IN PUNICODE_STRING RegistryPath
    16.     )
    17. {
    18.     MyTest();
    19.     return STATUS_SUCCESS;
    20.  
    21. } // end DriverEntry()
    22. int _stdcall MyTest()
    23. {
    24.     return 1;
    25. }
    У MyTest такие символы ?MyTest@@YGHXZ
    Поменял объявление на такое
    int _cdecl MyTest()
    та же строка ?MyTest@@YGHXZ - компилятору по-моему пофиг на объявления _cdecl и _stdcall,

    Можешь скомпилить вышеуказанный пример и сообщить свои результаты?
     
  13. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    а вот билдеровский создает правильную строку _DriverEntry@8

    Возможно где-то глобальные настройки студии мешают жить, в общем без реверса делать нечего, это единственный способ вывести студию на чистую воду.
    Возможно патч нужно поставить на студию, у меня ни одного еще не стоит.
    Сохранить старую студию поставить патч, сравнить папки.
    Я уже убедился на высоком абстрактном уровне программирования, можно шельмовать сколько угодно, но истина всегда заключена в машинном коде
    (или в нашем случае мнемонических командах ассеблера) Ассеблер ниже всех поэтому он силнее всех( парафраз китайской пословицы: Почему Океан силнее всех? Потому что он ниже всех. Конфуций по-моему). Или почему уборщица самый опасный человек в организации? Уборщиком пойти что-ли?
    (Убирать людей из которых дермо лезет(тех, кто такие компиляторы делает) :)))))
     
  14. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    между прочим вот выдержка из IDA pro
    Код (Text):
    1. text:00000008 ?DriverEntry@@YGJPAU_DRIVER_OBJECT@@PAU_UNICODE_STRING@@@Z proc near
    2. .text:00000008                 push    ebp
    3. .text:00000009                 mov     ebp, esp
    4. .text:0000000B                 call    ?MyTest@@YAHXZ  ; MyTest(void)
    5. .text:00000010                 xor     eax, eax
    6. .text:00000012                 pop     ebp
    7. .text:00000013                 retn    8
    8. .text:00000013 ?DriverEntry@@YGJPAU_DRIVER_OBJECT@@PAU_UNICODE_STRING@@@Z endp
    Как видим несмотря на краказяблики, имеем _stdcall функцию, никак не _cdecl
    Как я и говорил, Ассемблер - руль!
     
  15. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    DriverEntr@@YGJPAU_DRIVER_OBJECT_@@PAU_UNICODE_STRING@@@Z - это С++!!!
    хоть Вы меня за яйца повесьте.

    вот как только начнёт оно компилироваться как плоский си, то сразу всё и соберётся как надо.
    возможно Вам реверсинг подскажет как этого добиться...
     
  16. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Да уж, забавно будет повозиться....
     
  17. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    В общем почитал о манглинг в интере krabs прав, происходит замангаление функций в стандарте С++. Поэтому сделал следующее
    Код (Text):
    1. export "C"
    2. {
    3. EXPORT
    4. VOID
    5. NdisInitializeEvent(
    6.     IN  PNDIS_EVENT             Event
    7. );
    8. }
    до этого было так
    Код (Text):
    1. EXPORT
    2. VOID
    3. NdisInitializeEvent(
    4.     IN  PNDIS_EVENT             Event
    5. );
    Проект успешно начал собираться и линкер увидел функцию NdisInitializeEvent поскольк та стала собираться в обжект файле в нужном
    формате, однако таким образом уродовать ndis.h думаю плохая затея.
    Вот такие бывают чудеса.
     
  18. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    а что если изуродовать сорц так:
    Код (Text):
    1. extern "C"
    2. {
    3. #include "ntddk.h"
    4. }
     
  19. neutronion

    neutronion New Member

    Публикаций:
    0
    Регистрация:
    31 мар 2010
    Сообщения:
    1.100
    Вот так теперь получается собирать проект, вот блин, век живи век учись.
    Спасибо. Тему можно закрывать. Хотя... вопрос то остался почему косячит студия... :)
    Правда я сделал так:
    Код (Text):
    1. extern "C"
    2. {
    3. #include "ndis.h"
    4. }
    Потому как только с этой библиотекой проблемы.
     
  20. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    Ну в принципе-то решение вполне годное найдено, многие так делают и пишут свой код на C++.

    Но если хотите разобраться, присылайте проект целиком ну или файл проекта хотя бы - я поковыряюсь в нём.