Программная среда для динамического анализа бинарного кода

В выполнении исследований программного обеспечения,


В выполнении исследований программного обеспечения, оформленного в виде готового к работе бинарного кода, часто без исходных текстов, заинтересованы многие организации, решающие задачи сертификации ПО, а также проблемы отладки своих разработок или их совместимости с другими программами и системами. Всем им требуется проводить анализ бинарного кода различных программ, как по отдельности, так и в комплексе со всей средой исполнения компьютера, иногда вплоть до самого низкоуровневого кода операционной системы. Целью таких исследований является получение информации об особенностях реализации алгоритмов, восстановление реализации этих алгоритмов и их представление в понятном аналитику виде, восстановление протоколов обмена информацией и форматов данных, а также поиск «недокументированных» возможностей, ошибок и уязвимостей.
В качестве примера рассмотрим ситуацию, когда требуется исследовать работу ПО, передающего данные по сети. Поскольку в работу вовлекается код не только самой программы, но и операционной системы и драйверов сетевых интерфейсов, недостаточно исследовать содержимое исполняемого файла программы. Требуется провести анализ всего стека сетевых протоколов, поскольку ошибки реализации и недокументированные возможности одних компонент могут влиять на работу и использоваться другими компонентами. Общий объём бинарного кода, который представляет для аналитика интерес, может составлять десятки мегабайт. Решение этой задачи логично разбивается на решение ряда подзадач:

  1. Поиск «точек зацепления», т.е. мест в системе, с которых целесообразно начинать исследование.
  2. Раскрутка от точки зацепления назад (исследование кода, который привёл в точку) или вперёд (исследование кода, который работал после точки) с целью нахождения реализации алгоритма.
  3. Поиск и анализ данных, влияющих на алгоритм по входу, и данных, образующихся по выходу алгоритма.
  4. Восстановление алгоритмов, протоколов и форматов данных.
  5. Выявление недекларированных возможностей, уязвимостей реализации.

Важно отметить, что перечисленные подзадачи возникают при решении практически любых других задач, связанных с исследованием бинарного кода.
Главным (и, возможно, единственным до сегодняшнего дня) эффективным методом решения таких задач является комбинация методов статического анализа (используется дизассемблер и декомпилятор) и «ручного» динамического анализа (используется отладчик и некоторые вспомогательные средства – дамперы, мониторы и т.д.).
Статический анализ позволяет выполнять локальные исследования бинарного кода, к которому не применялись способы затруднения анализа. Из способов затруднения анализа отметим следующие:

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

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


Главной проблемой динамического анализа является то, что на данный момент нет доступных средств автоматизации труда, и практически все действия, выполняемые аналитиком, являются ручными операциями. Ситуацию усугубляет применение активных защит от динамического анализа, когда код содержит средства обнаружения работы под отладчиком и реагирования в виде неправильного функционирования, обфускация кода, использование виртуальных машин и многое другое. При правильной реализации такие методы защиты сводят к минимуму вероятность успеха исследования.
Вычислительная мощь компьютеров растёт с каждым днём, и это позволяет реализовывать всё более сложные, комплексные и ресурсоёмкие алгоритмы усложнения и запутывания кода. Человеческих сил и возможностей уже недостаточно для анализа гигантских объёмов информации, содержащихся в исследуемых системах. Развитие средств запутывания алгоритмов, в том числе, и на аппаратном уровне, влечет невозможность решения задач восстановления алгоритмов существующими методами. Средства запутывания все более востребованы на рынке, и сейчас наблюдается активное их развитие и распространение.
В данной работе описывается TrEx – программная среда динамического анализа бинарного кода. Возможности среды позволяют решать задачу восстановления алгоритма, преодолевая при этом комплекс средств защиты от анализа. Программные инструменты среды базируются анализе потоков данных в трассе выполнения программы и позволяют выполнять быстрое прототипирование специфических для каждого отдельного случая алгоритмов.
Статья состоит из пяти разделов. Во втором разделе кратко описывается методика, на основе которой предлагается решать поставленную задачу. В третьем разделе описывается программная система, реализующая эту методику. В четвертом разделе рассматриваются дальнейшие пути развития программной системы. В последнем, пятом, разделе делаются итоговые заключения.

Содержание раздела