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

Общие данные

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

  • обратная разработка приложений из операционной системы;

  • обратная разработка прошивок устройств;

  • обратная разработка формата файла.

Считается, что наиболее простой вариант обратной разработки - обратная разработка приложений из ОС. В этом виде обратной разработки руководствуются простыми правилами:

  1. Анализ приложения=чтение документации по API операционной системы.

  2. Анализ приложения проще провести на уже запущенном приложении (есть возможность писать лог вызова API функций).

До 90% алгоритма таких приложений можно восстановить не вникая в промежуточные преобразования, а просто читать последовательность вызовов API функций. При таком подходе очень просто выявлять авторские конструкции, который использует программист. Потому что остальной код будет практически полностью обитать в библиотеках операционной системы.

Давайте рассмотрим такой пример, приложение для операционной системы windows должно произвести процедуру шифрования файла с использованием популярного алгоритма шифрования. Давайте для примера выберем AES. Какие API библиотеки и функции для этого может предложить операционная система:

  1. Стандартная библиотека для криптографии:

    • старые версии ОС до 10й - wincrypt.h

    • новые версии ОС от 10 - bcrypt.h

  2. Функции для работы с AES wincrypt.h:

    • CryptAcquireContext -> должна вызываться с параметрами, которые описывают алгоритм AES

    • CryptGenKey

    • CryptEncrypt

    • CryptReleaseContext Для bcrypt.h:

    • BCryptOpenAlgorithmProvider -> должна вызываться с параметрами, которые описывают алгоритм AES

    • BCryptGetProperty

    • BCryptGenerateSymmetricKey

    • BCryptEncrypt

По сути на этом шах и мат, больше ничего не нужно знать, чтобы понять где будет вызываться процедура шифрования. То есть чтобы дальше получить необходимые данные от приложения или заставить его выдать ключ необходимо просто поставить точку останова в отладчике на нужно функции (определяется задачей исследования) и все данные теперь доступны. В итоге профит.

Всё бы это было так просто, если бы не одно НО - операционные системы позволяют приложениям приносить с собой библиотеки, которые приложение будет использовать для части своего функционала. Той части, которая будет выполнять что-то действительно полезное - считывать информацию из проприетарного формата файла, шифровать данные и т.д. и в этом случае API функции операционной системы будут вызываться только в случае, если приложению необходимо получить доступ к ресурсам ОС или устройству. Именно в этом варианте анализ приложения перестает быть такой простой задачей и нужно будет погружаться в особенности того как приложение работает с данными и что именно делает.

Чтобы делать это успешно нужно представлять что именно мы ищем. В нашей статье будем разбираться именно с криптографическими алгоритмами, но аналогичные рассуждения можно производить и по отношению к анализу любого другого алгоритма.

И так шаги для проведения реконструкции алгоритма:

  • выявить область применения;

  • выяснить примитивы для обработки данных алгоритмом;

  • выяснить какие наиболее популярные константы, конструкции кода используются для описания примитивов.

В качестве примера попробуем разобраться с AES симметричным алгоритмом криптографии.

Пример сбора данных

Область применения

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

Соответственно отсюда область применения можно вычислить достаточно просто:

  • алгоритма может применяться для шифрования файлов в несколько гигибайт объема;

  • алгоритм может использоваться для так называемого поточного шифрования. Очень часто это шифрование работает при сетевых соединениях.

Примитивы для обработки данных

Алгоритм использует достаточно сложный математический аппарат. Успех его анализа в приложении может зависеть от того как хорошо аналитик понимает этот математический аппарат. Так как на устройствах скорее всего используемые операции для преобразования данных могут оптимизироваться и заменяться наиболее эффективными аналогами. Это может затруднить анализ.

Официальная документация алгоритма находится тут.

Основная работа алгоритма AES начинается с того, что алгоритм будет разбивать данные порциями по 16 байт. Затем будет проводиться процедура шифрования. В зависимости от того какой режим работы и какой длины ключ был выбран, алгоритм будет проводить различной степени сложности преобразования. Чтобы было проще обрабатывать информацию, алгоритм создает так называемую таблицу и работает с её строками и столбцами.

Основные действия при преобразовании данных:

  1. Замена байт по заложенному в алгоритм массиву.

  2. Перемешивание строк при преобразовании.

  3. Перемешивание столбцов при преобразовании.

  4. Добавление к данным блоков данных из ключа.

С этим набором данных можно теперь поискать примеры имплементаций алгоритма.

Популярные константы и кодовые конструкции

Алгоритм не может работать самостоятельно, генерируя все данные налету. Так происходит в силу того, что алгоритм должен иметь заданную стойкость для защиты данных, поэтому в такие алгоритмы как AES записывается таблица замены, которая участвует в примере действий 1, которую описали выше. Найти эту таблицу достаточно просто. В документации она указана последовательностью чисел, соответственно в приложениях это будет массив шестнадцатеричных чисел. Ниже примедена часть этих чисел:

0x63	0x7C	0x77	0x7B	0xF2	0x6B	0x6F	0xC5	0x30	0x01	0x67	0x2B	0xFE	0xD7	0xAB	0x76
0xCA	0x82	0xC9	0x7D	0xFA	0x59	0x47	0xF0	0xAD	0xD4	0xA2	0xAF	0x9C	0xA4	0x72	0xC0
0xB7	0xFD	0x93	0x26	0x36	0x3F	0xF7	0xCC	0x34	0xA5	0xE5	0xF1	0x71	0xD8	0x31	0x15
....

Как видно из последовательности, числа записаны так же в таблицу шириной в 16 байт, для удобства поиска нужных индексов.

Из всего выше перечисленного у нас есть мощный артефакт, который можно использовать для поиска AES алгоритма шифрования в любом коде (если не позаботились сокрытием этих данных). Это данные таблицы замен. Кстати, уже существуют скрипты, которые позволяют обнаруживать самые популярные константы алгоритмов шифрования. Можно использовать например вот этот.

Для этого этапа, пожалуй, лучше всего использовать представление файла в наиболее низкоуровневом варианте, то есть в ассемблерном листинге. Ниже будут примеры на псевдокоде, который очень схож с синтаксисом ассемблера для intel платформы.

С разной степенью оптимизации код может отличаться, но основная суть будет одна и та же. Ниже приведены маски кода, которые получились от приложений, которые были скомпилированы без оптимизации:

Алгоритм создания раундового ключа:

mov register, memory[source]
mov memory[source], register
...
...

add register, 4
cmp register, 0x10
...
...
xor register, memory[source]
xor register, memory[source]
int register
add register, 4
xor register, memory[source]
xor register, memory[source]
...

Шаблон обработки алгоритма для перемешивания колонок или строк:

xor register, register
call routine
xor register, register
mov register, register
xor register, register
xor register, register
xor register, register
xor register, register
...

Таким образом для идентификации алгоритма у нас есть:

  1. Набор констант для идентификации.

  2. Шаблон кода для идентификации примитивов алгоритма шифрования.

Взяв эти данные можно искать алгоритмы криптографии, которые будут имплементироваться приложением самостоятельно согласно документации, либо обнаруживать собственные модифицированные версии.

В заключение хочу пригласить всех на бесплатный урок курса Reverse Engineering, где рассмотрим проблемы, возникающие при восстановлении таблицы импорта, почему её нужно восстанавливать при снятии дампов памяти и на практике напишем свою программку на С для автоматизации процесса.

Комментарии (0)