Рубрика:
Безопасность /
Исследование
|
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|
АНТОН КАРЕВ, ведущий эксперт Алтайского края по кибербезопасности с 20-летним стажем. Окончил физтех АлтГУ. Занимается технологической разведкой и подготовкой аналитических обзоров для «красной» команды правительственных хакеров, anton.barnaul.1984@mail.ru
Полная классификация методов деобфускации бинарного кода десктопных приложений
Изучив отраслевые доклады с конференций и материалы из научных журналов, опубликованные за последние 20 лет, можно выделить четыре основополагающих мотива, которыми вдохновляются элитные кодокопатели, разрабатывающие все новые и новые методы деобфускации, и также четыре категории методов деобфускации, к которым сводятся все ныне существующие методы анализа бинарного кода
Отталкиваясь от этих четырех мотивов и четырех методов, я классифицировал все потенциально возможные виды сценариев деобфускации, распределив их по 14 категориям. Приведу краткое описание всех этих 14 категорий и для каждой из этих категорий даем ссылки на наиболее полезные доклады и статьи, из опубликованных за последние 20 лет.
Четыре мотива, которыми вдохновляются кодокопатели
В зависимости от преследуемых целей, доступных ресурсов и срочности кодокопатель прибегает к тому или иному методу деобфускации.
С одной стороны, например, крупная софтверная компания, которая пытается понять защищенный обфускацией фрагмент бинарного кода из программы конкурента, может позволить себе прибегнуть к сложным и времезатратным методам деобфускации, поскольку она не ограничена в ресурсах и во времени.
С другой стороны, поставщик антивирусного ПО, которому необходимо оперативно анализировать сотни тысяч различных образцов вредоносных фрагментов кода, на ежедневной основе осуществляет упрощенный и менее затратный по времени анализ.
Четыре основополагающих мотива кодокопания (расположены в порядке увеличения сложности реализации соответствующих этим мотивам действий):
1) Поиск местоположения данных. В бинарный код программы могут быть зашиты конфиденциальные данные, причем не открытым текстом, а в запутанном виде, с прогоном через процедуру обфускации. Кодокопатель может преследовать цель заполучить эти данные в их изначальном виде, какими они были до процедуры обфускации. Например, извлечь секретный криптографический ключ, чтобы иметь возможность расшифровывать данные в другом контексте, нежели тот, который предусмотрен легальным использованием программы. В частности, для обхода DRM-механизмов.
Другие типичные примеры, которые относятся к этой категории мотивов, – извлечение лицензионных ключей, сертификатов, учетных данных для удаленного доступа к сервисам, извлечение данных о конфигурации устройства.
Мотивы кодокопателя: стремление найти уязвимости, исправить недостатки в ПО, исходный код которого недоступен, или создать новые программные продукты, которые совместимы с проприетарным ПО, изготовленным сторонней софтверной компанией |
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) Автоматический динамический анализ. Инструменты, реализующие этот метод анализа бинарного кода, запускают анализируемую программу на выполнение и наблюдают за ее активностью.
Преимущество динамического анализа в том, что с его помощью можно очень точно определить поведение программы вдоль наблюдаемых трасс выполнения (из графа потока управления).
Однако данные, собранные из одного или нескольких прогонов программы, не являются достаточными, чтобы делать выводы о поведении программы в целом. Потому что если программа проявляет определенный тип поведения только при очень специфических обстоятельствах, то на соответствующий код программа может не попасть даже при многих прогонах.
Примеры инструментов, реализующих методы автоматического динамического анализа:
- управляемые фаззеры (такие, как AFL);
- утилиты, основанные на символическом выполнении [17],
- динамические генераторы тестов [18, 19, 20].
Подобные инструменты, реализующие методы динамического анализа, являются на сегодняшний день важной частью криминалистики [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. Ссылки на наиболее полезные доклады и статьи по анализу кода
|
Сопоставление шаблонов |
Автоматический статический анализ |
Автоматический динамический анализ |
Ручной анализ |
Локализация данных |
[9] |
[32] [44] |
[28] [29] [40] [41] |
[14] [22] [25] |
Локализация кода |
[1] [10] |
[3] [7] [44] |
[4] [27] [39] [43] |
[16] [35] |
Извлечение кода |
Неприменимо |
[33] |
[4] [37] [38] |
[12] [13] |
Понимание кода |
Неприменимо |
[11] [30] |
[34] |
[6] [31] [36] |
- Mila Dalla. Modeling Metamorphism by Abstract Interpretation // Theoretical Computer Science. v.577, 2015, pp. 74-97.
- Edward Schwartz. Native x86 Decompilation Using Semantics-Preserving Structural Analysis and Iterative Control-Flow Structuring // Proceedings of the 22th Usenix Security Symposium. 2013, pp. 353-368.
- Martial Bourquin. BinSlayer: accurate comparison of binary executables // Proceedings of the 2nd ACM SIGPLAN Program Protection and Reverse Engineering Workshop. 2013.
- Junyuan Zeng. Obfuscation Resilient Binary Code Reuse through Trace-Oriented Programming // Proceedings of the 20th ACM Conference on Computer and Communications Security. 2013, pp. 487-498.
- Flemming Nielson. Principles of Program Analysis. Springer. 1999. – 452 p.
- Dhiru Kholia. Looking inside the (Drop)Box // Proceedings of the 7th USENIX Workshop on Offensive Technologies (WOOT). 2013.
- Gregoire Jacob. A Static, Packer-Agnostic Filter to Detect Similar Malware Samples // Proceedings of the International Conference on Detection of Intrusions and Malware & Vulnerability Assessment (DIMVA). 2012, pp. 102-122.
- David Brumley. A Binary Analysis Platform // Proceedings of the 23th International Conference on Computer Aided Verification (CAV). 2011, pp. 463-469.
- Andreas Moser. Limits of Static Analysis for Malware Detection // Proceedings of the 23rd Annual Computer Security Applications Conference (ACSAC). 2007, pp. 421-430.
- Kent Griffin. Automatic Generation of String Signatures for Malware Detection // Proceedings of the International Workshop on Recent Advances in Intrusion Detection (RAID). 2009, pp. 101-120.
- Jason Raber. Deobfuscator: An Automated Approach to the Identification and Removal of Code Obfuscation // Proceedings of the 14th Working Conference on Reverse Engineering (WCRE). 2007, pp. 275-276.
- Chris Fox. A Fully Automated Conditioned Program Slicer // Software: Practice and Experience. 34(1), 2004, pp. 15-46.
- Sebastian Danicic. ConSUS: A Light-Weight Program Conditioner // Journal of Systems and Software. 77(3), 2005, pp. 241-262.
- Amitabh Saxena. Towards Security Notions for White-Box Cryptography // Proceedings of the International Conference on Information Security. 2009, pp. 49-58.
- Gogul Balakrishnan. Analyzing Memory Accesses in x86 Executables // Proceedings of the International Conference of Compiler Construction. 2004, pp. 5-23.
- Daniel Quist. Visualizing Compiled Executables for Malware Analysis // Proceedings of the 6th International Workshop on Visualization for Cyber Security (VizSec). 2009, pp. 27-32.
- James King. Symbolic execution and program testing // Communications of the ACM. 19(7), 1976, pp. 385-394.
- Patrice Godefroid. DART: Directed Automated Random Testing // Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI). 2005, pp. 213-223.
- Vijay Ganesh. EXE: Automatically Generating Inputs of Death // Proceedings of the 13th ACM Conference on Computer and Communications Security. 2006, pp. 322-335.
- Koushik Sen. CUTE: a concolic unit testing engine for C // Proceedings of the 10th European Software Engineering Conference held jointly with 13th ACM SIGSOFT International Symposium on Foundations of Software Engineering. 2005, pp. 263-272.
- Aditya Thakur. Directed Proof Generation for Machine Code // Proceedings of the 22th International Conference on Computer Aided Verification (CAV). 2010, pp. 288-305.
- Brecht Wyseur. White-Box Cryptography. Ph.D. Dissertation. KU Leuven. 2009.
- Joe Stewart. Ollybone: Semi-Automatic Unpacking on IA-32 // DEF CON. 2006.
- Eldan Eilan. Reversing: Secrets of Reverse Engineering. Wiley. 2005. – 624 p.
- Yoni De Mulder. Cryptanalysis of a Perturbated White-Box AES Implementation // Proceedings of the International Conference on Cryptology in India: Progress in Cryptology (INDOCRYPT). 2010, pp. 292-310.
- Hovav Shacham. The geometry of innocent flesh on the bone: Return-into-libc without function calls (on the x86) // Proceedings of the 14th ACM conference on Computer and communications security. 2007, pp. 552-561.
- Kevin Coogan. Deobfuscation of Virtualization-Obfuscated Software: A Semantics-Based Approach // Proceedings of the 18th ACM Conference on Computer and Communications Security. 2011, pp. 275-284.
- Anthony Cozzie. Digging for Data Structures // Proceedings of the 8th USENIX Symposium on Operating Systems Design and Implementation (OSDI). 2008, pp. 255-266.
- Zhiqiang Lin. Automatic Reverse Engineering of Data Structures from Binary Execution // Proceedings of the 17th Network and Distributed System Security Symposium (NDSS). 2010.
- Spencer Rugaber. The Interleaving Problem in Program Understanding // Proceedings of the 2nd Working Conference on Reverse Engineering (WCRE). 1995, pp. 166-175.
- Chris Eagle. The IDA Pro Book: The Unofficial Guide to the World’s Most Popular Disassembler. No Starch Press. 2008. – 650 p.
- Johannes Kinder. Jakstab: A Static Analysis Platform for Binaries // Proceedings of the 20th International Conference on Computer Aided Verification (CAV). 2008, pp. 423-427.
- Harry Sneed. Encapsulation of Legacy Software: A Technique for Reusing Legacy Software Components // Annals of Software Engineering 9(1-2), 2000, pp. 293-313.
- Sharath Udupa. Deobfuscation: Reverse Engineering Obfuscated Code // Proceedings of the 12th Working Conference on Reverse Engineering (WCRE). 2005.
- Rolf Rolles. Unpacking Virtualization Obfuscators // Proceedings of the 3rd USENIX Workshop on Offensive Technologies (WOOT). 2009.
- Matej Myska. The True Story of DRM // Masaryk University Journal of Law and Technology. 3(2), 2009, pp. 267-278.
- Clements Kolbitsch. Inspector Gadget: Automated Extraction of Proprietary Gadgets from Malware Binaries // Proceedings of the 30th IEEE Symposium on Security and Privacy. 2010, pp. 29-44.
- Juan Caballero. Binary Code Extraction and Interface Identification for Security Applications // Proceedings of Network and Distributed System Security Symposium (NDSS). 2009.
- Felix Grobert. Automated Identification of Cryptographic Primitives in Binary Programs // Proceedings of the 12th International Workshop on Recent Advances in Intrusion Detection (RAID). 2011, pp. 41-60.
- Ziming Zhao. Automatic Extraction of Secrets from Malware // Proceedings of the 18th Working Conference on Reverse Engineering (WCRE). 2011, pp. 159-168.
- Asia Slowinska. Howard: A Dynamic Excavator for Reverse Engineering Data Structures // Proceedings of Network and Distributed System Security Symposium (NDSS). 2011.
- Manuel Egele. A Survey on Automated Dynamic Malware-Analysis Techniques and Tools // ACM Computing Surveys 44(2), 2012.
- Joan Calvet. Aligot: Cryptographic Function Identification in Obfuscated Binary Programs // Proceedings of the 19th ACM Conference on Computer and Communications Security. 2012, pp. 169-182.
- Johannes Kinder. Towards Static Analysis of Virtualization-Obfuscated Binaries // Proceedings of the 19th Working Conference on Reverse Engineering (WCRE). 2012, pp. 61-70.
Ключевые слова: деобфускация, бинарный код.
Facebook
Мой мир
Вконтакте
Одноклассники
Google+
|