some more madness

git-svn-id: file:///home/svn/incoming/trunk@2765 4d416f70-5f16-0410-b530-b9f4589650da
unstable
Matt Miller 2005-07-16 08:12:58 +00:00
parent a820ba273c
commit 24c4a2513a
12 changed files with 243 additions and 50 deletions

View File

@ -25,6 +25,14 @@ class CommandShell
# #
include Msf::Session::Provider::SingleCommandShell include Msf::Session::Provider::SingleCommandShell
def desc
"Command Shell"
end
def type
"shell"
end
# #
# The shell will have been initialized by default # The shell will have been initialized by default
# #

View File

@ -30,10 +30,12 @@ class Framework
end end
require 'msf/core/module_manager' require 'msf/core/module_manager'
require 'msf/core/session_manager'
def initialize() def initialize()
self.events = EventDispatcher.new self.events = EventDispatcher.new
self.modules = ModuleManager.new(self) self.modules = ModuleManager.new(self)
self.sessions = SessionManager.new(self)
self.datastore = DataStore.new self.datastore = DataStore.new
end end
@ -74,12 +76,14 @@ class Framework
attr_reader :events attr_reader :events
attr_reader :modules attr_reader :modules
attr_reader :sessions
attr_reader :datastore attr_reader :datastore
protected protected
attr_writer :events attr_writer :events
attr_writer :modules attr_writer :modules
attr_writer :sessions
attr_writer :datastore attr_writer :datastore
end end

View File

@ -102,6 +102,9 @@ module Handler
if (self.session) if (self.session)
s = self.session.new(conn) s = self.session.new(conn)
# Pass along the framework context
s.framework = framework
# If the session is valid, register it with the framework and # If the session is valid, register it with the framework and
# notify any waiters we may have. # notify any waiters we may have.
if (s) if (s)
@ -140,9 +143,11 @@ protected
# new session. # new session.
# #
def register_session(session) def register_session(session)
session_waiter_event.notify(session) # Register the session with the framework
framework.sessions.register(session)
# TODO: register with the framework # Notify waiters that they should be ready to rock
session_waiter_event.notify(session)
end end
attr_accessor :session_waiter_event attr_accessor :session_waiter_event

View File

@ -80,7 +80,11 @@ module ReverseTcp
# as the input and output pipe. Client's are expected # as the input and output pipe. Client's are expected
# to implement the Stream interface. # to implement the Stream interface.
conn_threads << Thread.new { conn_threads << Thread.new {
handle_connection(client) begin
handle_connection(client)
rescue
elog("Exception raised from handle_connection: #{$!}")
end
} }
} }
end end

View File

@ -52,14 +52,58 @@ module Session
require 'msf/core/session/provider/multi_command_execution' require 'msf/core/session/provider/multi_command_execution'
require 'msf/core/session/provider/single_command_shell' require 'msf/core/session/provider/single_command_shell'
require 'msf/core/session/provider/multi_command_shell' require 'msf/core/session/provider/multi_command_shell'
#
# Returns the session's name if it's been assigned one, otherwise
# the sid is returned.
#
def name
return sname || sid
end
# #
# By default, sessions are not interactive. # Sets the session's name
# #
def interactive? def name=(name)
false self.sname = name
end end
#
# Returns the description of the session
#
def desc
end
#
# Returns the type of session in use
#
def type
end
#
# Returns the local side of the tunnel
#
def tunnel_local
end
#
# Returns the peer side of the tunnel
#
def tunnel_peer
end
#
# Returns a pretty representation of the tunnel
#
def tunnel_to_s
"#{(tunnel_local || '??').to_s} -> #{(tunnel_peer || '??').to_s}"
end
##
#
# Core interface
#
##
# #
# Perform session-specific cleanup # Perform session-specific cleanup
# #
@ -67,21 +111,13 @@ module Session
end end
# #
# Returns the session's name if it's been assigned one, otherwise # By default, sessions are not interactive.
# the sid is returned.
# #
def sname def interactive?
return name || sid false
end end
# attr_accessor :framework, :sid, :sname
# Sets the session's name
#
def sname=(name)
self.name = name
end
attr_accessor :framework, :sid, :name
protected protected

