UFOCTF 2017: декомпилируем Python в задании King Arthur (PPC600)

от автора


Приветствую тебя хабраюзер! Недавно, закончилась ежегодная олимпиада по информационной безопасности UFO CTF 2017. В этой статье будет райтап одного задания из раздела PPC, под названием «King Arthur», за который можно было получить максимальное количество очков — 600.

Начнём

В описании к заданию было следующее:

Мы получили какое-то странное вложение в e-mail от фаната рыцарей. Помогите разобраться, что имел в виду автор.

И был доступен для скачивания файл:

sword.py

#!/usr/bin/python import serpent """            ___           { _ }            |/|           {___}            |_|            |/|  .         |/|         .  (\________|w|________/)  ( ___________________ )   v       | | |       v           | | |           | | |           | | |PO0.HN7           | | |   *   TP0~~~<          z| | |ON4.YH1        OP6| | |          ON2| |           |PO3|           | |PY0           | | PY0           | | |PY0          z| | |PY0         PY0 | |z        PY0| | |          PY0| |           |PY0|           | |PH0           | | PY0           | | |PY0          z| | |PY0         PY0 | |z        PY0| | |          PY0| |           |PY0|           | |HN3           | | PY1           | | |PY0          z| | |PY0         PY0 | |z        PN3| | |          PT0| |           |PY0|           | |PN3           | | PY0           | | |PY0          z| | |TH3         PY0 | |z        PY0| | |          NY2| |           |PY0|           | |PY0           | | PN3           | | |PH0          z| | |PY0         PN4 | |z        PY0| | |          PY0| |           |NY2|           | |PT0           | | PY0           | | |YP3          z| | |PT0         PY0 | |z        PO4| | |          PY0| |           |PY0|           | |PT0           | | PN3           | | |PY0          z| | |PY0         HN2 | |z        YO1| | |          PO0| |           |PY0|           | |PY0           | | PY0           | | |TN2          z| | |YN3         YY7 | |z        YY7| | |          YY7| |           |YY7|           | |PO3           | | PY0           | | |PY0          z| | |PY0         PY0 | |z        PH0| | |          PY0| |           |PY0|           | |PY0           | | HO0           | | |PY0          z| | |PY0         PY0 | |z        PO0| | |          PY0| |           |PY0|           | |PY0           | | HN3           | | |YY4          z| | |PY0         PY0 | |z        PY0| | |          OP3| |           |PY0|           | |PY0           | | PN3           | | |PT0          z| | |PY0         PO4 | |z        PT0| | |          PY0| |           |NO3|           | |PT0           | | PY0           | | |NH3          z| | |PT0         PY0 | |z        PN3| | |          PY0| |           |PY0|           | |PN3           | | PH0           | | |PY0          z| | |PN3         PO0 | |z        PY0| | |          YP4| |           |PO0|           | |PY0           | | NP0           | | |PN3          z| | |PN0         PY0 | |z        TY3| | |          PO0| |           |PY0|           | |HO3           | | TO1           | | |PY0          z| | |PN3         YP0 | |z        PY0| | |          YH2| |           |YO2|           | |TN3           | | TN3           | | |PY0          z| | |NH3         PT0 | |z        PY0| | |          PN3| |           |PH0|           | |PY0           | | PN3           | | |PY0          z| | |PY0         PN3 | |z        PO0| | |          PY0| |           |YP4|           | |PO0           | | PY0           | | |NP0          z| | |PN3         YT0 | |z        PY0| | |          TY3| |           |PO0|           | |PY0           | | HO3           | | |HO3          z| | |PY0         PN3 | |z        YP0| | |          PY0| |           |YH2|           | |YO2           | | TN3           | | |TO2          z| | |PY0         NH3 | |z        PT0| | |          PY0| |           |PN3|           | |YH0           | | PY0           | | |TY0          z| | |PN3         YO0 | |z        PY0| | |          TY0| |           |PN3|           | |PO0           | | PY0           | | |TY0          z| | |YP4         PO0 | |z        PY0| | |          NP0| |           |PN3|           | |YN0           | | PY0           | | |TY3          z| | |PO0         PY0 | |z        HO3| | |          OT4| |           |PY0|           | |PN3           | | YP0           | | |PY0          z| | |YH2         YO2 | |z        TN3| | |          YN1| |           |PY0|           | |NH3           | | PT0           | | |PY0          z| | |PN3         TP0 | |z        PY0| | |          TY0| |           |PN3|           | |PH0           | | PY0           | | |TY0          z| | |PN3         PO0 | |z        PY0| | |          TY0| |           |YP4|           | |PO0           | | PY0           | | |NP0          z| | |PN3         TY0 | |z        PY0| | |          TY3| |           |PO0|           | |PY0           | | HO3           | | |TN2          z| | |PY0         PN3 | |z        YP0| | |          PY0| |           |YH2|           | |YO2           | | TN3           | | |YP0          z| | |PY0         PN3 | |z        TH0| | |          PY0| |           |YH2|           | |YO2           | | PN3           | | |PY0          z| | |PY0         HN2 | |z        YO1| | |          TO0| |           |PY0|           | |PY0           | | PY0           | | |TN2          z| | |HN3         TO0 | |z        PY0| | |          PY0| |           |PY0|           | |YP2           | | TN3           | | |OP3          z| | |YP3         HO3 | |z        PY1| | |          TH3| |           |YN3|           | |TN3           | | YP3           | | |NY1          z| | |PY1         TP0 | |z        YN3| | |          TN0| |           |PY0|           | |PY0           | | PY0           | | |YN3          z| | |PH0         PY0 | |z        PY0| | |          PY0| |           |OP3|           | |YH0           | | PY0           | | |PY0          z| | |PY0         ON2 | |z        TO2| | |          YH3| |           |NP1|           | |OT3           | | OT1           | | |OT1          z| | |HN3         YP0 | |z        PY0| | |          PY0| |           |PY0|           | |YT2           | | PT3           | | |YN3          z| | |TH3         PT1 | |z        OP3| | |          YO0| |           |PY0|           | |PY0           | | PY0           | | |NP3          z| | |PH2         YT3 | |z        PH2| | |          YH3| |           |NP1|           | |OT3           | | PT3           | | |YN3          z| | |HP0         PY0 | |z        PY0| | |          PY0| |           |YN3|           | |PP0           | | PY0           | | |PY0          z| | |PY0         OP3 | |z        YO0| | |          PY0| |           |PY0|           | |PY0           | | NP2           | | |HT1          z| | |HY2         ON2 | |z        HT3| | |          YH3| |           |YH3|           | |PH2           | | YN3           | | |PT0          z| | |PY0         PY0 | |z        PY0| | |          OP3| |           |YH0|           | |PY0           | | PY0           | | |PY0          z| | |HN1         OH2 | |z        OH1| | |          OP1| |           |TY3|           | |YO3           | | OH3           | | |HN3          z| | |YO0         PY0 | |z        PY0| | |          PY0| |           |HN2|           | |OY3           | | PO3           | | |PO3          z| | |YP3         HN3 | |z        HN3| | |          PT1| |           |YO1|           | |PH0           | | PY0           | | |PY0          z| | |PY0         OP3 | |z        YN0| | |          PY0| |           |PY0|           | |PY0           | | HO3           | | |PT3          z| | |OH3         YY2 | |z        YN3| | |          TN3| |           |HY3|           | |OY3           | | OP3           | | |OP3          z| | |PN0         PY0 | |z        PY0| | |          PY0| |           |TH3|           | |YN3           | | TN3           | | |YP3          z| | |YO1         PH0 | |z        PY0| | |          PY0| |           |PY0|           | |HO2           | | PN0           | | |PY0          z| | |PY0         PY0 | |z        HO2| | |          YP0| |           |PY0|           | |PY0           | | PY0           | | |YO1          z| | |PY0         PY0 | |z        PY0| | |          PY0| |           |YO1|           | |PY0           | | PY0           | | |PY0          z| | |PY0         HN3 | |z        HP2| | |          PY0| |           |PY0|           | |PY0           | | PN2           | | |NY1          z| | |NH2         PN2 | |z        HP3| | |          OH3| |           |TN3|           | |TH3           | | HP3           | | |PT3          z| | |PN3         HN3 | |z        NH2| | |          OY2| |           |YT2|           | |HP2           | | PO2           | | |OP2          z| | |YT2         NH2 | |z        OP2| | |          PT2| |           |HN2|           | |TY2           | | HN2           | | |NH2          z| | |HN3         YP3 | |z        HO3| | |          HY3| |           |YP3|           | |TN3           | | OP3           | | |NH2          z| | |HN3         HP3 | |z        OY3| | |          HO3| |           |PO3|           | |YP3           | | HN3           | | |NH2          z| | |HN2         YP3 | |z        HO3| | |          HY3| |           |YP3|           | |TN3           | | OP3           | | |TO1          z| | |TO3         PT3 | |z        HN3| | |          OP3| |           |YP3|           | |HO3           | | NH2           | | |HN2          z| | |YP3         HO3 | |z        HY3| | |          YP3| |           |TN3|           | |OP3           | | TO1           | | |TO3          z| | |PT3         HN3 | |z        OP3| | |          YP3| |           |HO3|           | |NH2           | | OP3           | | |YP3          z| | |HN3         OP3 | |z        TN1| | |          HY3| |           |NP3|           | |HN3           | | PN0           | | |PY0          z| | |PY0         PY0 | |z        OP3| | |          PT3| |           |HN3|           | |TY3           | | PN0           | | |PY0          z| | |PY0         PY0 | |z        HN3| | |          HY0| |           |PY0|           | |PY0           | | PY0           | | |PY0          z| | |PT0         TH0 | |z        PT0| | |          NP0| |           |PT0|           | |YO0           | | PT0           | | |NP0          z| | |PT0         YO0 | |z        PO0| | |          NH0| |           |PT0|           | |TH1           | | PH0           | | |YO1          z| | |PH0         PY0 | |z        PY0| | |          PY0| |           |OP3|           | |YH0           | | PY0           | | |PY0          z| | |PY0         HN3 | |z        YP3| | |          HO3| |           |HY3|           | |YP3           | | TN3           | | |OP3          z| | |OP3         PN0 | |z        PY0| | |          PY0| |           |PY0|           | |OP3           | | PT3           | | |HN3          z| | |TY3         YO1 | |z        PH0| | |          PY0| |           |PY0|           | |PY0           | | HO2           | | |YT0          z| | |PY0         PY0 | |z        PY0| | |          HO2| |           |YH0|           | |PY0           | | PY0           | | |PY0          z| | |YO1         PY0 | |z        PY0| | |          PY0| |           |PY0|           | |YO1           | | PY0           | | |PY0          z| | |PY0         PY0 | |z        HN3| | |          HP2| |           |PY0|           | |PY0           | | PY0           | | |PN2          z| | |NY1         NH2 | |z        PN2| | |          HP3| |           |OH3|           | |TN3           | | TH3           | | |HP3          z| | |PT3         PN3 | |z        HN3| | |          NH2| |           |OY2|           | |YT2           | | HP2           | | |PO2          z| | |OP2         YT2 | |z        NH2| | |          OP2| |           |PT2|           | |HN2           | | TY2           | | |HN2          z| | |NH2         HN3 | |z        YP3| | |          HO3| |           |HY3|           | |YP3           | | TN3           | | |OP3          z| | |NH2         HN3 | |z        HP3| | |          OY3| |           |HO3|           | |PO3           | | YP3           | | |HN3          z| | |NH2         HN2 | |z        YP3| | |          HO3| |           |HY3|           | |YP3           | | TN3           | | |OP3          z| | |TO1         TO3 | |z        PT3| | |          HN3| |           |OP3|           | |YP3           | | HO3           | | |NH2          z| | |HN2         YP3 | |z        HO3| | |          HY3| |           |YP3|           | |TN3           | | OP3           | | |TO1          z| | |TO3         PT3 | |z        HN3| | |          OP3| |           |YP3|           | |HO3           | | NH2           | | |OP3          z| | |YP3         HN3 | |z        OP3| | |          TN1| |           |HY3|           | |NP3           | | HN3           | | |YO0          z| | |PY0         PY0 | |z        PY0| | |          NH1| |           |TO3|           | |HP3           | | PN3           | | |OY3          z| | |TH3         YP3 | |z        PP1| | |          PT0| |           |PY0|           | |PY0           | | PY0           | | |HN3          z| | |PN0         PY0 | |z        PY0| | |          PY0| |           |TH0|           | |PO0           | | YN0           | | |TO0          z| | |zz            z | |           z | |           | | |           | | |            \|/             v """

