|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2) Поиск местоположения программных функций. Кодокопатель может захотеть найти точку входа к нужной ему функции, в коде, который был подвергнут процедуре обфускации. Например, найти точку входа в функцию, осуществляющую криптографическое шифрование, для последующего анализа этой функции. Другой целью может быть поиск точного местоположения механизма защиты от копирования, чтобы обойти его. Например, местоположения функции проверки наличия аппаратного ключа или функции проверки лицензионного ключа. Здесь также могут быть такие подцели, как поиск ответа на общие вопросы, вроде: «Реализована ли в данной программе такая-то функциональность (например, алгоритм шифрования AES)?» или «Эта программа вредоносна или нет?». 3) Извлечение фрагментов кода. Кодокопатель может захотеть извлечь фрагмент кода (из программы, которая прошла процедуру обфускации) вместе со всеми смежными фрагментами, без которых интересующий фрагмент кода не будет работать. Например, извлечь криптографический алгоритм для создания кастомизированной процедуры дешифрования. Причем так, чтобы не пришлось полностью разбираться во всем бинарном коде этого алгоритма. Такой подход часто используется для обхода DRM-механизмов. Например, чтобы не разбираться, как именно работает процедура дешифрования, встроенная в медиаплеер, она просто вырезается из этого плеера и встраивается в пиратский плеер, который расшифровывает цифровые носители без применения ограничительных механизмов DRM. Другой целью может быть использование фрагментов кода из коммерческого ПО конкурентов. В этом втором примере интересующий фрагмент кода может иметь значительные размеры, и поэтому поиск смежных участков кода, без которых он не может работать, представляет собой нетривиальную задачу. Для того чтобы избавить себя от решения этой сложной задачи, кодокопатели иногда предпринимают следующий трюк: запускают программу конкурента целиком, находят точку входа нужной функции и передают ей необходимые входные данные. Такой подход чем-то схож с концепцией ROP-программирования (Return Oriented Programming; возвратно-ориентированное программирование), которая подразумевает повторное использование фрагментов кода целевой программы для создания в ней новой функциональности [26]. 4) Понимание кода. Кодокопатель хочет полностью понять фрагмент кода из программы, которая прошла процедуру обфускации, или даже всю программу. Например, кодокопатель может захотеть разобраться, как работает проприетарная процедура шифрования, встроенная в программу, с тем, чтобы в дальнейшем определить стратегию криптоанализа. Другими мотивами кодокопателя здесь могут быть: стремление найти уязвимости, исправить недостатки в ПО, исходный код которого недоступен, или создать новые программные продукты, которые совместимы с проприетарным программным обеспечением, изготовленным сторонней софтверной компанией. Так или иначе, все цели из этой категории, как правило, связаны со стремлением получить подробные сведения о реализации проприетарных компонентов: форматы файлов, протоколы взаимодействия, что зачастую представляет собой кражу интеллектуальной собственности. Четыре основополагающих метода деобфускации1) Сопоставление шаблонов. Простейший и самый быстрый метод анализа. Представляет собой синтаксический разбор бинарного кода программы: идентификацию статичных последовательностей инструкций при помощи регулярных выражений и интеллектуальных классификаторов данных (основанных на технологии машинного обучения). Это быстрые автоматические методы для поиска и распутывания известных фрагментов бинарного кода исследуемой программы. Под «известными фрагментами бинарного кода» здесь подразумеваются артефакты, оставленные утилитами обфускации, сигнатуры известных библиотек и т.п. В отличие от методов статического и динамического анализа сопоставление шаблонов подразумевает исключительно синтаксическое исследование кода. Анализ семантики программы при этом не осуществляется. Типы шаблонов могут варьироваться от простых бинарных цепочек до регулярных выражений и скриптовых языков, допускающих использование метасимволов.
Один из наиболее популярных инструментов, реализующих метод сопоставления шаблонов, – это технология F.L.I.R.T. (Fast Library Identiftcation and Recognition Technology), встроенная в дизассемблер IDA. F.L.I.R.T. использует сигнатуры для идентификации библиотечных функций с целью упрощения процесса ручного анализа бинарного кода. Распознанные функции именуются и комментируются с использованием сохраненной (внутри F.L.I.R.T.) информации, чтобы помочь кодокопателю понять соответствующий участок кода. 2) Автоматический статический анализ. Представляет собой анализ семантики бинарного кода, без фактического выполнения программы. Наиболее распространенные инструменты, реализующие метод автоматического синтаксического анализа, – это дизассемблеры. Инструменты автоматического статического анализа могут использоваться:
Примеры инструментов, реализующих метод статического анализа: CODESURFER/X86 [15], JAKSTAB [32], BAP [8]. Слабость синтаксического анализа в сравнении с динамическим анализом заключается в том, что в результирующем графе потока выполнения содержатся даже те части программы, на которые управление никогда не передается. Подробное введение в статический анализ представлено в классическом учебнике [5]. 3) Автоматический динамический анализ. Инструменты, реализующие этот метод анализа бинарного кода, запускают анализируемую программу на выполнение и наблюдают за ее активностью. Преимущество динамического анализа в том, что с его помощью можно очень точно определить поведение программы вдоль наблюдаемых трасс выполнения (из графа потока управления). Однако данные, собранные из одного или нескольких прогонов программы, не являются достаточными, чтобы делать выводы о поведении программы в целом. Потому что если программа проявляет определенный тип поведения только при очень специфических обстоятельствах, то на соответствующий код программа может не попасть даже при многих прогонах. Примеры инструментов, реализующих методы автоматического динамического анализа:
Подобные инструменты, реализующие методы динамического анализа, являются на сегодняшний день важной частью криминалистики [42]. По сравнению со статическим анализом практическое преимущество динамического анализа при распутывании кода, подвергнутого обфускации, в том, что инструменты, реализующие методы динамического анализа, более легко оперируют бинарными файлами. Зачастую анализировать бинарный код динамически даже намного проще, чем подвергнутый обфускации исходный код, из которого этот бинарный код скомпилирован. Потому что следы, зафиксированные в рантайме, показывают распутанное поведение программы. Поэтому утилиты динамического анализа могут легко отслеживать самомодифицирующийся код, воспринимая его как обычный код [21]. Статическим анализаторам эта задача не по зубам. 4) Ручной анализ. Сколь бы совершенными ни были специализированные автоматические утилиты анализа, они обеспечивают максимально полезный результат только тогда, когда находятся в умелых руках живого кодокопателя, т.е. работают не в автоматическом режиме, а в автоматизированном. Стандарт де-факто в этом отношении – дизассемблер IDA, который на сегодняшний день включает в себя декомпилятор для всех трех распространенных архитектур процессора: x86, x64 и ARM. Еще один полезный инструмент: PHOENIX [2]. Это относительно новый декомпилятор, преобразующий бинарные файлы в исходные коды языка Си. PHOENIX реализует алгоритм структурного анализа, который использует итеративные стратегии уточнения. Основной движущей силой развития техник и утилит ручного анализа является мотив «понимания кода». Как правило, в контексте взлома программного обеспечения. В давние времена стандартом де-факто для этого был отладчик SoftICE. Однако поскольку этот непревзойденный инструмент больше не поддерживается, кодокопатели вынуждены пользоваться менее могущественной альтернативой – отладчиком OllyDBG.
Отладчик OllyDBG в какой-то степени обеспечивает те возможности, которые раньше кодокопателям предоставлял SoftICE, плюс для него есть большое количество плагинов, автоматизирующих процесс взлома. Например, Ollybone [23] для полуавтоматической распаковки. Наиболее удачное и подробное введение в реверсинг софта изложено в учебнике «Reversing: Secrets of Reverse Engineering» [24]. 14 сценариев деобфускацииОтталкиваясь от четырех вышеперечисленных мотивов и четырех вышеперечисленных методов, я классифицировал все потенциально возможные виды сценариев деобфускации, распределив их по 14 категориям. Ниже представляю краткое описание всех этих 14 категорий, а в конце для каждой из этих категорий даем ссылки на наиболее полезные доклады и статьи из опубликованных за последние 20 лет. 1) Поиск местоположения данных посредством сопоставления шаблонов. Сопоставляющий алгоритм используется для определения наличия и местоположения данных, которые удовлетворяют заданному шаблону. Шаблоны, через которые осуществляется автоматическая идентификация данных внутри программы, описывают структуру этих данных: длина, тип данных, окружающий эти данные код. 2) Поиск местоположения кода посредством сопоставления шаблонов. Отдельные фрагменты кода обнаруживаются посредством сопоставления шаблонов. Например, цепочки команд с использованием метасимволов. Благодаря метасимволам сопоставляющий алгоритм способен распознать гипотетическую цепочку «A-B-C-D», даже если она присутствует не полностью (например, «A-B-D») или в нее произведена вставка (например, «A-B-X-C-D»). 3) Поиск местоположения данных посредством статического анализа. При статическом анализе интерпретируется семантика программы для локализации искомых данных. Например, локализуя входные аргументы, которые передаются в функцию, можно выявить криптографический ключ, который используется для дешифрования носителя данных с DRM-защитой или для отправки данных на внешнее устройство. 4) Поиск местоположения кода посредством статического анализа. Этому сценарию следуют некоторые из дизассемблеров, которые интерпретируют инструкции из потока команд, используя эвристику или формальные методы. Граф потока управления, как правило, позволяет распознавать характерные структуры. Например, характерные особенности управляющего потока, присущие криптографическому алгоритму, помогают локализовать в бинарном файле реализацию соответствующего алгоритма. 5) Извлечение кода посредством статического анализа. Здесь статический анализ используется для выявления зависимостей извлекаемого фрагмента кода, которые необходимо извлечь вместе с основным кодом, чтобы его можно было автономно выполнять за пределами исходной программы. 6) Понимание кода посредством статического анализа. В этом сценарии задействуются статические методы деобфускации, которые способны преобразовывать запутанный код либо необходимый фрагмент программы, либо всю программу в низкоуровневое или высокоуровневое представление, удобное для ручного анализа. 7) Поиск местоположения данных посредством динамического анализа. Инструменты динамического анализа наблюдают в рантайме за данными, к которым программа обращается или которые программа сохраняет, и затем используют эти наблюдения для локализации искомых данных. Например, в параметрах системных вызовов или в определенных ячейках памяти. 8) Поиск местоположения кода посредством динамического анализа. Динамический анализ позволяет отследить в рантайме поведение программы и ее взаимодействие с окружающей средой, в которой эта программа выполняется. Например, обращение к системным вызовам. В этом сценарии искомая функциональность локализуется посредством выявления специфичного рантайм-поведения программы. 9) Извлечение кода посредством динамического анализа. В этом сценарии локализуется искомый фрагмент кода и определяются его зависимости вдоль наблюдаемых следов выполнения. Поскольку след, полученный из однократного прогона программы, как правило, не покрывает всех зависимостей извлекаемого фрагмента кода, программа прогоняется несколько раз. В конце концов формируется итоговый граф потока управления, по которому затем извлекается весь нужный код со всеми нужными зависимостями, чтобы в итоге этот код мог выполняться автономно. 10) Понимание кода посредством динамического анализа. Аналогично сценарию понимания кода для статического анализа здесь задействуются автоматические методы динамической деобфускации, которые способны преобразовывать запутанный код либо необходимый фрагмент программы, либо всю программу в низкоуровневое или высокоуровневое представление, удобное для ручного анализа. 11-14) Ручной анализ (четыре сценария). Статические или динамические подходы, усиленные ручным анализом, преследуют своей целью получить полное понимание о представляющем интерес аспекте программы. Этот аспект может представлять собой:
Таблица 1. Ссылки на наиболее полезные доклады и статьи по анализу кода
Ключевые слова: деобфускация, бинарный код. Комментарии отсутствуют
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|