Reversing Python (Part 7)
Мои познания ещё далеки от гуру в питоне, но синтаксис я уже изучил.
Поэтому, в то время пока Стас штурмовал стеганографию, я разбирал строки кода небольшого скрипта.
#!/usr/bin/python2.7 import random lr = '\x64' print ''' ___________.__ _________ __ \__ ___/| |__ ____ / _____/ ____ _____ | | __ ____ | | | | \_/ __ \ \_____ \ / \\__ \ | |/ // __ \ | | | Y \ ___/ / \ | \/ __ \| <\ ___/ |____| |___| /\___ > /_______ /___| (____ /__|_ \\___ > \/ \/ \/ \/ \/ \/ \/ ''' the_key_is_bellow='bmVlZCBvbmx5IDEw' chains = [0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x72, 0x6f, 0x6c, 0x6c] # dGhpcyBpcyBhIHRyb2xs db = '\x6e' ef = '\x63' chars = [] keys = [0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x21, 0x21] # cGFzc3dvcmQhIQ== nn = '\x61' lock_pick = random.randint(0, 0x3e8) lock = lock_pick * 2 password = [0x69, 0x74, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x61, 0x73, 0x79] # %69%74%73%20%6e%6f%74%20%74%68%61%74%20%65%61%73%79 lock = lock + 10 ty = '\x61' lock = lock / 2 auth = [0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67] # 6b65657020747279696e67 lock = lock - lock_pick gh = '\x6e' print 'Your number is ' + str(lock_pick) for key in keys: keys_encrypt = lock ^ key chars.append(keys_encrypt) for chain in chains: chains_encrypt = chain + 0xA chars.append(chains_encrypt) aa = '\x61' rr = '\x6f' slither = aa + db + nn + ef + rr + gh + lr + ty print 'Authentication required' print '' user_input = raw_input('Enter your username\n') if user_input == slither: pass else: print 'Wrong username try harder' exit() pass_input = raw_input('Enter your password\n') for passes in pass_input: for char in chars: if passes == str(chr(char)): print 'Good Job' break else: print 'Wrong password try harder' exit(0) break
Эти 58 строк кода заняли у меня 1.5 часа анализа переменных, шифров и подсказки от бота:
Задание:Reversing Python
Points: 15
Описание: В этот раз змея запуталась настолько, что не понятно, где ее хвост, а где голова. Все, что тебе надо — это разобраться в этой путанице и найти ее голову. Говорят, что длина змеи 10 метров.
10 метров как можно догадаться — длина флага — 10 символов.
При запуске скрипт генерирует случайное число с помощью random.randint(0, 0x3e8) и выводит в строке «Your number is …»
Естественно были мысли что флаг как-то связан с этим числом, но оказалось что оно здесь лишь для отвлечения внимания.
Пришла умная мысль что разбирать работу скрипта нужно с конца… Точнее со строк которые запрашивают «username»
Я немного схитрил и указал в коде вывести username при любом неправильном вводе
'''' if user_input == slither: pass else: print 'username must be '+slither exit() ''''
Отлично, мы узнали username, но вот с паролем нам так не повезёт
Скрипт выдаёт только первый символ пароля — «u» Значит надо думать шире…
Первая буква username «a» является переменной » a =’\x61′ «а это значит что перед нами кодировка HEX… Идём дальше
Всего в скрипте 4 основных переменных: chains, keys, lock_pick и lock. Password и Auth лишь для отвлечения внимания и по факту нигде не используются.
lock_pick генерирует случайное число, а lock сначала умножает его на 2, затем добавляет 10, делит на 2 и вычитает исходное число lock_pick.
На примере 169 проведём эти вычисления — «((169*2)+10)/2-169 = 5» И это независимо от того, какое значение примет lock_pick.
Далее разберем цикл для keys и chains. Каждый из них по своему модифицирует указанные ранее значения в массивах keys и chains.
^ — знак карет — Бинарный «Исключительное ИЛИ» оператор копирует бит только если бит присутствует в одном из операндов, но не в обоих сразу.
Например первый знак в переменной keys: 5 ^ 0x70 = 117, а str(chr(117)) это «u»
Можно по буквам перебрать, а можно цикл написать… кому как удобнее)
Включайте мозг и пробуйте…