Всем привет!
Сегодня рассмотрим задание "Абсолютная безопасность" из раздела криптографии на Codeby Games.Итак, приступим!
Ищем вектор
Нам дается IP'шник, и три подсказки:- Возможно проверка на утечку флага является "узким местом"?
- Вы не любите кошек? Да вы просто не умеете их готовить!
- Я думаю стоит накапливать зашифрованные флаги.
Откроем IP. Видим, что он обнаружил контент, который не может обработать браузер.
Поэтому смотрим на вторую подсказку и запускаем netcat (для винды - ncat) и подключаемся:
ncat 62.173.140.174 11000
Для взаимодействия у нас есть две команды: "request" и "exit". Если с "exit" все ясно, то с "request" нет. Для этого смотрим вверх и видим кусок кода, который используется при отправке request'а.
Python:
async def gen_enc_flag():
rand_bytes = urandom(23)
enc = bytes(i ^ j for i, j in zip(flag, rand_bytes))
for i in range(23):
assert enc[i] != flag[i], "leak detected"
return enc.hex()
Я в коде не силен, поэтому просто загрузил код в ChatGPT
За его ответ судить не берусь, но общее понимание появилось.
Сначала функция генерирует 23 рандомных байта, далее она делает XOR байта первого символа флага с первым сгенерированным байтом, потом тоже самое со вторым и.т.д.
После XOR'ов всех символов флага программа проверяет на равенство каждый байт зашифрованного флага и изначального. Если таковой есть, то печатает "Leaked some plaintext".
Получается, что в каждом зашифрованном флаге на своем месте нет ни одного символа от изначального.
Т.е если флаг - CODEBY{eto_ne_flag}, то первый байт (43 для "C") нам никогда не встретится. Тоже самое и для остальных символов.
Сбор флагов
Тут мы обращаемся к третьей подсказке "Я думаю, стоит накапливать зашифрованные флаги". Осталось определиться с количеством собираемых флагов. Слышал, что 5000 достаточно, но я определил для себя - 30000. Так сказать, наверняка .Ясно дело, что вручную это ооочень долго, поэтому автоматизируем, используя pynput для ввода с клавиатуры.
Сам код:
Python:
import time
import pynput
from pynput.keyboard import Key, Controller
keyboard = Controller() # Create the controller
i=0
time.sleep(10)
while i<30000 :
keyboard.type('request')
time.sleep(0.1)
keyboard.press(Key.enter)
time.sleep(0.1)
i+=1
Перед тем, как запускать, идем обратно в netcat, останавливаем и опять запускаем, но уже с записью в файл:
ncat 62.173.140.174 11000 -o dump.txt
Запускаем скрипт и переходим в окно netcat'а.
Ждем. Сборка 30000 шифрованных флагов у меня заняла ≈ 1.5-2 часа.
По окончании сбора флагов получаем файл. Теперь нам надо почистить файл от лишнего, оставив только флаги. Открываем VSCode и удаляем ненужное. Я не стал это автоматизировать, т.к делается это за две минуты простой заменой.
Наш дамп до:
После:
Находим флаг
Теперь создаем второй скрипт для нахождения флага:
Python:
start = 0
end = 2
two_bytes = []
text = ''
hex_numbers = ['00','01','02','03','04','05','06','07','08','09','0a','0b','0c','0d','0e','0f',
'10','11','12','13','14','15','16','17','18','19','1a','1b','1c','1d','1e','1f',
'20','21','22','23','24','25','26','27','28','29','2a','2b','2c','2d','2e','2f',
'30','31','32','33','34','35','36','37','38','39','3a','3b','3c','3d','3e','3f',
'40','41','42','43','44','45','46','47','48','49','4a','4b','4c','4d','4e','4f',
'50','51','52','53','54','55','56','57','58','59','5a','5b','5c','5d','5e','5f',
'60','61','62','63','64','65','66','67','68','69','6a','6b','6c','6d','6e','6f',
'70','71','72','73','74','75','76','77','78','79','7a','7b','7c','7d','7e','7f',
'80','81','82','83','84','85','86','87','88','89','8a','8b','8c','8d','8e','8f',
'90','91','92','93','94','95','96','97','98','99','9a','9b','9c','9d','9e','9f',
'a0','a1','a2','a3','a4','a5','a6','a7','a8','a9','aa','ab','ac','ad','ae','af',
'b0','b1','b2','b3','b4','b5','b6','b7','b8','b9','ba','bb','bc','bd','be','bf',
'c0','c1','c2','c3','c4','c5','c6','c7','c8','c9','ca','cb','cc','cd','ce','cf',
'd0','d1','d2','d3','d4','d5','d6','d7','d8','d9','da','db','dc','dd','de','df',
'e0','e1','e2','e3','e4','e5','e6','e7','e8','e9','ea','eb','ec','ed','ee','ef',
'f0','f1','f2','f3','f4','f5','f6','f7','f8','f9','fa','fb','fc','fd','fe','ff',]
remove = "{}'"
for i in range(23):
with open('C:/Users/event/Desktop/dump.txt', 'r') as f:
for line in f:
first_two = line[start:end]
two_bytes.append(first_two)
data = set(hex_numbers) - set(two_bytes)
clear_data = ''.join([char for char in data if char not in remove])
bytes_object = bytes.fromhex(clear_data)
text = "".join([text, bytes_object.decode("utf-8")])
start += 2
end += 2
two_bytes = []
print(text)
Здесь мы объявляем массив всех hex-символов (hex_numbers).
Далее достаем все hex-значения символов из дампа и находим единственное неиспользованное. Его перегоняем в ASCII и добавляем в text.
Запускаем, получаем флаг, сдаем.
Спасибо за прочтение!
Есть критика или пожелание - пишите!)
Последнее редактирование модератором: