Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement vnc hash types #16341

Merged
merged 2 commits into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 89 additions & 86 deletions lib/metasploit/framework/hashes/identify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,103 +19,106 @@ def identify_hash(hash)
hash = hash.to_s.strip
case
# operating systems
when hash.start_with?('$1$') && hash.length == 34
return 'md5'
when hash.start_with?('$2$') && hash.length == 59,
when hash.start_with?('$1$') && hash.length == 34
return 'md5'
when hash.start_with?('$2$') && hash.length == 59,
hash.start_with?('$2a$') && hash.length == 60,
hash.start_with?('$2b$') && hash.length == 60,
hash.start_with?('$2x$') && hash.length == 60,
hash.start_with?('$2y$') && hash.length == 60
return 'bf' #bcrypt
when hash.start_with?('$5$') && hash.split('$').last.length == 43
# we dont check full length since it may have 'rounds=' in the [1] area or not with an arbitrary length number
return 'sha256,crypt'
when hash.start_with?('$6$') && hash.split('$').last.length == 86
# we dont check full length since it may have 'rounds=' in the [1] area or not with an arbitrary length number
return 'sha512,crypt'
when hash.start_with?('@S@') && hash.length == 148
return 'qnx,sha512'
when hash.start_with?('@s@') && hash.length == 84
return 'qnx,sha256'
when hash.start_with?('@m@') && hash.length == 52
return 'qnx,md5'
when hash.start_with?('_') && hash.length == 20
return 'des,bsdi,crypt'
when hash =~ /^[\.\/\dA-Za-z]{13}$/ # hash.length == 13
return 'des,crypt'
when hash =~ /^\$dynamic_82\$[\da-f]{128}\$HEX\$[\da-f]{32}$/ # jtr vmware ldap https://github.com/rapid7/metasploit-framework/pull/13865#issuecomment-660718108
return 'dynamic_82'
when hash.start_with?(/{SSHA}/i)
return 'ssha'
when hash.start_with?(/{SHA512}/i)
return 'raw-sha512'
when hash.start_with?(/{SHA256}/i)
return 'raw-sha256'
when hash.start_with?(/{SHA}/i)
return 'raw-sha1'
when hash.start_with?(/{MD5}/i)
return 'raw-md5'
when hash.start_with?(/{SMD5}/i)
return 'smd5'
when hash.start_with?(/{SSHA256}/i)
return 'ssha256'
when hash.start_with?(/{SSHA512}/i)
return 'ssha512'
return 'bf' # bcrypt
when hash.start_with?('$5$') && hash.split('$').last.length == 43
# we dont check full length since it may have 'rounds=' in the [1] area or not with an arbitrary length number
return 'sha256,crypt'
when hash.start_with?('$6$') && hash.split('$').last.length == 86
# we dont check full length since it may have 'rounds=' in the [1] area or not with an arbitrary length number
return 'sha512,crypt'
when hash.start_with?('@S@') && hash.length == 148
return 'qnx,sha512'
when hash.start_with?('@s@') && hash.length == 84
return 'qnx,sha256'
when hash.start_with?('@m@') && hash.length == 52
return 'qnx,md5'
when hash.start_with?('_') && hash.length == 20
return 'des,bsdi,crypt'
when hash =~ %r{^[./\dA-Za-z]{13}$} # hash.length == 13
return 'des,crypt'
when hash =~ /^\$dynamic_82\$[\da-f]{128}\$HEX\$[\da-f]{32}$/ # jtr vmware ldap https://github.com/rapid7/metasploit-framework/pull/13865#issuecomment-660718108
return 'dynamic_82'
when hash.start_with?(/{SSHA}/i)
return 'ssha'
when hash.start_with?(/{SHA512}/i)
return 'raw-sha512'
when hash.start_with?(/{SHA256}/i)
return 'raw-sha256'
when hash.start_with?(/{SHA}/i)
return 'raw-sha1'
when hash.start_with?(/{MD5}/i)
return 'raw-md5'
when hash.start_with?(/{SMD5}/i)
return 'smd5'
when hash.start_with?(/{SSHA256}/i)
return 'ssha256'
when hash.start_with?(/{SSHA512}/i)
return 'ssha512'
# windows
when hash.length == 65 && hash =~ /^[\da-fA-F]{32}:[\da-fA-F]{32}$/ && hash.split(':').first.upcase == 'AAD3B435B51404EEAAD3B435B51404EE'
return 'nt'
when hash.length == 65 && hash =~ /^[\da-fA-F]{32}:[\da-fA-F]{32}$/
return 'lm'
when hash.length == 65 && hash =~ /^[\da-fA-F]{32}:[\da-fA-F]{32}$/ && hash.split(':').first.upcase == 'AAD3B435B51404EEAAD3B435B51404EE'
return 'nt'
when hash.length == 65 && hash =~ /^[\da-fA-F]{32}:[\da-fA-F]{32}$/
return 'lm'
# OSX
when hash.start_with?('$ml$') && hash.split('$').last.length == 256
return 'pbkdf2-hmac-sha512,osx' # 10.8+
when hash =~ /^[\da-fA-F]{48}$/ # hash.length == 48
return 'xsha,osx' # 10.4-10.6
when hash.start_with?('$ml$') && hash.split('$').last.length == 256
return 'pbkdf2-hmac-sha512,osx' # 10.8+
when hash =~ /^[\da-fA-F]{48}$/ # hash.length == 48
return 'xsha,osx' # 10.4-10.6
# databases
when hash.start_with?('0x0100') && hash.length == 54
return 'mssql05'
when hash.start_with?('0x0100') && hash.length == 94
return 'mssql'
when hash.start_with?('0x0200') && hash.length == 142
return 'mssql12'
when hash =~ /^[\da-f]{16}$/ # hash.length == 16
return 'mysql' # mysql323 (pre 4.1)
when hash.start_with?('*') && hash.length == 41
return 'mysql-sha1' # mysql 4.1+
when hash.start_with?('md5') && hash.length == 35
return 'postgres'
when hash =~ /^[\da-fA-F]{16}$/
return 'des,oracle' # pre 11g
when hash =~ /^S:[\dA-F]{60}$/
return 'raw-sha1,oracle11'
when hash =~ /^S:[\dA-F]{60};H:[\dA-F]{32};T:[\dA-F]{160}$/
return 'raw-sha1,oracle'
when hash =~ /^H:[\dA-F]{32};T:[\dA-F]{160}$/
return 'pbkdf2,oracle12c'
when hash.start_with?('0x0100') && hash.length == 54
return 'mssql05'
when hash.start_with?('0x0100') && hash.length == 94
return 'mssql'
when hash.start_with?('0x0200') && hash.length == 142
return 'mssql12'
when hash =~ /^[\da-f]{16}$/ # hash.length == 16
return 'mysql' # mysql323 (pre 4.1)
when hash.start_with?('*') && hash.length == 41
return 'mysql-sha1' # mysql 4.1+
when hash.start_with?('md5') && hash.length == 35
return 'postgres'
when hash =~ /^[\da-fA-F]{16}$/
return 'des,oracle' # pre 11g
when hash =~ /^S:[\dA-F]{60}$/
return 'raw-sha1,oracle11'
when hash =~ /^S:[\dA-F]{60};H:[\dA-F]{32};T:[\dA-F]{160}$/
return 'raw-sha1,oracle'
when hash =~ /^H:[\dA-F]{32};T:[\dA-F]{160}$/
return 'pbkdf2,oracle12c'
# webapps
when hash.start_with?('$P$') && hash.length == 34,
when hash.start_with?('$P$') && hash.length == 34,
hash.start_with?('$H$') && hash.length == 34
return 'phpass' # wordpress, drupal, phpbb3 (H not P)
when hash.start_with?('$ml$') && hash.length == 203
return 'PBKDF2-HMAC-SHA512'
when hash.start_with?('{PKCS5S2}') && hash.length == 73
return 'PBKDF2-HMAC-SHA1'
when hash.start_with?('$B$') && hash.split('$').last.length == 32
return 'mediawiki'
return 'phpass' # wordpress, drupal, phpbb3 (H not P)
when hash.start_with?('$ml$') && hash.length == 203
return 'PBKDF2-HMAC-SHA512'
when hash.start_with?('{PKCS5S2}') && hash.length == 73
return 'PBKDF2-HMAC-SHA1'
when hash.start_with?('$B$') && hash.split('$').last.length == 32
return 'mediawiki'
# mobile
when hash =~/^[A-F0-9]{40}:[a-f0-9]{16}$/
return 'android-sha1'
when hash =~/^[A-F0-9]{32}:[a-f0-9]{16}$/
return 'android-md5'
when hash =~ /^[A-F0-9]{40}:[a-f0-9]{16}$/
return 'android-sha1'
when hash =~ /^[A-F0-9]{32}:[a-f0-9]{16}$/
return 'android-md5'
# other
when hash =~ /^<\d+@.+?>#[\w]{32}$/
return 'hmac-md5'
when hash.length == 114 && hash.start_with?('$M$')
return 'F5-Secure-Vault'
when hash =~ /^M\$[[:print:]]+#[\da-fA-F]{32}(?:(?::[[:print:]]*$)|$)/
return 'mscash'
when hash =~ /^\$DCC2\$\d+#[[:print:]]+#[\da-fA-F]{32}(?:(?::[[:print:]]*$)|$)/
return 'mscash2'
when hash =~ /^<\d+@.+?>#\w{32}$/
return 'hmac-md5'
when hash.length == 114 && hash.start_with?('$M$')
return 'F5-Secure-Vault'
when hash =~ /^M\$[[:print:]]+#[\da-fA-F]{32}(?:(?::[[:print:]]*$)|$)/
return 'mscash'
when hash =~ /^\$DCC2\$\d+#[[:print:]]+#[\da-fA-F]{32}(?:(?::[[:print:]]*$)|$)/
return 'mscash2'
when hash =~ /^\*?[\da-fA-F]{32}\*[\da-fA-F]{32}$/
# we accept the beginning star as optional
return 'vnc'
end
''
end
29 changes: 16 additions & 13 deletions lib/metasploit/framework/password_crackers/hashcat/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
def hash_to_hashcat(cred)
case cred.private.type
when 'Metasploit::Credential::NTLMHash'
both = cred.private.data.split(":")
if both[0].upcase == 'AAD3B435B51404EEAAD3B435B51404EE' #lanman empty, return ntlm
both = cred.private.data.split(':')
if both[0].upcase == 'AAD3B435B51404EEAAD3B435B51404EE' # lanman empty, return ntlm
return both[1] # ntlm hash-mode: 1000
end
return both[0] #give lanman, hash-mode: 3000
when 'Metasploit::Credential::PostgresMD5' #hash-mode: 12

