UFOCTF 2017:アーサー王のクエストでのPythonの逆コンパイル(PPC600)



ごあいさつhabrayuzer! 最近、年次UFO CTF 2017 Information Security Olympiadが終了しました。この記事では、 PPCセクションの「King Arthur」というワンタスクのライトがあり、最大ポイント数600を獲得できます。



始めましょう



割り当ての説明には次のものがありました。

ナイトファンから奇妙なメールの添付ファイルを受け取りました。 著者が何を念頭に置いていたかを理解してください。


また、ファイルはダウンロード可能です。



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 """
      
      







輸入蛇行はすぐに注目を集めます。 グーグルの「python serpent sword」のリクエストに応じて、 gitレポジトリに出くわすことができます 。これは、説明から判断すると必要なものです。



コードserpent.pyを調べたところ、コードを剣に「変換」する原理の説明が見つかりました。



16進数65が与えられた場合:

65%32 = 1

床(65/32)= 2

したがって、65のアルファベット記号は、インデックス1の記号:「PT」です。

65は、1の32モジュラスの3番目のオカレンスでもあります(1

もちろん最初の出現であり、33は2番目の出現です。)

したがって、この16進記号のコードは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に変更し 、元に戻します:



 redihi@kali:KingArthur$ python sword.ss.py RuntimeError: Bad magic number in .pyc file
      
      





sword.ss.pycファイル削除されないようにコードをわずかに変更すると、受信したファイルに破損したヘッダーがあることがわかります。



長い検索の後、 .pycファイルのヘッダーのおおよその説明を見つけます。 しかし、それをtrueに変更する試みはすべて成功しませんでした。



同じ記事には、ファイル全体ではなく、コードの別のセクションをコンパイルする例があります。 おそらく同じ方法で、ヘッダーをバイパスして、残りのコードを復元します。 これらの目的のために小さなスクリプトを投げています。



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
      
      







開始後、出力を取得します。



 redihi@kali: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つのコードオブジェクトがあります。必要です。 さらに数行追加して、逆コンパイルします。



 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!



All Articles