Akira промахнулся
На данную статью меня вдохновила работа коллег из компании Avast. Мне скинули ее товарищи со словами, вот и про тебя не забыли упомянуть. Ну, приятно же, когда западные коллеги соблюдают нормы приличия и упоминают источники информации, не смотря на всю эту вакханалию с геополитикой.
Прочитав статью Avast, я нашел в ней несколько косяков, связанных с тем, что коллеги неверно интерпретировали режимы шифрования Akira, полученные в результате их анализа образцов. Вследствие этого, декриптор не будет корректно обрабатывать некоторые зашифрованные файлы. Я сразу отписал им про это, получился в итоге достаточно адекватный диалог, один из авторов утилиты заверил, что они предварительно проверяют значения полей метаданных зашифрованных файлов, соответственно зашифрованные файлы с другими значениями в метаданных декриптор обрабатывать не будет, а главное, не будет и портить их. Ну окей, почему бы и нет, их право, будут обновлять утилиту расшифровки в ходе эксплуатации, не проблема. За инфу сказали спасибо, на этом мы любезно разошлись. Еще раз хочу сказать, что мне нравится, когда профессионализм не смешивается с эмоциями, которых сейчас и так чересчур много, даже в нашем сообществе ИБ.
В последнее время я взял за правило после исследования очередного семейства программ-вымогателей публиковать посвященные этому семейству скрипты. В основном, эти скрипты предназначены для извлечения конфигурации программ-вымогателей, для анализа образцов, для расшифровки файлов и т.п. Скрипты расшифровки файлов, по моему мнению, наглядно демонстрируют криптосхему и особенности шифрования, реализованные в конкретном семействе программ-вымогателей. Могут они помочь и с расшифровкой файла, если есть приватный ключ. Поначалу я делал все это исключительно для себя, но потом стал регулярно получать положительные фидбеки от коллег. Это дополнительно стало мотивировать и дальше делиться подобной информацией.
Программами-вымогателями, используемыми для атак на западные компании, в настоящее время занимаюсь больше по инерции и в качестве хобби. Что греха таить, наши соотечественники талантливы во всем, анализ созданных ими программ-вымогателей так же сложен, как и интересен. Встречаются крайне интересные идеи и решения. История с LockBit показала, что этот труд оказывается нужным и с точки зрения приоритетов моей работы. После утечки билдеров LockBit 3.0 Black в сентябре 2022 года, эти программы-вымогатели стали активно использоваться для атак на российские компании. В качестве примера могу привести группу Shadow Ransomware, которая особенно преуспела в этом.
Впервые образец Akira для Windows мне попался в конце апреля, а в июне обнаружил первый образец Akira для Linux. Тогда еще, в апреле, сразу опубликовал скрипты и YARA-правило для Akira.
Итак, в чем кроется «секрет» расшифровки Akira Ransomware?
Программа-вымогатель Akira для Windows шифрует файлы потоковым алгоритмом шифрования ChaCha20/8 — это быстрый вариант ChaCha20 с 8 раундами. Алгоритм ChaCha20 разработал ныне живущий гений криптографии Daniel Bernstein. В качестве ключа в ChaCha20 используются данные размером 32 байт, также для предотвращения атаки повторного воспроизведения используется одноразовый код (nonce) размером 8 или 12 байт. В Akira используется nonce размером 8 байт, но в данном случае это не имеет никакого принципиального значения. Номер текущего блока ChaCha20 определяется значением счетчика 64-байтных блоков ChaCha20 (counter), в самом начале шифрования он обычно равен 0. Счетчик инкрементируется после каждого обработанного блока ChaCha20. Также есть еще и константы общим размером 32 байта, некоторые авторы шифровальщиков экспериментируют с ними, изменяя их. Например, в некоторых образцах семейства шифровальщиков Proxima используется »hardcore blowjob» вместо стандартных »expand 32-byte k». В Akira же используются стандартные константы. Со своей стороны всячески рекомендую познакомиться более детально с алгоритмом, который давно завоевал широкую популярность.
Итак, при запуске программа-вымогатель Akira генерирует ключ (32 байта) и nonce (8 байт) (рис. 1).
Рис. 1 Фрагмент кода генерации ключа и nonce в Akira
Видим, что все честно: для генерации ключа (32 байта) и nonce (8 байт) используется функция Crypto API CryptGenRandom
, затем эти данные (40 байт) шифруются публичным ключом RSA-4096, содержащимся в теле программы-вымогателя. Функция CryptGenRandom
генерирует случайные данные качественно с точки зрения криптографии и претензий в этом смысле не вызывает. Чтобы сразу отмести первый вариант, который может прийти в голову: сбрутить 40 качественно сгенерированных случайных байт или получить их из зашифрованных RSA-4096 данных без приватного ключа не реально. Так как же можно расшифровать данные? Вся прелесть в том, что приведенный выше код выполняется только один раз, при запуске программы-вымогателя, то есть сгенерированные ключ и nonce ChaCha20/8 используются для шифрования всех файлов на хосте!
Теперь обратимся к зашифрованным Akira файлам. Они могут шифроваться 3 различными способами:
0 (full) | Полное шифрование. |
1 (part) | Частичное шифрование. |
2 (spot) | Шифрование блоками («пятнами»). |
У программ-вымогателей Akira есть параметр командной строки ‑‑encryption_percent
, с помощью которого задается процент шифрования данных в файле. По умолчанию он равен 50 (‑‑encryption_percent=50
). В этом случае при частичном шифровании шифруется первая половина файла, а в больших файлах — 4 блока. Специалисты Avast при создании своего декриптора рассматривали только этот конкретный случай. Не буду здесь расписывать, как вычисляются размеры блоки и интервалы между блоками. С этим всем можно ознакомиться скриптах, посвященных семейству Akira. Отмечу только, что если указать значение процента шифрования более 50, например ‑‑encryption_percent=80
, блоки наслаиваются и их части шифруются повторно несколько раз, что однозначно является еще одним «косяком» авторов Akira.
После шифрования файла в его конец дописывается блок метаданных размером 534 байта следующего формата:
Смещение | Размер | Описание |
000h | 512 | Зашифрованные с помощью RSA-4096 ключ и nonce ChaCha20/8 (32 + 8 байт) |
200h | 12 | Нулевые байты (не используется) |
20Ch | 1 | Способ шифрования: |
20Dh | 1 | Процент шифрования данных в файле (0…100). По умолчанию используется значение 32h (50%) |
20Eh | 8 | Размер оригинального файла в байтах (little endian) |
Так все-таки, как расшифровать файлы? Алгоритм ChaCha20, как и другие потоковые алгоритмы, создает условно бесконечный ключевой поток (keystream), который используется для шифрования данных. В ChaCha20 keystream определяется ключом и nonce. Позиция в keystream определяется counter и позицией байта в текущем блоке. Начальное значение counter в Akira равно 0. При шифровании байт данных перемножается по модулю 2 (побайтовая операция XOR) с текущим байтом keystream (рис. 2).
Рис. 2. Фрагмент кода на Python, реализующий алгоритм ChaCha20
Резонно, если ключ и nonce одинаковые для всех файлов хоста, значит у всех зашифрованных файлов будет одинаковый keystream. Очевидно, что nonce не выполнил в Akira своего изначального предназначения. Таким образом, для расшифровки данных можно обойтись без ключа и nonce, а будет достаточно готового keystream, но достаточной длины. А чтобы получить keystream нужна пара файлов: зашифрованный файл и соответствующий ему оригинальный файл. С помощью операции XOR между соответствующими байтами можно получить заветный keystream, который позволит расшифровать остальные файлы также с помощью операции XOR. Очевидно, что чем длиннее получится извлечь keystream ChaCha20, тем больше удастся расшифровать файлов на хосте. Я опубликовал концепт скрипта Python для извлечения keystream, который можно доработать в свой альтернативный декриптор Akira.
Единственный нюанс, на который следует обратить внимание. При шифровании блоками (spot) нарушается последовательность потока keystream ChaCha20, это вызвано тем, что авторы Akira решили при шифровании следующего блока задавать следующее значение counter. Это можно увидеть в опубликованном скрипте расшифровки файла. Соответственно, это приведет к тому, что в извлеченном keystream в пограничных блоках ChaCha20 не будет хватать последних байтов (от 1 до 63 байт) до конца необработанного блока ChaCha20. Эту проблему можно решить использованием дополнительной пары или пар зашифрованного и оригинального файлов, что позволит восполнить неизвестные байты и соответственно получить непрерывный keystream. Ну, а далее дело техники — расшифровка осуществляется аналогично шифрованию Akira, только используется извлеченный keystream и побайтовая операция XOR.
Ничего нового в таком подходе нет, год назад мы разработали аналогичный декриптор для Hive, который позволил успешно расшифровать данные в больнице в одной стране Юго-Восточной Азии…