metasploit-framework/modules/auxiliary/analyze/jtr_crack_fast.rb

160 lines
5.2 KiB
Ruby
Raw Normal View History

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
#
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::JohnTheRipper
def initialize
super(
'Name' => 'John the Ripper Password Cracker (Fast Mode)',
'Version' => '$Revision$',
'Description' => %Q{
This module uses John the Ripper to identify weak passwords that have been
acquired as hashed files (loot) or raw LANMAN/NTLM hashes (hashdump). The goal
of this module is to find trivial passwords in a short amount of time. To
crack complex passwords or use large wordlists, John the Ripper should be
used outside of Metasploit. This initial version just handles LM/NTLM credentials
from hashdump and uses the standard wordlist and rules.
},
'Author' => 'hdm',
'License' => MSF_LICENSE # JtR itself is GPLv2, but this wrapper is MSF (BSD)
)
end
def run
wordlist = Rex::Quickfile.new("jtrtmp")
hashlist = Rex::Quickfile.new("jtrtmp")
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)
wordlist.close
# 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" )
end
hashlist.close
if smb_hashes.length > 0
cracked_ntlm = {}
cracked_lm = {}
added = []
# 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
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
end
end