Задача о восстановлении преобразованных строк

Задача о восстановлении преобразованных строк

Тирекс
Тирекс Самый зубастый автор
22 мая 2024

Задача подойдет всем, кто знаком с программированием.

Изображение записи

Условие

На очень важном хосте N отработал вирус, в результате все чувствительные данные превратились в наборы символов и чисел. Бэкапы также повреждены, но специалистам удалось достать файл с логинами и преобразованными паролями.

В нем было следующее:

root:51/\/51/\/57/\/57/\/55/\/55/\/57/\/57/\/49/\/49/\/98/\/98/\/55/\/55/\/101/\/101/\/55/\/55/\/49/\/49/\/50/\/50/\/97/\/97/\/99/\/99/\/53/\/53/\/48/\/48/\/56/\/56/\/100/\/100/\/50/\/50/\/48/\/48/\/48/\/48/\/101/\/101/\/56/\/56/\/50/\/50/\/49/\/49/\/50/\/50/\/101/\/101/\/57/\/57/\/51/\/51/\/49/\/49/\/49/\/49/\/102/\/102/\/56/\/56/\/100/\/100/\/100/\/100/\/102/\/102/\/57/\/57/\/52/\/52/\/100/\/100/\/97/\/97/\/51/\/51/\/51/\/51/\/55/\/55/\/48/\/48/\/54/\/54/\/99/\/99/\/55/\/55/\/53/\/53/\/97/\/97/\/55/\/55/\/49/\/49/\/97/\/97/\/56/\/56/\/102/\/102/\/57/\/57/\/48/\/48/\/55/\/55/\/55/\/55/\/49/\/49/\/55/\/55/\/98/\/98/\/49/\/49/\/102/\/102/\/57/\/57/\/55/\/55

admin:54/\/54/\/100/\/100/\/52/\/52/\/53/\/53/\/50/\/50/\/53/\/53/\/99/\/99/\/50/\/50/\/97/\/97/\/50/\/50/\/49/\/49/\/102/\/102/\/57/\/57/\/98/\/98/\/101/\/101/\/49/\/49/\/99/\/99/\/99/\/99/\/97/\/97/\/57/\/57/\/101/\/101/\/52/\/52/\/49/\/49/\/102/\/102/\/51/\/51/\/97/\/97/\/97/\/97/\/52/\/52/\/48/\/48/\/50/\/50/\/101/\/101/\/48/\/48/\/55/\/55/\/54/\/54/\/53/\/53/\/101/\/101/\/101/\/101/\/53/\/53/\/102/\/102/\/99/\/99/\/99/\/99/\/51/\/51/\/101/\/101/\/55/\/55/\/102/\/102/\/101/\/101/\/97/\/97/\/51/\/51/\/52/\/52/\/97/\/97/\/49/\/49/\/54/\/54/\/57/\/57/\/98/\/98/\/49/\/49/\/55/\/55/\/51/\/51/\/48/\/48/\/97/\/97/\/101/\/101/\/51/\/51/\/56/\/56/\/54/\/54/\/101/\/101

operator:56/\/56/\/53/\/53/\/102/\/102/\/56/\/56/\/99/\/99/\/55/\/55/\/48/\/48/\/99/\/99/\/54/\/54/\/100/\/100/\/98/\/98/\/55/\/55/\/55/\/55/\/55/\/55/\/97/\/97/\/97/\/97/\/100/\/100/\/101/\/101/\/54/\/54/\/97/\/97/\/52/\/52/\/97/\/97/\/101/\/101/\/48/\/48/\/100/\/100/\/102/\/102/\/54/\/54/\/55/\/55/\/97/\/97/\/101/\/101/\/100/\/100/\/99/\/99/\/49/\/49/\/55/\/55/\/57/\/57/\/98/\/98/\/55/\/55/\/98/\/98/\/51/\/51/\/98/\/98/\/53/\/53/\/97/\/97/\/56/\/56/\/102/\/102/\/54/\/54/\/52/\/52/\/54/\/54/\/50/\/50/\/53/\/53/\/57/\/57/\/49/\/49/\/48/\/48/\/57/\/57/\/55/\/55/\/50/\/50/\/97/\/97/\/50/\/50/\/50/\/50/\/57/\/57/\/98/\/98/\/54/\/54/\/97/\/97/\/53/\/53/\/97/\/97

