Revamp the event system and add some ui hooks. Sessions are still ghetto -- we get interact events (in a lame way) but no input or output events yet. see 619
git-svn-id: file:///home/svn/framework3/trunk@7947 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
0f798f4674
commit
4f92d9f431
|
@ -83,4 +83,4 @@ class CommandShell
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -196,6 +196,7 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
||||||
# Interacts with the meterpreter client at a user interface level.
|
# Interacts with the meterpreter client at a user interface level.
|
||||||
#
|
#
|
||||||
def _interact
|
def _interact
|
||||||
|
framework.events.on_session_interact(self)
|
||||||
# Call the console interaction subsystem of the meterpreter client and
|
# Call the console interaction subsystem of the meterpreter client and
|
||||||
# pass it a block that returns whether or not we should still be
|
# pass it a block that returns whether or not we should still be
|
||||||
# interacting. This will allow the shell to abort if interaction is
|
# interacting. This will allow the shell to abort if interaction is
|
||||||
|
|
|
@ -117,6 +117,7 @@ module Exploit
|
||||||
driver.use_job = true
|
driver.use_job = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
exploit.framework.events.on_module_run(exploit)
|
||||||
# Let's rock this party
|
# Let's rock this party
|
||||||
session = driver.run
|
session = driver.run
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,13 @@ module GeneralEventSubscriber
|
||||||
#
|
#
|
||||||
def on_module_created(instance)
|
def on_module_created(instance)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Called when a module is run
|
||||||
|
#
|
||||||
|
def on_module_run(instance)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@ -42,6 +49,7 @@ class EventDispatcher
|
||||||
self.exploit_event_subscribers = []
|
self.exploit_event_subscribers = []
|
||||||
self.session_event_subscribers = []
|
self.session_event_subscribers = []
|
||||||
self.db_event_subscribers = []
|
self.db_event_subscribers = []
|
||||||
|
self.ui_event_subscribers = []
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -87,7 +95,7 @@ class EventDispatcher
|
||||||
# This method adds an exploit event subscriber. Exploit event subscribers
|
# This method adds an exploit event subscriber. Exploit event subscribers
|
||||||
# receive notifications when events occur that pertain to exploits, such as
|
# receive notifications when events occur that pertain to exploits, such as
|
||||||
# the success or failure of an exploitation attempt. The subscriber
|
# the success or failure of an exploitation attempt. The subscriber
|
||||||
# provided must implement the ExploitEvents module methods in some form.
|
# provided must implement the ExploitEvent module methods in some form.
|
||||||
#
|
#
|
||||||
def add_exploit_subscriber(subscriber)
|
def add_exploit_subscriber(subscriber)
|
||||||
add_event_subscriber(exploit_event_subscribers, subscriber)
|
add_event_subscriber(exploit_event_subscribers, subscriber)
|
||||||
|
@ -103,7 +111,7 @@ class EventDispatcher
|
||||||
#
|
#
|
||||||
# This method adds a session event subscriber. Session event subscribers
|
# This method adds a session event subscriber. Session event subscribers
|
||||||
# receive notifications when sessions are opened and closed. The
|
# receive notifications when sessions are opened and closed. The
|
||||||
# subscriber provided must implement the SessionEvents module methods in
|
# subscriber provided must implement the SessionEvent module methods in
|
||||||
# some form.
|
# some form.
|
||||||
#
|
#
|
||||||
def add_session_subscriber(subscriber)
|
def add_session_subscriber(subscriber)
|
||||||
|
@ -127,59 +135,65 @@ class EventDispatcher
|
||||||
# Called when a module is loaded into the framework. This, in turn,
|
# Called when a module is loaded into the framework. This, in turn,
|
||||||
# notifies all registered general event subscribers.
|
# notifies all registered general event subscribers.
|
||||||
#
|
#
|
||||||
|
# This is covered by the method_missing logic, but defining it manually
|
||||||
|
# reduces startup time by about 10%.
|
||||||
|
#
|
||||||
def on_module_load(name, mod)
|
def on_module_load(name, mod)
|
||||||
general_event_subscribers.each { |subscriber|
|
general_event_subscribers.each { |subscriber|
|
||||||
subscriber.on_module_load(name, mod)
|
subscriber.on_module_load(name, mod)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
|
||||||
# Called when a module is unloaded from the framework. This, in turn,
|
|
||||||
# notifies all registered general event subscribers.
|
|
||||||
#
|
|
||||||
def on_module_created(instance)
|
|
||||||
general_event_subscribers.each { |subscriber|
|
|
||||||
subscriber.on_module_created(instance)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Capture incoming events and pass them off to the subscribers
|
# Capture incoming events and pass them off to the subscribers
|
||||||
#
|
#
|
||||||
|
# When receiving an on_* event, look for a subscriber type matching the
|
||||||
|
# type of the event. If one exists, send the event on to each subscriber
|
||||||
|
# of that type. Otherwise, try to send the event each of the general
|
||||||
|
# subscribers.
|
||||||
|
#
|
||||||
|
# Event method names should be like "on_<type>_<event>", e.g.:
|
||||||
|
# on_exploit_success.
|
||||||
|
#
|
||||||
def method_missing(name, *args)
|
def method_missing(name, *args)
|
||||||
|
|
||||||
case name.to_s
|
event,type,rest = name.to_s.split("_", 3)
|
||||||
|
subscribers = "#{type}_event_subscribers"
|
||||||
# Exploit events
|
found = false
|
||||||
when /^on_exploit/
|
case event
|
||||||
exploit_event_subscribers.each do |subscriber|
|
when "on"
|
||||||
next if not subscriber.respond_to?(name)
|
#$stdout.puts("Got event: #{name}, looking for #{type}_event_subscribers")
|
||||||
subscriber.send(name, *args)
|
if respond_to?(subscribers)
|
||||||
end
|
found = true
|
||||||
|
self.send(subscribers).each do |sub|
|
||||||
# Session events
|
next if not sub.respond_to?(name)
|
||||||
when /^on_session/
|
#$stdout.puts("Found subscriber: #{sub}")
|
||||||
session_event_subscribers.each do |subscriber|
|
sub.send(name, *args)
|
||||||
next if not subscriber.respond_to?(name)
|
end
|
||||||
subscriber.send(name, *args)
|
else
|
||||||
end
|
general_event_subscribers.each do |sub|
|
||||||
|
next if not sub.respond_to?(name)
|
||||||
# db events
|
#$stdout.puts("Found general subscriber: #{sub}")
|
||||||
when /^on_db/
|
sub.send(name, *args)
|
||||||
# Only process these events if the db is active
|
found = true
|
||||||
if (framework.db.active)
|
|
||||||
db_event_subscribers.each do |subscriber|
|
|
||||||
next if not subscriber.respond_to?(name)
|
|
||||||
subscriber.send(name, *args)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# Everything else
|
when "add"
|
||||||
else
|
if respond_to?(subscribers)
|
||||||
|
found = true
|
||||||
|
add_event_subscriber(self.send(subscribers), *args)
|
||||||
|
end
|
||||||
|
when "remove"
|
||||||
|
if respond_to?(subscribers)
|
||||||
|
found = true
|
||||||
|
remove_event_subscriber(self.send(subscribers), *args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not found
|
||||||
|
#$stdout.puts("Event dispatcher received an unhandled event: #{name} #{args}")
|
||||||
elog("Event dispatcher received an unhandled event: #{name}")
|
elog("Event dispatcher received an unhandled event: #{name}")
|
||||||
return false
|
end
|
||||||
end
|
return found
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -203,6 +217,7 @@ protected
|
||||||
attr_accessor :exploit_event_subscribers # :nodoc:
|
attr_accessor :exploit_event_subscribers # :nodoc:
|
||||||
attr_accessor :session_event_subscribers # :nodoc:
|
attr_accessor :session_event_subscribers # :nodoc:
|
||||||
attr_accessor :db_event_subscribers # :nodoc:
|
attr_accessor :db_event_subscribers # :nodoc:
|
||||||
|
attr_accessor :ui_event_subscribers # :nodoc:
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,19 @@ module SessionEvent
|
||||||
#
|
#
|
||||||
def on_session_close(session)
|
def on_session_close(session)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Called when the user interacts with a session.
|
||||||
|
#
|
||||||
|
def on_session_interact(session)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Called when the user writes data to a session.
|
||||||
|
#
|
||||||
|
def on_session_command(session, command)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@ -212,4 +224,4 @@ protected
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,10 +33,11 @@ protected
|
||||||
# overriden by derived classes if they wish to do this another way.
|
# overriden by derived classes if they wish to do this another way.
|
||||||
#
|
#
|
||||||
def _interact
|
def _interact
|
||||||
|
framework.events.on_session_interact(self)
|
||||||
interact_stream(rstream)
|
interact_stream(rstream)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -89,6 +89,7 @@ protected
|
||||||
# Stub method that is meant to handler interaction.
|
# Stub method that is meant to handler interaction.
|
||||||
#
|
#
|
||||||
def _interact
|
def _interact
|
||||||
|
framework.events.on_session_interact(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -119,6 +120,7 @@ protected
|
||||||
# If the session reaches EOF, deregister it.
|
# If the session reaches EOF, deregister it.
|
||||||
#
|
#
|
||||||
def _interact_complete
|
def _interact_complete
|
||||||
|
framework.events.on_session_interact_completed()
|
||||||
framework.sessions.deregister(self)
|
framework.sessions.deregister(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -132,4 +134,4 @@ protected
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,19 @@ module Msf
|
||||||
module Ui
|
module Ui
|
||||||
module Console
|
module Console
|
||||||
|
|
||||||
|
class UiEventSubscriber
|
||||||
|
def on_ui_command(line)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_ui_command_completed(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_ui_stop()
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_ui_start()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
###
|
###
|
||||||
#
|
#
|
||||||
|
@ -250,6 +263,7 @@ class Driver < Msf::Ui::Driver
|
||||||
end
|
end
|
||||||
print("\n")
|
print("\n")
|
||||||
end
|
end
|
||||||
|
framework.events.on_ui_start(Msf::Framework::Revision)
|
||||||
|
|
||||||
# Build the banner message
|
# Build the banner message
|
||||||
run_single("banner")
|
run_single("banner")
|
||||||
|
@ -324,6 +338,22 @@ class Driver < Msf::Ui::Driver
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Overload the parent's run_single so we can fire events before and after
|
||||||
|
# running the command.
|
||||||
|
#
|
||||||
|
def run_single(line, user_initiated = false)
|
||||||
|
framework.events.on_ui_command(line)
|
||||||
|
ret = super(line)
|
||||||
|
framework.events.on_ui_command_completed(ret)
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
framework.events.on_ui_stop()
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
attr_writer :framework # :nodoc:
|
attr_writer :framework # :nodoc:
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
|
||||||
|
class Plugin::EventTester < Msf::Plugin
|
||||||
|
class Subscriber
|
||||||
|
def respond_to?(name)
|
||||||
|
# Why yes, I can do that.
|
||||||
|
true
|
||||||
|
end
|
||||||
|
def method_missing(name, *args)
|
||||||
|
$stdout.puts("Subscriber called #{name}(#{args})")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def name; "event_tester"; end
|
||||||
|
|
||||||
|
def initialize(framework, opts)
|
||||||
|
super
|
||||||
|
@subscriber = Subscriber.new
|
||||||
|
framework.events.add_exploit_subscriber(@subscriber)
|
||||||
|
framework.events.add_session_subscriber(@subscriber)
|
||||||
|
framework.events.add_general_subscriber(@subscriber)
|
||||||
|
framework.events.add_db_subscriber(@subscriber)
|
||||||
|
framework.events.add_ui_subscriber(@subscriber)
|
||||||
|
end
|
||||||
|
def cleanup
|
||||||
|
framework.events.remove_exploit_subscriber(@subscriber)
|
||||||
|
framework.events.remove_session_subscriber(@subscriber)
|
||||||
|
framework.events.remove_general_subscriber(@subscriber)
|
||||||
|
framework.events.remove_db_subscriber(@subscriber)
|
||||||
|
framework.events.remove_ui_subscriber(@subscriber)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue