Эксперт Positive Technologies Дмитрий Скляров представил сравнительный анализ нашумевшего вируса-вымогателя NotPetya, атаковавшего компании в этот вторник, с образцом Petya от 2016 года и поделился своими наблюдениями по поводу возможности восстановления зашифрованных ими данных.

Мы исследовали части двух вирусов, отвечающие за шифрование MFT. Данное шифрование выполняется при наличии у вымогателя прав администратора.

Что делает NotPetya


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

В первую очередь, посмотрим на сектор 0x20 диска, который является чем-то вроде «конфига» для конкретной машины. При заражении в сектор 0x20 записываются следующие значения:

— Признак того, что MFT не была зашифрована (значение 0)
— EncryptionKey (случайная последовательность длиной 32 байта)
— Nonce (случайная последовательность длиной 8 байт)
— Personal installation key (случайная последовательность длиной 60 символов из алфавита «123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz»)

Случайные данные получаются через функцию CryptGenRandom, которая считается криптографически стойкой.

В сектор 0x21 записывается 512 байт со значением 0x07.

В сектор 0x22 записывается оригинальный MBR, в котором каждый байт поXORен со значением 0x07.

После первой перезагрузки происходит зашифрование MFT. Перед этим:

— читается сектор 0x20,
— устанавливается признак зашифрования MFT (значение 1),
— EncryptionKey копируется во временный буфер,
— поле с EncryptionKey затирается нулевыми байтами
— сектор 0x20 записывается на диск,
— читается сектор 0x21 (все 0x07),
— его содержимое зашифровывается на EncryptionKey + Nonce,
— сектор 0x21 записывается на диск.

Затем сектора MFT зашифровываются на том же EncryptionKey + Nonce. Код алгоритма шифрования очень похож на алгоритм Salsa20, но есть отличия. Вместо константы «expand 32-byte k» используется константа «-1nvalid s3ct-id». И пока мне не удалось повторить результаты зашифрования на известном ключе. Возможно, у них где-то ошибка, что, похоже, подтверждается этим постом.

Алгоритм Salsa20 считается стойким.

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

Ключ должен быть строкой символов из набора «0123456789abcdef» длиной 32. Эта строка прогоняется через некую функцию, принимающую на вход произвольное кол-во байт, и выдающую 32 байта. Предположительно это хеш-функция SPONGENT (надо проверять). Затем выход циклически прогоняется через ту же функцию 128 раз, и этот результат принимается как EncryptionKey. Для проверки правильности ключа делается попытка расшифровать содержимое сектора 0x21, и если там оказывается ожидаемый открытый текст (все 0x07) – запускается процесс расшифрования MFT и восстановления MBR.

Могут ли злоумышленники расшифровать файлы пользователей


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

  1. Personal installation key, который надо сообщить авторам вируса после выплаты выкупа, никак не связан с EncryptionKey. И то, и другое — случайные данные. Из одного невозможно получить другое, если только злоумышленники не знают что-то про CryptGenRandom. Еще вариант — они должны отправлять пару EncryptionKey + Personal installation key на свой сервер, но о такой активности вроде никто не сообщал (и я ее в коде не видел, хотя это не исключено на 100%).

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

  3. Энтропия EncryptionKey составляет 32*8 == 256 бит. Энтропия hex-ключа, вводимого пользователем, составляет 32*4 == 128 бит. Любая операция может только уменьшить энтропию. Из 32 шестнадцатеричных символов невозможно получить 32 байта с определенными значениями.

Отличия от Petya образца 9 января 2016


Petya не захотел инфицировать мою тестовую машину. Может ему нужна сеть или что-то еще. Пришлось дампить из памяти.

Я не успел посмотреть код, который формирует сектора, используемые из устанавливаемого вредоносом MBR, но посмотрел скриншоты и код, который выполнится после перезагрузки.

