diff --git a/scripts/meterpreter/event_manager.rb b/scripts/meterpreter/event_manager.rb index 53cbfed957..2fe2bb8d88 100644 --- a/scripts/meterpreter/event_manager.rb +++ b/scripts/meterpreter/event_manager.rb @@ -4,20 +4,24 @@ #------------------------------------------------------------------------------- ################## Variable Declarations ################## @client = client -clear_evt = false -event_name = nil -log_path = nil -supress_print = nil +eventlog_name = nil +print_logs = false +list_logs = false +clear_logs = false +local_log = false +local_log_path = nil +supress_print = false filter = '\d*' +filter_string = "*" meter_type = client.platform opts = Rex::Parser::Arguments.new( - "-h" => [ false, "Help menu." ], - "-i" => [ false, "List Present Event Logs on the System and thrie configuration"], - "-e" => [ true, "Event Log to Open."], - "-f" => [ true, "Event ID to filter events on."], - "-l" => [ true, "Log to CSV file, path for folder to save log can be provided."], - "-c" => [ false, "Clear a given Event Log or all if none specified."], - "-s" => [ false, "Suppress printing filtered logs to screen."] + "-h" => [ false, "Help menu" ], + "-i" => [ false, "Show information about Event Logs on the System and their configuration"], + "-l" => [ true, "List a given Event Log (or ALL if no argument specified)"], + "-c" => [ true, "Clear a given Event Log (or ALL if no argument specified)"], + "-f" => [ true, "Event ID to filter events on"], + "-s" => [ true, "Save logs to local CSV file, optionally specify alternate folder in which to save logs"], + "-p" => [ false, "Supress printing filtered logs to screen"] ) @@ -25,7 +29,7 @@ opts = Rex::Parser::Arguments.new( # Usage Message Function #------------------------------------------------------------------------------- -def usage +def usage(opts) print_line "Meterpreter Script for Windows Event Log Query and Clear." print_line(opts.usage) raise Rex::Script::Completed @@ -34,17 +38,54 @@ end # Wrong Meterpreter Version Message Function #------------------------------------------------------------------------------- def wrong_meter_version(meter = meter_type) - print_error("#{meter} version of Meterpreter is not supported with this Script!") + print_error("#{meter} version of Meterpreter is not supported with this script!") raise Rex::Script::Completed end # Function for Enumerating EventLogs #------------------------------------------------------------------------------- -def info_evt() +def get_log_details + logs_detail = Array.new + + eventlog_list.each do |log_name| + + # Create a hash to store the log info in (and throw default info in) + log_detail = Hash.new + log_detail[:name] = log_name + log_detail[:retention] = "Disabled" + log_detail[:size] = 0 + log_detail[:number_of_records] = 0 + + key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\" + if @client.sys.config.sysinfo['OS'] =~ /Windows 2003|.Net|XP|2000/ + key = "#{key}Eventlog" + else + key = "#{key}eventlog" + end + + begin + unless (registry_getvaldata("#{key}\\#{log_name}","Retention") == 0) then log_detail[:retention] = "Disabled" end + log_detail[:size] = registry_getvaldata("#{key}\\#{log_name}","MaxSize") + + # Open the event log + eventlog = @client.sys.eventlog.open(log_name) + log_detail[:num_of_records] = eventlog.length + rescue + log_detail[:num_of_records] = "Access Denied" + end + + + logs_detail << log_detail + end + + return logs_detail +end + + +# Function for Printing Event Log Details +#------------------------------------------------------------------------------- +def print_log_details print_status("Retriving Event Log Configuration") - ret = "Enabled" - size = 0 - record_num = 0 tbl = Rex::Ui::Text::Table.new( 'Header' => "Event Logs on System", 'Indent' => 1, @@ -52,39 +93,27 @@ def info_evt() [ "Name", "Retention", - "Maximun Size", + "Maximum Size", "Records" ]) + + eventlog_details = get_log_details - eventlog_list.each do |en| - key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\" - if @client.sys.config.sysinfo['OS'] =~ /Windows 2003|.Net|XP|2000/ - key = "#{key}Eventlog" - else - key = "#{key}eventlog" - end - begin - if registry_getvaldata("#{key}\\#{en}","Retention") == 0 - ret = "Disable" - end - size = registry_getvaldata("#{key}\\#{en}","MaxSize") - log = client.sys.eventlog.open(en) - record_num = log.length - rescue - record_num = "Access Denied" - end - tbl << [en,ret,"#{size}K",record_num] + eventlog_details.each do |log_detail| + tbl << [log_detail[:name],log_detail[:retention],"#{log_detail[:size]}K",log_detail[:num_of_records]] end + print_line("\n" + tbl.to_s + "\n") end + # Function for doings queries of EventLogs #------------------------------------------------------------------------------- -def list_logs(event_name,filter,logs,sup_print) +def list_logs(eventlog_name,filter,filter_string,logs,local_log,sup_print) begin event_data = "" csv_data = "EventID,Date,Data\n" - log = client.sys.eventlog.open(event_name) + log = @client.sys.eventlog.open(eventlog_name) log.each_backwards do |e| if e.eventid.to_s =~ /#{filter}/ if not sup_print @@ -99,104 +128,124 @@ def list_logs(event_name,filter,logs,sup_print) end print_status end - csv_data << "#{e.eventid},#{e.generated},\"#{event_data}\"\n" - event_data = "" + csv_data << "#{e.eventid},#{e.generated},\"#{event_data}\"\n" + event_data = "" end end rescue - print_error("Failed to Open Event Log #{event_name}") + print_error("Failed to Open Event Log #{eventlog_name}") raise Rex::Script::Completed end - log_file = File.join(logs, "#{event_name}.csv") - print_good("CSV File saved to #{log_file}") - file_local_write(log_file,csv_data) + + if local_log + log_file = File.join(logs, "#{eventlog_name}.csv") + print_good("CSV File saved to #{log_file}") + file_local_write(log_file,csv_data) + end end # Function for clearing EventLogs #------------------------------------------------------------------------------- -def evt_clear(evt) - evntlog = [] - if evt.nil? - evntlog = eventloglist +def clear_logs(log_name=nil) + log_names = [] + if log_name.nil? + log_names = eventlog_list else - evntlog << evt + log_names << log_name end - evntlog.each do |e| + + log_names.each do |name| begin - print_status("Clearing #{e}") - log = client.sys.eventlog.open(e) - log.clear - print_status("Event Log #{e} Cleared!") + print_status("Clearing #{name}") + event_log = @client.sys.eventlog.open(name) + event_log.clear + print_status("Event Log #{name} Cleared!") rescue - print_error("Failed to Clear #{e}, Access Denied") + print_error("Failed to Clear #{name}, Access Denied") end end - return evntlog + + return log_names end ################## Main ################## opts.parse(args) { |opt, idx, val| case opt - when "-h" - usage - when "-i" - info_evt - raise Rex::Script::Completed - when "-f" - filter = val - when "-e" - eventlog_list.each do |en| - if en.downcase == val.downcase - event_name = en + when "-h" + usage(opts) + when "-i" + print_logs = true + print_log_details + raise Rex::Script::Completed + when "-c" + clear_logs = true + eventlog_name = val + when "-l" + list_logs = true + eventlog_name = val + when "-f" + filter = val + when "-s" + local_log = true + if File.directory?(val) + local_log_path = val + else + print_error("Log folder #{val} does not exist!") + raise Rex::Script::Completed end - end - if not event_name - print_error("Eventlog Name Not Found!") - raise Rex::Script::Completed - end - when "-l" - if File.directory?(val) - log_path = val - else - print_error("Log folder #{val} does not exist!") - raise Rex::Script::Completed - end - when "-c" - clear_evt = true - when "-s" - supress_print = true + when "-p" + supress_print = true end } # Check for Version of Meterpreter wrong_meter_version(meter_type) if meter_type !~ /win32|win64/i -if event_name +# Print usage & exit if the user didn't specify an action +# to default to just running for all logs) +if !list_logs and !clear_logs and !print_logs + usage(opts) +end - # Log Folder Creation - #----------------------------------------------------------------------- - #Get Hostname - host = @client.sys.config.sysinfo["Computer"] +# Log Folder Creation +#----------------------------------------------------------------------- +#Get Hostname +host = @client.sys.config.sysinfo["Computer"] - # Create Filename info to be appended to downloaded files - filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") +# Create Filename info to be appended to downloaded files +filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S") - # Create a directory for the logs - if log_path - logs = ::File.join(log_path, host + filenameinfo ) +# Create a directory for any local logging if the user desires +if local_log + if local_log_path + logs = ::File.join(local_log_path, host + filenameinfo ) else logs = ::File.join(Msf::Config.log_directory, "scripts", 'event_manager', host + filenameinfo ) end - - # Create the log directory + ::FileUtils.mkdir_p(logs) - #----------------------------------------------------------------------- +end - if not clear_evt - list_logs(event_name,filter,logs,supress_print) +# List the logs if the user desires +if list_logs + if eventlog_name + list_logs(eventlog_name,filter,filter_string,logs,local_log,supress_print) else - evt_clear(event_name) + eventlog_list.each { |eventlog_name| + print_status eventlog_name + ": " + list_logs(eventlog_name,filter,filter_string,logs,local_log,supress_print) + } end -else - usage +end + +# Finally, clear the specified logs if the user desires +if clear_logs + if eventlog_name + clear_logs(eventlog_name) + else + eventlog_list.each { |eventlog_name| + print_status eventlog_name + ": " + clear_logs(eventlog_name) + } + end end \ No newline at end of file