Skip to content

Commit 5e43bec

Browse files
authored
Merge pull request #20920 from rudraditya21/fix/cracker-auto-action
Handle ACTION=auto with CRACKER_PATH in password crackers
2 parents 967b43e + a3dd697 commit 5e43bec

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

lib/msf/core/auxiliary/password_cracker.rb

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def new_password_cracker(cracking_application)
8282
optimize: datastore['OptimizeKernel'],
8383
wordlist: datastore['CUSTOM_WORDLIST']
8484
)
85-
cracker.cracker = cracking_application
85+
cracker.cracker = resolve_cracking_application(cracking_application, cracker)
8686
begin
8787
cracker.binary_path
8888
rescue Metasploit::Framework::PasswordCracker::PasswordCrackerNotFoundError => e
@@ -97,6 +97,36 @@ def new_password_cracker(cracking_application)
9797
cracker
9898
end
9999

100+
def resolve_cracking_application(cracking_application, cracker)
101+
return cracking_application unless cracking_application == 'auto'
102+
103+
if cracker.cracker_path.present?
104+
basename = ::File.basename(cracker.cracker_path).downcase
105+
return 'john' if basename.start_with?('john')
106+
return 'hashcat' if basename.start_with?('hashcat')
107+
108+
fail_with(
109+
Msf::Module::Failure::BadConfig,
110+
"CRACKER_PATH '#{cracker.cracker_path}' does not look like john or hashcat; set ACTION to 'john' or 'hashcat'."
111+
)
112+
end
113+
114+
%w[john hashcat].each do |candidate|
115+
cracker.cracker = candidate
116+
begin
117+
cracker.binary_path
118+
return candidate
119+
rescue Metasploit::Framework::PasswordCracker::PasswordCrackerNotFoundError
120+
next
121+
end
122+
end
123+
124+
fail_with(
125+
Msf::Module::Failure::BadConfig,
126+
'No suitable john/hashcat binary was found on the system. Set CRACKER_PATH or ACTION.'
127+
)
128+
end
129+
100130
# This method instantiates a {Metasploit::Framework::JtR::Wordlist}, writes the data
101131
# out to a file and returns the {Rex::Quickfile} object.
102132
#
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
5+
RSpec.describe Msf::Auxiliary::PasswordCracker do
6+
class DummyPasswordCracker
7+
include Msf::Auxiliary::PasswordCracker
8+
9+
attr_accessor :datastore, :framework
10+
11+
def initialize
12+
self.datastore = {}
13+
db = Struct.new(:active).new(true)
14+
self.framework = Struct.new(:db).new(db)
15+
end
16+
17+
def fail_with(_type, message)
18+
raise RuntimeError, message
19+
end
20+
end
21+
22+
subject(:helper) { DummyPasswordCracker.new }
23+
24+
describe '#resolve_cracking_application' do
25+
it 'infers john from CRACKER_PATH when ACTION is auto' do
26+
helper.datastore['CRACKER_PATH'] = '/opt/john/run/john'
27+
cracker = Metasploit::Framework::PasswordCracker::Cracker.new(cracker_path: helper.datastore['CRACKER_PATH'])
28+
29+
expect(helper.resolve_cracking_application('auto', cracker)).to eq('john')
30+
end
31+
32+
it 'infers hashcat from CRACKER_PATH when ACTION is auto' do
33+
helper.datastore['CRACKER_PATH'] = '/opt/hashcat/hashcat'
34+
cracker = Metasploit::Framework::PasswordCracker::Cracker.new(cracker_path: helper.datastore['CRACKER_PATH'])
35+
36+
expect(helper.resolve_cracking_application('auto', cracker)).to eq('hashcat')
37+
end
38+
39+
it 'raises a BadConfig style error when CRACKER_PATH is unknown with ACTION auto' do
40+
helper.datastore['CRACKER_PATH'] = '/opt/tools/myawesomecracker'
41+
cracker = Metasploit::Framework::PasswordCracker::Cracker.new(cracker_path: helper.datastore['CRACKER_PATH'])
42+
43+
expect {
44+
helper.resolve_cracking_application('auto', cracker)
45+
}.to raise_error(RuntimeError, /CRACKER_PATH .* set ACTION to 'john' or 'hashcat'/)
46+
end
47+
48+
it 'falls back to PATH discovery when CRACKER_PATH is unset' do
49+
helper.datastore['CRACKER_PATH'] = nil
50+
cracker = Metasploit::Framework::PasswordCracker::Cracker.new
51+
52+
allow(cracker).to receive(:binary_path) do
53+
if cracker.cracker == 'john'
54+
raise Metasploit::Framework::PasswordCracker::PasswordCrackerNotFoundError
55+
end
56+
'/usr/bin/hashcat'
57+
end
58+
59+
expect(helper.resolve_cracking_application('auto', cracker)).to eq('hashcat')
60+
end
61+
end
62+
end

0 commit comments

Comments
 (0)