Разбор задач из CTF по реверсу: The Doors of Dorun

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

Условие

*A.U.R.O.R.A.: Lieutenant, your co-pilot was abducted by aliens and put into prison. They are out hunting now and it’s your chance to set him free! He is held behind the Doors, the jambs invisible to the eye, and matched so perfectly with the metal bulkhead that when closed the Doors could not be seen.

The inscription on the archivolt read:

"The Doors of Dorun, Lord of Omega. Speak, friend, and enter. I, Norvy, made them. Calabrimbor of Alpha Centauri drew these signs".

But be careful and hurry up. They can be back any moment.*

Решение

В первую очередь, мы запускаем CrackMe, и на экране появляется следующее окно:

Попробуем ввести любое слово и нажать «Try», но пароль не подходит, и мы видим такое сообщение:

Сам по себе CrackMe представляет собой 64-битный исполняемый файл PE-формата. Откроем его в IdaPro и попробуем найти строчку «the door is still closed!»:

На эту строчку существует только одна перекрестная ссылка:

Вот функция, в которой IdaPro нашла обращения к этой строчке:

Здесь мы также видим зашифрованный флаг (легко убедится, что функция sub_140001160 занимается дешифровкой) и функцию, определяющую правильность пароля: «sub_1400012C0». При помощи GetDlgItemTextW в эту функцию передаётся строка, введённая в поле для ввода пароля. Проанализируем эту функцию:

Здесь прослеживается цикл и два массива из пяти элементов. Также происходит проверка длины введённого пароля:

Проанализировав эту функцию, мы видим, что пароль из четырёх символов в кодировке UTF-16 (кодировка для WideChar в Windows) состоит из двух чисел c размером DWORD. Далее, мы видим, что остатки от деления этих чисел на числа ((1 << (1 << i)) + 1) сравниваются с захардкоженными значениями.

Можно заметить, что ((1 << (1 << i)) + 1) = 2^(2^i) + 1, и что это числа Ферма: 3, 5, 17, 257, 65537. Алгоритм проверки пароля далее можно свести к двум системам сравнений:

X1 % 3 = 0
X1 % 5 = 0
X1 % 17 = 1
X1 % 257 = 241
X1 % 65537 = 995
X2 % 3 = 1
X2 % 5 = 4
X2 % 17 = 6
X2 % 257 = 104
X2 % 65537 = 413

Восстановить исходные числа нам поможет Китайская теорема об остатках. В интернете можно найти решатели таких сравнений:

Итак, мы получили два числа, которые теперь необходимо преобразовать в строку UTF16. Для этого можно использовать Python (при этом не забываем про обратный порядок байт):

Теперь осталось проверить полученный результат. Введём эту строку в окно для ввода пароля.

Вот и всё! Мы открыли врата.

Ответ: ctfzone{ch1n4_t0wn}

За подготовку материала выражается благодарность CTF-сообществу и специалистам из компании BI.ZONE.