Классический подход к анализу программного обеспечения методом серого ящика
Классическим подходом к анализу программного обеспечения методом серого ящика является анализ дизассемблированного представления исследуемого программного решения.
Современное программное обеспечение, как уже сообщалось ранее, состоит как из Native-компонентов, так и из модулей, реализованных в виде байт-кода. Миграция приложений для Microsoft Windows под платформу .NET Framework происходит постепенно по причине объемности современных программных решений, что обуславливает смешивание Native и Managed модулей в рамках одного проекта. Примером такого смешивания может быть геологический пакет Schlumberger Petrel.
В настоящее время имеется ряд инструментов анализа как Native, так и основанных на байт-коде программных решений. Разделим существующие средства анализа программного обеспечения методом серого ящика на следующие категории:
1) Дизассемблеры. К таким инструментам относится Hex Rays IDA Pro.
a. Для Native программных компонентов дизассемблеры формируют код на языке программирования Assembler [7] соответствующей архитектуры процессора. В состав пакета Microsoft Windows SDK так же включена утилита «dumpbin» [8] выполняющая дизассемблирование. Важно отметить, что последующая компиляция результатов работы дизассемблера в общем случае не даст возможности собрать функционирующее программное решение.
b. Для байт-кода (в качестве примера рассмотрим байт-код платформы .NET Framework) дизассемблеры формируют код на промежуточном языке CIL [9]. Для дизассемблирования байт кода Microsoft так же предоставляет штатное решение «ildasm» [10]. Отметим, что сборка управляемых программных решений по результатам работы дизассемблера в общем случае является возможной.
2) Декомпиляторы. К таким инструментам относится Red Gate .NET Reflector для платформы .NET Framework. Результатом работы данного декомпилятора является код на выбранном пользователем языке программирования для платформы .NET Framework (C#, Visual Basic .NET и т.п.). Многие декомпиляторы предоставляют возможность экспортировать декомпилированный код в проект для Microsoft Visual Studio. В общем случае компиляция декомпилированной программы является возможной. Для Native решений отсутствуют полноценные декомпиляторы.
3) Отладчики. Утилиты данного типа позволяют проводить отладку программного обеспечения и могут ассоциироваться как со встроенными в интегрированную среду разработки решениями, так и с компонентами, запускаемыми отдельно. В данном контексте под отладчиками будем понимать соответствующие инструменты, но применительно к дизассемблированным или декомпилированным формам программного обеспечения.
a. Для Native программных решений отладка происходит в режиме ассемблера соответствующей архитектуры процессора.
b. Для байт-кода (в качестве примера рассмотрим байт-код платформы .NET Framework) отладка может происходить как на уровне CIL (или другого промежуточного языка для другой платформы), так и на основе декомпилированных листингов (например, в случае успешного экспорта и компиляции результатов работы декомпилятора)
4) Инструменты мониторинга активности программного обеспечения. К таким инструментам можно отнести целый пакет утилит SysinternalsSuite [11].
Инструменты приведенных категорий обычно используются по отдельности применительно к исследованию функционирования программного обеспечения. В то же время они дают в значительной степени разнородные результаты своей работы. Так, в рамках одного программного решения могут быть как Native модули, так и компоненты разработанные под платформу .NET Framework. Тогда применение дизассемблера для Native модуля позволит получить ассемблерное представление программного решения, а использование декомпилятора для компонента, функционирующего под управлением .NET Framework – высокоуровневый программный код. Средства анализа активности программного обеспечения выявить наиболее интересные модули и участки программного кода. Применение отладчика дает возможность более подробно изучить некоторые элементы программного решения во время выполнения программы.
Приведем участок дизассемблированного представления Native (Рис. 1) и разработанного под платформу .NET Framework (Рис. 2) программного компонента. На рис 3. Изображен участок декомпилированного кода программного компонента, разработанного под платформу .NET Framework.
Рис 1. Дизассемблированное представление участка программного кода Native программного компонента.
Рис 2. Дизассемблированное представление участка программного кода компонента, разработанного под платформу .NET Framework.
Рис 3. Участок декомпилированного кода программного компонента, разработанного под платформу .NET Framework.
Приведенные на рис. 1-3 примеры реверс-инжиниринга являются наиболее простыми. Во всех случаях был рассмотрен программный код, вызывающий функцию MessageBox из библиотеки user32.dll. Данные примеры приведены для визуализации различий в результатах работы высокоуровневых декомпиляторов и дизассемблеров для Native и байт-кода платформы .NET Framework. Несмотря на наличие вызовов Windows API из программного модуля, реализованного на языке программирования C# под платформу .NET Framework, это не приводит к значительному усложнению декомпилированного и дизассемблированного листингов.
Таким образом, в ходе классического анализа программного обеспечения методом серого ящика применяются самые различные инструменты. Наиболее частыми из них являются дизассемблеры, декомпиляторы, отладчики, мониторы активности программных продуктов и многое другое.