fidius-evasiondb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +9 -0
- data/.yardopts +6 -0
- data/Gemfile +5 -0
- data/LICENSE +57 -0
- data/README.md +180 -0
- data/Rakefile +33 -0
- data/bin/fidius-evasiondb +111 -0
- data/evasion-db.gemspec +37 -0
- data/lib/db/db-install.rb +103 -0
- data/lib/db/migrations/001_create_packets.rb +18 -0
- data/lib/db/migrations/002_create_idmef_events.rb +23 -0
- data/lib/db/migrations/003_create_attack_modules.rb +14 -0
- data/lib/db/migrations/004_create_attack_options.rb +14 -0
- data/lib/db/migrations/005_create_attack_payloads.rb +13 -0
- data/lib/evasion-db/base.rb +80 -0
- data/lib/evasion-db/idmef-fetchers/fetchers.rb +67 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/fetcher.rb +8 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/additional_data.rb +16 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/address.rb +8 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/alert.rb +46 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/analyzer.rb +18 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/classification.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/connection.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/detect_time.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/impact.rb +19 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/prelude_event.rb +120 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/service.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/patches/postgres_patch.rb +12 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/prelude_event_fetcher.rb +67 -0
- data/lib/evasion-db/idmef-fetchers/test-fetcher/fetcher.rb +6 -0
- data/lib/evasion-db/idmef-fetchers/test-fetcher/lib/test_fetcher.rb +19 -0
- data/lib/evasion-db/knowledge/attack_module.rb +41 -0
- data/lib/evasion-db/knowledge/attack_option.rb +12 -0
- data/lib/evasion-db/knowledge/attack_payload.rb +13 -0
- data/lib/evasion-db/knowledge/connection.rb +7 -0
- data/lib/evasion-db/knowledge/idmef_event.rb +21 -0
- data/lib/evasion-db/knowledge/packet.rb +17 -0
- data/lib/evasion-db/knowledge.rb +128 -0
- data/lib/evasion-db/log_matches_helper.rb +43 -0
- data/lib/evasion-db/recorders/msf-recorder/lib/msf-recorder.rb +78 -0
- data/lib/evasion-db/recorders/msf-recorder/recorder.rb +6 -0
- data/lib/evasion-db/recorders/recorders.rb +61 -0
- data/lib/evasion-db/version.rb +5 -0
- data/lib/fidius-evasiondb.rb +27 -0
- data/lib/msf-plugins/database.yml.example +24 -0
- data/lib/msf-plugins/evasiondb.rb +378 -0
- data/test/config/database.yml +11 -0
- data/test/config/prelude.sql +439 -0
- data/test/helper.rb +50 -0
- data/test/preludedb_helper.rb +70 -0
- data/test/test_fetchers.rb +34 -0
- data/test/test_knowledge.rb +102 -0
- data/test/test_preludedb.rb +41 -0
- data/test/test_recorders.rb +115 -0
- metadata +238 -0
@@ -0,0 +1,378 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Msf
|
3
|
+
class Plugin::EvasionDB < Msf::Plugin
|
4
|
+
class ConsoleCommandDispatcher
|
5
|
+
include Msf::Ui::Console::CommandDispatcher
|
6
|
+
def name
|
7
|
+
"FIDIUS-EvasionDB"
|
8
|
+
end
|
9
|
+
|
10
|
+
def explain_db_connection
|
11
|
+
print_status("Usage: ")
|
12
|
+
print_status("evasion_db_connect path/to/database.yml")
|
13
|
+
print_status()
|
14
|
+
print_status("database.yml must have evasion_db entry which points to prelude db")
|
15
|
+
print_status()
|
16
|
+
print_status("example:")
|
17
|
+
print_status("evasion_db:")
|
18
|
+
print_status(" adapter: mysql")
|
19
|
+
print_status(" host: localhost")
|
20
|
+
print_status(" port: 3306")
|
21
|
+
print_status(" encoding: utf8")
|
22
|
+
print_status(" database: msf")
|
23
|
+
print_status(" username: root")
|
24
|
+
print_status(" password:")
|
25
|
+
end
|
26
|
+
|
27
|
+
def commands
|
28
|
+
{
|
29
|
+
"fetch_events" => "fetch events which were created in the meanwhile",
|
30
|
+
"show_events" => "shows all fetched idmef-events",
|
31
|
+
"show_event" => "shows information about an idmef-event",
|
32
|
+
"show_packet" => "shows information about a packet",
|
33
|
+
"send_packet" => "send a given packet to generate false positive",
|
34
|
+
"send_event_payload" => "send a given payload of an idmef-event to generate false positive",
|
35
|
+
"config_exploit" => "configures an exploit with the options of a previous runtime",
|
36
|
+
"delete_events" => "deletes events from knowledge",
|
37
|
+
"set_autologging" => "true|false automatically log all executed modules"
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_cmd(cmd)
|
42
|
+
$console.run_single(cmd)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_hex_dump(str, from=-1, to=-1)
|
46
|
+
width=16
|
47
|
+
buf = ''
|
48
|
+
idx = 0
|
49
|
+
cnt = 0
|
50
|
+
snl = false
|
51
|
+
lst = 0
|
52
|
+
rclosed = true
|
53
|
+
while (idx < str.length)
|
54
|
+
chunk = str[idx, width]
|
55
|
+
line = chunk.unpack("H*")[0].scan(/../).join(" ")
|
56
|
+
if from >= idx && from < idx+width
|
57
|
+
line[(idx-from).abs*3] = "%bld%red#{line[(idx-from).abs*3]}"
|
58
|
+
end
|
59
|
+
if to >= idx && to < idx+width
|
60
|
+
offset = 0
|
61
|
+
offset = "%bld%red".length if line["%bld%red"]
|
62
|
+
begin
|
63
|
+
line[(idx-to).abs*3+offset+1] = "#{line[(idx-to).abs*3+offset+1]}%clr"
|
64
|
+
rescue
|
65
|
+
# rescue if the index is out of range, than end mark
|
66
|
+
line[line.length-1] = "#{line[line.length-1]}%clr"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
buf << line
|
70
|
+
|
71
|
+
line_length = line.gsub("%bld%red","").gsub("%clr","").length
|
72
|
+
if (lst == 0)
|
73
|
+
lst = line_length
|
74
|
+
buf << " " * 4
|
75
|
+
else
|
76
|
+
buf << " " * ((lst - line_length) + 4).abs
|
77
|
+
end
|
78
|
+
|
79
|
+
index = 0
|
80
|
+
chunk.unpack("C*").each do |c|
|
81
|
+
if from >= idx && from < idx+width && (idx-from).abs == index || !rclosed
|
82
|
+
buf << "%bld%red"
|
83
|
+
rclosed = false
|
84
|
+
end
|
85
|
+
|
86
|
+
if (c > 0x1f and c < 0x7f)
|
87
|
+
buf << c.chr
|
88
|
+
else
|
89
|
+
buf << "."
|
90
|
+
end
|
91
|
+
if to >= idx && to < idx+width && (idx-to).abs == index
|
92
|
+
buf << "%clr"
|
93
|
+
rclosed = true
|
94
|
+
end
|
95
|
+
|
96
|
+
index = index+1
|
97
|
+
end
|
98
|
+
buf << "\n"
|
99
|
+
|
100
|
+
idx += width
|
101
|
+
end
|
102
|
+
buf << "%clr" unless rclosed
|
103
|
+
buf << "\n"
|
104
|
+
end
|
105
|
+
|
106
|
+
def send_payload_to_host(payload,host,port)
|
107
|
+
begin
|
108
|
+
c = Rex::Socket.create_tcp('PeerHost'=>host,'PeerPort' => port)
|
109
|
+
c.write(payload)
|
110
|
+
c.close
|
111
|
+
rescue
|
112
|
+
print_error "#{$!} in #{$!.backtrace}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def cmd_send_packet(*args)
|
117
|
+
raise "please provide packet id" if args.size != 1
|
118
|
+
packet = FIDIUS::EvasionDB::Knowledge.get_packet(args[0].to_i)
|
119
|
+
send_payload_to_host(packet.payload,packet.dest_addr,packet.dest_port)
|
120
|
+
end
|
121
|
+
|
122
|
+
def cmd_send_event_payload(*args)
|
123
|
+
raise "please provide packet id" if args.size != 1
|
124
|
+
event = FIDIUS::EvasionDB::Knowledge.get_event(args[0].to_i)
|
125
|
+
send_payload_to_host(event.payload,event.dest_ip,445)
|
126
|
+
end
|
127
|
+
|
128
|
+
def cmd_show_events(*args)
|
129
|
+
exploits = FIDIUS::EvasionDB::Knowledge.get_exploits
|
130
|
+
exploits.each do |exploit|
|
131
|
+
events = exploit.idmef_events
|
132
|
+
print_line "-"*60
|
133
|
+
print_line "(#{exploit.id})#{exploit.name} with #{exploit.attack_options.size} options"
|
134
|
+
print_line "-"*60
|
135
|
+
print_line "#{events.size} idmef-events fetched"
|
136
|
+
print_line "-"*60
|
137
|
+
events.each do |event|
|
138
|
+
print_line "(#{event.id})#{event.text} with #{event.payload_size} bytes payload"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def cmd_set_autologging(*args)
|
144
|
+
raise "please use set_autologging true|false" if args.size != 1
|
145
|
+
$auto_logging = args[0] == true
|
146
|
+
end
|
147
|
+
|
148
|
+
def cmd_delete_events(*args)
|
149
|
+
raise "please provide id" if args.size != 1
|
150
|
+
exploit = FIDIUS::EvasionDB::Knowledge.get_exploit(args[0].to_i)
|
151
|
+
exploit.destroy
|
152
|
+
end
|
153
|
+
|
154
|
+
def cmd_config_exploit(*args)
|
155
|
+
raise "please provide id" if args.size != 1
|
156
|
+
exploit = FIDIUS::EvasionDB::Knowledge.get_exploit(args[0].to_i)
|
157
|
+
run_cmd("use #{exploit.name}")
|
158
|
+
exploit.attack_options.each do |option|
|
159
|
+
run_cmd("set #{option.option_key} #{option.option_value}")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def cmd_show_packet(*args)
|
164
|
+
raise "please provide packet_id" if args.size != 1
|
165
|
+
packet = FIDIUS::EvasionDB::Knowledge::Packet.find(args[0].to_i)
|
166
|
+
|
167
|
+
hex = to_hex_dump(packet.payload)
|
168
|
+
print_line hex
|
169
|
+
end
|
170
|
+
|
171
|
+
def cmd_show_event(*args)
|
172
|
+
raise "please provide event_id" if args.size != 1
|
173
|
+
event_id = args[0].to_i
|
174
|
+
print_line "event_id:#{event_id}"
|
175
|
+
event = FIDIUS::EvasionDB::Knowledge.get_event(event_id)
|
176
|
+
packet = FIDIUS::EvasionDB::Knowledge.get_packet_for_event(event_id)
|
177
|
+
print_line "(#{event.id}) Event(#{event.text}) : #{event.payload_size} bytes payload"
|
178
|
+
if packet
|
179
|
+
print_line "#{packet.inspect}"
|
180
|
+
print_line "#{packet[:packet].inspect}"
|
181
|
+
print_line "PACKET(#{packet[:packet].id}): "
|
182
|
+
print_line "#{packet[:packet].payload.size} bytes"
|
183
|
+
print_line "match #{packet[:index]} - #{packet[:index]+packet[:length]-1}"
|
184
|
+
hex = to_hex_dump(packet[:packet].payload,packet[:index],packet[:index]+packet[:length]-1)
|
185
|
+
print_line hex
|
186
|
+
else
|
187
|
+
print_line "no packets available"
|
188
|
+
end
|
189
|
+
print_line "EVENT PAYLOAD(#{event.payload.size}) bytes:"
|
190
|
+
hex = to_hex_dump(event.payload)
|
191
|
+
print_line hex
|
192
|
+
end
|
193
|
+
|
194
|
+
def cmd_fetch_events(*args)
|
195
|
+
#events = FIDIUS::EvasionDB::Knowledge.fetch_events
|
196
|
+
FIDIUS::EvasionDB.current_fetcher.local_ip = nil
|
197
|
+
events = FIDIUS::EvasionDB.current_fetcher.fetch_events
|
198
|
+
if events
|
199
|
+
print_status "#{events.size} events generated"
|
200
|
+
print_status
|
201
|
+
events.each do |e|
|
202
|
+
print_line "(#{e.id}) Event(#{e.text}) : #{e.payload_size} bytes payload (#{e.src_ip} -> #{e.dest_ip})"
|
203
|
+
print_status "#{e}"
|
204
|
+
end
|
205
|
+
else
|
206
|
+
print_status "0 events generated"
|
207
|
+
end
|
208
|
+
FIDIUS::EvasionDB.current_fetcher.begin_record
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def initialize(framework, opts)
|
213
|
+
super
|
214
|
+
require 'fidius-evasiondb'
|
215
|
+
msf_home = File.expand_path("../..",__FILE__)
|
216
|
+
dbconfig_path = File.join(msf_home,"data","database.yml")
|
217
|
+
raise "no database.yml in #{dbconfig_path}" if !File.exists?(dbconfig_path)
|
218
|
+
|
219
|
+
$console = opts['ConsoleDriver']
|
220
|
+
$auto_logging = true
|
221
|
+
FIDIUS::EvasionDB.config(dbconfig_path)
|
222
|
+
FIDIUS::EvasionDB.use_recoder "Msf-Recorder"
|
223
|
+
FIDIUS::EvasionDB.use_fetcher "PreludeDB"
|
224
|
+
|
225
|
+
add_console_dispatcher(ConsoleCommandDispatcher)
|
226
|
+
framework.events.add_general_subscriber(FIDIUS::ModuleRunCallback.new)
|
227
|
+
|
228
|
+
FIDIUS::PacketLogger.init_with_framework(framework)
|
229
|
+
FIDIUS::PacketLogger.on_log do |caused_by, data, socket|
|
230
|
+
FIDIUS::EvasionDB.current_recorder.log_packet(caused_by,data,socket)
|
231
|
+
end
|
232
|
+
FIDIUS::EvasionDB.current_fetcher.begin_record
|
233
|
+
print_status("EvasionDB plugin loaded.")
|
234
|
+
end
|
235
|
+
|
236
|
+
def cleanup
|
237
|
+
remove_console_dispatcher(ConsoleCommandDispatcher)
|
238
|
+
end
|
239
|
+
|
240
|
+
def name
|
241
|
+
"FIDIUS-EvasionDB"
|
242
|
+
end
|
243
|
+
|
244
|
+
def desc
|
245
|
+
""
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
module FIDIUS
|
252
|
+
class PacketLogger
|
253
|
+
def self.on_log(&block)
|
254
|
+
$block = block
|
255
|
+
end
|
256
|
+
|
257
|
+
def self.log_packet(socket,data,module_instance=nil)
|
258
|
+
begin
|
259
|
+
$block.call module_instance, data, socket
|
260
|
+
rescue
|
261
|
+
#PUT HERE IS RESPONSIBLE FOR NO SESSION ? $stdout.puts "ERROR #{$!}:#{$!.backtract}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def self.inspect_socket(socket)
|
266
|
+
"#{socket.localhost}:#{socket.localport} -> #{socket.peerhost}:#{socket.peerport}"
|
267
|
+
end
|
268
|
+
|
269
|
+
class MySocketEventHandler
|
270
|
+
include Rex::Socket::Comm::Events
|
271
|
+
|
272
|
+
def initialize
|
273
|
+
|
274
|
+
end
|
275
|
+
|
276
|
+
def on_before_socket_create(comm, param)
|
277
|
+
end
|
278
|
+
|
279
|
+
def on_socket_created(comm, sock, param)
|
280
|
+
sock.extend(FIDIUS::SocketTracer)
|
281
|
+
sock.context = param.context
|
282
|
+
sock.params = param
|
283
|
+
sock.initlog
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def self.init_with_framework(framework)
|
288
|
+
$eh = MySocketEventHandler.new
|
289
|
+
Rex::Socket::Comm::Local.register_event_handler($eh)
|
290
|
+
end
|
291
|
+
|
292
|
+
def self.cleanup
|
293
|
+
Rex::Socket::Comm::Local.deregister_event_handler($eh)
|
294
|
+
end
|
295
|
+
end #PacketLogger
|
296
|
+
|
297
|
+
class ModuleRunCallback
|
298
|
+
def on_module_run(instance)
|
299
|
+
FIDIUS::EvasionDB.current_recorder.module_started(instance) if $auto_logging
|
300
|
+
end
|
301
|
+
#
|
302
|
+
# Called when a module finishes
|
303
|
+
#
|
304
|
+
def on_module_complete(instance)
|
305
|
+
FIDIUS::EvasionDB.current_recorder.module_completed(instance) if $auto_logging
|
306
|
+
end
|
307
|
+
|
308
|
+
#
|
309
|
+
# Called when a module raises an exception
|
310
|
+
#
|
311
|
+
def on_module_error(instance, exception)
|
312
|
+
FIDIUS::EvasionDB.current_recorder.module_error(instance,exception) if $auto_logging
|
313
|
+
end
|
314
|
+
end #class ModuleRunCallback
|
315
|
+
|
316
|
+
end #FIDIUS
|
317
|
+
|
318
|
+
# This extends the PacketDispatcher from Rex
|
319
|
+
# with Logging
|
320
|
+
# Original Source is: lib/rex/post/meterpreter/packet_dispatcher.rb
|
321
|
+
module Rex::Post::Meterpreter::PacketDispatcher
|
322
|
+
def send_packet(packet, completion_routine = nil, completion_param = nil)
|
323
|
+
FIDIUS::PacketLogger.log_packet(self.sock,packet.to_r,"Meterpreter")
|
324
|
+
if (completion_routine)
|
325
|
+
add_response_waiter(packet, completion_routine, completion_param)
|
326
|
+
end
|
327
|
+
|
328
|
+
bytes = 0
|
329
|
+
raw = packet.to_r
|
330
|
+
|
331
|
+
if (raw)
|
332
|
+
begin
|
333
|
+
bytes = self.sock.write(raw)
|
334
|
+
rescue ::Exception => e
|
335
|
+
# Mark the session itself as dead
|
336
|
+
self.alive = false
|
337
|
+
|
338
|
+
# Indicate that the dispatcher should shut down too
|
339
|
+
@finish = true
|
340
|
+
|
341
|
+
# Reraise the error to the top-level caller
|
342
|
+
raise e
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
return bytes
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
# This module extends the captured socket instance
|
351
|
+
# Copied from plugins/socket_logger.rb
|
352
|
+
module FIDIUS
|
353
|
+
module SocketTracer
|
354
|
+
@@last_id = 0
|
355
|
+
|
356
|
+
attr_accessor :context, :params
|
357
|
+
|
358
|
+
# Hook the write method
|
359
|
+
def write(buf, opts = {})
|
360
|
+
module_instance = context['MsfExploit'] if context['MsfExploit']
|
361
|
+
FIDIUS::PacketLogger.log_packet(self,buf,module_instance)
|
362
|
+
super(buf, opts)
|
363
|
+
end
|
364
|
+
|
365
|
+
# Hook the read method
|
366
|
+
def read(length = nil, opts = {})
|
367
|
+
r = super(length, opts)
|
368
|
+
return r
|
369
|
+
end
|
370
|
+
|
371
|
+
def close(*args)
|
372
|
+
super(*args)
|
373
|
+
end
|
374
|
+
|
375
|
+
def initlog
|
376
|
+
end
|
377
|
+
end #SocketTracer
|
378
|
+
end #FIDIUS
|