Сразу привлекает внимание строка import serpent. По запросу «python serpent sword» в гугл можно наткнуться на git-репозиторий, который судя по описанию — как раз то что нам нужно.

Изучив код serpent.py находим там описание принципа «превращения» кода в меч:

Given the hex digit 65:
65 % 32 = 1
floor( 65 / 32 ) = 2
so the alphabet symbol for 65 is the symbol at index 1: ‘PT’.
65 is also the 3rd occurrence of a 32-modulus of 1 (with 1
being the first occurrence and 33 being the second of course.)
so the code for this hex symbol is PT2

Но самое интересное расположено ниже:

elif scriptType is _SERPENT:      pyc = _serpent_sword_alphabet_to_hex(_lex_hex(sys.argv[0]))     pycout = ".".join(sys.argv[0].split(".")[0:-1])+".pyc"      with open(pycout, "wb") as f:         for val in pyc:         f.write(chr(val))

Этот код, считывает преобразованный файл, и переводит его обратно в .pyc. Переименуем файл sword.py в sword.ss.py и попробуем его обратить:

gh0st3rs@gh0st3rs-pc:KingArthur$ python sword.ss.py  RuntimeError: Bad magic number in .pyc file

Немного изменив код, таким образом чтобы файл sword.ss.pyc не удалялся обнаруживаем, что у полученного файла поврежден заголовок.

