From ecfdec9678d3ce221d93044ced77980fb53ddc30 Mon Sep 17 00:00:00 2001 From: Hakil Date: Sat, 26 Jul 2025 18:36:14 +0200 Subject: [PATCH] Fix issue #20396 --- modules/auxiliary/analyze/crack_windows.rb | 49 +++++++++++++++++----- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/modules/auxiliary/analyze/crack_windows.rb b/modules/auxiliary/analyze/crack_windows.rb index df39e301c3..6555d46678 100644 --- a/modules/auxiliary/analyze/crack_windows.rb +++ b/modules/auxiliary/analyze/crack_windows.rb @@ -30,8 +30,9 @@ class MetasploitModule < Msf::Auxiliary 'Actions' => [ ['john', { 'Description' => 'Use John the Ripper' }], ['hashcat', { 'Description' => 'Use Hashcat' }], + ['auto', { 'Description' => 'Use either John the Ripper or Hashcat, if both are present, use Hashcat' }] ], - 'DefaultAction' => 'john', + 'DefaultAction' => 'auto', 'Notes' => { 'Stability' => [CRASH_SAFE], 'SideEffects' => [], @@ -62,9 +63,11 @@ class MetasploitModule < Msf::Auxiliary def show_command(cracker_instance) return unless datastore['ShowCommand'] - if action.name == 'john' + newaction = getaction() + + if newaction == 'john' cmd = cracker_instance.john_crack_command - elsif action.name == 'hashcat' + elsif newaction == 'hashcat' cmd = cracker_instance.hashcat_crack_command end print_status(" Cracking Command: #{cmd.join(' ')}") @@ -96,13 +99,16 @@ class MetasploitModule < Msf::Auxiliary end def check_results(passwords, results, hash_type, method) + + newaction = getaction() + passwords.each do |password_line| password_line.chomp! next if password_line.blank? fields = password_line.split(':') cred = { 'hash_type' => hash_type, 'method' => method } - if action.name == 'john' + if newaction == 'john' # If we don't have an expected minimum number of fields, this is probably not a hash line next unless fields.count > 2 @@ -136,7 +142,7 @@ class MetasploitModule < Msf::Auxiliary cred['password'] = john_lm_upper_to_ntlm(password, nt_hash) end next if cred['password'].nil? - elsif action.name == 'hashcat' + elsif newaction == 'hashcat' next unless fields.count >= 2 cred['core_id'] = fields.shift @@ -163,6 +169,9 @@ class MetasploitModule < Msf::Auxiliary end def run + + newaction = getaction() + tbl = cracker_results_table # array of hashes in jtr_format in the db, converted to an OR combined regex @@ -178,7 +187,7 @@ class MetasploitModule < Msf::Auxiliary # build our job list hash_types_to_crack.each do |hash_type| - job = hash_job(hash_type, action.name) + job = hash_job(hash_type, newaction) if job.nil? print_status("No #{hash_type} found to crack") else @@ -196,7 +205,7 @@ class MetasploitModule < Msf::Auxiliary # Inner array format: db_id, hash_type, username, password, method_of_crack results = [] - cracker = new_password_cracker(action.name) + cracker = new_password_cracker(newaction) # generate our wordlist and close the file handle. wordlist = wordlist_file @@ -220,7 +229,7 @@ class MetasploitModule < Msf::Auxiliary # dupe our original cracker so we can safely change options between each run cracker_instance = cracker.dup cracker_instance.format = format - if action.name == 'john' + if newaction == 'john' cracker_instance.fork = datastore['FORK'] end @@ -231,7 +240,7 @@ class MetasploitModule < Msf::Auxiliary job['cred_ids_left_to_crack'] = job['cred_ids_left_to_crack'] - results.map { |i| i[0].to_i } # remove cracked hashes from the hash list next if job['cred_ids_left_to_crack'].empty? - if action.name == 'john' + if newaction == 'john' print_status "Cracking #{format} hashes in single mode..." cracker_instance.mode_single(wordlist.path) show_command cracker_instance @@ -274,7 +283,7 @@ class MetasploitModule < Msf::Auxiliary print_status "Cracking #{format} hashes in wordlist mode..." cracker_instance.mode_wordlist(wordlist.path) # Turn on KoreLogic rules if the user asked for it - if action.name == 'john' && datastore['KORELOGIC'] + if newaction == 'john' && datastore['KORELOGIC'] cracker_instance.rules = 'KoreLogicRules' print_status 'Applying KoreLogic ruleset...' end @@ -299,4 +308,24 @@ class MetasploitModule < Msf::Auxiliary end end end + + def getaction + newaction = action.name + if action.name == 'auto' + path = Rex::FileUtils.find_full_path('hashcat') || + Rex::FileUtils.find_full_path('hashcat.exe') + if path + newaction = 'hashcat' + else + path = Rex::FileUtils.find_full_path('john') || + Rex::FileUtils.find_full_path('john.exe') + if path + newaction = 'john' + else + raise PasswordCrackerNotFoundError, 'No suitable john/hashcat binary was found on the system' + end + end + end + return newaction + end end