user:52/\/52/\/50/\/50/\/51/\/51/\/52/\/52/\/97/\/97/\/57/\/57/\/99/\/99/\/101/\/101/\/97/\/97/\/50/\/50/\/49/\/49/\/102/\/102/\/97/\/97/\/57/\/57/\/49/\/49/\/49/\/49/\/49/\/49/\/49/\/49/\/48/\/48/\/99/\/99/\/102/\/102/\/51/\/51/\/54/\/54/\/101/\/101/\/57/\/57/\/54/\/54/\/99/\/99/\/100/\/100/\/56/\/56/\/56/\/56/\/55/\/55/\/48/\/48/\/52/\/52/\/57/\/57/\/53/\/53/\/52/\/52/\/51/\/51/\/99/\/99/\/97/\/97/\/51/\/51/\/49/\/49/\/101/\/101/\/55/\/55/\/99/\/99/\/57/\/57/\/53/\/53/\/101/\/101/\/48/\/48/\/52/\/52/\/48/\/48/\/50/\/50/\/56/\/56/\/50/\/50/\/57/\/57/\/48/\/48/\/98/\/98/\/100/\/100/\/101/\/101/\/49/\/49/\/100/\/100/\/98/\/98/\/49/\/49/\/101/\/101/\/48/\/48



Исходный формат строк в файле был таким:

login:hashedpassword

В результате реверса вируса найден код, преобразовывающий хэши паролей:


    hashed_password = '' #hashed passwd is here
passwd = list(hashed_password.swapcase())
passwd_1 = []
for item in passwd:
    passwd_1 += item*2
passwd_2 = []
for item in passwd_1:
    passwd_2.append(str(ord(item)))
passwd_final = '/\/'.join(passwd_2)

Задача

Помогите понять способ восстановления данных, преобразовав эти наборы символов в исходные хэши паролей.

Решение

Из условия понятно: все, что идет после двоеточия, относится к преобразованному хэшу паролей. Значит, необходимо работать с этой частью.

Пошагово проанализируем код преобразования строки и напишем преобразование в обратном порядке.

Искомый хэш записывается в переменную hashed_password. Далее в строке…


    passwd = list(hashed_password.swapcase())

… регистр символов меняется на противоположный и строки преобразуются в список символов.

После чего здесь…


    passwd_1 = []
for item in passwd:
    passwd_1 += item*2

… создается новый массив, состоящий из дублирования символов.

Затем в части кода…


    passwd_2 = []
for item in passwd_1:
    passwd_2.append(str(ord(item)))

… каждый элемент массива passwd_1 преобразовывается в свой ASCII-код и новыми символами заполняется новый массив.

И наконец составляется строка из элементов массива passwd_2 с добавлением разделителей:


    passwd_final = '/\/'.join(passwd_2)

Преобразуем строку обратно.

1. Трансформируем строку passwd_final в список, удалив ‘/\/’ и дубли символов:


    reverse_str = passwd_final.split('/\/')[1::2]

2. Далее для каждого элемента списка выполним обратное преобразование из кода ASCII:


    reverse = []
for item in reverse_str:
    reverse.append(chr(int(item)))

3. Соберем новую строку, выполнив изменение регистра символов на противоположный:


    reverse = ''.join(reverse).swapcase()

В результате получим искомые строки:

root:39791B7E712AC508D200E8212E9311F8DDF94DA33706C75A71A8F907717B1F97

admin:6D4525C2A21F9BE1CCA9E41F3AA402E0765EE5FCC3E7FEA34A169B1730AE386E

operator:85F8C70C6DB777AADE6A4AE0DF67AEDC179B7B3B5A8F64625910972A229B6A5A

user:4234A9CEA21FA911110CF36E96CD887049543CA31E7C95E04028290BDE1DB1E0

Готово!

Полезные материалы для обучения