Отличия:

  1. Используются сектора 0x36-0x39 (против 0x20-0x23 у NotPetya).
  2. Большинство сервисных функций (вывод текста, чтение/запись секторов) идентичны Petya.
  3. Присутствует функция и строки для вывода баннера с черепом. В NotPetya очень похожая функция тоже есть, но, вероятно, она никогда не вызывается, а строки обнулены.
  4. Длина Personal installation key составляет 90 символов (15 групп по 6 символов) против 60 у NotPetya. Используя алфавит из 58 символов можно закодировать максимум 527 бит информации (против 351 у NotPetya).
  5. В дампе Petya видны строки secp256k1 и secp192k1, что подталкивает к мысли о том, что Personal installation key является производным от EncryptionKey, и вычисляется при помощи криптографии на эллиптических кривых.
  6. Ключ, вводимый пользователем для запуска расшифрования, должен быть строкой из алфавита «123456789abcdefghijkmnopqrstuvwxABCDEFGHJKLMNPQRSTUVWX» длиной 16 символов.
  7. Нет ничего похожего на SPONGENT (или какой-то другой хеш).
  8. В Salsa20 используется оригинальная константа «expand 32-byte k». При этом, код функций почти идентичен, и если код Petya наверняка был сгенерирован компилятором (сработала оптимизация на повторяющихся символах), то в NotPetya, похоже, просто заменили константы.

Petya:



NotPetya:



Я бы предположил, что существовал другой образец Petya, на базе которого и был создан NotPetya путем замены констант и строк.

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

UPD



Среди различных версий вредоноса Petya от 2016 года, который под разными цветами (1, 2) выступал в дуэте с вымогателем mischa и еще в таком виде, следует обратить внимание на PetyaGoldenEye.malware, впервые отправленный на VirusTotal в декабре прошлого года.

Код, который NotPetya записывает при заражении в начало диска, и который запускается из MBR, чрезвычайно похож на код, записываемый PetyaGoldenEye: SHA256:b5ef16922e2c76b09edd71471dd837e89811c5e658406a8495c1364d0d9dc690.

Обнаруженные отличия NotPetya от PetyaGoldenEye:



  • Изменены многие текстовые строки (исправлен текст сообщения о выкупе, убрана картинка с черепом);
  • Изменены смещения до некоторых строк (начала строк «съехали» из-за изменения размера сообщений);
  • В функции по адресу 0000:86E0 перепрыгивается (никогда не выполняется) кусок кода, отвечающий за вывод баннера (мигающего «черепа с костями») до нажатия любой клавиши;
  • Там же изменен цвет баннера с желтого (0xE) на красный (0xC), но баннер все равно не показывается;
  • По адресу 0000:848E убран (заменен на три инструкции NOP) вызов функции, очищающей буфер клавиатуры (не требуется, так как не ожидалось нажатие);
  • В функции по адресу 0000:96D4 (expand для Salsa20) начальное состояние строки заменено с «expand 32-byte k» на «-1nvalid s3ct-id»;
  • В функции по адресу 0000:998E (permute для SPONGENT) изменено начальное значение LFSR (linear-feedback shift register), вместо 0x9E используется 0xA3.


Больше никаких изменений в коде не обнаружено. А теперь посмотрим на криптографию.

Хеш-функция SPONGENT



Код, реализующий SPONGENT был, вероятно взят отсюда. Если в функции permute() заменить начальное значение переменной «lfsr» и переписать функцию spongent() так, чтобы она принимала на вход не Null-terminated строку, а указатель на массив и длину массива, получится код эквивалентный использованному в NotPetya.
Примечательно, что начальное значение LFSR == 0x9E (как описано в оригинальной спецификации для SPONGENT-256/256/16) дает 140 раундов, а использованное в NotPetya начальное значение 0xA3 дает 152 раунда (криптостойкость слегка увеличена).

Функция шифрования Salsa20



Код, реализующий Salsa20 был, вероятно, позаимствован отсюда. Если в функции s20_expand32() заменить значение массива «o» и заменить тело функции s20_littleendian() строкой «return *(__int16*)b;», получится код эквивалентный использованному в NotPetya.

Из-за того, что функция s20_littleendian() реализована неправильно (вероятно, вследствие неправильного определения типа или ошибки 16-битового компилятора), значения двух из каждых четырех байт в массиве «keystream» никак не используются. Это фактически делает ключ шифрования 128-битовым, а не 256-битовым. Однако, полный перебор 128-битового ключевого пространства на современном уровне технологий считается нерешаемой задачей.

Выводы и предположения



Авторы Petya реализовали шифрование MFT при помощи стойких (хотя и не очень широко распространенных) криптографических примитивов, код которых был позаимствован из репозиториев на GitHub.

В процессе подготовки первой версии (Petya Red) были допущены ошибки, и это позволило расшифровывать данные без уплаты выкупа.

