116 lines
3.1 KiB
Ruby
116 lines
3.1 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'yaml'
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Auxiliary::Report
|
|
include Msf::Post::File
|
|
include Msf::Post::Windows::Registry
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Windows Gather File and Registry Artifacts Enumeration',
|
|
'Description' => %q{
|
|
This module will check the file system and registry for particular artifacts.
|
|
|
|
The list of artifacts is read in YAML format from data/post/enum_artifacts_list.txt
|
|
or a user specified file. Any matches are written to the loot.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => [ 'averagesecurityguy <stephen[at]averagesecurityguy.info>' ],
|
|
'Platform' => [ 'win' ],
|
|
'SessionTypes' => %w[shell powershell meterpreter],
|
|
'Notes' => {
|
|
'Stability' => [CRASH_SAFE],
|
|
'Reliability' => [],
|
|
'SideEffects' => []
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options([
|
|
OptPath.new(
|
|
'ARTIFACTS',
|
|
[
|
|
true,
|
|
'Full path to artifacts file.',
|
|
::File.join(Msf::Config.data_directory, 'post', 'enum_artifacts_list.txt')
|
|
]
|
|
)
|
|
])
|
|
end
|
|
|
|
def run
|
|
# Load artifacts from yaml file. Artifacts are organized by what they are evidence of.
|
|
begin
|
|
yaml = YAML.load_file(datastore['ARTIFACTS'])
|
|
raise 'File is not valid YAML' unless yaml.instance_of?(Hash)
|
|
rescue StandardError => e
|
|
fail_with(Failure::BadConfig, "Could not load artifacts YAML file '#{datastore['ARTIFACTS']}' : #{e.message}")
|
|
end
|
|
|
|
loot_data = ''
|
|
|
|
yaml.each_key do |key|
|
|
print_status("Searching for artifacts of #{key}")
|
|
artifacts = []
|
|
|
|
# Process file entries
|
|
files = yaml[key]['files']
|
|
vprint_status("Processing #{files.length} file entries for #{key} ...")
|
|
|
|
files.each do |file|
|
|
fname = file['name']
|
|
csum = file['csum']
|
|
|
|
digest = file_remote_digestmd5(fname)
|
|
if digest == csum
|
|
artifacts << fname
|
|
end
|
|
end
|
|
|
|
# Process registry entries
|
|
regs = yaml[key]['reg_entries']
|
|
vprint_status("Processing #{regs.length} registry entries for #{key} ...")
|
|
|
|
regs.each do |reg|
|
|
k = reg['key']
|
|
v = reg['val']
|
|
rdata = registry_getvaldata(k, v)
|
|
if rdata.to_s == reg['data']
|
|
artifacts << "#{k}\\#{v}"
|
|
end
|
|
end
|
|
|
|
# Process matches
|
|
if artifacts.empty?
|
|
print_status("No artifacts of #{key} found.")
|
|
next
|
|
end
|
|
|
|
print_status("Artifacts of #{key} found.")
|
|
loot_data << "Evidence of #{key} found.\n"
|
|
loot_data << artifacts.map { |a| "\t#{a}\n" }.join
|
|
end
|
|
|
|
return if loot_data.blank?
|
|
|
|
vprint_line(loot_data)
|
|
|
|
loot_name = 'Enumerated Artifacts'
|
|
f = store_loot(
|
|
loot_name.downcase.split.join('.'),
|
|
'text/plain',
|
|
session,
|
|
loot_data,
|
|
loot_name
|
|
)
|
|
print_good("#{loot_name} stored in: #{f}")
|
|
end
|
|
end
|