Проверка прототипа функции из DLL, Как предотвратить ошибку?

Тема в разделе "WASM.WIN32", создана пользователем DeRekX, 4 июн 2010.

  1. DeRekX

    DeRekX New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2007
    Сообщения:
    98
    Адрес:
    Russia
    Всем привет
    Задача: пройти по файлам dll, найти функцию по имени, успешно вызвать
    Решение:
    Код (Text):
    1. typedef void (__cdecl *my_func)(int, int);
    2.  
    3. int main()
    4. {
    5.     HINSTANCE module = LoadLibrary(__TEXT("C://my_file.dll"));
    6.     if (module)
    7.     {
    8.         LPCSTR func_name = "testf";
    9.         my_func func_from_dll = (my_func)GetProcAddress(module, func_name);
    10.         if (func_from_dll)
    11.         {
    12.             int a; int b;
    13.             try // не спасет всё равно
    14.             {
    15.                 func_from_dll(a, b);
    16.             }
    17.             catch (...)
    18.             {
    19.                 printf("Catch");
    20.             }
    21.         }
    22.         else
    23.         {
    24.             //...
    25.         }
    26.         FreeLibrary(module);
    27.     }
    28.     else
    29.     {
    30.         //...
    31.     }
    32.     return 1;
    33. }
    Результат: всё по идее хорошо, но если прототип совпадает, а если нет? я так понимаю (и получаю) падение программы. у функции нет контроля над тем, что ты пытаешься загрузить, есть имя в def и адрес, к прототипу любого вида можно привезти
    Вопрос: можно ли как - нибудь избежать падения, при динамическом импорте функций из библиотек, при несовпадании прототипов? какие - нибудь дополнительные проверки или другие функции для этих целей.

    Надеюсь вопрос понятен, заранее благодарен за помощь

    ___
    Подойдёт ли альтернативный вариант ? :
    Код (Text):
    1.   __try
    2.     {
    3. // вызываем функцию с произвольным набором параметров
    4.     }
    5.     __except(EXCEPTION_EXECUTE_HANDLER)
    6.     {
    7. // обрабатываем исключение
    8.     }
    Надежный ли это вариант ловли вызова с неверными параметрами? у меня на тестовом примере исключение отрабатывает.
     
  2. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    SetUnhandledExceptionFilter попробуй
     
  3. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    Помоему на винграде вам уже дали достаточно ответов %)
     
  4. DeRekX

    DeRekX New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2007
    Сообщения:
    98
    Адрес:
    Russia
    punxer
    пример кода покажите который решает эту задачу.

    GoldFinch
    Ответов много, но ни один не подходит)
    Возможно, Вы, что-нибудь новое предложите.
     
  5. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    создать несколько прототипов с 1 2 3 4 5 6 7 8 9 параметрами и вызывать их поочереди восстанавливая стек при исключении и не забыть про возвращаемое значение которого может и не быть


    Код (Text):
    1. SetUnhandledExceptionFilter(UnhandledFilter);
    2.  
    3.  
    4. LONG WINAPI UnhandledFilter(__in  struct _EXCEPTION_POINTERS *ExceptionInfo)
    5. {
    6.  
    7.  
    8.            // тут нада пробовать восстановить стек и потанцевать с бубном что бы не упасть
    9.  
    10.     return EXCEPTION_CONTINUE_EXECUTION;
    11. }
     
  6. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    punxer
    как в С\С++ восстановить стек? откуда восстановить? Куда вернуть управление?
     
  7. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    асмовские вставки
     
  8. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    сохранить стек и регистры до этого кола
     
  9. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    punxer
    код этих вставок покажите.
    алсо если вызываемая функция потрет стек, никакой обработчик не поможет.
     
  10. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    я и говорю сохранить определенную верхушку стека
    все в теории исходя из того что нет ничего невозможного
     
  11. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Интересная задачка. Можно покопать на досуге может и выйдет чего полезное
     
  12. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    DeRekX
    Изучите конвенции вызовов функций и реализацию на ассемблере...
    Далее, берете анализатор кода и проводите предварительный анализ кода функции - как минимум вы получите количество (и размер?) переменных в интерфейсе функции.
    А поделки типа - вызвать и посмотреть не упадет ли поток - это не серьезно...

    Естественно, никто вам не скажет о "информационной наполненности" параметров (типа DWORD или HANDLE) - это можно понять только при анализе кода функции.
     
  13. punxer

    punxer Андрей

    Публикаций:
    0
    Регистрация:
    16 окт 2006
    Сообщения:
    1.327
    Адрес:
    Ржев
    Получается прям брутфорс параметров))
     
  14. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    надежное решение уже говорили - вызывать функцию в отдельном контексте.

    дешевое решение для защиты стека - это ставить сех, создавать в стеке пустое место, чтобы функция не потерла много стека, и вызывать функцию
    Код (Text):
    1. __try{
    2. __asm sub esp, 0x800
    3. func(x, y, z);
    4. } __finally {}
     
  15. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    А зачем это надо?

    Что будет если функа имеет условие:

    void UpsetCallerExpectations(int Param, int *Crash)
    {
    if ( Param < 0 ) *Crash= 0x17;
    }

    ?
     
  16. DeRekX

    DeRekX New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2007
    Сообщения:
    98
    Адрес:
    Russia
    Любопытно, что весь промышленный софт работает на dll.
    А как - никто не знает)
     
  17. DeRekX

    DeRekX New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2007
    Сообщения:
    98
    Адрес:
    Russia
    GoldFinch
    Не поверю, что нужно создавать отдельную непростую архитектуру с процессами, чтобы просто безопасно вызвать функцию.
     
  18. DeRekX

    DeRekX New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2007
    Сообщения:
    98
    Адрес:
    Russia
    gorodon
    назовите, пожалуйста, какой-нибудь серьёзный продукт использующий предлагаемый Вами подход.
     
  19. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    DeRekX
    о процессах никто не говорил
     
  20. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    DeRekX
    А что если вы попадете на функу типа ExitProcess :)

    Имхо неверный и небезопасный у вас подход - надо вам написать анализатор кода. Как например это делает IDA (да, иногда она ошибается, но в целом - правильно все). И вообще возьмите IDA и напишите к ней плуг под вашу задачу.

    Как? Явно не так как вы написали :). Покажите коммерческий софт, который проверяет кол-во параметров функции через их вызов (пальцем в небо считайте). Я такого еще не видел.

    Заморочиться на процессах можно, поставить инжектов следить за поведением и тп. Но чую, вы замучаетесь исправлять разные ошибки вашего кода. Не знаю, если лень встраивать дизасм и писать анализатор, можете убить (да именно убить) время на это, неясное решение задачи.

    Повторю ключ вопроса "Зачем вызывать для проверки?".