После долгих поисков, находим примерное описание заголовка .pyc файла. Но все попытки изменить его на верный не увенчались успехом.

Там же в статье, есть пример компиляции не всего файла, а отдельного участка кода. Вероятно таким же образом получится минуя заголовок, восстановить оставшуюся часть кода. Накидаем для этих целей небольшой скрипт:

unserpent.py

#!/usr/bin/python import re import sys import marshal  alphabet = [     "PY", "PT", "PH", "PO", "PN", "YP", "YT", "YH", "YO", "YN", "TP", "TY", "TH", "TO", "TN",     "HP", "HY", "HT", "HO", "HN", "OP", "OY", "OT", "OH", "ON", "NP", "NY", "NT", "NH", "NO",     "PP", "YY" ]   def _serpent_sword_alphabet_to_hex(sentence):     "Convert the serpent alphabet string back to python bytecode"     return [alphabet.index(symbol[0:-1]) + int(symbol[-1]) * 32 for symbol in sentence]   def _lex_hex(infile):     "Extract the serpent string from the ss file"     with open(infile, 'r') as source:         regex = re.compile(r'[PYTHON][PYTHON][0-9]')         tokens = []         for line in source:             pos = 0             while(pos < len(line)):                 match = regex.match(line, pos)                 if match:                     tokens.append(match.group(0))                 pos += 1         return tokens   def convert_to_pyc(fname):     pyc = _serpent_sword_alphabet_to_hex(_lex_hex(fname))     pycout = ".".join(fname.split(".")[0:-1]) + ".pyc"     with open(pycout, "wb") as f:         for val in pyc:             f.write(chr(val))     f.close()     return pycout   fname = sys.argv[1] pycout = convert_to_pyc(fname) f = open(pycout, "rb").read() for x in range(len(f)):     try:         code = marshal.loads(f[x:])         print('Offset found: %d' % x)         print('\targcount: %s' % code.co_argcount)         print('\tcode: %s' % code.co_code.encode('hex'))         print('\tconsts count: %d' % len(code.co_consts))         for item in code.co_consts:             print('\t\t%s: %r' % (type(item), item))         print('\tfilename: %s' % code.co_filename)         print('\tfirstlineno: %s' % code.co_firstlineno)         print('\tflags: %s' % code.co_flags)         print('\tname: %s' % code.co_name)         print('\tnlocals: %s' % code.co_nlocals)         print('\tstacksize: %s' % code.co_stacksize)         print('\tvarnames count: %d' % len(code.co_varnames))         for item in code.co_varnames:             print('\t\t%r' % item)         break     except ValueError:         continue

