Path: blob/master/modules/post/windows/gather/enum_av_excluded.rb
19535 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::Windows::Registry78def initialize(info = {})9super(10update_info(11info,12'Name' => 'Windows Antivirus Exclusions Enumeration',13'Description' => %q{14This module will enumerate the file, directory, process and15extension-based exclusions from supported AV products, which16currently includes Microsoft Defender, Microsoft Security17Essentials/Antimalware, and Symantec Endpoint Protection.18},19'License' => MSF_LICENSE,20'Author' => [21'Andrew Smith', # original metasploit module22'Jon Hart <jon_hart[at]rapid7.com>' # improved metasploit module23],24'Platform' => [ 'win' ],25# XXX: this will work with 'shell' when the sysinfo parts are removed26# and https://github.com/rapid7/metasploit-framework/issues/632827# is fixed28'SessionTypes' => [ 'meterpreter' ],29'Notes' => {30'Stability' => [CRASH_SAFE],31'SideEffects' => [],32'Reliability' => []33}34)35)3637register_options(38[39OptBool.new('DEFENDER', [true, 'Enumerate exclusions for Microsoft Defender', true]),40OptBool.new('ESSENTIALS', [true, 'Enumerate exclusions for Microsoft Security Essentials/Antimalware', true]),41OptBool.new('SEP', [true, 'Enumerate exclusions for Symantec Endpoint Protection (SEP)', true])42]43)44end4546DEFENDER = 'Windows Defender'47DEFENDER_BASE_KEY = 'HKLM\\SOFTWARE\\Microsoft\\Windows Defender'48ESSENTIALS = 'Microsoft Security Essentials / Antimalware'49ESSENTIALS_BASE_KEY = 'HKLM\\SOFTWARE\\Microsoft\\Microsoft Antimalware'50SEP = 'Symantec Endpoint Protection (SEP)'51SEP_BASE_KEY = 'HKLM\\SOFTWARE\\Symantec\\Symantec Endpoint Protection'5253def av_installed?(base_key, product)54if registry_key_exist?(base_key)55print_good("Found #{product}")56true57else58false59end60end6162def excluded_sep63base_exclusion_key = "#{SEP_BASE_KEY}\\Exclusions\\ScanningEngines\\Directory"64admin_exclusion_key = "#{base_exclusion_key}\\Admin"65client_exclusion_key = "#{base_exclusion_key}\\Client"6667admin_paths = []68if (admin_exclusion_keys = registry_enumkeys(admin_exclusion_key, @registry_view))69admin_exclusion_keys.map do |key|70admin_paths << registry_getvaldata("#{admin_exclusion_key}\\#{key}", 'DirectoryName', @registry_view)71end72print_exclusions_table(SEP, 'admin path', admin_paths)73end74client_paths = []75if (client_exclusion_keys = registry_enumkeys(client_exclusion_key, @registry_view))76client_exclusion_keys.map do |key|77client_paths << registry_getvaldata("#{client_exclusion_key}\\#{key}", 'DirectoryName', @registry_view)78end79end80print_exclusions_table(SEP, 'client path', client_paths)81end8283def excluded_defender84print_exclusions_table(DEFENDER, 'extension', registry_enumvals("#{DEFENDER_BASE_KEY}\\Exclusions\\Extensions", @registry_view))85print_exclusions_table(DEFENDER, 'path', registry_enumvals("#{DEFENDER_BASE_KEY}\\Exclusions\\Paths", @registry_view))86print_exclusions_table(DEFENDER, 'process', registry_enumvals("#{DEFENDER_BASE_KEY}\\Exclusions\\Processes", @registry_view))87end8889def excluded_mssec90print_exclusions_table(ESSENTIALS, 'extension', registry_enumvals("#{ESSENTIALS_BASE_KEY}\\Exclusions\\Extensions", @registry_view))91print_exclusions_table(ESSENTIALS, 'path', registry_enumvals("#{ESSENTIALS_BASE_KEY}\\Exclusions\\Paths", @registry_view))92print_exclusions_table(ESSENTIALS, 'process', registry_enumvals("#{ESSENTIALS_BASE_KEY}\\Exclusions\\Processes", @registry_view))93end9495def print_exclusions_table(product, exclusion_type, exclusions)96exclusions ||= []97exclusions = exclusions.compact.reject(&:blank?)98if exclusions.empty?99print_status("No #{exclusion_type} exclusions for #{product}")100return101end102table = Rex::Text::Table.new(103'Header' => "#{product} excluded #{exclusion_type.pluralize}",104'Indent' => 1,105'Columns' => [ exclusion_type.capitalize ]106)107exclusions.map { |exclusion| table << [exclusion] }108print_line(table.to_s)109end110111def setup112unless datastore['DEFENDER'] || datastore['ESSENTIALS'] || datastore['SEP']113fail_with(Failure::BadConfig, 'Must set one or more of DEFENDER, ESSENTIALS or SEP to true')114end115116# all of these target applications seemingly store their registry117# keys/values at the same architecture of the host, so if we happen to be118# in a 32-bit process on a 64-bit machine, ensure that we read from the119# 64-bit keys/values, and otherwise use the native keys/values120if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86121@registry_view = REGISTRY_VIEW_64_BIT122else123@registry_view = REGISTRY_VIEW_NATIVE124end125end126127def run128print_status("Enumerating Excluded Paths for AV on #{sysinfo['Computer']}")129130found = false131if datastore['DEFENDER'] && av_installed?(DEFENDER_BASE_KEY, DEFENDER)132found = true133excluded_defender134end135if datastore['ESSENTIALS'] && av_installed?(ESSENTIALS_BASE_KEY, ESSENTIALS)136found = true137excluded_mssec138end139if datastore['SEP'] && av_installed?(SEP_BASE_KEY, SEP)140found = true141excluded_sep142end143144print_error 'No supported AV identified' unless found145end146end147148149