Рекламні оголошення

Аналіз вихідного коду шифрувальника HelloKitty

Складання та почерк.

З метою аналізу було взято вихідний код, що втік у паблік 10.10.2023.
Програма написана мовою C++ (використовується стандарт C++17 та підтримка Windows XP) і збиралася на MSVS 2015.
Теги файлів проекту свідчать про створення вихідного коду на російськомовній ОС.

У шляхах включень збирання присутні:

c:\Projects\LockerInnocentFork\lk\NTRUEncrypt\include\
c:\Projects\LockerInnocentFork\lk\mbedtls\include

наводять на думку про форку проекту LockerInnocent. Інформації щодо нього я не знайшов (але й не особливо шукав).

Алгоритм.

Математично шифрування реалізовано з використанням бібліотеки криптографічних примітивів mbedtls та алгоритму NTRUEncrypt, що зараз вважається стійким до злому квантовими комп'ютерами. NTRUстворений у 1996 року в якості альтернативи RSA та алгоритмам на основі еліптичних кривих (ECC), і вважається все ще погано вивченим.

Ключ генерується з прапором NTRU_EES743EP1

що згідно з прикладеною документацією є аналогом RSA з довжиною ключа 1920 байт.

Публічний ключ завдовжки 1028 байт вшивається один для кожного окремого білда HelloKitty.

початкова стадія.

Виконання шифрувальника починається із заборони системі упускати програму при критичних помилках та заборони закриття консолі за Ctrl + C.
Далі йде формування записки з викупом із SHA256 публічного ключа.
Здійснюється запис часу початку роботи і після закінчення шифрування відображається витрачений час.
Йде перевірка єдино підтримуваного ключа командного рядка: -шлях “шлях”. Якщо він вказаний, шифрується лише ця папка.
Через WMI видаляються тіньові копії та чиститься вміст кошика та створюються потоки.

Швидкість, паралелізація та пошук​.

Для обробки файлів заздалегідь створюються потоки в кількості, рівному числу ядер процесора * 2, що вважається досить ефективним. Файли обробляються асинхронно з отриманням повідомлення про закінчення через I/O completion port, після чого відбувається шифрування чергового блоку чи файлу у тому потоці без створення нового.

Для виміру та відображення швидкості створюється окремий потік, який скидає лічильник кожну 1 секунду та виводить виміри швидкості читання та запису в заголовок консольного вікна.

В цей час основний потік створює додаткові потоки для пошуку та початку обробки файлів, розташованих на локальних, знімних та мережевих дисках.

Для кожної літери створюється свій потік. Усі вони запустяться у паралелі, що є дуже не оптимальним і перевантажить диск запитами у разі, якщо фізичний диск не SSD і має багато логічних розділів.

Сам пошук реалізований через FindFirstFileW та рекурсію, що при порівняльному аналізі з іншими шифрувальниками за даними дослідникаЧуонг Донг є сильно не оптимальним і може призводити до переповнення стека. Існують лінійні алгоритми рекурсивного пошуку без рекурсії на базі купи, позбавлені цього недоліку.

Наступні файли та папки пропускаються:

Частина відповідає за етап завантаження системи і при їх зміні ОС не зможе запуститися.

Файли розміром <= 1 МБ не обробляються. За документи невеликого розміру можна не переживати

Якщо файл має атрибут “Тільки читання”, цей атрибут забирається.

Запис файлу та його структура.

Файли жертви відкриваються через CreateFileW з шарингом прав на читання та асинхронним режимом роботи. Робиться це відразу тим самим потоком, що шукає файли. А як ми пам'ятаємо вище, число цих потоків = числу дисків. Файли могли б відкриватися в нескінченній кількості. Для вирішення цієї проблеми при перерахуванні файлів перевіряється максимальна кількість відкритих файлів.. Потік йде у нескінченний цикл повторної перевірки цього значення, якщо воно вище 200.

Дескриптор файлу асоціюється з портом вводу-виводу.

Той самий потік читає перший блок даних, заповнюючи OVERLAPPED структуру первинними даними, потрібними для шифрування (см. далі).

А за запис та читання наступних блоків даних відповідають вже інші потоки (Вони, що = кількість ядер *2). Вони витягують із черги I/O порту завершені операції читання/запису та обробляють черговий блок даних довільного файлу.

Якщо читання першого блоку невдало, I/O операція скасовується.

У процесі шифрування блоків файлу, I/O порт у покажчику OVERLAPPED утримує службову структуру over_struct, що має всю інформацію про хід шифрування конкретного файлу:

таку як шлях до файлу, його розмір, поточний блок даних, сидіти, контекст класу криптографії.

Файл обробляється блоками максимум по 160 КБ (DEFAULT_BLOCK_SIZE).

Поле operation містить поточний стан об'єкта, за яким визначається, що робити далі з поточним блоком або вказівником файлу.

*retry поля не задіяні, але за задумом, схоже, були відповідальні за повторну спробу читання/запису у разі невдачі.

Ця структура включає іншу структуру – enc_header, необхідну для обробки файлу:

Як сигнатура (магічного числа) використовується значення 0xBAADC0DE

encType містить опціональні прапори, один з:

ENCTYPE_FULL_FILE = 2 (обработка файла целиком)
ENCTYPE_RANDOM_BLOCKS = 4 (обработка рандомных участков)
ENCTYPE_LIMIT_FILE_SIZE = 8 (ограничение длины файла для обработки)
ENCTYPE_USE_CRC32 = 16 (создание контрольной суммы самого заголовка для верификаци, что он не повреждён)
qwMaxEnctyptionSize – ограничение максимальной длины обработки файла (для флага ENCTYPE_USE_CRC32).
endBlockCrc32 – CRC32 заголовка (для флага ENCTYPE_USE_CRC32).
aes_key и aes_iv – ключ и вектор инициализации.

Потім байти структури enc_header шифруються та записуються в кінець файлу (ntru_encrypted поле) у вигляді структури enc_end_of_file_ntru:

туди ж пишеться cipher Len (розмір ntru_encrypted у байтах) та сигнатура прапора про завершення шифрування зі значенням ENCRYPTED_FILE_FLAG (0xABCCDCDA + 1).

Наприкінці файл перейменовують, додаючи розширення .kitty

Конфігурація білда.

Конфігурація вшита в вихідний код.

і містить поля:

  • configSignature (не використовується, містить число 0xAAEECCD0)
  • реальний розмір блоку
  • максимальна довжина файлу для обробки, у разі включення режиму bFullFileEncrypt
  • прапор включення запису та перевірки контрольної суми CRC32 заголовка хвоста
  • прапор “Шифрування файлу повністю”
  • прапор “Шифрувати рандомні блоки” (повинен бути обов'язково обраний або цей прапор, або шифрування повністю).

Стандартні налаштування: шифрування рандомних блоків розміром 160 КБ, і перевірити CRC32.

Мережеві функції.

Перед запуском пошуку на мережевих дисках, основний потік знижує свої права елегантним способом (зазвичай використовують токен, вкрадений в іншого процесу) – у даному випадку в коді поточний процес отримує розгорнуту інформацію про свій власний токен, а саме пов'язаний з ним limited token, т.к. по суті підвищення прав здійснюється приєднанням до поточного (обмежений) підвищений маркер жетон.

Робиться це, тому що зазвичай мережні диски підключаються з-під обмежених прав, і через evelated token не видно.

Пошук мережеву кулю реалізовано через функцію WNetOpenEnumW. Для пошуку файлів для кожної з куля створюється окремий потік, виконуючий той же, код як і пошук локальних файлів. Надалі їх шифрування займається загальний з локальними файлами набір потоків. Це може призвести до блокування всієї процедури шифрування., якщо наприклад, потрапить один сильно загальмований мережевий ресурс.

Максимальна кількість потоків пошуку (мережевих та локальних) жорстко обмежено межею в 64. В іншому випадку, всі наступні мережеві ресурси пропускаються.

Записка про викуп.

У кожній директорії створюється записка з ім'ям read_me_lkdtt.txt
Для зв'язку із зловмисниками пропонується перейти на сайт, розташований на сервісі у мережі Tor.

Захист та зняття блокувань із файлу

Якщо не вдається відкрити файл, програма перевіряє, чи не зайнятий він іншими процесами, та знімає блокування, використовуючи Restart Manager. Код позбавлений додаткового. перевірок і цілком може упустити систему в BSOD.

Самовидалення реалізовано із затримкою через пінг на loopback та командою cmd, однак у вихідному дзвінку виклик закоментований.

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

Робота шифрувальника завершується очікуванням всіх потоків пошуку і досягненням кількості відкритих дескрипторів файлів числа 0.

Мертвий код.

ймовірно, деякі версії містили захист від повторного запуску шифруючої частини. У коді є рядки, що ніяк не використовуються

У вихіднику закоментовано функціонал, відповідальний за вбивство процесів за списком. Що примітно в комплекті йде список із аж 1686 імен процесів.

Дешифрувальник.

Створює мютекс “EnigmaThread“, щоб запобігти повторному запуску

Дешифрування виконується у зворотному порядку через вилучення структури enc_end_of_file_ntru з хвоста файлу та його розшифрування приватним ключем, вшитим у конкретний білд.
Обробка файлів виконується в багатопотоковому режимі через пул потоків та синхронне I/O з відкриттям файлу через \\?\ префікс, а значить підтримкою довгих шляхів.
Якщо в конфізі білда було вибрано опцію розрахунку CRC32, то розшифрований заголовок звіряється з контрольною сумою, правда вже після спроби розшифрувати файл. У разі розбіжності, файл не буде перейменований.

Дешифрувальник також підтримує ключ командного рядка -path “” для вибору конкретного шляху розшифровки.

Висновки робіть самі

Стаття написана для розвитку вміння читати чужий код, кращого розуміння технік роботи сучасних зловредів та можливостей з пошуку артефактів, яких у HelloKitty скажемо, не так вже й багато; а також через бажання випустити хоч якусь статтю за довгий час перерви, зробивши її у стилі статей блогу експерта реверсингу Chuong, який вміє писати також докладно та красиво, при цьому не маючи на руках вихідного коду

У статті також залишено невеликі натяки на недоліки, якими так чи інакше можна скористатися для запобігання або мінімізації ефективності шифрування, у тому числі зі створенням спец. інструментів. Послідовність розгортання конкретних зловредів та розуміння, які функції виконує процес у конкретний момент часу може допомогти авторам антивірусних рішень правильно організувати захист та підібрати правила поведінкового аналізу для блокування вже запущеного шифрувальника.

Статтю складено Драгок та є інтелектуальною власністю SafeZone.cc
Перепублікування на інші ресурси без письмового дозволу адміністратора заборонено.