Статья расскажет на примере алгоритма AES как можно найти конструкции алгоритма шифрования и доказать, что приложение действительно использует именно этот алгоритм для преобразования данных. Почему реверсить крипту сложно? Если рассматривать обратную разработку как дисциплину, в которой анализ данных подразделяется на различные виды, то можно выделить следующие группы: обратная разработка приложений из операционной системы; обратная разработка прошивок устройств; обратная разработка формата файла. Считается, что наиболее простой вариант обратной разработки - обратная разработка приложений из ОС. В этом виде обратной разработки руководствуются простыми правилами: Анализ приложения=чтение документации по API операционной системы. Анализ приложения проще провести на уже запущенном приложении (есть возможность писать лог вызова API функций). До 90% алгоритма таких приложений можно восстановить не вникая в промежуточные преобразования, а просто читать последовательность вызовов API функций. При таком подходе очень просто выявлять авторские конструкции, который использует программист. Потому что остальной код будет практически полностью обитать в библиотеках операционной системы. Давайте рассмотрим такой пример, приложение для операционной системы windows должно произвести процедуру шифрования файла с использованием популярного алгоритма шифрования. Давайте для примера выберем AES. Какие API библиотеки и функции для этого может предложить операционная система: Стандартная библиотека для криптографии:  старые версии ОС до 10й - wincrypt.h новые версии ОС от 10 - bcrypt.h Функции для работы с AES wincrypt.h:  CryptAcquireContext -> должна вызываться с параметрами, которые описывают алгоритм AES CryptGenKey CryptEncrypt CryptReleaseContext Для bcrypt.h: BCryptOpenAlgorithmProvider -> должна вызываться с параметрами, которые описывают алгоритм AES BCryptGetProperty BCryptGenerateSymmetricKey BCryptEncrypt По сути на этом шах и мат, больше ничего не нужно знать, чтобы понять где будет вызываться процедура шифрования. То есть чтобы дальше получить необходимые данные от приложения или заставить его выдать ключ необходимо просто поставить точку останова в отладчике на нужно функции (определяется задачей исследования) и все данные теперь доступны. В итоге профит. Всё бы это было так просто, если бы не одно НО - операционные системы позволяют приложениям приносить с собой библиотеки, которые приложение будет использовать для части своего функционала. Той части, которая будет выполнять что-то действительно полезное - считывать информацию из проприетарного формата файла, шифровать данные и т.д. и в этом случае API функции операционной системы будут вызываться только в случае, если приложению необходимо получить доступ к ресурсам ОС или устройству. Именно в этом варианте анализ приложения перестает быть такой простой задачей и нужно будет погружаться в особенности того как приложение работает с данными и что именно делает. Чтобы делать это успешно нужно представлять что именно мы ищем. В нашей статье будем разбираться именно с криптографическими алгоритмами, но аналогичные рассуждения можно производить и по отношению к анализу любого другого алгоритма. И так шаги для проведения реконструкции алгоритма: выявить область применения; выяснить примитивы для обработки данных алгоритмом; выяснить какие наиболее популярные константы, конструкции кода используются для описания примитивов. В качестве примера попробуем разобраться с AES симметричным алгоритмом криптографии. Симметричные алгоритмы используются для преобразования большого количества данных, примитивы, которые они используют достаточно эффективно можно имплементировать на современном железе. Поэтому эти алгоритмы используются в разных режимах и являются основными рабочими лошадками если нужно очень много информации быстро преобразовать в нечитаемый вид. Соответственно отсюда область применения можно вычислить достаточно просто: алгоритма может применяться для шифрования файлов в несколько гигибайт объема; алгоритм может использоваться для так называемого поточного шифрования. Очень часто это шифрование работает при сетевых соединениях. Алгоритм использует достаточно сложный математический аппарат. Успех его анализа в приложении может зависеть от того как хорошо аналитик понимает этот математический аппарат. Так как на устройствах скорее всего используемые операции для преобразования данных могут оптимизироваться и заменяться наиболее эффективными аналогами. Это может затруднить анализ. Официальная документация алгоритма находится тут. Основная работа алгоритма AES начинается с того, что алгоритм будет разбивать данные порциями по 16 байт. Затем будет проводиться процедура шифрования. В зависимости от того какой режим работы и какой длины ключ был выбран, алгоритм будет проводить различной степени сложности преобразования. Чтобы было проще обрабатывать информацию, алгоритм создает так называемую таблицу и работает с её строками и столбцами. Основные действия при преобразовании данных: Замена байт по заложенному в алгоритм массиву. Перемешивание строк при преобразовании. Перемешивание столбцов при преобразовании. Добавление к данным блоков данных из ключа. С этим набором данных можно теперь поискать примеры имплементаций алгоритма. Алгоритм не может работать самостоятельно, генерируя все данные налету. Так происходит в силу того, что алгоритм должен иметь заданную стойкость для защиты данных, поэтому в такие алгоритмы как AES записывается таблица замены, которая участвует в примере действий 1, которую описали выше. Найти эту таблицу достаточно просто. В документации она указана последовательностью чисел, соответственно в приложениях это будет массив шестнадцатеричных чисел. Ниже примедена часть этих чисел: Как видно из последовательности, числа записаны так же в таблицу шириной в 16 байт, для удобства поиска нужных индексов. Из всего выше перечисленного у нас есть мощный артефакт, который можно использовать для поиска AES алгоритма шифрования в любом коде (если не позаботились сокрытием этих данных). Это данные таблицы замен. Кстати, уже существуют скрипты, которые позволяют обнаруживать самые популярные константы алгоритмов шифрования. Можно использовать например вот этот. Для этого этапа, пожалуй, лучше всего использовать представление файла в наиболее низкоуровневом варианте, то есть в ассемблерном листинге. Ниже будут примеры на псевдокоде, который очень схож с синтаксисом ассемблера для intel платформы. С разной степенью оптимизации код может отличаться, но основная суть будет одна и та же. Ниже приведены маски кода, которые получились от приложений, которые были скомпилированы без оптимизации: Алгоритм создания раундового ключа: Шаблон обработки алгоритма для перемешивания колонок или строк: Таким образом для идентификации алгоритма у нас есть: Набор констант для идентификации. Шаблон кода для идентификации примитивов алгоритма шифрования. Взяв эти данные можно искать алгоритмы криптографии, которые будут имплементироваться приложением самостоятельно согласно документации, либо обнаруживать собственные модифицированные версии. В заключение хочу пригласить всех на бесплатный урок курса Reverse Engineering, где рассмотрим проблемы, возникающие при восстановлении таблицы импорта, почему её нужно восстанавливать при снятии дампов памяти и на практике напишем свою программку на С для автоматизации процесса. Зарегистрироваться на бесплатный урок