Бэкдор с паролем 123456 и ключи в коде: как ИИ вскрывал «шифрованные» USB-накопители

—

от автора

У «защищённой» флешки было два скрытых аккаунта с паролями 123456 и SECZURE.COM, и любым из них файлы расшифровывались без пароля администратора. В трёх других продуктах для шифрования и защиты от копирования ключ вообще не зависел от пароля пользователя: его удавалось достать из самой программы и файлов на накопителе. ИИ-агент находил такие ошибки за минуты, причём в одном случае повторил за семь минут то, на что у меня раньше ушло ручное исследование с отладчиком.

В начале этого года я показывал на конференции RE//verse, как вскрывать зашифрованные USB-накопители с помощью отладки с перемоткой времени (time-travel debugging, TTD): видео, слайды. В последнее время я много и успешно реверсил и искал уязвимости вместе с ИИ, и мне захотелось проверить, как он справится с теми же задачами.

Результат превзошёл ожидания. На одном зашифрованном накопителе нашёлся бэкдор, который позволил расшифровать файлы альтернативными паролями. Моё прежнее исследование ИИ повторил за семь минут одним статическим анализом. Ещё два продукта для защиты USB, которые я раньше не изучал, он тоже вскрыл.

Флешка с защитой от копирования

Первым был накопитель YutianDun (御天盾) от SecZure. Он прячет зашифрованные файлы от Проводника Windows и открывает их во встроенных просмотрщиках, которые, по заявлению производителя, не дают копировать, делать скриншоты и печатать.

Забавно, что этот накопитель я уже изучал. В статье «Examining USB Copy Protection» в пятом выпуске журнала Paged Out! (ноябрь 2024) я показал, что DLL, внедрённая в процесс его PDF-просмотрщика, читает защищённый файл, который из другого процесса прочитать нельзя. Защита от копирования на этом и закончилась.

На этот раз я разбирал его с помощью TTD вместе с ИИ. Трасса показала, что программа перехватывает NtCreateFile и NtReadFile внутри PDF-просмотрщика и подсовывает ему уже расшифрованные данные. Моя DLL работала в том же процессе и поэтому спокойно читала расшифрованные байты, хотя тогда я не знал, как именно это устроено.

Криптосистема в двух словах

Теперь я решил проверить саму криптосистему. Если упростить, пароль администратора хешируется, и хешем расшифровывается значение, которое в коде называется «идентификатор» (identifier). Из идентификатора выводится ключ AES, которым зашифрованы байты файлов. В упрощённом псевдокоде:

credential = MD5(b"[SECZURE]" + password).hexdigest().upper().encode("ascii")wrap_key = HMAC_MD5(credential, credential).hexdigest().upper()[:16].encode("ascii")identifier = AES_128_ECB_decrypt(wrap_key, hex_decode(administrator_record.wrapped_identifier)).rstrip(b"\0")file_key = HMAC_MD5(identifier, identifier).hexdigest().upper()[:16].encode("ascii")plaintext = AES_128_ECB_decrypt(file_key, ciphertext)

Несколько слабых мест видно сразу. Во-первых, ключ получается быстрыми MD5 и HMAC-MD5, без медленной функции вроде PBKDF2. Во-вторых, ключ AES собирается из 16 шестнадцатеричных символов, а это не больше 64 бит энтропии. Но перебрать 2^64 вариантов всё равно нереально. Пока шифрование выглядело стойким.

Другие загадочные пользователи

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

Важнее другое: в той же записи лежит ещё одна зашифрованная копия того же идентификатора содержимого, а пароль по умолчанию, судя по коду, 123456. Я проверил: идентификатор Buffer действительно расшифровывается паролем 123456, а выведенным из него ключом AES расшифровываются файлы. Дальнейший анализ кода показал ещё один встроенный аккаунт, System, с фиксированным паролем SECZURE.COM. На двух проверенных накопителях оба аккаунта открывали идентификатор каждого из них.

Administrator password ──→ Administrator's wrapped identifier ──┐Buffer / 123456        ──→ Buffer's wrapped identifier        ──┼─→ content identifier → AES file keySystem / SECZURE.COM   ──→ System's wrapped identifier        ──┘

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

