Задача о восстановлении преобразованных строк
Задача подойдет всем, кто знаком с программированием.
Условие
На очень важном хосте 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
Готово!