Three Guards | DEFCON Quals CTF 23 | Writeup
In this intriguing scenario, we are presented with a set of files containing multiple “guards” that have imposed restrictions on syscalls.
Upon careful examination, it becomes evident that the input is divided by a colon (‘:’) using the partition function in the main.py file. It is also worth noting that each guard is assigned a unique name: Bob, Charles, and Sam, respectively. Furthermore, we are provided with specific abilities and limitations of each guard. Bob can read files but is unable to open them, Charles can open files but cannot read their contents, while Sam holds a staunch aversion towards any attempts to exploit potential loopholes.
Additionally, every guard possesses the capability to execute Python code using the ‘exec’ function.
Moving forward, it is crucial to recognize that each guard is restricted from using certain syscalls. Guard 1 (Bob) is forbidden from utilizing syscalls in the ‘avoid’ list, which includes values [2, 40, 56, 59]. Guard 2 (Charles) is similarly restrained and cannot employ syscalls found in the ‘avoid’ list: [0, 17, 19, 40, 56, 59]. On the other hand, Guard 3’s restrictions extend further, blocking an even broader range of syscalls: [0, 2, 17, 19, 40, 56, 59]. Given this information, it becomes apparent that Guard 3 serves little purpose since it restricts more syscalls than both Guard 1 and Guard 2.
Consequently, the recommended syntax for executing commands is as follows: <guard name>: exec: <python code to be executed>.
To begin the exploration, I employed the following command to display the contents of the files:
Charles:exec:import os; os.system("ls")
Ultimately, I utilized the subsequent command to print the contents of the ‘flag.txt’ file:
Charles:exec:print(open("flag.txt").read())