TODO 笔记:msf rpc console 不能同时对一个session进行操作
lib/msf/ui/web/driver.rb
# -*- coding: binary -*-
require 'rex/proto/http'
require 'msf/core'
require 'msf/base'
require 'msf/ui'
module Msf
module Ui
module Web
require 'rex/ui/text/bidirectional_pipe'
require 'msf/ui/web/console'
###
#
# This class implements a user interface driver on a web interface.
#
###
class Driver < Msf::Ui::Driver
attr_accessor :framework # :nodoc:
attr_accessor :consoles # :nodoc:
attr_accessor :sessions # :nodoc:
attr_accessor :last_console # :nodoc:
ConfigCore = "framework/core"
ConfigGroup = "framework/ui/web"
#
# Initializes a web driver instance and prepares it for listening to HTTP
# requests. The constructor takes a hash of options that can control how
# the web server will operate.
#
def initialize(opts = {})
# Call the parent
super()
# Set the passed options hash for referencing later on.
self.opts = opts
self.consoles = {}
self.sessions = {}
if(opts[:framework])
self.framework = opts[:framework]
else
# Initialize configuration
Msf::Config.init
# Initialize logging
initialize_logging
# Initialize attributes
self.framework = Msf::Simple::Framework.create
end
# Initialize the console count
self.last_console = 0
end
def create_console(opts={})
# Destroy any unused consoles
clean_consoles
console = WebConsole.new(self.framework, self.last_console, opts)
self.last_console += 1
self.consoles[console.console_id.to_s] = console
console.console_id.to_s
end
def destroy_console(cid)
con = self.consoles[cid]
if(con)
con.shutdown
self.consoles.delete(cid)
end
end
def write_console(id, buf)
self.consoles[id] ? self.consoles[id].write(buf) : nil
end
def read_console(id)
self.consoles[id] ? self.consoles[id].read() : nil
end
def clean_consoles(timeout=300)
self.consoles.each_pair do |id, con|
if (con.last_access + timeout < Time.now)
con.shutdown
self.consoles.delete(id)
end
end
end
def write_session(id, buf)
ses = self.framework.sessions[id]
return if not ses
return if not ses.user_input
ses.user_input.put(buf)
end
def read_session(id)
ses = self.framework.sessions[id]
return if not ses
return if not ses.user_output
ses.user_output.read_subscriber('session_reader')
end
# Detach the session from an existing input/output pair
def connect_session(id)
# Ignore invalid sessions
ses = self.framework.sessions[id]
return if not ses
# Has this session already been detached?
if (ses.user_output)
return if ses.user_output.has_subscriber?('session_reader')
end
# Create a new pipe
spipe = WebConsole::WebConsolePipe.new
spipe.input = spipe.pipe_input
# Create a read subscriber
spipe.create_subscriber('session_reader')
framework.threads.spawn("ConnectSessionInteraction", false) do
ses.interact(spipe.input, spipe)
end
end
def sessions
self.framework.sessions
end
#
# Stub
#
def run
true
end
protected
attr_accessor :opts # :nodoc:
#
# Initializes logging for the web interface
#
def initialize_logging
level = (opts['LogLevel'] || 0).to_i
Msf::Logging.enable_log_source(LogSource, level)
end
end
# Add DriverFactory, makes it possible to get the same Driver instance
class DriverFactory
include Singleton
def initialize()
@drivers = Hash.new
@mutex = Mutex.new
end
def get_or_create(opts={}, name='default')
if not @drivers.key?(name)
@mutex.synchronize {
if not @drivers.key?(name)
@drivers[name] = Driver.new(opts)
return @drivers[name]
end
}
end
return @drivers[name]
end
end
end
end
end
感觉可能是需要对 connect_session 改动一下
后面有时间验证一下