Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > низкоуровневое тестирование


Автор: BearFear 14.8.2012, 22:57
Всем категорический КУ! Возможно ли одному реализовать простенькую систему тестирования экзешного кода (возможно по всем канонам ООП) без владения исходниками тестируемого ПО?
Ну вот примерно такая задача:
 - прочитать заголовки и найти виртуальную точку входа
 - запустить процесс и подвергнуть его анализу
   - поиск всех call ... ret
   - поиск подвызовов
   - тестирование конкретной функции
   - сбор всех аргументов для подвызовов
   - по итогу тестирования функции сверить аргументы для сабколлов с критериями
   - тестирование подвызовов
   - итд

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

Автор: BearFear 14.8.2012, 23:28
Или может быть вполне, есть какие то уже готовые средства для подобного тестирования?

Автор: korian 15.8.2012, 14:45
Сначала определите, что вы конкретно собираетесь тестировать, а потом придите к выводу, что это не возможно  smile 
Т.е. я даже не понимаю, как реализовать то, что вы хотите, когда есть исходный код.
Т.е. вот есть функция, с исходным кодом, как вы предлагаете ее протестировать в автоматическом режиме?

Автор: BearFear 15.8.2012, 21:06
Вот в том то и дело, что исходников нет. Был бы (допустим) исходник, то проблем не было бы. Но ведь как то наверняка люди тестируют?
Я полагаю что протестировать не зная исходника можно только если гепотетически асм интерпретировать в С, после чего уже протестировать.
Но это очень жирно будет, сначала делать исходники, потом собирать по новой... Вот предположим что приложение тестирования это отладчик.
В таком случае у нас есть доступ ко всему тому что у подчиненного процесса есть. Можем мы многократно вызвать одну и ту же функцию из
самодельного отладчика зная лишь адресс CALL, который извлекли под средством парсинга бинарного экзешника? WinAPI вроди бы располагает
такими функциями (о WinAPI знаю по учебнику, где средства отладки не оговариваются)?

Автор: korian 15.8.2012, 22:00
Что вы вкладываете в понятие протестировать?
Допустим, все то, что вы хотите у вас есть, что дальше? Что такое тест? Что он должен тестировать?

Автор: BearFear 15.8.2012, 22:58
Ну что обычно юнит-тестами делают? smile Проверка ветвлений для поиска каких то ошибок. Например, программа работает, до тех пор пока юзер не введет 257 символов в текстовое поле. В этом случае программа может грохнуться, но до этого не грохалась. И надо как то обнаружить такую вероятность. Например, void set_text(const char *buffer) а внутри функция тайком по непредусмотрительности кодеров создает массив размером 256 байт, в надежде что клиент больше не введет, затем в этот массив скидывает читаемые из buffer данные, предварительно преобразовывая их. Все ок... до того момента пока юзер не впишет 257й символ. 1 байт не доставит хлопот... наверно smile до поры до времени smile пока за ним не последует ещо и ещо. А исходников нет, немцы сожгли компьютер где были исходники, осталась только экзешка стянутая советским шпиеном у немецкого шпиена который стянул с того компа который после этого сожгли немцы. В общем ну нет исходника ваще никак smile
И вот например, можно было бы как то просканировать экзешник, на наличие всех CALL в main (тру main который  _main, а не __main или ___main исключая их же все эти.).
Например что бы было так... 
- читаем экзешник
- танцами с бубном нашли _main отмели конструктор или что там вызывается до выполнения кодерских задумок на С\С++
- прочитали ВСЕ CALL которые не являются внешними для данной проги (исключая все malloc и прочие)
- затем! На основе всех этих адресов CALL составить план работы
  - план работы таков:
    Есть CALL а есть SUBCALL (сабколл это условно подвызов в CALL. Ну как в мейне другие функции вызываютсо).
    На основе всех этих данных составить статистику зависимости. Типо того
    main -> function_a
    main -> function_b
    function_a -> function_b
    ...
    Ну короче почти тоже самое что граф тока без имен, чисто адреса. Имен мы не знаем и знать по сути не можем.
Далее...
- магическим образом узнаем какие аргументы передаются в функцию (олли например как то умудряется определить атрибут stdcall или cdecl например)
- вызываем по очереди все функции из статистики с разными наборами аргументов по всем параметрам ОТ и ДО для допустимых типов
  например если создается 4 байтовая переменная, следовательно все от 0 до 0-1. Если это строка, указатель на массив, то от 0 символов до N (заданных    
  в настроке тестирующей проги или ваще через prompt в консоли) и сразными значениями этих символов.
