TJCTF 2018 - Mirror Mirror (Misc)

This challenge was a pretty cool pyjail with lot of different ways to solve it. I was playing with python bytecode few week ago so I decided to do it with. The information provided was a tcp port to connect with netcat and the flag was 100 points!

Getting the function code

switch :: ~/CTF/tjctf/canary » nc problem1.tjctf.org 8004
Hi! Are you looking for the flag? Try get_flag() for free flags. Remember, wrap your input in double quotes. Good luck!
>>> dir()
['__builtins__', '__doc__', '__name__', 'get_flag']
>>> get_flag("aaa")
a is not a valid character

 

So what does this function do, we have to analyse it. It data is available here : get_flag.func_code

>>> dir(get_flag.func_code)
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
>>>

 

So we can now generate some 'pseudo python code' with the function dis.disassemble_string

import dis

co_code = 'd\x01\x00}\x01\x00x\xa2\x00t\x00\x00|\x00\x00\x83\x01\x00D]\x94\x00}\x02\x00t\x01\x00|\x02\x00\x83\x01\x00}\x03\x00|\x03\x00d\x02\x00k\x05\x00o:\x00|\x03\x00d\x03\x00k\x01\x00p\x82\x00|\x03\x00d\x04\x00k\x05\x00oR\x00|\x03\x00d\x05\x00k\x01\x00p\x82\x00|\x03\x00d\x06\x00k\x05\x00oj\x00|\x03\x00d\x07\x00k\x01\x00p\x82\x00|\x03\x00d\x08\x00k\x02\x00p\x82\x00|\x03\x00d\t\x00k\x02\x00r\xa7\x00t\x02\x00|\x02\x00d\n\x00\x17\x83\x01\x00\x01t\x03\x00j\x04\x00j\x05\x00\x83\x00\x00\x01d\x00\x00Sn\x00\x00q\x13\x00Wt\x06\x00|\x00\x00\x83\x01\x00|\x01\x00k\x02\x00r\xa6\x11t\x02\x00d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17d\x0b\x00\ri\x00\x00g\x00\x00k\x00\x00d\x00\x00i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x85\x03\x00\x19i\x00\x00g\x00\x00k\x00\x00\x0fi\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>i\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0fi\x00\x00g\x00\x00k\x00\x00>\x0f\x16\x17\x83\x01\x00\x01n\n\x00t\x02\x00d\x0c\x00\x83\x01\x00\x01t\x03\x00j\x04\x00j\x05\x00\x83\x00\x00\x01d\x00\x00S'

co_argc =1
co_nlocas = 4
stack_size = 8
flags = 0
consts = (None, 'this_is_the_super_secret_string', 48, 57, 65, 90, 97, 122, 44, 95, ' is not a valid character', '%\xcb', "You didn't guess the value of my super_secret_string")
names = ('str', 'ord', 'print', 'sys', 'stdout', 'flush', 'eval')
varnames = ('input', 'super_secret_string', 'each', 'val')
file_name = 'pasimportant'
name = 'get_flag'
firstlineno = 15
lnotab = '\x00\x01\x06\x01\x13\x01\x0c\x01`\x01\x0e\x01\r\x01\x0b\x01\x12\x01\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xf9\x02\n\x01'


dis.disassemble_string(
    list(co_code),
    1,
    varnames,
    names,
    consts
)

 