NetacFileLock: второй заход

Следующей была NetacFileLock. Её я уже разбирал с TTD: тогда я шёл от шифротекста назад, пока не добрался до ключа AES. На этот раз я дал ровно один промпт:

This is a file encryption utility. Analyze its crypto system and see if it is secure. You can use Binary Ninja MCP to help you.

(«Это утилита для шифрования файлов. Разбери её криптосистему и оцени, надёжна ли она. Можешь использовать Binary Ninja MCP».)

За семь минут Codex добрался до главной ошибки: программа инициализировала AES-256 фиксированным 32-байтным ключом, зашитым в исполняемый файл. Пароль пользователя проверялся отдельно и на ключ шифрования никак не влиял. Значит, расшифровать файл может кто угодно, не зная пароля.

За эти семь минут агент нашёл и другое, причём часть находок в моём докладе не упоминалась:

  • NetacFileLock записывала пароль пользователя в диагностические логи.

  • Она шифровала независимые 16-байтные блоки без IV и без сцепления, то есть вела себя как ECB.

  • Пароль проверялся через MD5.

  • В качестве «подписи» файла использовался MD5 без ключа.

  • Вариант с SM4 использовал другой фиксированный ключ.

В моём исследовании оставался открытый вопрос: почему зашифрована только треть тестового файла. Теперь ответ есть и на него. Дело не в PDF: в быстром режиме так обрабатывается любой файл больше 1024 байт, если он относится к одному из форматов:

PNG, JPEG, GIF, TIFF, DWG, PSD, PST, DBX, Office, MDB, WPD,PDF, ZIP, RAR, WAV, AVI, RAM, RM, MPEG, MOV, ASF, and MIDI

Спрашивать у ИИ, зачем кому-то понадобилось так делать, я не стал.

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

KakaSoft: защита от копирования

Дальше хотелось проверить ИИ на чём-то новом. Немного поискав, я нашёл многообещающую категорию товаров: USB-накопители «с защитой от копирования». Производители утверждают, что записанные на них файлы можно просматривать только через их программу и вынести с устройства нельзя. Я сразу засомневался. Если клиент показывает файл, он обязан его расшифровать, а когда компьютер, на котором идёт расшифровка, принадлежит пользователю, помешать извлечению крайне трудно.

Начал я с KakaSoft USB Copy Protection 5.6.0.299. Я работал на macOS, а программа есть только под Windows. Это почти не мешало: я попросил ИИ разобраться с установщиком и проанализировать извлечённые из него бинарники Windows.

Программа предлагала три уровня защиты. Уровень Normal («Скрыть и запереть файлы») вообще ничего не шифрует. High («Перемешать и зашифровать заголовки файлов») делает XOR не больше чем первых 16 385 байт с однобайтовым ключом, выведенным из пароля. Возможных ключей всего 256, известные сигнатуры файлов сразу выдают ключ, а всё после перемешанного начала остаётся открытым текстом. Highest («256-битное шифрование Blowfish») выглядел самым надёжным, его я и выбрал.

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

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

Накопитель под защитой KakaSoft: виден только USBCopyProtect.exe

Накопитель под защитой KakaSoft: виден только USBCopyProtect.exe

ИИ это не смутило. Сначала он нашёл защищённые данные: KakaSoft спрятала их в необычном дереве каталогов на томе exFAT. Разбор сырых записей каталогов дал вот такое дерево:

USB root└── HPSafeBox                              [hidden + system]    ├── desktop.ini                        [hidden + system]    ├── con.{d3e34b21-9d75-101a-8c3d-00aa001a1652}    └── Important Folder        └── Com1.{d3e34b21-9d75-101a-8c3d-00aa001a1652}            └── \x7f\x7f..           [unusual UTF-16 name]                ├── Info.bd                ├── Daily.db                └── NLLastF                [hidden + system]                    └── test.txt.txt        [667 bytes]

У HPSafeBox и NLLastF стоят атрибуты exFAT «скрытый» и «системный». Компонент Com1.{...} соединяет зарезервированное в Windows имя устройства COM1 с суффиксом в виде CLSID оболочки. Имя следующего каталога на диске начинается с двух символов DEL (0x7f), за которыми идут символ из области частного использования Unicode U+E347 и две точки. Такие имена сбивают обычную обработку путей в Windows и помогают скрыть дерево от Проводника.