return both[0] # give lanman, hash-mode: 3000
when 'Metasploit::Credential::PostgresMD5' # hash-mode: 12
if cred.private.jtr_format =~ /postgres|raw-md5/
hash_string = cred.private.data
hash_string.gsub!(/^md5/, '')
Expand Down Expand Up @@ -44,26 +45,26 @@ def hash_to_hashcat(cred)
when /raw-sha1|oracle11/ # oracle 11, hash-mode: 112
if cred.private.data =~ /S:([\dA-F]{60})/ # oracle 11
# hashcat wants a 40 character string, : 20 character string
return $1.scan(/.{1,40}/m).join(':').downcase
return Regexp.last_match(1).scan(/.{1,40}/m).join(':').downcase
end
when /oracle12c/
if cred.private.data =~ /T:([\dA-F]{160})/ # oracle 12c, hash-mode: 12300
return $1.upcase
return Regexp.last_match(1).upcase
end
when /dynamic_1506|postgres/
#this may not be correct
# this may not be correct
if cred.private.data =~ /H:([\dA-F]{32})/ # oracle 11, hash-mode: 3100
return "#{$1}:#{cred.public.username}"
return "#{Regexp.last_match(1)}:#{cred.public.username}"
end
when /oracle/ # oracle
if cred.private.jtr_format.start_with?('des') # 'des,oracle', not oracle11/12c, hash-mode: 3100
return "#{cred.private.data}"
return cred.private.data.to_s
end
when /dynamic_82/
return cred.private.data.sub('$HEX$', ':').sub('$dynamic_82$','')
return cred.private.data.sub('$HEX$', ':').sub('$dynamic_82$', '')
when /mysql-sha1/
# lowercase, and remove the first character if its a *
return cred.private.data.downcase.sub('*','')
return cred.private.data.downcase.sub('*', '')
when /md5|des|bsdi|crypt|bf/, /mssql|mssql05|mssql12|mysql/, /sha256|sha-256/,
/sha512|sha-512/, /xsha|xsha512|PBKDF2-HMAC-SHA512/,
/mediawiki|phpass|PBKDF2-HMAC-SHA1/,
Expand Down Expand Up @@ -93,9 +94,11 @@ def hash_to_hashcat(cred)
# netntlm, netntlmv2
# hash-mode: 5500 5600
return cred.private.data
when /^vnc$/
# https://hashcat.net/forum/thread-8833.html
# while we can do the transformation, we'd have to throw extra flags at hashcat which aren't currently written into the lib for automation
nil
end
end
nil
end


