successfully cracking ntlm hashes

still need to handle casing for lm
bug/bundler_fix
David Maloney 2014-06-23 14:40:32 -05:00
parent 57cc390681
commit b246e66eb8
No known key found for this signature in database
GPG Key ID: DEDBA9DC3A913DB2
1 changed files with 60 additions and 117 deletions

View File

@ -27,132 +27,75 @@ class Metasploit3 < Msf::Auxiliary
end
def run
wordlist = Rex::Quickfile.new("jtrtmp")
hashlist = Rex::Quickfile.new("jtrtmp")
cracker = new_john_cracker
begin
# Seed the wordlist with usernames, passwords, and hostnames
seed = []
myworkspace.hosts.find(:all).each {|o| seed << john_expand_word( o.name ) if o.name }
myworkspace.creds.each do |o|
seed << john_expand_word( o.user ) if o.user
seed << john_expand_word( o.pass ) if (o.pass and o.ptype !~ /hash/)
end
# Grab any known passwords out of the john.pot file
john_cracked_passwords.values {|v| seed << v }
# Write the seed file
wordlist.write( seed.flatten.uniq.join("\n") + "\n" )
print_status("Seeded the password database with #{seed.length} words...")
# Append the standard JtR wordlist as well
::File.open(john_wordlist_path, "rb") do |fd|
wordlist.write fd.read(fd.stat.size)
end
# Close the wordlist to prevent sharing violations (windows)
#generate our wordlist and close the file handle
wordlist = wordlist_file
wordlist.close
print_status "Wordlist file written out to #{wordlist.path}"
cracker.wordlist = wordlist.path
cracker.hash_path = hash_file
# Create a PWDUMP style input file for SMB Hashes
smb_hashes = myworkspace.creds.select{|x| x.ptype == "smb_hash" }
smb_hashes.each do |cred|
hashlist.write( "cred_#{cred[:id]}:#{cred[:id]}:#{cred[:pass]}:::\n" )
['lm','nt'].each do |format|
# dupe our original cracker so we can safely change options between each run
cracker_instance = cracker.dup
cracker_instance.format = format
print_status "Cracking #{format} hashes in normal wordlist mode..."
cracker_instance.crack do |line|
print_status line.chomp
end
print_status "Cracking #{format} hashes in single mode..."
cracker_instance.rules = 'single'
cracker_instance.crack do |line|
print_status line.chomp
end
print_status "Cracking #{format} hashes in incremental mode (All4)..."
cracker_instance.rules = nil
cracker_instance.wordlist = nil
cracker_instance.incremental = 'All4'
cracker_instance.crack do |line|
print_status line.chomp
end
print_status "Cracking #{format} hashes in incremental mode (Digits5)..."
cracker_instance.incremental = 'Digits5'
cracker_instance.crack do |line|
print_status line.chomp
end
print_status "Cracked Passwords this run:"
cracker_instance.each_cracked_password do |password_line|
password_line.chomp!
next if password_line.blank?
fields = password_line.split(":")
# If we don't have an expected minimum number of fields, this is probably not a hash line
next unless fields.count >=7
username = fields.shift
core_id = fields.pop
4.times{ fields.pop }
password = fields.join(':')
print_good "#{username}:#{password}:#{core_id}"
#create_cracked_credential( username: username, password: password, core_id: core_id)
end
end
end
def hash_file
hashlist = Rex::Quickfile.new("hashes_tmp")
Metasploit::Credential::NTLMHash.joins(:cores).where(metasploit_credential_cores: { workspace_id: myworkspace.id } ).each do |hash|
hash.cores.each do |core|
user = core.public.username
hash_string = "#{hash.data}"
id = core.id
hashlist.puts "#{user}:#{id}:#{hash_string}:::#{id}"
end
end
hashlist.close
if smb_hashes.length > 0
cracked_ntlm = {}
cracked_lm = {}
added = []
john_crack(hashlist.path, :wordlist => datastore['Wordlist'], :format => 'lm')
john_crack(hashlist.path, :wordlist => datastore['Wordlist'], :format => 'nt')
# Crack this in LANMAN format using wordlist mode with tweaked rules
john_crack(hashlist.path, :wordlist => wordlist.path, :rules => 'single', :format => 'lm')
# Crack this in LANMAN format using various incremntal modes
john_crack(hashlist.path, :incremental => "All4", :format => 'lm')
john_crack(hashlist.path, :incremental => "Digits5", :format => 'lm')
# Parse cracked passwords and permute LANMAN->NTLM as needed
cracked = john_show_passwords(hashlist.path, 'lm')
cracked[:users].each_pair do |k,v|
next if v == ""
next if (v[0,7] == "???????" or v[7,7] == "???????")
next if not k =~ /^cred_(\d+)/m
cid = $1.to_i
cracked_lm[k] = v
cred_find = smb_hashes.select{|x| x[:id] == cid}
next if cred_find.length == 0
cred = cred_find.first
ntlm = cred.pass.split(":", 2).last
done = john_lm_upper_to_ntlm(v, ntlm)
cracked_ntlm[k] = done if done
end
# Append any cracked values to the wordlist
tfd = ::File.open(wordlist.path, "ab")
cracked_lm.values.each {|w| if not added.include?(w); tfd.write( w + "\n" ); added << w; end }
cracked_ntlm.values.each {|w| if not added.include?(w); tfd.write( w + "\n" ); added << w; end }
tfd.close
# Crack this in NTLM format
john_crack(hashlist.path, :wordlist => wordlist.path, :rules => 'single', :format => 'nt')
# Crack this in NTLM format using various incremntal modes
john_crack(hashlist.path, :incremental => "All4", :format => 'nt')
john_crack(hashlist.path, :incremental => "Digits5", :format => 'nt')
# Parse cracked passwords
cracked = john_show_passwords(hashlist.path, 'nt')
cracked[:users].each_pair do |k,v|
next if cracked_ntlm[k]
cracked_ntlm[k] = v
end
# Append any cracked values to the wordlist
tfd = ::File.open(wordlist.path, "ab")
cracked_ntlm.values.each {|w| if not added.include?(w); tfd.write( w + "\n" ); added << w; end }
tfd.close
# Store the cracked results based on user_id => cred.id
cracked_ntlm.each_pair do |k,v|
next if not k =~ /^cred_(\d+)/m
cid = $1.to_i
cred_find = smb_hashes.select{|x| x[:id] == cid}
next if cred_find.length == 0
cred = cred_find.first
next if cred.user.to_s.strip.length == 0
print_good("Cracked: #{cred.user}:#{v} (#{cred.service.host.address}:#{cred.service.port})")
report_auth_info(
:host => cred.service.host,
:service => cred.service,
:user => cred.user,
:pass => v,
:type => "password",
:source_id => cred[:id],
:source_type => 'cracked'
)
end
end
# XXX: Enter other hash types here (shadow, etc)
rescue ::Timeout::Error
ensure
wordlist.close rescue nil
hashlist.close rescue nil
::File.unlink(wordlist.path) rescue nil
::File.unlink(hashlist.path) rescue nil
end
print_status "Hashes Written out to #{hashlist.path}"
hashlist.path
end
end