View File

@ -30,6 +30,34 @@ module Basic
true true
end end
#
# Description of the session
#
def desc
"Basic Session"
end
#
# Basic session
#
def type
"basic"
end
#
# Returns the local information
#
def tunnel_local
rstream.localinfo
end
#
# Returns the remote peer information
#
def tunnel_peer
rstream.peerinfo
end
# #
# Closes rstream. # Closes rstream.
# #
@ -44,6 +72,8 @@ module Basic
# rstream to loutput. # rstream to loutput.
# #
def interact def interact
eof = false
callcc { |ctx| callcc { |ctx|
while true while true
begin begin
@ -52,18 +82,23 @@ module Basic
# abort the interaction. If they do, then we return out of # abort the interaction. If they do, then we return out of
# the interact function and call it a day. # the interact function and call it a day.
rescue Interrupt rescue Interrupt
loutput.print("\nStop interacting with session #{sname}? [y/N] ") loutput.print("\nStop interacting with session #{name}? [y/N] ")
r = linput.gets r = linput.gets
# Break out of the continuation # Break out of the continuation
ctx.call if (r =~ /^y/i) ctx.call if (r =~ /^y/i)
rescue EOFError rescue EOFError
loutput.print_line("Session #{sname} terminating...") loutput.print_line("Session #{name} terminating...")
eof = true
ctx.call ctx.call
end end
end end
} }
# If we hit end-of-file, then that means we should finish off this
# session and call it a day.
framework.sessions.deregister(self) if (eof == true)
end end
# #

View File

@ -16,37 +16,15 @@ module Msf
# with. # with.
# #
### ###
class SessionManager class SessionManager < Hash
include Enumerable include Framework::Offspring
def initialize(framework) def initialize(framework)
self.framework = framework self.framework = framework
self.sessions = {}
self.sid_pool = 0 self.sid_pool = 0
end end
#
# Returns the session object that is associated with the supplied sid
#
def [](sid)
return get(sid)
end
#
# Register the supplied session
#
def <<(session)
return register(session)
end
#
# Implement for Enumerable
#
def each(&block)
sessions.each(&block)
end
# #
# Registers the supplied session object with the framework and returns # Registers the supplied session object with the framework and returns
# a unique session identifier to the caller. # a unique session identifier to the caller.
@ -60,7 +38,7 @@ class SessionManager
next_sid = (self.sid_pool += 1) next_sid = (self.sid_pool += 1)
# Insert the session into the session hash table # Insert the session into the session hash table
sessions[next_sid] = session self[next_sid] = session
# Initialize the session's sid and framework instance pointer # Initialize the session's sid and framework instance pointer
session.sid = next_sid session.sid = next_sid
@ -80,7 +58,7 @@ class SessionManager
framework.events.on_session_close(session) framework.events.on_session_close(session)
# Remove it from the hash # Remove it from the hash
sessions.delete(session.sid) self.delete(session.sid)
# Close it down # Close it down
session.cleanup session.cleanup
@ -90,12 +68,12 @@ class SessionManager
# Returns the session associated with the supplied sid, if any # Returns the session associated with the supplied sid, if any
# #
def get(sid) def get(sid)
return sessions[sid] return self[sid]
end end
protected protected
attr_accessor :sid_pool, :sessions, :framework attr_accessor :sid_pool, :sessions
end end

View File

@ -1,6 +1,7 @@
require 'msf/core' require 'msf/core'
require 'msf/base' require 'msf/base'
require 'msf/ui' require 'msf/ui'
require 'msf/ui/console/framework_event_manager'
require 'msf/ui/console/command_dispatcher' require 'msf/ui/console/command_dispatcher'
require 'msf/ui/console/shell' require 'msf/ui/console/shell'
require 'msf/ui/console/table' require 'msf/ui/console/table'
@ -23,6 +24,14 @@ class Driver < Msf::Ui::Driver
ConfigGroup = "framework/ui/console" ConfigGroup = "framework/ui/console"
#
# The console driver processes various framework notified events.
#
include FrameworkEventManager
#
# The console driver is a command shell.
#
include Msf::Ui::Console::Shell include Msf::Ui::Console::Shell
def initialize(prompt = "%umsf", prompt_char = ">%c") def initialize(prompt = "%umsf", prompt_char = ">%c")
@ -39,6 +48,9 @@ class Driver < Msf::Ui::Driver
# Initialize the super # Initialize the super
super super
# Register event handlers
register_event_handlers
# Process things before we actually display the prompt and get rocking # Process things before we actually display the prompt and get rocking
on_startup on_startup