Вот сокращённый шестнадцатеричный дамп скрытого 667-байтного test.txt.txt:

00000000: a0 ea 96 ca 0e 03 f0 98 0b 3e ad 18 99 a7 e3 9d  .........>......00000010: 08 b2 f6 55 b7 2f 47 3c 0e 66 2b a9 1f 82 97 c8  ...U./G<.f+.....00000020: b5 47 c4 22 09 08 30 2c 7a 65 9b b8 b3 1e 87 25  .G."..0,ze.....%00000030: 45 35 49 a4 58 1c 63 5b 4e e3 ee 0a 05 48 b3 56  E5I.X.c[N....H.V...00000250: 20 32 34 31 38 35 36 35 37 33 31 34 32 41 44 38   241856573142AD800000260: 38 32 30 36 43 45 31 42 46 38 33 35 46 41 38 46  8206CE1BF835FA8F00000270: 37 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  7...............00000280: 00 00 00 0e 6b 61 6b 61 65 6e 63 72 79 70 74 69  ....kakaencrypti00000290: 6f 6e 08 42 6c 6f 77 46 69 73 68                 on.BlowFish

Первые восемь байт — случайная соль, следующие восемь — IV для Blowfish в режиме CBC, шифротекст начинается со смещения 0x10. Последние 75 байт начинаются с 0x250. В этом хвосте лежит 32-символьное проверочное значение, а за ним читаемые строки kakaencryption и BlowFish:

8-byte salt | 8-byte IV | Blowfish ciphertext | 75-byte trailer

Клиент оказался 32-битной программой на Delphi. ИИ прошёл по её классу TBlowfishEncryption и выяснил, как эти байты расшифровываются. Соль и IV у каждого файла свои. Роковая ошибка была в том, как выводится ключ:

internal password = modified MD5 of an embedded seedfile key          = RIPEMD-128(salt || internal password)plaintext         = Blowfish-CBC-Decrypt(file key, IV, ciphertext)

Первый хеш явно был построен на MD5, но стандартным MD5 не был. Вот первые восемь операций третьего раунда в обычной реализации:

HH(a, b, c, d, x[ 5],  4, 0xfffa3942);HH(d, a, b, c, x[ 8], 11, 0x8771f681);HH(c, d, a, b, x[11], 16, 0x6d9d6122);HH(b, c, d, a, x[14], 23, 0xfde5380c);HH(a, b, c, d, x[ 1],  4, 0xa4beea44);HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);HH(b, c, d, a, x[10], 23, 0xbebfbc70);

Величины сдвигов повторяются: 4, 11, 16, 23. KakaSoft оставила те же константы и тот же порядок слов сообщения, но в соответствующих вызовах у неё сдвиги 4, 11, 16, 16, 4, 11, 11, 4. Изменённые аргументы видны в декомпилированном клиенте:

Изменённые величины сдвигов третьего раунда MD5 у KakaSoft

Изменённые величины сдвигов третьего раунда MD5 у KakaSoft

Обычно хеш переводится в текст так:

static const char hex[] = "0123456789ABCDEF";out[i * 2]     = hex[digest[i] >> 4];out[i * 2 + 1] = hex[digest[i] & 0x0f];

KakaSoft делает ту же подстановку, только по алфавиту 1903642857ACBEDF:

Переставленный шестнадцатеричный алфавит у KakaSoft

Переставленный шестнадцатеричный алфавит у KakaSoft

Второе изменение — простая замена символов. Отличие самого хеша от стандартного MD5 дают именно изменённые сдвиги.

Вместо того чтобы вручную переписывать этот самодельный хеш, ИИ эмулировал нужный участок кода клиента и получил фиксированный внутренний пароль:

AEF33093...DA1E

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

На статическую часть ушло около двух минут на распаковку установщика и ещё семь минут на анализ криптографии, и от меня потребовалось два промпта. Когда я подключил защищённый накопитель, ИИ понадобилось около 26 минут и шесть коротких промптов, в основном подтверждений про подключённый диск, тестовый пароль и направление анализа. За это время он извлёк скрытый файл, восстановил самодельную конструкцию на основе MD5 и доказал, что файл расшифровывается без пароля.