switch@debian:~/Documents$ python resolv.py | more
          0 LOAD_CONST          1 ('this_is_the_super_secret_string')
          3 STORE_FAST          1 (super_secret_string)
          6 SETUP_LOOP        162 (to 171)
          9 LOAD_GLOBAL         0 (str)
         12 LOAD_FAST           0 (input)
         15 CALL_FUNCTION       1
         18 GET_ITER       
    >>   19 FOR_ITER          148 (to 170)
         22 STORE_FAST          2 (each)
         25 LOAD_GLOBAL         1 (ord)
         28 LOAD_FAST           2 (each)
         31 CALL_FUNCTION       1
         34 STORE_FAST          3 (val)
         37 LOAD_FAST           3 (val)
         40 LOAD_CONST          2 (48)
         43 COMPARE_OP          5 (>=)
         46 JUMP_IF_FALSE_OR_POP    58
         49 LOAD_FAST           3 (val)
         52 LOAD_CONST          3 (57)
         55 COMPARE_OP          1 (<=)
    >>   58 JUMP_IF_TRUE_OR_POP   130
         61 LOAD_FAST           3 (val)
         64 LOAD_CONST          4 (65)
         67 COMPARE_OP          5 (>=)
         70 JUMP_IF_FALSE_OR_POP    82
         73 LOAD_FAST           3 (val)
         76 LOAD_CONST          5 (90)
         79 COMPARE_OP          1 (<=)
    >>   82 JUMP_IF_TRUE_OR_POP   130
         85 LOAD_FAST           3 (val)
         88 LOAD_CONST          6 (97)
         91 COMPARE_OP          5 (>=)
         94 JUMP_IF_FALSE_OR_POP   106
         97 LOAD_FAST           3 (val)
        100 LOAD_CONST          7 (122)
        103 COMPARE_OP          1 (<=)
    >>  106 JUMP_IF_TRUE_OR_POP   130
        109 LOAD_FAST           3 (val)
        112 LOAD_CONST          8 (44)
        115 COMPARE_OP          2 (==)
        118 JUMP_IF_TRUE_OR_POP   130
        121 LOAD_FAST           3 (val)
        124 LOAD_CONST          9 (95)
        127 COMPARE_OP          2 (==)
    >>  130 POP_JUMP_IF_FALSE   167
        133 LOAD_GLOBAL         2 (print)
        136 LOAD_FAST           2 (each)
        139 LOAD_CONST         10 (' is not a valid character')
        142 BINARY_ADD     
        143 CALL_FUNCTION       1
        146 POP_TOP        
        147 LOAD_GLOBAL         3 (sys)
        150 LOAD_ATTR           4 (stdout)
        153 LOAD_ATTR           5 (flush)
        156 CALL_FUNCTION       0
        159 POP_TOP        
        160 LOAD_CONST          0 (None)
        163 RETURN_VALUE   
        164 JUMP_FORWARD        0 (to 167)
    >>  167 JUMP_ABSOLUTE      19
    >>  170 POP_BLOCK      
    >>  171 LOAD_GLOBAL         6 (eval)
        174 LOAD_FAST           0 (input)
        177 CALL_FUNCTION       1
        180 LOAD_FAST           1 (super_secret_string)
        183 COMPARE_OP          2 (==)
        186 POP_JUMP_IF_FALSE  4518
        189 LOAD_GLOBAL         2 (print)
        192 LOAD_CONST         11 ('%\xcb')
        195 UNARY_CONVERT  
        196 BUILD_MAP           0
        199 BUILD_LIST          0
        202 COMPARE_OP          0 (<)
        205 LOAD_CONST          0 (None)
        208 BUILD_MAP           0
        211 BUILD_LIST          0

[...]
       4507 BINARY_LSHIFT  
       4508 UNARY_INVERT   
       4509 BINARY_MODULO  
       4510 BINARY_ADD     
       4511 CALL_FUNCTION       1
       4514 POP_TOP        
       4515 JUMP_FORWARD       10 (to 4528)
    >> 4518 LOAD_GLOBAL         2 (print)
       4521 LOAD_CONST         12 ("You didn't guess the value of my super_secret_string")
       4524 CALL_FUNCTION       1
       4527 POP_TOP        
    >> 4528 LOAD_GLOBAL         3 (sys)
       4531 LOAD_ATTR           4 (stdout)
       4534 LOAD_ATTR           5 (flush)
       4537 CALL_FUNCTION       0
       4540 POP_TOP        
       4541 LOAD_CONST          0 (None)
       4544 RETURN_VALUE   

 

Reversing the function get_flag

After some investigations the function workflow seems to look like this :

 

First the function store "this_is_the_super_secret_string" in a variable named super_secret_thing. Then it call the function input and do a for each loop on the result.

 

This foreach loop check if each character provided by the user didn't match : A-Za-z0-9;_. If the user provide one of these the function jump to line 130 which will display "%s is not a valid character" % each then will exit.

 