View File

@ -0,0 +1,49 @@
module Msf
module Ui
module Console
###
#
# FrameworkEventManager
# ---------------------
#
# Handles events of various types that are sent from the framework.
#
###
module FrameworkEventManager
include Msf::SessionEvents
#
# Subscribes to the framework as a subscriber of various events.
#
def register_event_handlers
framework.events.add_session_subscriber(self)
end
#
# Unsubscribes from the framework.
#
def deregister_event_handlers
framework.events.remove_session_subscriber(self)
end
#
# Called when a session is registered with the framework.
#
def on_session_open(session)
output.print_status("#{session.desc} session opened (#{session.tunnel_to_s})")
end
#
# Called when a session is closed and removed from the framework.
#
def on_session_close(session)
output.print_status("#{session.desc} session closed (#{session.tunnel_to_s})")
end
end
end
end
end

View File

@ -73,6 +73,18 @@ module Stream
poll_fd poll_fd
end end
#
# Returns peer information, such as host and port.
#
def peerinfo
end
#
# Returns local information, such as host and port.
#
def localinfo
end
## ##
# #
# Common methods # Common methods

View File

@ -114,6 +114,22 @@ class Socket
return self.sock return self.sock
end end
#
# Returns local connection information.
#
def getlocalname
return Socket.from_sockaddr(self.sock.getsockname)
end
alias getsockname getlocalname
#
# Return peer connection information.
#
def getpeername
return Socket.from_sockaddr(self.sock.getpeername)
end
attr_reader :sock attr_reader :sock
attr_reader :peerhost, :peerport, :localhost, :localport attr_reader :peerhost, :peerport, :localhost, :localport

View File

@ -39,12 +39,16 @@ class Rex::Socket::Tcp < Rex::Socket
# #
## ##
#
# Writes to the TCP connection.
#
def write(buf, opts = {}) def write(buf, opts = {})
return sock.syswrite(buf) return sock.syswrite(buf)
end end
# #
# Raises EOFError if it reaches end-of-file # Reads from the TCP connection and raises EOFError if there is no data
# left.
# #
def read(length = nil, opts = {}) def read(length = nil, opts = {})
length = 16384 unless length length = 16384 unless length
@ -52,22 +56,52 @@ class Rex::Socket::Tcp < Rex::Socket
return sock.sysread(length) return sock.sysread(length)
end end
#
# Calls shutdown on the TCP connection.
#
def shutdown(how = SHUT_RDWR) def shutdown(how = SHUT_RDWR)
return (sock.shutdown(how) == 0) return (sock.shutdown(how) == 0)
end end
def has_read_data?(timeout = 0) #
# Checks to see if the connection has read data.
#
def has_read_data?(timeout = nil)
timeout = timeout.to_i if (timeout) timeout = timeout.to_i if (timeout)
return (select([ poll_fd ], nil, nil, timeout) != nil) return (select([ poll_fd ], nil, nil, timeout) != nil)
end end
#
# Closes the connection.
#
def close def close
self.sock.close if (self.sock) self.sock.close if (self.sock)
end end
#
# Returns the file descriptor to use with calls to select.
#
def poll_fd def poll_fd
return self.sock return self.sock
end end
#
# Returns peer information (host + port) in host:port format.
#
def peerinfo
if (pi = getpeername)
return pi[1] + ':' + pi[2].to_s
end
end
#
# Returns local information (host + port) in host:port format.
#
def localinfo
if (pi = getlocalname)
return pi[1] + ':' + pi[2].to_s
end
end
end end