• Профессиональным авторам. Срочный заказ!

    Необходимо сделать развернутое описание каждой из наших услуг. Ограничений на объем текста нет. ЦА - руководство компаний (сухой технический текст). При отсутствии исполнителей среди участников форума, работа будет передана фрилансерам 10 февраля.

    Подробнее о заказе ...

CTF CTF для новичков KHS 2018 (Part 7) - Reversing Python

clevergod

clevergod

Gold Team
22.04.2017
76
351
Reversing Python (Part 7)

Данный таск выполнял мой колега и друг Антон и разбор будет с его слов.

Мои познания ещё далеки от гуру в питоне, но синтаксис я уже изучил.
Поэтому, в то время пока @clevergod штурмовал стеганографию, я разбирал строки кода небольшого скрипта.

Python:
#!/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 символов.

snake-username.png

При запуске скрипт генерирует случайное число с помощью random.randint(0, 0x3e8) и выводит в строке "Your number is ..."

Естественно были мысли что флаг как-то связан с этим числом, но оказалось что оно здесь лишь для отвлечения внимания.
Пришла умная мысль что разбирать работу скрипта нужно с конца... Точнее со строк которые запрашивают "username"
Я немного схитрил и указал в коде вывести username при любом неправильном вводе

Python:
''''
if user_input == slither:
    pass
else:
    print 'username must be '+slither
    exit()
''''
Отлично, мы узнали username, но вот с паролем нам так не повезёт
snake-anaconda.png


Скрипт выдаёт только первый символ пароля - "u" Значит надо думать шире...
snake-u.png


Первая буква 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"



Можно по буквам перебрать, а можно цикл написать... кому как удобнее)
Включайте мозг и пробуйте...

Тем, кто пропустил что-то, задач было 11: Brain, Finde the cat, FTP-authentication, Reversing Python, Steganography 2, Steganography 3, Steganography 4, Steganography 5, WTFilee, Command & Control, Command & Control2
 
Мы в соцсетях: