CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/tools/password/hmac_sha1_crack.rb
Views: 11766
1
#!/usr/bin/env ruby
2
3
##
4
# This module requires Metasploit: https://metasploit.com/download
5
# Current source: https://github.com/rapid7/metasploit-framework
6
##
7
8
#
9
# This script cracks HMAC SHA1 hashes. It is strangely necessary as existing tools
10
# have issues with binary salt values and extremely large salt values. The primary
11
# goal of this tool is to handle IPMI 2.0 HMAC SHA1 hashes.
12
#
13
# Support for this format is being added to both hashcat and jtr, hopefully
14
# making this code obsolete.
15
#
16
17
msfbase = __FILE__
18
while File.symlink?(msfbase)
19
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
20
end
21
22
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib')))
23
require 'msfenv'
24
25
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
26
27
require 'rex'
28
require 'openssl'
29
30
def usage
31
$stderr.puts("\nUsage: #{$0} hashes.txt <wordlist | - >\n")
32
$stderr.puts("The format of hash file is <identifier>:<hex-salt>:<hash>\n\n")
33
exit
34
end
35
36
hash_inp = ARGV.shift || usage()
37
word_inp = ARGV.shift || usage()
38
39
usage if [hash_inp, word_inp].include?("-h") or [hash_inp, word_inp].include?("--help")
40
41
hash_fd = ::File.open(hash_inp, "rb")
42
word_fd = $stdin
43
44
if word_inp != "-"
45
word_fd = ::File.open(word_inp, "rb")
46
end
47
48
hashes = []
49
hash_fd.each_line do |line|
50
next unless line.strip.length > 0
51
h_id, h_salt, h_hash = line.unpack("C*").pack("C*").strip.split(':', 3)
52
53
unless h_id and h_salt and h_hash
54
$stderr.puts "[-] Invalid hash entry, missing field: #{line}"
55
next
56
end
57
unless h_salt =~ /^[a-f0-9]+$/i
58
$stderr.puts "[-] Invalid hash entry, salt must be in hex: #{line}"
59
next
60
end
61
hashes << [h_id, [h_salt].pack("H*"), [h_hash].pack("H*") ]
62
end
63
hash_fd.close
64
65
stime = Time.now.to_f
66
count = 0
67
cracked = 0
68
69
word_fd.each_line do |line|
70
# Preferable to strip so we can test passwords made of whitespace (or null)
71
line = line.unpack("C*").pack("C*").sub(/\r?\n?$/, '')
72
hashes.each do |hinfo|
73
if OpenSSL::HMAC.digest('sha1', line.to_s, hinfo[1]) == hinfo[2]
74
$stdout.puts [ hinfo[0], hinfo[1].unpack("H*").first, hinfo[2].unpack("H*").first, line.to_s ].join(":")
75
$stdout.flush
76
hinfo[3] = true
77
cracked += 1
78
end
79
count += 1
80
81
if count % 2500000 == 0
82
$stderr.puts "[*] Found #{cracked} passwords with #{hashes.length} left (#{(count / (Time.now.to_f - stime)).to_i}/s)"
83
end
84
end
85
hashes.delete_if {|e| e[3] }
86
break if hashes.length == 0
87
88
end
89
word_fd.close
90
91
$stderr.puts "[*] Cracked #{cracked} passwords with #{hashes.length} left (#{(count / (Time.now.to_f - stime)).to_i}/s)"
92
93