Updates to enum_artifacts

unstable
Stephen Haywood 2012-01-26 19:35:39 -05:00
parent bddeb9912b
commit efda420e5f
3 changed files with 99 additions and 55 deletions

View File

@ -1,14 +1,36 @@
# This file contains a list of artifacts used by the enum_artifacts post module
# Artifacts should be listed one per line and use the following formats:
# File entries
# file|path/to/file|md5sum
# YAML:1.0
# Configuration file for enum_artifacts.rb module
# This file contains a YAML formated list of artifacts used by the
# enum_artifacts post module. Artifacts should be listed using the following
# format:
#
# Registry entries
# reg|hive|key|value
# ---
# malware_name:
# files:
# - name: path\to\file
# csum: 00112233445566778899aabbccddeeff
# - name: path\to\another\file
# csum: 112233445566778899aabbccddeeff00
#
# reg_entries:
# - key: registry_key
# val: registry_value
# data: data
#
# Happy hunting
---
test_evidence:
files:
- name: c:\ntdetect.comx
csum: b2de3452de03674c6cec68b8c8ce7c78
- name: c:\boot.ini
csum: fa579938b0733b87066546afe951082c
reg_entries:
- key: HKEY_LOCAL_MACHINE\SYSTEM\Selectx
val: Current
data: 1
- key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ACPI
val: DisplayName
data: Microsoft ACPI Driver
file|c:\ntdetect.com|b2de3452de03674c6cec68b8c8ce7c78
file|c:\boot.ini|fa579938b0733b87066546afe951082c
reg|HKEY_LOCAL_MACHINE\SYSTEM\Select|Current|1
reg|HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ACPI|DisplayName|Microsoft ACPI Driver

View File

@ -38,7 +38,11 @@ module File
#
def file_remote_digestmd5(file2md5)
chksum = Digest::MD5.hexdigest(read_file(file2md5))
data = read_file(file2md5)
chksum = nil
if data
chksum = Digest::MD5.hexdigest(data)
end
return chksum
end
@ -61,7 +65,11 @@ module File
#
def file_remote_digestsha1(file2sha1)
chksum = Digest::SHA1.hexdigest(read_file(file2sha1))
data = read_file(file2sha1)
chksum = nil
if data
chksum = Digest::SHA1.hexdigest(data)
end
return chksum
end
@ -84,7 +92,11 @@ module File
#
def file_remote_digestsha2(file2sha2)
chksum = Digest::SHA256.hexdigest(read_file(file2sha2))
data = read_file(file2sha2)
chksum = nil
if data
chksum = Digest::SHA256.hexdigest(data)
end
return chksum
end

View File

@ -9,6 +9,7 @@ require 'rex'
require 'msf/core'
require 'msf/core/post/file'
require 'msf/core/post/windows/registry'
require 'yaml'
class Metasploit3 < Msf::Post
@ -21,7 +22,7 @@ class Metasploit3 < Msf::Post
'Name' => 'Windows 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 from data/post/artifacts or a user specified file. Any
list of artifacts is read 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>' ],
@ -36,14 +37,15 @@ class Metasploit3 < Msf::Post
true,
'Full path to artifacts file.',
::File.join(Msf::Config.data_directory, 'post', 'enum_artifacts_list.txt')
])
]),
OptString.new( 'VERBOSE', [false, "Show verbose output", false] )
], self.class)
end
def run
# Store any found artifacts so they can be written to loot
files_found = []
reg_found = []
evidence = {}
if datastore['VERBOSE'] == 'true' then verbose = true end
# Check artifacts file path
filename = datastore['ARTIFACTS']
@ -52,55 +54,63 @@ class Metasploit3 < Msf::Post
return
end
# Start enumerating
print_status("Processing artifacts file...")
file = ::File.open(filename, "rb")
file.each_line do |line|
line.strip!
next if line.length < 1
next if line[0,1] == "#"
# 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 = []
# Check registry
if line =~ /^reg/
type, reg_key, val, data = line.split("|")
reg_data = registry_getvaldata(reg_key, val)
if reg_data.to_s == data
reg_found << "#{reg_key}\\#{val}"
# Process file entries
if verbose
print_status("Processing #{files.length.to_s} file entries for #{key}.")
end
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}.")
end
regs.each do |reg|
rdata = registry_getvaldata(reg['key'], reg['val'])
if rdata.to_s == reg['data']
found << reg['key'] + '\\' + reg['val']
end
end
# Check file
if line =~ /^file/
type, file, hash = line.split("|")
digest = file_remote_digestmd5(file)
if digest == hash
files_found << file
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
end
# Reporting. In case the user wants to separte artifact types (file vs registry),
# we've already done it at this point.
if files_found.empty?
print_status("No file artifacts found")
else
save(files_found, "Enumerated File Artifacts")
end
if reg_found.empty?
print_status("No registry artifacts found")
else
save(reg_found, "Enumerated Registry Artifacts")
end
save(evidence, "Enumerated Artifacts")
end
def save(data, name)
f = store_loot('enumerated.artifacts', 'text/plain', session, data.join("\n"), name)
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)
print_status("#{name} stored in: #{f}")
end
end
=begin
To-do: Use CSV or yaml format to store enum_artifacts_list.txt
=end