picoctf/rev/picker_3/picker-III.py

199 lines
4.3 KiB
Python

import re
USER_ALIVE = True
FUNC_TABLE_SIZE = 4
FUNC_TABLE_ENTRY_SIZE = 32
CORRUPT_MESSAGE = 'Table corrupted. Try entering \'reset\' to fix it'
func_table = ''
def reset_table():
global func_table
# This table is formatted for easier viewing, but it is really one line
func_table = \
'''\
print_table \
read_variable \
write_variable \
getRandomNumber \
'''
def check_table():
global func_table
if( len(func_table) != FUNC_TABLE_ENTRY_SIZE * FUNC_TABLE_SIZE):
return False
return True
def get_func(n):
global func_table
# Check table for viability
if( not check_table() ):
print(CORRUPT_MESSAGE)
return
# Get function name from table
func_name = ''
func_name_offset = n * FUNC_TABLE_ENTRY_SIZE
for i in range(func_name_offset, func_name_offset+FUNC_TABLE_ENTRY_SIZE):
if( func_table[i] == ' '):
func_name = func_table[func_name_offset:i]
break
if( func_name == '' ):
func_name = func_table[func_name_offset:func_name_offset+FUNC_TABLE_ENTRY_SIZE]
return func_name
def print_table():
# Check table for viability
if( not check_table() ):
print(CORRUPT_MESSAGE)
return
for i in range(0, FUNC_TABLE_SIZE):
j = i + 1
print(str(j)+': ' + get_func(i))
def filter_var_name(var_name):
r = re.search('^[a-zA-Z_][a-zA-Z_0-9]*$', var_name)
if r:
return True
else:
return False
def read_variable():
var_name = input('Please enter variable name to read: ')
if( filter_var_name(var_name) ):
eval('print('+var_name+')')
else:
print('Illegal variable name')
def filter_value(value):
if ';' in value or '(' in value or ')' in value:
return False
else:
return True
def write_variable():
var_name = input('Please enter variable name to write: ')
if( filter_var_name(var_name) ):
value = input('Please enter new value of variable: ')
if( filter_value(value) ):
exec('global '+var_name+'; '+var_name+' = '+value)
else:
print('Illegal value')
else:
print('Illegal variable name')
def call_func(n):
"""
Calls the nth function in the function table.
Arguments:
n: The function to call. The first function is 0.
"""
# Check table for viability
if( not check_table() ):
print(CORRUPT_MESSAGE)
return
# Check n
if( n < 0 ):
print('n cannot be less than 0. Aborting...')
return
elif( n >= FUNC_TABLE_SIZE ):
print('n cannot be greater than or equal to the function table size of '+FUNC_TABLE_SIZE)
return
# Get function name from table
func_name = get_func(n)
# Run the function
eval(func_name+'()')
def dummy_func1():
print('in dummy_func1')
def dummy_func2():
print('in dummy_func2')
def dummy_func3():
print('in dummy_func3')
def dummy_func4():
print('in dummy_func4')
def getRandomNumber():
print(4) # Chosen by fair die roll.
# Guaranteed to be random.
# (See XKCD)
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)
def help_text():
print(
'''
This program fixes vulnerabilities in its predecessor by limiting what
functions can be called to a table of predefined functions. This still puts
the user in charge, but prevents them from calling undesirable subroutines.
* Enter 'quit' to quit the program.
* Enter 'help' for this text.
* Enter 'reset' to reset the table.
* Enter '1' to execute the first function in the table.
* Enter '2' to execute the second function in the table.
* Enter '3' to execute the third function in the table.
* Enter '4' to execute the fourth function in the table.
Here's the current table:
'''
)
print_table()
reset_table()
while(USER_ALIVE):
choice = input('==> ')
if( choice == 'quit' or choice == 'exit' or choice == 'q' ):
USER_ALIVE = False
elif( choice == 'help' or choice == '?' ):
help_text()
elif( choice == 'reset' ):
reset_table()
elif( choice == '1' ):
call_func(0)
elif( choice == '2' ):
call_func(1)
elif( choice == '3' ):
call_func(2)
elif( choice == '4' ):
call_func(3)
else:
print('Did not understand "'+choice+'" Have you tried "help"?')