Развлекайтесь, взламывая строки Unicode с помощью CyberChef

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

Но ASCII ограничен количеством символов, которые он может преобразовать в целое число. Поэтому были изобретены другие схемы кодирования символов. Unicode (nd) был изобретен как альтернативный стандарт, который мог отображать гораздо больше символов, чем ASCII. В этой статье я буду работать над задачей picoCTF, которая имеет дело со строкой в ​​кодировке Unicode, состоящей из китайских символов — с косвенной помощью того, кто ранее ее решил.

Краткое содержание

  1. Фон
  2. Решение
  3. Конец дела
  4. Рекомендации

Фон

Интересно, что это на самом деле… «enc

''.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.