После запуска получаем вывод:

gh0st3rs@gh0st3rs-pc:KingArthur$ ./unserpent.py sword.ss.py Offset found: 7 	argcount: 0 	code: 6401006400006c00005a00006402008400005a01006501008300000164000053 	consts count: 3 		<type 'NoneType'>: None 		<type 'int'>: -1 		<type 'code'>: <code object task at 0x7f7e85aa9eb0, file "D:\Downloads\UFOCTF\TASKS\serpent\sources\Serpent-master\Serpent-master\test.py", line 4> 	filename: D:\Downloads\UFOCTF\TASKS\serpent\sources\Serpent-master\Serpent-master\test.py 	firstlineno: 1 	flags: 0 	name: <module> 	nlocals: 0 	stacksize: 2 	varnames count: 2 		'serpent' 		'task'

Как можно заметить, тут есть ещё 1 объект code, он то нам и нужен. Добавим ещё пару строк, для его декомпиляции:

import uncompyle6 ... uncompyle6.main.uncompyle(2.7, code.co_consts[2], sys.stdout)

Снова запускаем и получаем готовый скрипт:

# uncompyle6 version 2.9.10 # Python bytecode 2.7 # Decompiled from: Python 2.7.6 (default, Oct 26 2016, 20:30:19)  # [GCC 4.8.4] # Embedded file name: D:\Downloads\UFOCTF\TASKS\serpent\sources\Serpent-master\Serpent-master\test.py line = raw_input('Enter line: \n') if line[:14:2] != 'XMg9v66':     print 'Fail!' elif line[14::2] != 'yBfBg9va':     print 'Fail!' elif line[-15:-30:-2] != 'Y1PXqggB':     print 'Fail!' elif line[-1:-14:-2] != '3W74khw':     print 'Fail!' else:     print 'Success!'

Осталось дело за малым, по полученному коду восстанавливаем флаг:

ufoctf{XBMggg9qvX6P61yYBwfhBkg497vWa3}

Задание пройдено! +600 к рейтингу!
ссылка на оригинал статьи https://habrahabr.ru/post/325580/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *