Hacker.gifts, или Что подарить программисту?
- понедельник, 13 декабря 2021 г. в 00:31:31
Сегодня, пока начинается наш курс по Fullstack-разработке на Python, рассказываем о стартапе Hacker.gifts, который отвечает на вопрос в заголовке. Автор оригинальной статьи приобрёл головоломку для себя, чтобы помочь читателям разобраться, понравиться ли она кому-то ещё. Под катом вы найдёте решение, общие впечатления и ссылку на задачу посложнее.
В посте нет моих подсказок и файлов, потому что я не знаю, повторяются ли головоломки и не нарушаю ли я какое-то соглашение. Такие данные скрыты символом X
.
Разместив заказ на сайте, вы получите виртуальную открытку с первой головоломкой, вроде той, что ниже. Вы можете задать имя на открытке, её дизайн и сообщение, которое появится после решения всех головоломок.
Отсканировав QR, вы получите что-то вроде этого:
U2VjcmV0IGhleGR1b..............YzMS00NTQyKQo=
Строки, которые заканчиваются символом =
, я обычно видел в алгоритмах, работающих с base64, поэтому решил начать именно с base64. Тогда же я подумал, что декодирование можно автоматизировать, поэтому придумал программу, чтобы декодировать QR и конвертировать base64:
from pyzbar.pyzbar import decode
from PIL import Image
import base64
def solve():
# let's see what's inside the QR
qr = decode(Image.open('../puzzle/card.png'))
data = qr[0].data.decode("utf-8")
print(f"QR data: {data}")
# the last "=" in data looks like it's base64
# let's try that
base64_message = data
base64_bytes = base64_message.encode('ascii')
message_bytes = base64.b64decode(base64_bytes)
plain_msg = message_bytes.decode('ascii')
print(f"Base64: {plain_msg}")
Декодированный текст содержит ссылку на сайт и некий код доступа. Ссылку и код я скрыл символами X, о которых говорил выше.
Секретный hex-дамп: https://XXXXX.XXXXX/ (XXXX-XXXX-XXXX)
После ввода этого кода на сайте по ссылке вас ждёт замечательный hex-дамп. Когда до него дошло, я отметил для себя, что не хочу автоматизировать просмотр сайта. А вот выдержка из дампа:
Первый важный момент — дамп начинается с rar, так что файл, должно быть, сжат и, вероятно, защищён паролем из-за текста внизу. Похоже, что пароля просто нет. Сначала я подумал, что это какая-то ошибка, попробовал несколько раз и заподозрил, что пароль каким-то образом скрыт. Например, в комментарии.
Итак, мы знаем, что файл rar защищён паролем, так что следующий шаг — найти пароль — провести реверс-инжиниринг дампа. Именно это и сделает представленный ниже метод:
def reverse_dump():
newFileBytes = []
with open("../puzzle/hex.txt", "r") as txt_file:
lines = txt_file.readlines()
for line in lines:
if line.startswith("0"):
parts = line.split(" ")
for i, p in enumerate(parts):
if i > 0 and p != "" and not p.startswith("|") and not p.startswith("."):
newFileBytes.append(int(p, base=16))
with open("../puzzle/hex.rar", "wb") as rar_file:
for byte in newFileBytes:
rar_file.write(byte.to_bytes(1, byteorder='big'))
После распаковки одного файла вы получите ещё два:
instr.txt
key
Файл инструкций Instr.text содержит:
Цель — залогиниться на каком-то сервере.
Стихотворение хайку, в нём зашифрован IP.
Незашифрованный пароль от SSH.
Инструкции, как брут-форсом получить другой пароль, чтобы расшифровать файл ключа SSH и залогиниться на сервере.
Начнём с IP-адреса. На него указывает этот хипку:
This hipku will point to a server:
The placid XXXXX hawk
dives in the XXXXX river.
Jasmine XXXXX drop.
Опечатка в слове "хайку" [haiku — hipku] намеренная. Это подсказка, что IP скрыт в стихотворении. Но как его интерпретировать? Вначале я подумал, что это может быть известным стихотворением с изменениями символов, например «placid» — это place. Но, немного погуглив, я обнаружил программу hipku, которая преобразует IP в стихотворение. Быть может, намёк прозрачнее, чем я думал. Расшифровка оказалась довольно простой:
from pyhipku import decode
def reverse_haiku():
print(decode('The placid XXXXX hawk\ndives in the XXXXX river.\nJasmine XXXXX drop.\n'))
167.XX.XXX.XXX
А теперь перебором найдём пароль. В инструкциях сказано, что он состоит из семи цифр, а ещё даётся подсказка — начало хеша пароля (SHA-256):
from hashlib import sha256
from brute import brute
def brute_force():
# replace "XXXXXXXXXX" with your real SHA-256 hint
expected = str.lower("XXXXXXXXXX")
for pwd in brute(length=7, letters=False, numbers=True, symbols=False):
hashed = sha256(pwd.encode('utf-8')).hexdigest()
# print(hashed)
if hashed.startswith(expected):
print(pwd)
Теперь разберёмся с ключом. Файл key
выглядит примерно так:
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END EC PRIVATE KEY-----
В прошлом я часто пользовался PuTTY и знаю, что этой программе нужны ключи в формате ppk, поэтому догадался: чтобы получить пароль, нужно что-то сделать с текстом в key. Здесь мне помог PuTTYgen:
В этом окне нужно ввести полученный перебором пароль, и кликнуть на Save Private Key.
Когда я залогинился на сервере, меня приветствовала консольная версия игры Space Invaders. Пройти нужно было только первый уровень. И вообще это несложно, но игра через SSH немного подтормаживала.
И вот оно! Моё секретное сообщение появилось!
Сделав заказ, вы получите URL-адрес и сможете отслеживать, что делает ваш друг. И это одна из причин, почему в головоломке есть посещение сайта и вход на сервер. Ещё важнее, что вы сможете направлять друзей, если они где-то застряли.
Как видите, есть подсказки. Именно это мы и сделали, но воспользовались другими инструментами. На решение и записи для поста я потратил около 4 часов. Начал я ночью, а затем ушёл спать. Это объясняет "18 часов" на скриншоте.
С точки зрения той части, которую получат ваши друзья, — совершенно точно стоило. Покупка прошла хорошо, платёж был простым, всё пришло сразу же, сайт отслеживания отработал и т. д.
Что касается цены, сделать вывод сложно: о развлечениях у всех нас разные представления. Также всё зависит от ваших прошлых впечатлений и от того, сколько времени займёт решение головоломки. В любом случае вы можете судить об этом по моему решению. Неплохо было бы иметь больше вариантов по длине или по сложности.
Надеюсь, что вы получили удовольствие. Если вам нравятся такие головоломки, я рад предложить кое-что посложнее: Tom’s Data Onion. Я просто взорвался, пока решал её. Это было нелегко, но я узнал несколько интересных вещей.
А решать на Python практические задачи вы научитесь на наших курсах:
Узнайте подробности акции.
Data Science и Machine Learning
Python, веб-разработка
Мобильная разработка
Java и C#
От основ — в глубину
А также