metasploit-framework/lib/msf/core/recon_manager.rb

145 lines
2.9 KiB
Ruby

require 'thread'
require 'msf/core/recon'
module Msf
###
#
# HostState
# ---------
#
# The states that a host can be in.
#
###
module HostState
#
# The host is alive.
#
Alive = "alive"
#
# The host is dead.
#
Dead = "down"
#
# The host state is unknown.
#
Unknown = "unknown"
end
###
#
# ReconManager
# ------------
#
# This class manages the tracking of entities and the dispatching of events
# pertaining to recon information collection. When hosts are discovered, the
# recon module tracks them and dispatches the appropriate events to the
# framework event manager so that subscribers can be notified.
#
###
class ReconManager
include Framework::Offspring
###
#
# ExtendedHostState
# -----------------
#
# This mixin is used to extend Host entity instances such that the recon
# manager can track internal state information.
#
###
module ExtendedHostState
#
# Tracks the number of manager state unknowns returned.
#
attr_accessor :_mgr_state_unknown
end
def initialize(framework)
self.framework = framework;
self.host_hash = Hash.new
self.host_hash_mutex = Mutex.new
end
##
#
# Host reporting
#
##
#
# Reports a host as being in a given state by address.
#
def report_host_state(mod, address, state, context = nil)
# TODO: use the current thread's Comm as part of the hash key to support
# conflicting addresses in different networks (established through
# different comms).
hash_key = address
# If a host already exists with this information, then check to see what
# status we received.
if (host = host_hash[hash_key])
if (state == HostState::Unknown)
host._mgr_state_unknown += 1
elsif (state == HostState::Dead)
dead_host(host, context)
else
host._mgr_state_unknown = 0
end
# Otherwise, if we have no host yet, get one and start handling it.
elsif (state == HostState::Alive)
host = Recon::Entity::Host.new(address)
new_host(hash_key, host, context)
end
# TODO: evalulate _mgr_state_unknown to determine if the host should be
# dead
end
protected
#
# Called when a new host is detected.
#
def new_host(hash_key, host, context)
# Extend the host and initialize it properly
host.extend(ExtendedHostState)
host._mgr_state_unknown = 0
# Add the host tot he host hash
host_hash_mutex.synchronize {
self.host_hash[hash_key] = host
}
ilog("recon: New host discoverered: #{host.pretty}", "core",
LEV_1)
# Notify any host event subscribes of our new found fate.
framework.events.on_host_changed(
context, host, ReconEvent::EntityChangeType::Add)
end
#
# Processes cleanup necessary when a dead host is encountered.
#
def dead_host(host, context)
host_hash_mutex.synchronize {
self.host_hash.delete(host)
}
# Notify any host event subscribers that the host has died.
framework.events.on_host_changed(
context, host, ReconEvent::EntityChangeType::Remove)
end
attr_accessor :host_hash
attr_accessor :host_hash_mutex
end
end