Развлекайтесь, взламывая строки Unicode с помощью CyberChef
Американский стандартный код для обмена информацией, или ASCII, был основной схемой кодирования во второй половине двадцатого века, когда вычислительная техника была еще в зачаточном состоянии. Он отображает 127 буквенно-цифровых, не буквенно-цифровых и некоторых других управляющих символов в число.
Но ASCII ограничен количеством символов, которые он может преобразовать в целое число. Поэтому были изобретены другие схемы кодирования символов. Unicode (nd) был изобретен как альтернативный стандарт, который мог отображать гораздо больше символов, чем ASCII. В этой статье я буду работать над задачей picoCTF, которая имеет дело со строкой в кодировке Unicode, состоящей из китайских символов — с косвенной помощью того, кто ранее ее решил.
Краткое содержание
- Фон
- Решение
- Конец дела
- Рекомендации
Фон
''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])"
— -«"Безумцы" (2021)".
Проблема связана с одной командой Python и файлом для загрузки по ссылке «enc». Это представлено как проблема обратного проектирования, и кажется, что строка должна быть объединена с использованием файла «enc» и с использованием алгоритма, представленного выше. Цель состоит в том, чтобы найти флаг в формате: «picoCTF{какая-то строка» с помощью неформальной процедуры обратного проектирования.
Решение
Сцена первая: неудачная попытка
Я начал с сброса информации в файл «enc»:
dna@deniers:~/Transformation$ cat enc 灩捯䍔䙻ㄶ形楴獟楮獴㌴摟潦弸弲㘶㠴挲ぽdna@deniers:~/Transformation$
Мой опыт работы с китайскими иероглифами практически отсутствует, особенно когда они закодированы на цифровом носителе. В этом задании была подсказка о том, что «[участник] может найти декодеры в Интернете». Итак, я попытался перевести этот текст с помощью Google Translate — как показано на рисунке 1:
Это, похоже, не дало никакой полезной информации (по крайней мере, мне). Поэтому я обратил свое внимание на команду Python, представленную в задаче:
''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])
Решил "приукрасить":
transform = "" for i in range(0, len(flag), 2): transform += chr( (ord(flag[i]) << 8) + ord(flag[i + 1]) )
flag
никогда не указывается в строке Python, указанной в задаче. Я решил взять подсказку на заметку и немного «поэкспериментировать», чтобы посмотреть, смогу ли я извлечь решение. Прежде чем сделать это, стоит обсудить, что делают некоторые из этих функций.
chr
— это функция, которая принимает целочисленное представление символа и возвращает его строковое представление (Документация Python 3.11.2 без даты), а ord
принимает строковое представление символа и возвращает его целочисленное значение (Там же). chr
является инверсией ord
, а ord
является инверсией chr
(Там же).
Сценарий Python, кажется, следует основной процедуре:
1. Declare a new string. 2. Take a string as an input. 3. Convert the current character into an integer, and perform a bitwise left shift (see Robertson et al 2021) with the additive expression of 8. 4. Convert the character with the position of the current character plus one (+1) to and integer, and then add that to the solution from step 2. 5. Convert the integer solution from step 3 to a character, and then append it to the new string. 6. Repeat steps 3–5 for every 2 characters.
Новая строка должна содержать хотя бы часть флага. Ниже приведен скрипт Python, который я собрал в попытке определить флаг (хотя бы его часть):
flag = "\u7069\u636f\u4354\u467b\u3136" flag += "\u5f62\u6974\u735f\u696e\u7374" flag += "\u3334\u645f\u6f66\u5f38\u5f32" flag += "\u3636\u3834\u6332\u307d" transform = [] for i in range(0, len(flag), 2): transform.append((ord(flag[i]) << 8) + ord(flag[i + 1])) print(transform)
Запуск скрипта выдает ошибку:
dna@deniers:~/Transformation$ python3 decoder.py /usr/lib/python3/dist-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (1.26.14) or chardet (3.0.4) doesn't match a supported version! warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported " Traceback (most recent call last): File "decoder.py", line 9, in <module> transform.append((ord(flag[i]) << 8) + ord(flag[i + 1])) IndexError: string index out of range dna@deniers:~/Transformation$
Это имеет смысл. Длина флага составляет девятнадцать (19) символов Юникода, а цикл for шагает по 2, поэтому, когда цикл достигает восемнадцатого (i = 17), когда он повторяется для следующего раунда, он пытается получить доступ к индексу, который отключен. -на единицу длина минус один (20–1=19). Я добавил немного отладки в скрипт в виде операторов print
:
dna@deniers:~/Transformation$ python3 decoder.py 7392367 4430459 3249506 6940511 6938996 3381343 7324984 6252598 3708722 /usr/lib/python3/dist-packages/requests/__init__.py:89: RequestsDependencyWarning: urllib3 (1.26.14) or chardet (3.0.4) doesn't match a supported version! warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported " Traceback (most recent call last): File "decoder.py", line 9, in <module> y = (ord(flag[i]) << 8) + ord(flag[i + 1]) IndexError: string index out of range dna@deniers:~/Transformation$
Что-то явно работает не так.
Сцена вторая: учиться у других
Я провел еще немного исследований и обнаружил, что CyberChef (n.d.) имеет магический код операции с интенсивным режимом, который может принимать строку Unicode и декодировать ее с использованием нескольких различных схем кодирования и базовых алгоритмов шифрования.
Чтобы расшифровать китайские иероглифы, импортируйте следующий рецепт:
[ { "op": "Magic", "args": [3, true, false, ""] } ]
Затем введите китайскую строку в форму ввода в правом верхнем углу CyberChef и «запеките» ее. Декодированная строка будет находиться в одной из схем кодирования, изображенных на рисунке 2:
Конец дела
Для многих это была очень простая задача. Но мне лично было трудно, потому что я борюсь с манипуляциями со строками. Этот вызов CTF демонстрирует по крайней мере одну вещь: хакеры, программисты и специалисты по компьютерам должны больше узнать о Unicode и о том, как компьютеры хранят строки в форматах, отличных от ASCII.
Благодарности
Я хотел бы поблагодарить xnomas (n.d.) за их решение, на которое я в конечном итоге ссылался, когда мои другие попытки декодировать рассматриваемую строку потерпели неудачу.
Рекомендации
CyberChef (без даты). Получено 15 февраля 2023 г. с: https://gchq.github.io/CyberChef.
Google Переводчик (nd). Получено 15 февраля 2023 г.: https://translate.google.com/.
Безумцы (2021). Преобразование. ПикоКТФ спортзал. Получено 15 февраля 2023 г. с сайта https://play.picoctf.org/practice/challenge/104.
Документация Python 3.11.2 (без даты). Встроенные функции. Получено 15 февраля 2023 г. с: https://docs.python.org/3/library/functions.html.
Робертсон и др. (2021). Операторы сдвига влево и вправо (‹‹ и ››). Обучение Майкрософт. Получено 15 февраля 2023 г. с сайта https://learn.microsoft.com/en-us/cpp/cpp/left-shift-and-right-shift-operators-input-and-output.
Юникод (без даты). Мировой стандарт для текста и эмодзи. Получено 15 февраля 2023 г. с сайта https://home.unicode.org/.
Викисклад (2019). Новый логотип Unicode. Получено 15 февраля 2023 г. с: https://en.wikipedia.org/wiki/Unicode#/media/File:New_Unicode_logo.svg.
ксномас (без даты). Отчет о трансформации picoCTF 2021. CTFвремя. Получено 15 февраля 2023 г. с: https://ctftime.org/writeup/26983.