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