Skip to content

Commit 8e1e505

Browse files
committed
Fix output of MSV creds dumping in Kiwi
The data being pulled out of the MSV credential dump was not being rendered propertly because it was assumed that all accounts would provide the same set of hashes/details for each entry found. However, this was not the case. Some have NTLM & SHA1, others have LM & NTLM, some have DPAPI when others don't. This code generates tables based on the values found, and renders those values in the appropriate columns, and if the values don't exist for a given account, the column is left blank. Fixes rapid7#8620
1 parent 05c7221 commit 8e1e505

File tree

2 files changed

+40
-7
lines changed
  • lib/rex/post/meterpreter

2 files changed

+40
-7
lines changed

lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,18 @@ def parse_msv(output)
308308
# did we find something?
309309
next if line.blank?
310310

311-
# the next 4 lines should be interesting
312311
msv = {}
313-
4.times do
314-
k, v = read_value(lines.shift)
315-
msv[k.strip] = v if k
312+
# loop until we find a line that doesn't start with
313+
# an asterisk, as this is the next credential set
314+
loop do
315+
line = lines.shift
316+
if line.strip.start_with?('*')
317+
k, v = read_value(line)
318+
msv[k.strip] = v if k
319+
else
320+
lines.unshift(line)
321+
break
322+
end
316323
end
317324

318325
if msv.length > 0

lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,18 +567,44 @@ def scrape_passwords(provider, method, args)
567567
output = ""
568568

569569
accounts.keys.each do |k|
570-
571570
next if accounts[k].length == 0
572571

572+
# Keep track of the columns that we were given, in
573+
# the order we are given them, while removing duplicates
574+
columns = []
575+
existing = Set.new
576+
accounts[k].each do |acct|
577+
acct.keys.each do |k|
578+
unless existing.include?(k)
579+
columns << k
580+
existing.add(k)
581+
end
582+
end
583+
end
584+
573585
table = Rex::Text::Table.new(
574586
'Header' => "#{k} credentials",
575587
'Indent' => 0,
576588
'SortIndex' => 0,
577-
'Columns' => accounts[k][0].keys
589+
'Columns' => columns
578590
)
579591

580592
accounts[k].each do |acct|
581-
table << acct.values
593+
values = []
594+
# Iterate through the given columns and match the values up
595+
# correctly based on the index of the column header.
596+
columns.each do |c|
597+
col_idx = acct.keys.index(c)
598+
# If the column exists, we'll use the value that is associated
599+
# with the column based on its index
600+
if col_idx
601+
values << acct.values[col_idx]
602+
else
603+
# Otherwise, just add a blank value
604+
values << ''
605+
end
606+
end
607+
table << values
582608
end
583609

584610
output << table.to_s + "\n"

0 commit comments

Comments
 (0)