picoCTF: Picker 1 Write-up
Picker 1 - PicoCTF | Jun “Sky” Lu
Picker 1 Challenge
Overview:
The challenge requires you to analyze the python source code of the program and find a way to read the flag.txt file located in the same directory as the program. The instance provides the command to connect to the program via CLI and the source code file.
Initial Steps
Launch Instance
Note: The instance above is a different instance than in the write-up. In the write-up, the port 61353 was used instead.
Upon launching the instance, the command to connect to the instance with netcat is provided. For this specific instance, the command is:
nc saturn.picoctf.net 61353
Upon connecting to the instance, the program displays the output “Try entering “getRandomNumber” without the double quotes…
Initially, I tried inputs such as getRandomNumber with and without quotes and other basic commands, but this method does not work.
After downloading and inspecting the python source code file “Picker-I.py”, there were two blocks of interest:
import sys
def getRandomNumber():
print(4) # Chosen by fair die roll.
# Guaranteed to be random.
# (See XKCD)
def exit():
sys.exit(0)
def esoteric1():
esoteric = \
def win():
# This line will not work locally unless you create your own 'flag.txt' in
# the same directory as this script
flag = open('flag.txt', 'r').read()
#flag = flag[:-1]
flag = flag.strip()
str_flag = ''
for c in flag:
str_flag += str(hex(ord(c))) + ' '
print(str_flag)
#Rest of the code here...
#
while(True):
try:
print('Try entering "getRandomNumber" without the double quotes...')
user_input = input('==> ')
eval(user_input + '()')
except Exception as e:
print(e)
break
The key to solving this challenge is the program’s win() method and the input while loop. According to the python code, the win() method opens and reads the flag.txt file in the same directory, which should correctly display the flag.
def win():
# This line will not work locally unless you create your own 'flag.txt' in
# the same directory as this script
flag = open('flag.txt', 'r').read()
#flag = flag[:-1]
flag = flag.strip()
str_flag = ''
for c in flag:
str_flag += str(hex(ord(c))) + ' '
print(str_flag)
while(True):
try:
print('Try entering "getRandomNumber" without the double quotes...')
user_input = input('==> ')
eval(user_input + '()')
except Exception as e:
print(e)
break
In the input while loop, the block is relatively straightforward. The user’s input is evaluated with the eval command, which reads a string and parses it as an expression. The user input is appended with parenthesis, meaning the input is taken as ‘string()’.
Source: https://www.geeksforgeeks.org/eval-in-python/
Exploitation:
Since the eval function interprets the user input as a python expression, the input, ‘win’, can be used to read the flag.txt file in the directory of the launched instance.
The contents of the flag.txt file was outputted. The file contains a cipher-text presumably of the flag which can be decoded using dcode.fr
Decrypt the Cipher and Obtain the Flag
After inserting the result into dcode.fr’s cipher identifier, the code turns out to be ASCII code. After using the ASCII code cipher decoder, the result was the flag.