Module: Msf::Auxiliary::PasswordCracker
- Includes:
- Report
- Defined in:
- lib/msf/core/auxiliary/password_cracker.rb
Overview
This module provides methods for working with a Password Cracker
Instance Method Summary collapse
-
#append_results(tbl, cracked_hashes) ⇒ String
This method appends a list of cracked hashes to the list used to generate the printed table.
-
#cracker_results_table ⇒ Rex::Text::Table
This method returns a cracker results table.
-
#hash_job(jtr_type, cracker) ⇒ Hash
This method creates a job for the password cracker to do.
-
#initialize(info = {}) ⇒ Object
Initializes an instance of an auxiliary module that calls out to John the Ripper (jtr).
- #john_lm_upper_to_ntlm(pwd, hash) ⇒ String?
-
#new_password_cracker(cracking_application) ⇒ nilClass, Metasploit::Framework::PasswordCracker::Cracker
This method creates a new Metasploit::Framework::PasswordCracker::Cracker and populates some of the attributes based on the module datastore options.
-
#password_cracked?(hash) ⇒ Boolean
This method determines if a given password hash already been cracked in the database.
-
#process_cracker_results(results, cred) ⇒ Array
This method takes a results table, and a newly cracked cred, and adds the cred to the table if it isn’t there already.
-
#wordlist_file(max_len = 0) ⇒ nilClass, Rex::Quickfile
This method instantiates a Metasploit::Framework::JtR::Wordlist, writes the data out to a file and returns the Rex::Quickfile object.
Methods included from Report
#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot
Methods included from Metasploit::Framework::Require
optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines
Instance Method Details
#append_results(tbl, cracked_hashes) ⇒ String
This method appends a list of cracked hashes to the list used to generate the printed table
207 208 209 210 211 212 213 214 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 207 def append_results(tbl, cracked_hashes) cracked_hashes.each do |row| next if tbl.rows.include? row tbl << row end tbl.to_s end |
#cracker_results_table ⇒ Rex::Text::Table
This method returns a cracker results table
219 220 221 222 223 224 225 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 219 def cracker_results_table Rex::Text::Table.new( 'Header' => 'Cracked Hashes', 'Indent' => 1, 'Columns' => ['DB ID', 'Hash Type', 'Username', 'Cracked Password', 'Method'] ) end |
#hash_job(jtr_type, cracker) ⇒ Hash
This method creates a job for the password cracker to do. A job is categorized by the hash type and will include the hash type (type), formatted_hashlist (hashes in the cracker’s format), creds (db objects for each hash), and cred_ids_left_to_crack (array of db ids that aren’t cracked yet)
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 144 def hash_job(jtr_type, cracker) # create the base data job = { 'type' => jtr_type, 'formatted_hashlist' => [], 'creds' => [], 'cred_ids_left_to_crack' => [] } job['db_formats'] = Metasploit::Framework::PasswordCracker::JtR::Formatter.jtr_to_db(jtr_type) if jtr_type == 'dynamic_1034' # postgres creds = framework.db.creds(workspace: myworkspace, type: 'Metasploit::Credential::PostgresMD5') elsif ['lm', 'nt'].include? jtr_type creds = framework.db.creds(workspace: myworkspace, type: 'Metasploit::Credential::NTLMHash') else creds = framework.db.creds(workspace: myworkspace, type: 'Metasploit::Credential::NonreplayableHash') end creds.each do |core| jtr_format = core.private.jtr_format # Unfortunately NTLMHash always set JtR Format to 'nt,lm' so we have to do a special case here # to figure out which it is if jtr_format == 'nt,lm' jtr_format = core.private.data.start_with?('aad3b435b51404eeaad3b435b51404ee') ? 'nt' : 'lm' end next unless job['db_formats'].include? jtr_format # only add hashes which havne't been cracked next if password_cracked?(core.private.data) job['creds'] << core job['cred_ids_left_to_crack'] << core.id if cracker == 'john' job['formatted_hashlist'] << Metasploit::Framework::PasswordCracker::JtR::Formatter.hash_to_jtr(core) elsif cracker == 'hashcat' job['formatted_hashlist'] << Metasploit::Framework::PasswordCracker::Hashcat::Formatter.hash_to_hashcat(core) end end if job['creds'].length > 0 return job end nil end |
#initialize(info = {}) ⇒ Object
Initializes an instance of an auxiliary module that calls out to John the Ripper (jtr)
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 23 def initialize(info = {}) super ( [ OptPath.new('CONFIG', [false, 'The path to a John config file to use instead of the default']), OptPath.new('CUSTOM_WORDLIST', [false, 'The path to an optional custom wordlist']), OptInt.new('ITERATION_TIMEOUT', [false, 'The max-run-time for each iteration of cracking']), OptPath.new('CRACKER_PATH', [false, 'The absolute path to the cracker executable']), OptInt.new('FORK', [false, 'Forks for John the Ripper to use', 1]), OptBool.new('KORELOGIC', [false, 'Apply the KoreLogic rules to John the Ripper Wordlist Mode(slower)', false]), OptBool.new('MUTATE', [false, 'Apply common mutations to the Wordlist (SLOW)', false]), OptPath.new('POT', [false, 'The path to a John POT file to use instead of the default']), OptBool.new('USE_CREDS', [false, 'Use existing credential data saved in the database', true]), OptBool.new('USE_DB_INFO', [false, 'Use looted database schema info to seed the wordlist', true]), OptBool.new('USE_DEFAULT_WORDLIST', [false, 'Use the default metasploit wordlist', true]), OptBool.new('USE_HOSTNAMES', [false, 'Seed the wordlist with hostnames from the workspace', true]), OptBool.new('USE_ROOT_WORDS', [false, 'Use the Common Root Words Wordlist', true]) ], Msf::Auxiliary::PasswordCracker ) ( [ OptBool.new('DeleteTempFiles', [false, 'Delete temporary wordlist and hash files', true]), OptBool.new('OptimizeKernel', [false, 'Utilize Optimized Kernels in Hashcat', true]), OptBool.new('ShowCommand', [false, 'Print the cracker command being used', true]), ], Msf::Auxiliary::PasswordCracker ) end |
#john_lm_upper_to_ntlm(pwd, hash) ⇒ String?
59 60 61 62 63 64 65 66 67 68 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 59 def john_lm_upper_to_ntlm(pwd, hash) pwd = pwd.upcase hash = hash.upcase Rex::Text.permute_case(pwd).each do |str| if hash == Rex::Proto::NTLM::Crypt.ntlm_hash(str).unpack('H*')[0].upcase return str end end nil end |
#new_password_cracker(cracking_application) ⇒ nilClass, Metasploit::Framework::PasswordCracker::Cracker
This method creates a new Metasploit::Framework::PasswordCracker::Cracker and populates some of the attributes based on the module datastore options.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 75 def new_password_cracker(cracking_application) fail_with(Msf::Module::Failure::BadConfig, 'Password cracking is not available without an active database connection.') unless framework.db.active cracker = Metasploit::Framework::PasswordCracker::Cracker.new( config: datastore['CONFIG'], cracker_path: datastore['CRACKER_PATH'], max_runtime: datastore['ITERATION_TIMEOUT'], pot: datastore['POT'], optimize: datastore['OptimizeKernel'], wordlist: datastore['CUSTOM_WORDLIST'] ) cracker.cracker = cracking_application begin cracker.binary_path rescue Metasploit::Framework::PasswordCracker::PasswordCrackerNotFoundError => e fail_with(Msf::Module::Failure::BadConfig, e.) end # throw this to a local variable since it causes a shell out to pull the version cracker_version = cracker.cracker_version if cracker.cracker == 'john' && (cracker_version.nil? || !cracker_version.include?('jumbo')) fail_with(Msf::Module::Failure::BadConfig, 'John the Ripper JUMBO patch version required. See https://github.com/magnumripper/JohnTheRipper') end print_good("#{cracker.cracker} Version Detected: #{cracker_version}") cracker end |
#password_cracked?(hash) ⇒ Boolean
This method determines if a given password hash already been cracked in the database
126 127 128 129 130 131 132 133 134 135 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 126 def password_cracked?(hash) framework.db.creds({ pass: hash }).each do |test_cred| test_cred.public.cores.each do |core| if core.origin_type == 'Metasploit::Credential::Origin::CrackedPassword' return true end end end false end |
#process_cracker_results(results, cred) ⇒ Array
This method takes a results table, and a newly cracked cred, and adds the cred to the table if it isn’t there already. It also creates the cracked credential in the database.
190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 190 def process_cracker_results(results, cred) return results if cred['core_id'].nil? # make sure we have good data # make sure we dont add the same one again if results.select { |r| r.first == cred['core_id'] }.empty? results << [cred['core_id'], cred['hash_type'], cred['username'], cred['password'], cred['method']] end create_cracked_credential(username: cred['username'], password: cred['password'], core_id: cred['core_id']) results end |
#wordlist_file(max_len = 0) ⇒ nilClass, Rex::Quickfile
This method instantiates a Metasploit::Framework::JtR::Wordlist, writes the data out to a file and returns the Rex::Quickfile object.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/msf/core/auxiliary/password_cracker.rb', line 106 def wordlist_file(max_len = 0) return nil unless framework.db.active wordlist = Metasploit::Framework::PasswordCracker::Wordlist.new( custom_wordlist: datastore['CUSTOM_WORDLIST'], mutate: datastore['MUTATE'], use_creds: datastore['USE_CREDS'], use_db_info: datastore['USE_DB_INFO'], use_default_wordlist: datastore['USE_DEFAULT_WORDLIST'], use_hostnames: datastore['USE_HOSTNAMES'], use_common_root: datastore['USE_ROOT_WORDS'], workspace: myworkspace ) wordlist.to_file(max_len) end |