If our input string pass this kind of validation it will be passed through python function eval (line 171), the result will be compared with the variable super_secret_thing which contains "this_is_the_super_secret_string".

 

If the both variable are not equals we will jump to line 4518 which will display : "You didn't guess the value of my super_secret_string". Else the execution flow continues and will display the flag.

 

The flag is generated through a complex and very very long set of binary instruction, with array, dictionary conversion, left and right shift.

 

It will be a suicide to try to understand how the flag is generated and providing "this_is_the_super_secret_string" without using A-Za-z0-9;_ seems complicated.

 

But we have the code of the function, so we can patch it like it was a standard binary. We just have to know the right python bytecode opcode !

 

Patching the function

We can patch at different level, but I choosed the easiest one. We are gonna do a jump to the line wich display the flag.

 

For this we have to found the right opcode and it parameters via : https://github.com/python/cpython/blob/master/Lib/opcode.py#L155;

 

 

We will use the op_code 113 which mean JUMP_ABSOLUTE(line_number).

According to https://docs.python.org/2/library/dis.html#opcode-JUMP_ABSOLUTE there is only one parameters and this python bytecode instruction are 3 bytes long :

 

opcode    parameters_on_two_bytes

 

Python opcode are always one byte long, but the size of their argument depends on their opcode number.

The argument is one byte long if the opcode is under dis.HAVE_ARGUMENT and two byte long if the opcode is superior. For my python version dis.HAVE_ARGUMENT is 90. As JUMP_ABSOLUTE opcode is 113 the argument is two byte long.

 

 

So let's patch

co_code = list(co_code)
co_code[0] = '\x71'
co_code[1] = '\xbd'
co_code[2] = '\x00'

dis.disassemble_string(
    co_code,
    1,
    varnames,
    names,
    consts
)
switch@debian:~/Documents$ python resolv.py | more
          0 JUMP_ABSOLUTE     189
          3 STORE_FAST          1 (super_secret_string)
          6 SETUP_LOOP        162 (to 171)
          9 LOAD_GLOBAL         0 (str)
         12 LOAD_FAST           0 (input)

 

 

Great the code is patched, so now we just have to construct a function with all the argument and the patched bytecode

 

[...]

co_code = list(co_code)
co_code[0] = '\x71'
co_code[1] = '\xbd'
co_code[2] = '\x00'

patched = new.code(
    co_argc,
    co_nlocas,
    stack_size,
    flags,
    "".join(co_code),
    consts,
    names,
    varnames,
    file_name,
    name,
    firstlineno,
    lnotab
)

def get_flag():
    pass

get_flag.func_code = patched
get_flag("no_matter_what")

 

I've just remplaced the func_code object in the function get_flag() because when I tried to do 'eval(patched("..")) or exec patched("test")' I got an error "code object is not callable" I can't figure out why for the moment.

 

switch@debian:~/Documents$ python resolv.py 
tjctf{wh0_kn3w_pyth0n_w4s_s0_sl1pp3ry}

The other ways

As I said before there are lot of ways to solve this challenge, another team called Aperi'Kube did a nice write up with different way. Reading their write up the published the source code of the challenge, it allow myself to see the generation of the flag :

 

if(eval(input) == super_secret_string):
        print(`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~(~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~(((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~((~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~(~(((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~(~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(((~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~(((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(((~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(((((~(({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~((~(~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~(((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~((~((~(~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%((~(~((~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~((~(((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[])))+`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(~(~(~((((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))))

 

This is fucking weird but thanks to one of their member, Zeecka I was able to understand it better:

In 'print(`'%\xcb'`[{}<[]::~(~({}<[])<<({}<[]))]%(((~(~(~((~({}<[])<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))<<({}<[]))))'

{} < [] => True

True = 1

~(True) = -2

~({}<[]) << (True) = 4

`'%\xcb'`[1::3] == repr('%\xcb')[1::3] == "%c"

 

  • Python declare {} inferior to [] so {} < [] return True
  • True is a boolean which represent 1 (False : 0)
  • ~ It a bitwise operator like ~(x) => -x - 1
  • the backquotes are an alternative for the function repr()
print(`'%\xcb'`[1::3]%116)
print('%c' % 116)
==> t