Crypt, XOR, взлом нешифрованного ZIP и ГПСЧ. Решение задач с r0от-мi Crypto. Часть 2
Предыдущие статьи на эту тему: В данной статье узнаем про функцию crypt, узнаем как подбирать пароли к ZIP архиву с незашифрованными именами файлов, познакомимся с утилитой xortool, а так же разберемся с генератором псевдослучайных чисел.
Часть 1 — Кодировки, шифр сдвига, брут хешей и создание картинки с помощью PIL python.
Организационная информация
Специально для тех, кто хочет узнавать что-то новое и развиваться в любой из сфер информационной и компьютерной безопасности, я буду писать и рассказывать о следующих категориях:
- PWN;
- криптография (Crypto);
- cетевые технологии (Network);
- реверс (Reverse Engineering);
- стеганография (Stegano);
- поиск и эксплуатация WEB-уязвимостей.
Вдобавок к этому я поделюсь своим опытом в компьютерной криминалистике, анализе малвари и прошивок, атаках на беспроводные сети и локальные вычислительные сети, проведении пентестов и написании эксплоитов.
Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.
Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.
Вся информация представлена исключительно в образовательных целях.
ELF64 — PID encryption
Программа принимает в качестве аргумента строку и сравнивает ее с тем, что вернет функция cryрt от РID программы и строки "$1$awesome". Смотрим исходный код.
На выходе функции не просто хеш, а строка текста, которая также содержит соль, используемый хеш-алгоритм и параметры, с которыми был получен хеш, такие, как количество раундов и другие опции. Функция cryрt — библиотечная функция, которая используется для вычисления хеша пароля.
Таким образом нужно угадать PID, с которым будет запущена программа. Данная функция включена в языки программирования Perl, PHP, Pike, Python и Ruby. Подключившись по SSH видим, что нам дают программу, ее исходник, и файл с паролем.
К примеру, несколько раз подряд выполним ps. В Linux каждое новое запущенное приложение будет получать наиболее приближенный инкрементированое свободное значение PID. PID с каждым разом инкременитруется.
Давайте вомем PID, к примеру 30000 и выполним функцию crypt. Так можно посчитать хеш от любого свободного PID, и с этим значением в качестве аргумента бесконечно запускать программу. Я сделаю это в python.
Теперь запустим бесконечный цикл выполнения программы.
И спустя минуту, получаем облочку, откуда читаем пароль.
File — PKZIP
Это ZIP архив, защищенный паролем. Скачиваем файл, который нам дают. Так как имена файлов не зашифрованы, сделаем это утилитой fcrackzip, а в качестве словаря возьмем rockyou.txt. Давайте переберем пароль.
Разархивировав, получаем текстовый файл, где написано, что ответом является пароль от архива.
Known plaintext — XOR
Так как у нас использовался XOR (предполагаю с ключем малой длины) и имеется большой шифртекст, то можно использовать xortool. Нам дают зашифрованную с помощью XOR BMP картинку.
Попросим его определить ключ. Таким образом xortool считает, что наиболее вероятная длина ключа 6.
Ключ определен, но xortool уже сам расшифровал файл и сохранил в дирректорию xortool_out. Отлично.
Code — Pseudo Random Number Generator
К тому же говорят, что шифрование происходило в декабре 2012. Нам дают программу, с помощью которой зашифрован файл, а так же сам файл. Давайте рабирать код.
Далее проверяется наличие параметра программы — путь к файлу. В самом начале программы запоминается текущее время (точнее пройденное с 1 января 1970).
Дескрипторы обоих файлов передаются в функцию crypt_file. Далее этот файл открывается для чтения и создается новый файл для записи.
Результат шифрования записывается в новый созданный файл. В crypt_file функция genere_key() вовращает ключ 32 байта, который используется для XOR шифрования файла.
Из представленного алфавита на каждом шаге выбирается значение взависимости от значения holdrand, которое также изменяется на каждом шаге, при этом в самом начале оно равно текущему времени. Ключ состаявляется псевдослучайным образом.
Начальный код на python выглядит так.
Таким образом, нам нужно нам нужно сгенерировать возможные ключи.
keys = []
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789"
l = len(charset)
holdrand = None def Rand(): global holdrand holdrand = holdrand * 214013 + 2531011 return ((holdrand >> 16) & 0x7fff) def genere_key(): key = "".join( [ charset[Rand()%l] for _ in range(32) ] ) keys.append(key) start = ?
fin = ? for ts in range(start, fin): holdrand = ts genere_key()
Так как шифрование производилось в декабре 2012, то нам нужно перебрать все возможные значения от 1 до 31 декабря. Теперь разберемся границами времени.
start = 1354320000
fin = 1356998400
Благо в файле сохранилось его разрешение — это bz2. С границами определились, но ключей все равно будет очень много.
Допишем для ключей фильтр. То есть первые три байта файла должны быть “BZh”, четверым должен быть один из символов от “1” до “9”, и следующие шесть байт — 0x314159265359. Для этого нам нужны первые байты шифртекста.
def key_filter(key): ctext = "\x23\x17\x5d\x70\x5a\x11\x6d\x67\x37\x08" BZh = "BZh" sign = "".join( [ chr(ord(ctext[i])^ord(BZh[i])) for i in range(3) ] ) byte4 = "".join( [ chr(ord(ctext[3])^ord(i)) for i in "123456789" ] ) bytePI = chr(ord(ctext[4])^0x31) if sign in key[:3] and key[3] in byte4 and key[4] in bytePI: print(key)
И получим всего один ключ.
И с помощью того же xortool можно проксорить файл с ключем.
Таким обазом вы расшифровали архив.
Давайте соберем сообщество, в котором будут люди, разбирающиеся во многих сферах ИТ, тогда мы всегда сможем помочь друг другу по любым вопросам ИТ и ИБ. Вы можете присоединиться к нам в Telegram.