В последующих версиях (Petya Green, PetyaGoldenEye) ошибки частично были исправлены, и осталась только ошибка преобразования типов, снижающая эффективную длину ключа в два раза. Делались попытки реализовать атаку на исправленную версию, но к успеху они не привели.

Авторы NotPetya, вероятно, не имели доступа к исходным текстам Petya и не могли внести в них необходимые изменения и перекомпилировать проект. Они взяли за основу существующий код из PetyaGoldenEye, проанализировали его при помощи дизассемблера и внесли изменения при помощи шестнадцатеричного редактора.

Поиск способов вернуть файлы, зашифрованные NotPetya, продолжается.
Поделиться с друзьями
-->

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


  1. frees2
    29.06.2017 17:29
    +1

    Это четвёртая версия Петра (@ Hasherezade час назад).


  1. TheDaemon
    29.06.2017 17:32
    +3

    В теории, на SSD при перезаписи 0x20 сектора, ключ останется где-то в другом секторе флешки. И возможно есть шанс его оттуда выковырять.


  1. AVX
    29.06.2017 17:36

    Немного не понял — если для работы вируса нужна перезапись MBR, то обязательны права админа? А ранее писали о том, что распространяется в виде червя как и wanacry, плюс какой-то ещё неизвестный 0-day.
    Так нужны ли права админа для заражения, или же по сети залезет и без всяких прав зашифрует?


    1. hurtavy
      29.06.2017 18:12
      +3

      он использует уязвимость для получения соответствующих привелегий


  1. vilgeforce
    29.06.2017 17:54
    +1

    Ну что же вы опять-то? «Затем сектора MFT зашифровываются», а потом пишете про расшифровку файлов и почему она невозможна. Только MFT и файлы шифруются по-разному!


  1. Veliant
    29.06.2017 18:02

    А бага с усечением dword до 16 бит при шифровании salsa20 сохранилась?


  1. sim-dev
    29.06.2017 20:58
    -5

    Интересно, найдется ли кто-либо, кто извинится за слитую мне карму ровно за то, что я утверждал: умный преступник никаких ключей высылать не будет? История слива меня здесь просматривается.

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


    1. frees2
      29.06.2017 21:45

      1 Плюсуют- минусуют бывает группами. Очень чётко заметил.
      2 Иногда не за конкретный комментарий, а потом.

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

      Ибо по другому критичных комментариев в хабрахабре не будет.


      1. kenoma
        30.06.2017 09:41
        -2

        Достаточно деанонимизировать отметки в карму, тогда все моментально встанет на свои места.


        1. frees2
          30.06.2017 10:49

          Открытое голосование, как при Брежневе. Тоже не годится. Опыт истории…

          Вирулентные группы, поддерживают своих, до абсурда иногда.

          Медок. Конкретно не пишут почему… Видимо FreeBSD 7 старый
          какими средствами лучше разбирать объёмный XML

          Ответ.
          frees2 5 июня 2017 в 14:56 –10
          Во первых надо отказаться от формата и переходить на json в любом случае.


          1. kenoma
            30.06.2017 12:13

            А какие могут быть репрессии со стороны пользователя, которому поставили минус в карму?
            Ответный минус, разве что. Зато появляется почва для анализа и вскрываются злоупотребления.


            1. tyomitch
              02.07.2017 15:14
              +1

              «Злоупотребления» — это что? «Минусование не по правилам»?
              Так нет никаких правил минусования.


    1. playermet
      30.06.2017 11:35
      +1

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


    1. redreytar
      30.06.2017 14:21
      +1

      Мы при заражении шифровальщиком (из-за глупости буха и неопытности меня :-), плюс пара звезд не так сошлось) оплачивали. Это было где-то лет 4 назад. Триста баксов на qiwi кошелек. Прислали ключ, расшифровали. Практически все восстановилось корректно, только пару файлов из ~100 000 восстановилось некорректно. После оплаты и расшифровки сразу заявили в милицию, но никого так и не поймали.


  1. VictorAl
    29.06.2017 21:20

    А он шифрует еще и зеркало MFT или только основную?


    1. Sergey_datex
      29.06.2017 22:20
      +3

      у MFT нет полного зеркала. Есть MFTMirr, в которой хранятся копии только первых записей с описанием самого себя


  1. Regis
    30.06.2017 20:53

    У меня всё же стойкое впечатление, что это была целенаправленная атака.


    Q: Как нанести урон компаниям, но по возможности выставить это как "несчастный случай"?


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