Investigating the Source Code
In this CTF, we are given the source code for the Python script running on the server. This file is much more involved than Picker I/II, so let’s break down how the code works.
Code Breakdown
Getting User Input
The script will run in a loop, waiting for user input. It calls various functions given user input:
|
|
Handling User Input
The code holds a “table” mapping numbers 1 through 4 to different functions, which roughly looks like:
Input Number | Function in Code |
---|---|
1 | print_table() |
2 | read_variable() |
3 | write_variable() |
4 | getRandomNumber() |
After parsing through the various functions, the interesting function is the write_variable()
function:
|
|
The key line is exec(f'global {var_name}; {var_name} = {value}')
, which executes code to create or modify a global variable with the specified name and value.
Global Variable Implications
The global
keyword allows modification of global variables from within functions. In Python, global functions and variables are accessible throughout the module. By using write_variable()
, we can modify any global variable, including functions.
Here are some functions in the global scope of the file:
Function Name | Side Effect |
---|---|
win() | outputs flag |
read_variable() | outputs global scoped variable |
write_variable() | writes a value to a global variable |
getRandomNumber() | outputs ‘4’ |
Since we can modify any global value, we can change getRandomNumber()
to point to win()
, which will allow us to obtain the flag.
Getting the Flag
After connecting to the server, let’s run the write_variable()
function, and then run our modified getRandomNumber()
function:
Input Number | Function in Code |
---|---|
1 | print_table() |
2 | read_variable() |
3 | write_variable() |
4 | getRandomNumber() |
|
|
We got the flag! Let’s clean it up.
|
|