2012-01-06 22:43:50 +00:00
|
|
|
##
|
|
|
|
# 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 'rex'
|
2012-01-12 17:49:50 +00:00
|
|
|
require 'msf/core'
|
|
|
|
require 'msf/core/post/file'
|
2012-01-06 22:43:50 +00:00
|
|
|
require 'msf/core/post/windows/registry'
|
2012-01-27 00:35:39 +00:00
|
|
|
require 'yaml'
|
2012-01-06 22:43:50 +00:00
|
|
|
|
|
|
|
class Metasploit3 < Msf::Post
|
|
|
|
|
|
|
|
include Msf::Auxiliary::Report
|
2012-01-12 17:49:50 +00:00
|
|
|
include Msf::Post::File
|
2012-01-06 22:43:50 +00:00
|
|
|
include Msf::Post::Windows::Registry
|
2012-01-18 21:01:00 +00:00
|
|
|
|
2012-01-06 22:43:50 +00:00
|
|
|
def initialize(info={})
|
|
|
|
super( update_info( info,
|
2012-01-12 17:49:50 +00:00
|
|
|
'Name' => 'Windows File and Registry Artifacts Enumeration',
|
2012-01-12 23:26:35 +00:00
|
|
|
'Description' => %q{
|
2012-01-18 21:01:00 +00:00
|
|
|
This module will check the file system and registry for particular artifacts. The
|
2012-01-27 00:35:39 +00:00
|
|
|
list of artifacts is read from data/post/enum_artifacts_list.txt or a user specified file. Any
|
2012-01-12 23:26:35 +00:00
|
|
|
matches are written to the loot. },
|
2012-01-06 22:43:50 +00:00
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Author' => [ 'averagesecurityguy <stephen[at]averagesecurityguy.info>' ],
|
|
|
|
'Platform' => [ 'windows' ],
|
|
|
|
'SessionTypes' => [ 'meterpreter' ]
|
|
|
|
))
|
2012-01-12 23:26:35 +00:00
|
|
|
|
2012-01-06 22:43:50 +00:00
|
|
|
register_options(
|
|
|
|
[
|
2012-01-12 23:26:35 +00:00
|
|
|
OptPath.new( 'ARTIFACTS',
|
|
|
|
[
|
|
|
|
true,
|
|
|
|
'Full path to artifacts file.',
|
|
|
|
::File.join(Msf::Config.data_directory, 'post', 'enum_artifacts_list.txt')
|
2012-01-27 00:35:39 +00:00
|
|
|
]),
|
|
|
|
OptString.new( 'VERBOSE', [false, "Show verbose output", false] )
|
2012-01-06 22:43:50 +00:00
|
|
|
], self.class)
|
|
|
|
end
|
|
|
|
|
|
|
|
def run
|
|
|
|
# Store any found artifacts so they can be written to loot
|
2012-01-27 00:35:39 +00:00
|
|
|
evidence = {}
|
|
|
|
if datastore['VERBOSE'] == 'true' then verbose = true end
|
2012-01-06 22:43:50 +00:00
|
|
|
|
2012-01-12 23:26:35 +00:00
|
|
|
# Check artifacts file path
|
|
|
|
filename = datastore['ARTIFACTS']
|
|
|
|
if not ::File.exists?(filename)
|
|
|
|
print_error("Artifacts file does not exist!")
|
|
|
|
return
|
2012-01-06 22:43:50 +00:00
|
|
|
end
|
2012-01-12 23:26:35 +00:00
|
|
|
|
2012-01-27 00:35:39 +00:00
|
|
|
# Load artifacts from yaml file. Artifacts are organized by what they
|
|
|
|
# are evidence of.
|
|
|
|
yaml = YAML::load_file(filename)
|
|
|
|
yaml.each_key do |key|
|
|
|
|
print_status("Searching for artifacts of #{key}")
|
|
|
|
files = yaml[key]['files']
|
|
|
|
regs = yaml[key]['reg_entries']
|
|
|
|
found = []
|
2012-01-12 23:26:35 +00:00
|
|
|
|
2012-01-27 00:35:39 +00:00
|
|
|
# Process file entries
|
|
|
|
if verbose
|
|
|
|
print_status("Processing #{files.length.to_s} file entries for #{key}.")
|
2012-01-12 23:26:35 +00:00
|
|
|
end
|
|
|
|
|
2012-01-27 00:35:39 +00:00
|
|
|
files.each do |file|
|
|
|
|
digest = file_remote_digestmd5(file['name'])
|
|
|
|
# if the file doesn't exist then digest will be nil
|
|
|
|
next if digest == nil
|
|
|
|
if digest == file['csum'] then found << file['name'] end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Process registry entries
|
|
|
|
if verbose
|
|
|
|
print_status("Processing #{regs.length.to_s} registry entries for #{key}.")
|
2012-01-06 22:43:50 +00:00
|
|
|
end
|
|
|
|
|
2012-01-27 00:35:39 +00:00
|
|
|
regs.each do |reg|
|
|
|
|
rdata = registry_getvaldata(reg['key'], reg['val'])
|
|
|
|
if rdata.to_s == reg['data']
|
|
|
|
found << reg['key'] + '\\' + reg['val']
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Did we find anything? If so store it in the evidence hash to be
|
|
|
|
# saved in the loot.
|
|
|
|
if found.empty?
|
|
|
|
print_status("No artifacts of #{key} found.")
|
|
|
|
else
|
|
|
|
print_error("Artifacts of #{key} found.")
|
|
|
|
evidence[key] = found
|
|
|
|
end
|
2012-01-06 22:43:50 +00:00
|
|
|
end
|
|
|
|
|
2012-01-27 00:35:39 +00:00
|
|
|
save(evidence, "Enumerated Artifacts")
|
2012-01-06 22:43:50 +00:00
|
|
|
end
|
|
|
|
|
2012-01-12 23:26:35 +00:00
|
|
|
def save(data, name)
|
2012-01-27 00:35:39 +00:00
|
|
|
str = ""
|
|
|
|
data.each_pair do |key, val|
|
|
|
|
str << "Evidence of #{key} found.\n"
|
|
|
|
val.each do |v|
|
|
|
|
str << "\t" + v + "\n"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
f = store_loot('enumerated.artifacts', 'text/plain', session, str, name)
|
2012-01-12 23:26:35 +00:00
|
|
|
print_status("#{name} stored in: #{f}")
|
|
|
|
end
|
|
|
|
|
2012-01-06 22:43:50 +00:00
|
|
|
end
|