15 changes: 10 additions & 5 deletions lib/metasploit/framework/password_crackers/jtr/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def hash_to_jtr(cred)
when 'Metasploit::Credential::PostgresMD5'
if cred.private.jtr_format =~ /postgres|raw-md5/
# john --list=subformats | grep 'PostgreSQL MD5'
#UserFormat = dynamic_1034 type = dynamic_1034: md5($p.$u) (PostgreSQL MD5)
# UserFormat = dynamic_1034 type = dynamic_1034: md5($p.$u) (PostgreSQL MD5)
hash_string = cred.private.data
hash_string.gsub!(/^md5/, '')
return "#{cred.public.username}:$dynamic_1034$#{hash_string}"
Expand All @@ -36,15 +36,15 @@ def hash_to_jtr(cred)
# PBKDF2-based SHA512 hash specific to 12C (12.1.0.2+)
when /raw-sha1|oracle11/ # oracle 11
if cred.private.data =~ /S:([\dA-F]{60})/ # oracle 11
return "#{cred.public.username}:#{$1}:#{cred.id}:"
return "#{cred.public.username}:#{Regexp.last_match(1)}:#{cred.id}:"
end
when /oracle12c/
if cred.private.data =~ /T:([\dA-F]{160})/ # oracle 12c
return "#{cred.public.username}:$oracle12c$#{$1.downcase}:#{cred.id}:"
return "#{cred.public.username}:$oracle12c$#{Regexp.last_match(1).downcase}:#{cred.id}:"
end
when /dynamic_1506/
if cred.private.data =~ /H:([\dA-F]{32})/ # oracle 11
return "#{cred.public.username.upcase}:$dynamic_1506$#{$1}:#{cred.id}:"
return "#{cred.public.username.upcase}:$dynamic_1506$#{Regexp.last_match(1)}:#{cred.id}:"
end
when /oracle/ # oracle
if cred.private.jtr_format.start_with?('des') # 'des,oracle', not oracle11/12c
Expand All @@ -67,6 +67,9 @@ def hash_to_jtr(cred)
# with a sample hash of b31d032cfdcf47a399990a71e43c5d2a:144816. So this just outputs
# The hash as *hash*: so that it is both JTR and hashcat compatible
return "#{cred.private.data}:"
when /vnc/
# add a beginning * if one is missing
return "$vnc$#{cred.private.data.start_with?('*') ? cred.private.data.upcase : "*#{cred.private.data.upcase}"}"
else
# /mysql|mysql-sha1/
# /mssql|mssql05|mssql12/
Expand All @@ -76,7 +79,9 @@ def hash_to_jtr(cred)
# /ssha/
# /raw-sha512/
# /raw-sha256/
return "#{cred.public.username}:#{cred.private.data}:#{cred.id}:"
# This also handles *other* type credentials which aren't guaranteed to have a public

return "#{cred.public.nil? ? ' ' : cred.public.username}:#{cred.private.data}:#{cred.id}:"
end
end
nil
Expand Down
Loading