Контакты
Подписка
МЕНЮ
Контакты
Подписка

Реверс-инжиниринг в контексте безопасности настольных и мобильных приложений

Реверс-инжиниринг в контексте безопасности настольных и мобильных приложений

В рубрику "Защита информации" | К списку рубрик  |  К списку авторов  |  К списку публикаций

Реверс-инжиниринг в контексте безопасности настольных и мобильных приложений


Анна Андреева,
инженер Департамента тестирования безопасности белорусской компании
ЗАO«Технологии качества», бренд A1QA

Не секрет, многие из нас в детстве пытались разобрать игрушку, чтобы понять, как она устроена изнутри. Эта привычку некоторые пронесли через всю жизнь, применяя любопытство уже в своей профессии. По этому же примеру кодеры пытаются «разобрать» устройство программы, чтобы исправить ошибки либо усовершенствовать ее.

Что же из себя представляет Реверс-инжиниринг в IT?

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

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

Однако Реверс-инжиниринг зачастую используется «не по назначению» - ведь изучив архитектуру приложения или получив исходный код, можно внести в него изменения и использовать в своих «корыстных» целях. Вот несколько примеров:

  • Бесконечное использование пробных версий приложения. Скажем, у нас есть продукт, которым мы можем бесплатно пользоваться на протяжении месяца. При запуске приложения происходит проверка даты установки относительно текущей. Удалив эту проверку или заменив ее функцией, которая всегда будет возвращать нужный результат, приложение навсегда останется в режиме пробного использования.
  • Кража информации или кода. Целью злоумышленника может стать не само приложение, а его модуль или часть. Такая тактика актуальна для конкурирующих компаний по разработке ПО.
  • Обход технических средств защиты авторских прав. Целью взломщика является снятие защиты от копирования аудио и видео файлов, компьютерных игр, электронных книг для последующего свободного распространения.

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

Процесс получения исходного кода зависит от языка программирования и платформы, так как является процессом обратной компиляции. Например, приложения, разработанные в .Net framework, сначала компилируются в промежуточный язык Common Intermediate Language (CIL), а затем преобразуются в машинный код посредством Common Language Runtime (CLR) во время выполнения. Аналогично работает и компиляция Java и Python приложений: высокоуровневый код сначала компилируется в промежуточный язык низкого уровня — байт-код, а затем преобразуется в машинный код just-in-time компилятором.

Такая организация обеспечивает кроссплатформенность, а также позволяет писать различные части приложения на разных языках в рамках одного фреймворка. Однако, с точки зрения реверс-инжиниринга, из промежуточного языка (как CIL, так и байт-кода) можно получить информацию о классах, структурах, интерфейсах и т.д. и восстановить исходную архитектуру. Для этого существуют готовые утилиты, такие как .Net Reflector, MSIL Disassembler, ILSpy, dotPeek для .Net приложений, Javap, JAD, DJ для восстановления Java из байт-кода и pyREtic, pycdc, Uncompyle2 для работы с Python-приложениями.

Если злоумышленник в достаточной степени знаком с CIL или байт-кодом, то рано или поздно он сможет внести в него изменения, заново скомпилировать и заставить приложение работать в своих целях.

Реверс-инжиниринг приложений традиционных языков программирования (например, С, С++ илиObjectiveC) является более сложной задачей. Приложения, написанные на них, сразу компилируются в исполняемый машинный код, который не хранит в себе никакой информации о структуре исходного приложения: имен классов, названий функций или переменных и т.д. Дополнительным препятствием является то, что представление низкого уровня не содержит конструкций ветвления (if, forи т.п.), а для их восстановления требуется построения графа потока управляющих конструкций программы. Это требует значительных временных затрат. Но и это не может гарантировать сохранность исходного кода приложений. Имея глубокие знания в Assembler и навыки программирования, задача восстановления исходного кода (или идентичного по функциональности) становится лишь вопросом времени.

Так как же обезопасить свое приложение? Или хотя бы усложнить задачу злоумышленнику? Вот несколько популярных способов:

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

  • Проверка целостности – подтверждение того, что код не был изменен. Для этого подсчитываются контрольные суммы разных участков кода приложения и в случае несовпадения с заданным значением, приложение прекращает работать. Однако здесь тоже есть свои сложности – если злоумышленник получит доступ к исходному коду приложения, то он сможет удалить проверку целостности или заменить ее функцией, всегда возвращающей нужный результат.

  • Шифрование программного кода – проверка того, что только «легальные» покупатели могут использовать приложение, то есть без ключа шифрования программа становится неработоспособной, либо работает только по trial веткам. Однако и здесь ничто не может гарантировать сохранность кода – ведь можно раскрыть механизм генерирования ключей.

Существуют и другие методы защиты – водяные знаки, вынесение критических участков кода в отдельные модули, защищенные среды исполнения и т.д., однако ни один из них не может обеспечить полной безопасности. Подход к защите приложения должен быть уникален для каждого конкретного случая.

К примеру, обфускация кода не только является средством защиты, но в некоторых случаях может повышать производительность. Так, запись кода в одну строку или замена имен переменных на более краткие и неочевидные приводит к уменьшению размера сборки и увеличению производительности работы приложения. Однако такие виды обфускации как добавление веток кода или псевдонимов могут снижать скорость работы.

Поэтому выбирая методы для защиты кода, прежде всего, нужно руководствоваться моделью угроз, а именно: что в приложении нужно защищать и какими способами злоумышленник может попытаться это получить. Если это изменение кода – то стоит делать упор на проверку целостности, а если изучение части приложения – стоит рассмотреть вариант обфускации или шифрования. Хотя гарантированного решения не существует, при помощи описанных методов защиты можно максимально усложнить задачу злоумышленнику.

Опубликовано: Сайт ITSec.Ru-2014

Приобрести этот номер или подписаться

Статьи про теме