Class: Metasploit::Framework::PasswordCracker::Cracker
- Inherits:
-
Object
- Object
- Metasploit::Framework::PasswordCracker::Cracker
- Includes:
- ActiveModel::Validations
- Defined in:
- lib/metasploit/framework/password_crackers/cracker.rb
Instance Attribute Summary collapse
-
#attack ⇒ String
The attack mode for hashcat to use (not applicable to John).
-
#config ⇒ String
The path to an optional config file for John to use.
-
#cracker ⇒ String
Which cracker to use.
-
#cracker_path ⇒ String
This attribute allows the user to specify a cracker binary to use.
-
#fork ⇒ String
If the cracker type is john, the amount of forks to specify.
-
#format ⇒ String
If the cracker type is john, this format will automatically be translated to the hashcat equivalent via jtr_format_to_hashcat_format.
-
#hash_path ⇒ String
The path to the file containing the hashes.
-
#increment_length ⇒ Array
The incremental min and max to use.
-
#incremental ⇒ String
The incremental mode to use.
-
#mask ⇒ Object
If the cracker type is hashcat, If set, the mask to use.
-
#max_length ⇒ Integer
An optional maximum length of password to attempt cracking.
-
#max_runtime ⇒ Integer
An optional maximum duration of the cracking attempt in seconds.
-
#optimize ⇒ Boolean
If the Optimize flag should be given to Hashcat.
-
#pot ⇒ String
The file path to an alternative John pot file to use.
-
#rules ⇒ String
The wordlist mangling rules to use inside John/Hashcat.
-
#wordlist ⇒ String
The file path to the wordlist to use.
Instance Method Summary collapse
-
#binary_path ⇒ String, NilClass
This method follows a decision tree to determine the path to the cracker binary we should use.
-
#crack {|String| ... } ⇒ void
This method runs the command from #crack_command and yields each line of output.
-
#cracker_session_id ⇒ Object
This method is a getter for a random Session ID for the cracker.
-
#cracker_version ⇒ String
This method returns the version of John the Ripper or Hashcat being used.
-
#each_cracked_password ⇒ Array
This runs the show command in john and yields cracked passwords.
-
#hashcat_crack_command ⇒ Array
This method builds an array for the command to actually run the cracker.
-
#initialize(attributes = {}) ⇒ Cracker
constructor
A new instance of Cracker.
-
#john_config_file ⇒ String
This method returns the path to a default john.conf file.
-
#john_crack_command ⇒ Array
This method builds an array for the command to actually run the cracker.
-
#john_nolog_format ⇒ String
This method is used to determine which format of the no log option should be used –no-log vs –nolog github.com/openwall/john/commit/8982e4f7a2e874aab29807a05b421373015c9b61 We base this either on a date being in the version, or running the command and checking the output.
-
#john_pot_file ⇒ String
This method returns the path to a default john.pot file.
-
#jtr_format_to_hashcat_format(format) ⇒ String
This method takes a frameworkframework.dbframework.db.credframework.db.cred.privateframework.db.cred.private.jtr_format (string), and returns the string number associated to the hashcat format.
-
#mode_incremental ⇒ Object
This method sets the appropriate parameters to run a cracker in incremental mode.
-
#mode_normal ⇒ Object
This method sets the john to ‘normal’ mode.
-
#mode_pin ⇒ Object
This method sets the appropriate parameters to run a cracker in a pin mode (4-8 digits) on hashcat.
-
#mode_single(file) ⇒ Object
This method sets the john to single mode.
-
#mode_wordlist(file) ⇒ Object
This method sets the appropriate parameters to run a cracker in wordlist mode.
-
#show_command ⇒ Array
This method builds the command to show the cracked passwords.
Constructor Details
#initialize(attributes = {}) ⇒ Cracker
Returns a new instance of Cracker.
117 118 119 120 121 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 117 def initialize(attributes = {}) attributes.each do |attribute, value| public_send("#{attribute}=", value) end end |
Instance Attribute Details
#attack ⇒ String
Returns The attack mode for hashcat to use (not applicable to John).
12 13 14 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 12 def attack @attack end |
#config ⇒ String
Returns The path to an optional config file for John to use.
16 17 18 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 16 def config @config end |
#cracker ⇒ String
Returns Which cracker to use. ‘john’ and ‘hashcat’ are valid.
20 21 22 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 20 def cracker @cracker end |
#cracker_path ⇒ String
This attribute allows the user to specify a cracker binary to use. If not supplied, the Cracker will search the PATH for a suitable john or hashcat binary and finally fall back to the pre-compiled john versions shipped with Metasploit.
28 29 30 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 28 def cracker_path @cracker_path end |
#fork ⇒ String
If the cracker type is john, the amount of forks to specify
41 42 43 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 41 def fork @fork end |
#format ⇒ String
If the cracker type is john, this format will automatically be translated to the hashcat equivalent via jtr_format_to_hashcat_format
35 36 37 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 35 def format @format end |
#hash_path ⇒ String
Returns The path to the file containing the hashes.
45 46 47 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 45 def hash_path @hash_path end |
#increment_length ⇒ Array
Returns The incremental min and max to use.
53 54 55 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 53 def increment_length @increment_length end |
#incremental ⇒ String
Returns The incremental mode to use.
49 50 51 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 49 def incremental @incremental end |
#mask ⇒ Object
If the cracker type is hashcat, If set, the mask to use. Should consist of the character sets pre-defined by hashcat, such as ?d ?s ?l etc
@return [String] The mask to use
60 61 62 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 60 def mask @mask end |
#max_length ⇒ Integer
Returns An optional maximum length of password to attempt cracking.
68 69 70 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 68 def max_length @max_length end |
#max_runtime ⇒ Integer
Returns An optional maximum duration of the cracking attempt in seconds.
64 65 66 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 64 def max_runtime @max_runtime end |
#optimize ⇒ Boolean
Returns If the Optimize flag should be given to Hashcat.
72 73 74 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 72 def optimize @optimize end |
#pot ⇒ String
Returns The file path to an alternative John pot file to use.
76 77 78 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 76 def pot @pot end |
#rules ⇒ String
Returns The wordlist mangling rules to use inside John/Hashcat.
80 81 82 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 80 def rules @rules end |
#wordlist ⇒ String
Returns The file path to the wordlist to use.
84 85 86 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 84 def wordlist @wordlist end |
Instance Method Details
#binary_path ⇒ String, NilClass
This method follows a decision tree to determine the path to the cracker binary we should use.
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 298 def binary_path # Always prefer a manually entered path if cracker_path && ::File.file?(cracker_path) return cracker_path else # Look in the Environment PATH for the john binary if cracker == 'john' path = Rex::FileUtils.find_full_path('john') || Rex::FileUtils.find_full_path('john.exe') elsif cracker == 'hashcat' path = Rex::FileUtils.find_full_path('hashcat') || Rex::FileUtils.find_full_path('hashcat.exe') else raise PasswordCrackerNotFoundError, 'No suitable Cracker was selected, so a binary could not be found on the system' end if path && ::File.file?(path) return path end raise PasswordCrackerNotFoundError, 'No suitable john/hashcat binary was found on the system' end end |
#crack {|String| ... } ⇒ void
This method returns an undefined value.
This method runs the command from #crack_command and yields each line of output.
326 327 328 329 330 331 332 333 334 335 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 326 def crack(&block) if cracker == 'john' results = john_crack_command elsif cracker == 'hashcat' results = hashcat_crack_command end ::IO.popen(results, 'rb') do |fd| fd.each_line(&block) end end |
#cracker_session_id ⇒ Object
This method is a getter for a random Session ID for the cracker. It allows us to dinstiguish between cracking sessions.
@ return [String] the Session ID to use
553 554 555 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 553 def cracker_session_id @session_id ||= ::Rex::Text.rand_text_alphanumeric(8) end |
#cracker_version ⇒ String
This method returns the version of John the Ripper or Hashcat being used.
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 341 def cracker_version if cracker == 'john' cmd = binary_path elsif cracker == 'hashcat' cmd = binary_path cmd << (' -V') end ::IO.popen(cmd, 'rb') do |fd| fd.each_line do |line| if cracker == 'john' # John the Ripper 1.8.0.13-jumbo-1-bleeding-973a245b96 2018-12-17 20:12:51 +0100 OMP [linux-gnu 64-bit x86_64 AVX2 AC] # John the Ripper 1.9.0-jumbo-1 OMP [linux-gnu 64-bit x86_64 AVX2 AC] # John the Ripper password cracker, version 1.8.0.2-bleeding-jumbo_omp [64-bit AVX-autoconf] # John the Ripper password cracker, version 1.8.0 return Regexp.last_match(1).strip if line =~ /John the Ripper(?: password cracker, version)? ([^\[]+)/ elsif cracker == 'hashcat' # v5.1.0 return Regexp.last_match(1) if line =~ /(v[\d.]+)/ end end end nil end |
#each_cracked_password ⇒ Array
This runs the show command in john and yields cracked passwords.
531 532 533 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 531 def each_cracked_password ::IO.popen(show_command, 'rb').readlines end |
#hashcat_crack_command ⇒ Array
This method builds an array for the command to actually run the cracker. It builds the command from all of the attributes on the class.
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 446 def hashcat_crack_command cmd_string = binary_path cmd = [cmd_string, '--session=' + cracker_session_id, '--logfile-disable', '--quiet', '--username'] if pot.present? cmd << ('--potfile-path=' + pot) else cmd << ('--potfile-path=' + john_pot_file) end if format.present? cmd << ('--hash-type=' + jtr_format_to_hashcat_format(format)) end if optimize.present? # https://hashcat.net/wiki/doku.php?id=frequently_asked_questions#what_is_the_maximum_supported_password_length_for_optimized_kernels # Optimized Kernels has a large impact on speed. Here are some stats from Hashcat 5.1.0: # Kali Linux on Dell Precision M3800 ## hashcat -b -w 2 -m 0 # * Device #1: Quadro K1100M, 500/2002 MB allocatable, 2MCU # Speed.#1.........: 185.9 MH/s (11.15ms) @ Accel:64 Loops:16 Thr:1024 Vec:1 ## hashcat -b -w 2 -O -m 0 # * Device #1: Quadro K1100M, 500/2002 MB allocatable, 2MCU # Speed.#1.........: 463.6 MH/s (8.92ms) @ Accel:64 Loops:32 Thr:1024 Vec:1 # Windows 10 # PS C:\hashcat-5.1.0> .\hashcat64.exe -b -O -w 2 -m 0 # * Device #1: GeForce RTX 2070 SUPER, 2048/8192 MB allocatable, 40MCU # Speed.#1.........: 13914.0 MH/s (5.77ms) @ Accel:128 Loops:64 Thr:256 Vec:1 # PS C:\hashcat-5.1.0> .\hashcat64.exe -b -O -w 2 -m 0 # * Device #1: GeForce RTX 2070 SUPER, 2048/8192 MB allocatable, 40MCU # Speed.#1.........: 31545.6 MH/s (10.36ms) @ Accel:256 Loops:128 Thr:256 Vec:1 # This change should result in 225%-250% speed boost at the sacrifice of some password length, which most likely # wouldn't be tested inside of MSF since most users are using the MSF modules for word list and easy cracks. # Anything of length where this would cut off is most likely being done independently (outside MSF) cmd << ('-O') end if incremental.present? cmd << ('--increment') if increment_length.present? cmd << ('--increment-min=' + increment_length[0].to_s) cmd << ('--increment-max=' + increment_length[1].to_s) else # anything more than max 4 on even des took 8+min on an i7. # maybe in the future this can be adjusted or made a variable # but current time, we'll leave it as this seems like reasonable # time expectation for a module to run cmd << ('--increment-max=4') end end if rules.present? cmd << ('--rules-file=' + rules) end if attack.present? cmd << ('--attack-mode=' + attack) end if max_runtime.present? cmd << ('--runtime=' + max_runtime.to_s) end cmd << hash_path if mask.present? cmd << mask.to_s end # must be last if wordlist.present? cmd << (wordlist) end cmd end |
#john_config_file ⇒ String
This method returns the path to a default john.conf file.
538 539 540 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 538 def john_config_file ::File.join(::Msf::Config.data_directory, 'jtr', 'john.conf') end |
#john_crack_command ⇒ Array
This method builds an array for the command to actually run the cracker. It builds the command from all of the attributes on the class.
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 393 def john_crack_command cmd_string = binary_path cmd = [cmd_string, '--session=' + cracker_session_id, john_nolog_format] if config.present? cmd << ('--config=' + config) else cmd << ('--config=' + john_config_file) end if pot.present? cmd << ('--pot=' + pot) else cmd << ('--pot=' + john_pot_file) end if fork.present? && fork > 1 cmd << ('--fork=' + fork.to_s) end if format.present? cmd << ('--format=' + format) end if wordlist.present? cmd << ('--wordlist=' + wordlist) end if incremental.present? cmd << ('--incremental=' + incremental) end if rules.present? cmd << ('--rules=' + rules) end if max_runtime.present? cmd << ('--max-run-time=' + max_runtime.to_s) end if max_length.present? cmd << ('--max-len=' + max_length.to_s) end cmd << hash_path end |
#john_nolog_format ⇒ String
This method is used to determine which format of the no log option should be used –no-log vs –nolog github.com/openwall/john/commit/8982e4f7a2e874aab29807a05b421373015c9b61 We base this either on a date being in the version, or running the command and checking the output
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 370 def john_nolog_format if /(\d{4}-\d{2}-\d{2})/ =~ cracker_version # we lucked out and theres a date, we'll check its older than the commit that changed the nolog if Date.parse(Regexp.last_match(1)) < Date.parse('2020-11-27') return '--nolog' end return '--no-log' end # no date, so lets give it a run with the old format and check if we raise an error # on *nix 'unknown option' goes to stderr ::IO.popen([binary_path, '--nolog', { err: %i[child out] }], 'rb') do |fd| return '--nolog' unless fd.read.include? 'Unknown option' end '--no-log' end |
#john_pot_file ⇒ String
This method returns the path to a default john.pot file.
545 546 547 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 545 def john_pot_file ::File.join(::Msf::Config.config_directory, 'john.pot') end |
#jtr_format_to_hashcat_format(format) ⇒ String
This method takes a Metasploit::Framework::PasswordCracker::Cracker.frameworkframework.dbframework.db.credframework.db.cred.privateframework.db.cred.private.jtr_format (string), and returns the string number associated to the hashcat format
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 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 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 128 def jtr_format_to_hashcat_format(format) case format # nix when 'md5crypt' '500' when 'descrypt' '1500' when 'bsdicrypt' '12400' when 'sha256crypt' '7400' when 'sha512crypt' '1800' when 'bcrypt' '3200' # windows when 'lm', 'lanman' '3000' when 'nt', 'ntlm' '1000' when 'mscash' '1100' when 'mscash2' '2100' when 'netntlm' '5500' when 'netntlmv2' '5600' # dbs when 'mssql' '131' when 'mssql05' '132' when 'mssql12' '1731' # hashcat requires a format we dont have all the data for # in the current dumper, so this is disabled in module and lib # when 'oracle', 'des,oracle' # return '3100' when 'oracle11', 'raw-sha1,oracle' '112' when 'oracle12c', 'pbkdf2,oracle12c' '12300' when 'postgres', 'dynamic_1034', 'raw-md5,postgres' '12' when 'mysql' '200' when 'mysql-sha1' '300' when 'PBKDF2-HMAC-SHA512' # osx 10.8+ '7100' # osx when 'xsha' # osx 10.4-6 '122' when 'xsha512' # osx 10.7 '1722' # webapps when 'PBKDF2-HMAC-SHA1' # Atlassian '12001' when 'phpass' # Wordpress/PHPass, Joomla, phpBB3 '400' when 'mediawiki' # mediawiki b type '3711' # mobile when 'android-samsung-sha1' '5800' when 'android-sha1' '110' when 'android-md5' '10' when 'hmac-md5' '10200' when 'dynamic_82' '1710' when 'ssha' '111' when 'raw-sha512' '1700' when 'raw-sha256' '1400' when 'raw-sha1' '100' when 'raw-md5' '0' when 'smd5' '6300' when 'ssha256' '1411' when 'ssha512' '1711' when 'Raw-MD5u' '30' when 'pbkdf2-sha256' '10900' end end |
#mode_incremental ⇒ Object
This method sets the appropriate parameters to run a cracker in incremental mode
226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 226 def mode_incremental self.increment_length = nil self.wordlist = nil self.mask = nil self.max_runtime = nil if cracker == 'john' self.rules = nil self.incremental = 'Digits' elsif cracker == 'hashcat' self.attack = '3' self.incremental = true end end |
#mode_normal ⇒ Object
This method sets the john to ‘normal’ mode
270 271 272 273 274 275 276 277 278 279 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 270 def mode_normal if cracker == 'john' self.max_runtime = nil self.mask = nil self.wordlist = nil self.rules = nil self.incremental = nil self.increment_length = nil end end |
#mode_pin ⇒ Object
This method sets the appropriate parameters to run a cracker in a pin mode (4-8 digits) on hashcat
258 259 260 261 262 263 264 265 266 267 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 258 def mode_pin self.rules = nil if cracker == 'hashcat' self.attack = '3' self.mask = '?d' * 8 self.incremental = true self.increment_length = [4, 8] self.max_runtime = 300 # 5min on an i7 got through 4-7 digits. 8digit was 32min more end end |
#mode_single(file) ⇒ Object
This method sets the john to single mode
284 285 286 287 288 289 290 291 292 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 284 def mode_single(file) if cracker == 'john' self.wordlist = file self.rules = 'single' self.incremental = nil self.increment_length = nil self.mask = nil end end |
#mode_wordlist(file) ⇒ Object
This method sets the appropriate parameters to run a cracker in wordlist mode
243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 243 def mode_wordlist(file) self.increment_length = nil self.incremental = nil self.max_runtime = nil self.mask = nil if cracker == 'john' self.wordlist = file self.rules = 'wordlist' elsif cracker == 'hashcat' self.wordlist = file self.attack = '0' end end |
#show_command ⇒ Array
This method builds the command to show the cracked passwords.
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 |
# File 'lib/metasploit/framework/password_crackers/cracker.rb', line 561 def show_command cmd_string = binary_path pot_file = pot || john_pot_file if cracker == 'hashcat' cmd = [cmd_string, '--show', '--username', "--potfile-path=#{pot_file}", "--hash-type=#{jtr_format_to_hashcat_format(format)}"] elsif cracker == 'john' cmd = [cmd_string, '--show', "--pot=#{pot_file}", "--format=#{format}"] if config cmd << "--config=#{config}" else cmd << ('--config=' + john_config_file) end end cmd << hash_path end |