Nexcopy

Второй новой целью стал Nexcopy Copy Secure, подготовленный программой Drive Wizard 1.0.81. На накопителе лежали просмотрщики и для Windows, и для macOS. В версии для Mac сохранились осмысленные имена методов Objective-C, поэтому разобраться в её устройстве было особенно легко.

После подключения защищённого накопителя к Mac в Finder были видны только эти два просмотрщика:

Подготовленный накопитель Nexcopy: видны только просмотрщики для Mac и Windows

Подготовленный накопитель Nexcopy: видны только просмотрщики для Mac и Windows

На этот раз содержимое было зашифровано Triple DES с тремя ключами в режиме CBC. Проблема снова оказалась в том, где хранится ключ.

На накопителе лежал зашифрованный файл конфигурации. Просмотрщик открывал его вот этим фиксированным 32-байтным сертификатом, встроенным в приложение:

83E89F19...A56F

И 324-байтная конфигурация, и 140-байтный защищённый test.txt начинались с одного и того же 36-байтного ASCII-маркера. Вот зашифрованный контейнер test.txt целиком:

00000000: 31 42 46 37 41 38 41 30 2d 36 45 42 46 2d 34 36  1BF7A8A0-6EBF-4600000010: 42 38 2d 38 46 31 44 2d 35 35 41 44 42 36 41 46  B8-8F1D-55ADB6AF00000020: 42 35 44 32 3b 2f 7e af c0 8f 84 c4 7f 45 fc d6  B5D2;/~......E..00000030: f8 68 27 bc 73 7a 3b 7a 33 c7 9e f0 46 da 70 04  .h'.sz;z3...F.p.00000040: 53 44 46 4e 61 aa ea b9 aa d4 75 19 e8 32 b7 06  SDFNa.....u..2..00000050: 29 d0 3c f8 04 d7 af da c3 ab ae 46 87 a1 68 fd  ).<........F..h.00000060: 1e 9c 04 18 3c be 27 51 72 82 de 8b 5d 5c 49 98  ....<.'Qr...]\I.00000070: c3 97 97 91 d0 10 b0 01 e1 1c 38 49 9a fc e2 6b  ..........8I...k00000080: 72 8d 45 8b 58 48 8f e6 9b 4f f6 02              r.E.XH...O..

Первые 36 байт — маркер, остальные 104 байта — шифротекст 3DES-CBC с дополнением. Зашифрованная конфигурация устроена так же: тот же маркер и 288 байт шифротекста. Расшифровка встроенным сертификатом дала:

vid=FA6Epid="8598"prefix="7015A1496E"error_msg="Please contact [company information here] for an XXXXXXX."key="6CF96891F31A329CED2B33171D6518740AD1212B687CDACE892962F7C59F7172"password="123456"start=\Mac Viewer.app\Data

Поле key и было сертификатом содержимого: 24-байтный ключ 3DES и следом 8-байтный IV. Пароль был отдельной настройкой интерфейса.

fixed value in viewer        ↓encrypted configuration        ↓content key + IV ──→ protected-file decryptionUI password       ──→ string comparison in the viewerUSB identifiers   ──→ software device check

Пароль и проверка устройства решали только одно: продолжит ли работу официальный просмотрщик. В ключ файла они не входили. Просмотрщик для Mac попросту доставал сохранённый пароль и сравнивал его с введённым текстом через isEqualToString:.

С ключом содержимого и IV ИИ расшифровал шифротекст и восстановил исходное содержимое.

Защиту от копирования Nexcopy пыталась обеспечить и в самих просмотрщиках. Код перебирал процессы, перехватывал клавиши для скриншотов, использовал API буфера обмена и искал приложения вроде ScreenFlow, Camtasia, Debut, Grab и QuickTime. Случайного пользователя такие проверки, может, и остановят, но ключ содержимого они не защищают от того, кто изучит просмотрщик и повторит его расшифровку.

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

Выводы

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

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

ссылка на оригинал статьи https://habr.com/ru/articles/1102922/