и так далее. Написать такое самому, это дофига времени в принципе. Это даже  не то что дофига, это может вечность уйти. Но опять же, зависит от того, насколько универсальной будет прога тестирования. Если сделать тестировщика например сугубо под GCC компилируемые проги, где о всех атрибутах функций известно и возможно отсутствуют тропические атрибуты...
Вот собственно и вопрос. Если писать самому:
А - возможно ли это?
Б - какие API вызовы могут пригодиться, гепотетически?
Если не писать самому:
А - есть ли уже кем то написанные такие проги?
Б - если есть и вполне популярные, есть ли среди них бесплатные или опенсорцевые?

В случае если идти путем "велосипеда", то здесь я не прошу готовых решений, а хотел бы обсудить все возможные камни преткновения, для того что бы тупо выяснить - "а надо оно блин ваще? Может проще шпиена расстрелять и сделать вид что проги и не было? Все равно исходники немцы сожгли!".

Автор: korian 16.8.2012, 02:39
Я все равно не понимаю, допустим вы вытянули все функции из экзешника, и это, по моему мнению не так сложно, что дальше?
вот например есть функиця (на котору на самом деле есть только адрес):
Код

int func(int i) {
  if (i > 1)
      return i + 10;
  return i;
}

по логике программы на самом деле должно быть так:
Код

int func(int i) {
  if (i > 2)
      return i + 10;
  return i;
}

как вы будете это тестировать? а точнее определять, что на самом деле должно быть, не зная обсолютно ничего об найденной функции.

M
GremlinProg
пользуйтесь кнопкой Код

Автор: 500mhz 16.8.2012, 09:30
OllyDbg + HexRay вам в руки, ну и книжку по ассемблеру так как
Цитата

отмели конструктор или что там вызывается до выполнения кодерских задумок на С\С++

Этого вы там не особо увидите

Автор: BearFear 16.8.2012, 16:44
Олли уже стоит, асм по командам знаемс smile примерно, предположительно... в общем тела функций прочитать вполне могу, того что не знаю подучу. А на счет ХексРея спс, буду искать, смотреть что там.

Цитата

как вы будете это тестировать? а точнее определять, что на самом деле должно быть, не зная обсолютно ничего об найденной функции.


Уважаемый, ну как же... предварительный просмотр низкоуровневого кода вполне даст о себе знать. Уже не говоря о том, что имея в виду аргументы и возврат + подвызовы можно вполне себе смоделить тестер, пусть с небольшим покрытием. Это все реально и возможно. Я не знаю только какими средствами WinAPI (чистым API, без MSVC) это все можно организовать. Знаю есть функция чтения памяти процесса, но где и как применять... это найти смогу. Но вот какие еще есть возможности? Составить указатель на функцию и вызвать тоже можно без проблем... 

Автор: korian 16.8.2012, 20:59
Цитата(BearFear @  16.8.2012,  15:44 Найти цитируемый пост)
предварительный просмотр низкоуровневого кода вполне даст о себе знать

Я наверно чего-то не понимаю...
Вот вы нашли функцию, определили все параметры и тд. Вот она:
Код

int func(int i) {
  if (i > 1)
      return i + 10;
  return i;
}

С вашей точки зрения она правильно работает/реализована?
Как я это понимаю, чтобы определить правильно ли она работать, надо определить все места где она вызывается, проанализировать все эти функции, потом для каждой такой функции сделать тоже самое рекурсивно до самой точки входа, т.е. полностью понять весь функционал, который зашит в программу. Так вот, по моему мнению, намного проще и быстрее будет написать такую программу с нуля, чем реверс инжинерить асемблеровских код для того, чтобы понять как его оттестировать.
Даже если вы все это проделаете и у вас все получится... что дальше? зачем эти тесты? Судя по всему для того, чтобы можно было проверить новый бинарник (или нет?). но этот новый бинарник запросто может отличатся на 50% от того, для которого у вас есть тесты и всю работу придется делать заново. Как минимум определять адреса функций, на которые уже есть тесты.

M
GremlinProg
пользуйтесь кнопкой Код

Автор: korian 16.8.2012, 20:59
это был double click

Автор: BearFear 16.8.2012, 21:22
korian, я тоже об этом думал и не раз, при обнаружении ошибки надо будет писать патчи и прочее. Это все накладно. Но это не систематический тест всех бинарников. Это частный единичный случай всего smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)