Updates to enum_artifacts
parent
bddeb9912b
commit
efda420e5f
|
@ -1,14 +1,36 @@
|
||||||
# This file contains a list of artifacts used by the enum_artifacts post module
|
# YAML:1.0
|
||||||
# Artifacts should be listed one per line and use the following formats:
|
# Configuration file for enum_artifacts.rb module
|
||||||
# File entries
|
# This file contains a YAML formated list of artifacts used by the
|
||||||
# file|path/to/file|md5sum
|
# 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
|
# 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
|
|
||||||
|
|
|
@ -38,7 +38,11 @@ module File
|
||||||
#
|
#
|
||||||
|
|
||||||
def file_remote_digestmd5(file2md5)
|
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
|
return chksum
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,7 +65,11 @@ module File
|
||||||
#
|
#
|
||||||
|
|
||||||
def file_remote_digestsha1(file2sha1)
|
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
|
return chksum
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -84,7 +92,11 @@ module File
|
||||||
#
|
#
|
||||||
|
|
||||||
def file_remote_digestsha2(file2sha2)
|
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
|
return chksum
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ require 'rex'
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
require 'msf/core/post/file'
|
require 'msf/core/post/file'
|
||||||
require 'msf/core/post/windows/registry'
|
require 'msf/core/post/windows/registry'
|
||||||
|
require 'yaml'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ class Metasploit3 < Msf::Post
|
||||||
'Name' => 'Windows File and Registry Artifacts Enumeration',
|
'Name' => 'Windows File and Registry Artifacts Enumeration',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module will check the file system and registry for particular artifacts. The
|
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. },
|
matches are written to the loot. },
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' => [ 'averagesecurityguy <stephen[at]averagesecurityguy.info>' ],
|
'Author' => [ 'averagesecurityguy <stephen[at]averagesecurityguy.info>' ],
|
||||||
|
@ -36,14 +37,15 @@ class Metasploit3 < Msf::Post
|
||||||
true,
|
true,
|
||||||
'Full path to artifacts file.',
|
'Full path to artifacts file.',
|
||||||
::File.join(Msf::Config.data_directory, 'post', 'enum_artifacts_list.txt')
|
::File.join(Msf::Config.data_directory, 'post', 'enum_artifacts_list.txt')
|
||||||
])
|
]),
|
||||||
|
OptString.new( 'VERBOSE', [false, "Show verbose output", false] )
|
||||||
], self.class)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
# Store any found artifacts so they can be written to loot
|
# Store any found artifacts so they can be written to loot
|
||||||
files_found = []
|
evidence = {}
|
||||||
reg_found = []
|
if datastore['VERBOSE'] == 'true' then verbose = true end
|
||||||
|
|
||||||
# Check artifacts file path
|
# Check artifacts file path
|
||||||
filename = datastore['ARTIFACTS']
|
filename = datastore['ARTIFACTS']
|
||||||
|
@ -52,55 +54,63 @@ class Metasploit3 < Msf::Post
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# Start enumerating
|
# Load artifacts from yaml file. Artifacts are organized by what they
|
||||||
print_status("Processing artifacts file...")
|
# are evidence of.
|
||||||
file = ::File.open(filename, "rb")
|
yaml = YAML::load_file(filename)
|
||||||
file.each_line do |line|
|
yaml.each_key do |key|
|
||||||
line.strip!
|
print_status("Searching for artifacts of #{key}")
|
||||||
next if line.length < 1
|
files = yaml[key]['files']
|
||||||
next if line[0,1] == "#"
|
regs = yaml[key]['reg_entries']
|
||||||
|
found = []
|
||||||
|
|
||||||
# Check registry
|
# Process file entries
|
||||||
if line =~ /^reg/
|
if verbose
|
||||||
type, reg_key, val, data = line.split("|")
|
print_status("Processing #{files.length.to_s} file entries for #{key}.")
|
||||||
reg_data = registry_getvaldata(reg_key, val)
|
|
||||||
if reg_data.to_s == data
|
|
||||||
reg_found << "#{reg_key}\\#{val}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check file
|
files.each do |file|
|
||||||
if line =~ /^file/
|
digest = file_remote_digestmd5(file['name'])
|
||||||
type, file, hash = line.split("|")
|
# if the file doesn't exist then digest will be nil
|
||||||
digest = file_remote_digestmd5(file)
|
next if digest == nil
|
||||||
if digest == hash
|
if digest == file['csum'] then found << file['name'] end
|
||||||
files_found << file
|
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
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reporting. In case the user wants to separte artifact types (file vs registry),
|
save(evidence, "Enumerated Artifacts")
|
||||||
# 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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def save(data, name)
|
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}")
|
print_status("#{name} stored in: #{f}")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
|
||||||
To-do: Use CSV or yaml format to store enum_artifacts_list.txt
|
|
||||||
=end
|
|
||||||
|
|
Loading…
Reference in New Issue