mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
basic workings of auto-recon
git-svn-id: file:///home/svn/incoming/trunk@2987 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
1adc00a17d
commit
27b8f880ff
@ -105,9 +105,9 @@ Things that would be useful to have completed, but not a requirement:
|
||||
- framework-core
|
||||
- handler sharing
|
||||
- exploits using the same payload/handler can share (ref count)
|
||||
- framework-base
|
||||
- event correlation
|
||||
- recon events correlations
|
||||
X - framework-base
|
||||
X - event correlation
|
||||
X - recon events correlations
|
||||
- user interfaces
|
||||
- msfd
|
||||
- daemon interface, provides command line interaction and proxying
|
||||
|
@ -165,7 +165,9 @@ class EventDispatcher
|
||||
def on_host_changed(context, host, change_type)
|
||||
subscribers_rwlock.synchronize_read {
|
||||
recon_event_subscribers.each { |subscriber|
|
||||
next if (subscriber.include?(Msf::ReconEvent::HostSubscriber) == false)
|
||||
cls = (subscriber.kind_of?(Class)) ? subscriber : subscriber.class
|
||||
|
||||
next if (cls.include?(Msf::ReconEvent::HostSubscriber) == false)
|
||||
|
||||
subscriber.on_host_changed(context, host, change_type)
|
||||
}
|
||||
@ -180,7 +182,9 @@ class EventDispatcher
|
||||
def on_service_changed(context, host, service, change_type)
|
||||
subscribers_rwlock.synchronize_read {
|
||||
recon_event_subscribers.each { |subscriber|
|
||||
next if (subscriber.include?(Msf::ReconEvent::ServiceSubscriber) == false)
|
||||
cls = (subscriber.kind_of?(Class)) ? subscriber : subscriber.class
|
||||
|
||||
next if (cls.include?(Msf::ReconEvent::ServiceSubscriber) == false)
|
||||
|
||||
subscriber.on_service_changed(context, host, service, change_type)
|
||||
}
|
||||
|
@ -171,16 +171,12 @@ protected
|
||||
else
|
||||
self[name] = dup
|
||||
end
|
||||
|
||||
# Automatically subscribe a wrapper around this module to the necessary
|
||||
# event providers based on whatever events it wishes to receive.
|
||||
auto_subscribe_module(dup)
|
||||
|
||||
# Notify the framework that a module was loaded
|
||||
framework.events.on_module_load(name, dup)
|
||||
|
||||
|
||||
# Invalidate the sorted array
|
||||
invalidate_cache
|
||||
|
||||
# Return the duplicated instance for use
|
||||
dup
|
||||
end
|
||||
|
||||
#
|
||||
@ -191,50 +187,6 @@ protected
|
||||
mod_ranked = nil
|
||||
end
|
||||
|
||||
#
|
||||
# This method automatically subscribes a module to whatever event providers
|
||||
# it wishes to monitor. This can be used to allow modules to automatically
|
||||
# execute or perform other tasks when certain events occur. For instance,
|
||||
# when a new host is detected, other recon modules may wish to run such
|
||||
# that they can collect more information about the host that was detected.
|
||||
#
|
||||
def auto_subscribe_module(mod)
|
||||
# If auto-subscribe has been disabled
|
||||
if (framework.datastore['DisableAutoSubscribe'] and
|
||||
framework.datastore['DisableAutoSubscribe'] =~ /^(y|1|t)/)
|
||||
return
|
||||
end
|
||||
|
||||
# If auto-subscription is enabled (which it is by default), figure out
|
||||
# if it subscribes to any particular interfaces.
|
||||
|
||||
#
|
||||
# Recon event subscriber check
|
||||
#
|
||||
[
|
||||
Msf::ReconEvent::HostSubscriber,
|
||||
Msf::ReconEvent::ServiceSubscriber,
|
||||
].each { |iface|
|
||||
if (mod.include?(iface))
|
||||
framework.events.add_recon_subscriber(mod)
|
||||
end
|
||||
}
|
||||
|
||||
#
|
||||
# Exploit event subscriber check
|
||||
#
|
||||
if (mod.include?(ExploitEvent))
|
||||
framework.events.add_exploit_subscriber(mod)
|
||||
end
|
||||
|
||||
#
|
||||
# Session event subscriber check
|
||||
#
|
||||
if (mod.include?(SessionEvent))
|
||||
framework.events.add_session_subscriber(mod)
|
||||
end
|
||||
end
|
||||
|
||||
attr_writer :module_type
|
||||
attr_accessor :mod_arch_hash, :mod_platform_hash
|
||||
attr_accessor :mod_sorted, :mod_ranked
|
||||
@ -414,6 +366,25 @@ class ModuleManager < ModuleSet
|
||||
mod
|
||||
end
|
||||
|
||||
#
|
||||
# Overrides the module set method for adding a module so that some extra
|
||||
# steps can be taken to subscribe the module and notify the event
|
||||
# dispatcher.
|
||||
#
|
||||
def add_module(mod, name, file_path = nil)
|
||||
# Call the module set implementation of add_module
|
||||
dup = super
|
||||
|
||||
# Automatically subscribe a wrapper around this module to the necessary
|
||||
# event providers based on whatever events it wishes to receive. We
|
||||
# only do this if we are the module manager instance, as individual
|
||||
# module sets need not subscribe.
|
||||
auto_subscribe_module(dup)
|
||||
|
||||
# Notify the framework that a module was loaded
|
||||
framework.events.on_module_load(name, dup)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
@ -628,6 +599,51 @@ protected
|
||||
module_sets[type].add_module(mod, name, file_path)
|
||||
end
|
||||
|
||||
#
|
||||
# This method automatically subscribes a module to whatever event providers
|
||||
# it wishes to monitor. This can be used to allow modules to automatically
|
||||
# execute or perform other tasks when certain events occur. For instance,
|
||||
# when a new host is detected, other recon modules may wish to run such
|
||||
# that they can collect more information about the host that was detected.
|
||||
#
|
||||
def auto_subscribe_module(mod)
|
||||
# If auto-subscribe has been disabled
|
||||
if (framework.datastore['DisableAutoSubscribe'] and
|
||||
framework.datastore['DisableAutoSubscribe'] =~ /^(y|1|t)/)
|
||||
return
|
||||
end
|
||||
|
||||
# If auto-subscription is enabled (which it is by default), figure out
|
||||
# if it subscribes to any particular interfaces.
|
||||
inst = nil
|
||||
|
||||
#
|
||||
# Recon event subscriber check
|
||||
#
|
||||
[
|
||||
Msf::ReconEvent::HostSubscriber,
|
||||
Msf::ReconEvent::ServiceSubscriber,
|
||||
].each { |iface|
|
||||
if (mod.include?(iface) == true)
|
||||
framework.events.add_recon_subscriber((inst) ? inst : (inst = mod.new))
|
||||
end
|
||||
}
|
||||
|
||||
#
|
||||
# Exploit event subscriber check
|
||||
#
|
||||
if (mod.include?(ExploitEvent) == true)
|
||||
framework.events.add_exploit_subscriber((inst) ? inst : (inst = mod.new))
|
||||
end
|
||||
|
||||
#
|
||||
# Session event subscriber check
|
||||
#
|
||||
if (mod.include?(SessionEvent) == true)
|
||||
framework.events.add_session_subscriber((inst) ? inst : (inst = mod.new))
|
||||
end
|
||||
end
|
||||
|
||||
attr_accessor :modules, :module_sets
|
||||
attr_accessor :module_paths
|
||||
attr_accessor :module_history, :module_history_mtime
|
||||
|
@ -34,7 +34,7 @@ module ReconEvent
|
||||
# This routine is called when a change is made to a host, such as it being
|
||||
# added, modified, or removed.
|
||||
#
|
||||
def self.on_host_changed(context, host, change_type)
|
||||
def on_host_changed(context, host, change_type)
|
||||
case change_type
|
||||
when EntityChangeType::Add
|
||||
on_new_host(context, host)
|
||||
@ -45,65 +45,30 @@ module ReconEvent
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_host_changed(context, host, change_type)
|
||||
self.class.on_host_changed(context, host, change_type)
|
||||
end
|
||||
|
||||
#
|
||||
# This routine is called whenever a new host is found.
|
||||
#
|
||||
def self.on_new_host(context, host)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class methods.
|
||||
#
|
||||
def on_new_host(context, host)
|
||||
self.class.on_new_host(context, host)
|
||||
end
|
||||
|
||||
#
|
||||
# This routine is called whenever a change is made to an existing
|
||||
# host.
|
||||
#
|
||||
def self.on_updated_host(context, host)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_updated_host(context, host)
|
||||
self.class.on_updated_host(context, host)
|
||||
end
|
||||
|
||||
#
|
||||
# Called when a host is considered to be dead after having
|
||||
# previously been valid.
|
||||
#
|
||||
def self.on_dead_host(context, host)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_dead_host(context, host)
|
||||
self.class.on_dead_host(context, host)
|
||||
end
|
||||
|
||||
#
|
||||
# This routine is called whenever a host attribute is found.
|
||||
#
|
||||
def self.on_new_host_attribute(context, host, attribute)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_new_host_attribute(context, host, attribute)
|
||||
self.class.on_new_host_attribute(context, host, attribute)
|
||||
end
|
||||
|
||||
end
|
||||
@ -123,7 +88,7 @@ module ReconEvent
|
||||
# This routine is called when a change is made to a service, such as it being
|
||||
# added, modified, or removed.
|
||||
#
|
||||
def self.on_service_changed(context, host, service, change_type)
|
||||
def on_service_changed(context, host, service, change_type)
|
||||
case change_type
|
||||
when EntityChangeType::Add
|
||||
on_new_service(context, host, service)
|
||||
@ -134,67 +99,32 @@ module ReconEvent
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_service_changed(context, host, service, change_type)
|
||||
self.class.on_service_changed(context, host, service, change_type)
|
||||
end
|
||||
|
||||
#
|
||||
# This routine is called whenever a new service is found.
|
||||
#
|
||||
def self.on_new_service(context, host, service)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_new_service(context, host, service)
|
||||
self.class.on_new_service(context, host, service)
|
||||
end
|
||||
|
||||
#
|
||||
# This routine is called whenever a change is made to an existing
|
||||
# service.
|
||||
#
|
||||
def self.on_updated_service(context, host, service)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_updated_service(context, host, service)
|
||||
self.class.on_updated_service(context, host, service)
|
||||
end
|
||||
|
||||
#
|
||||
# Called when a service is considered to be dead after having
|
||||
# previously been valid.
|
||||
#
|
||||
def self.on_dead_service(context, host, service)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_dead_service(context, host, service)
|
||||
self.class.on_dead_service(context, host, service)
|
||||
end
|
||||
|
||||
#
|
||||
# This routine is called whenever a service attribute is found.
|
||||
#
|
||||
def self.on_new_service_attribute(context, host, service, attribute)
|
||||
def on_new_service_attribute(context, host, service, attribute)
|
||||
end
|
||||
|
||||
#
|
||||
# Calls the class method.
|
||||
#
|
||||
def on_new_service_attribute(context, host, service)
|
||||
self.class.on_new_service_attribute(context, host, service)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -28,6 +28,20 @@ module Container
|
||||
self._attr_hash = Hash.new
|
||||
end
|
||||
|
||||
#
|
||||
# Wraps get_attribute.
|
||||
#
|
||||
def [](key)
|
||||
get_attribute(key)
|
||||
end
|
||||
|
||||
#
|
||||
# Wraps set_attribute.
|
||||
#
|
||||
def []=(key, val)
|
||||
set_attribute(key, val)
|
||||
end
|
||||
|
||||
#
|
||||
# Sets the value of an attribute with the supplied name.
|
||||
#
|
||||
|
@ -55,6 +55,7 @@ class Discoverer < Msf::Recon
|
||||
end
|
||||
|
||||
require 'msf/core/recon/discoverer/host'
|
||||
require 'msf/core/recon/discoverer/service'
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
@ -258,7 +259,7 @@ protected
|
||||
if (discovery_threads.length == 0)
|
||||
# Call the discovery complete method
|
||||
discovery_complete(false)
|
||||
|
||||
|
||||
discovery_thread_event.set
|
||||
end
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
module Msf
|
||||
class Recon
|
||||
class Discoverer
|
||||
|
||||
###
|
||||
#
|
||||
# Service
|
||||
# -------
|
||||
#
|
||||
# This class provides a base class for all recon modules that attempt to
|
||||
# discover the presence of a service on a host.
|
||||
#
|
||||
###
|
||||
class Service < Msf::Recon::Discoverer
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
|
||||
# Register the options that this particular discovery module uses
|
||||
register_options(
|
||||
[
|
||||
Opt::RHOST
|
||||
], Msf::Recon::Discoverer::Service)
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns that this is a service discoverer recon module.
|
||||
#
|
||||
def discoverer_type
|
||||
Type::Service
|
||||
end
|
||||
|
||||
#
|
||||
# By default, service discoverer recon modules do no support
|
||||
# multi-threading.
|
||||
#
|
||||
def discoverer_flags
|
||||
0
|
||||
end
|
||||
|
||||
#
|
||||
# Probes a host entity to see what services it has open. Extended modules
|
||||
# should report service state changes directly via the report_service_state
|
||||
# instance method.
|
||||
#
|
||||
def probe_host(host)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
# Wraps the probing of a host.
|
||||
#
|
||||
def discovery_thread
|
||||
if ((host = framework.reconmgr.get_host(datastore['RHOST'])) == nil)
|
||||
host = Msf::Recon::Entity::Host.new(datastore['RHOST'])
|
||||
end
|
||||
|
||||
probe_host(host)
|
||||
end
|
||||
|
||||
#
|
||||
# This method reports the state of a service to the recon manager so that
|
||||
# it can be tracked appropriately.
|
||||
#
|
||||
def report_service_state(host, proto, port, istate)
|
||||
state = istate
|
||||
context = nil
|
||||
|
||||
# If the state passed in as an argument is a hash, then create an event
|
||||
# context that we'll pass along to the recon manager in case other
|
||||
# subscribers might be able to make use of it.
|
||||
if (istate.kind_of?(Hash))
|
||||
context = Msf::Recon::EventContext.new
|
||||
|
||||
context.from_hash(istate)
|
||||
|
||||
state = istate['state']
|
||||
end
|
||||
|
||||
# Log that we detected an up service
|
||||
if (state == ServiceState::Up)
|
||||
dlog("Found port #{port} (#{proto}) open on #{host.address}.", "core",
|
||||
LEV_2)
|
||||
end
|
||||
|
||||
# Pass the normalized service state notifications to the recon manager.
|
||||
framework.reconmgr.report_service_state(self, host, proto, port,
|
||||
state, context)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
@ -50,6 +50,8 @@ class Entity
|
||||
'unknown'
|
||||
end
|
||||
|
||||
attr_accessor :needs_register
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -2,6 +2,9 @@ module Msf
|
||||
class Recon
|
||||
class Entity
|
||||
|
||||
class Group
|
||||
end
|
||||
|
||||
###
|
||||
#
|
||||
# Container
|
||||
@ -17,20 +20,14 @@ module Container
|
||||
# Initializes the array of entities.
|
||||
#
|
||||
def initialize_entities
|
||||
self._entity_list = Array.new
|
||||
self._entity_sub_containers = Hash.new
|
||||
self._entity_hash = Hash.new
|
||||
end
|
||||
|
||||
#
|
||||
# This routine adds a sub-container of entities to this entity container.
|
||||
#
|
||||
def add_entity_subcontainer(name, container)
|
||||
self._entity_sub_containers[name] = container
|
||||
|
||||
instance_eval("
|
||||
def #{name}
|
||||
_entity_sub_containers['#{name}']
|
||||
end")
|
||||
def add_entity_subcontainer(name, container = Group.new)
|
||||
add_entity(name, container)
|
||||
end
|
||||
|
||||
#
|
||||
@ -43,31 +40,47 @@ module Container
|
||||
#
|
||||
# Adds an entity to the container.
|
||||
#
|
||||
def add_entity(entity)
|
||||
self._entity_list << entity
|
||||
end
|
||||
def add_entity(name, entity)
|
||||
self._entity_hash[name] = entity
|
||||
|
||||
def delete_entity(entity)
|
||||
self._entity_list.delete(entity)
|
||||
if (respond_to?(name) == false)
|
||||
instance_eval("
|
||||
def #{name}
|
||||
_entity_hash[#{name}]
|
||||
end
|
||||
")
|
||||
end
|
||||
|
||||
entity
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the list of entities to the caller.
|
||||
# Returns the entity associated with the supplied name.
|
||||
#
|
||||
def get_entity(name)
|
||||
_entity_hash[name]
|
||||
end
|
||||
|
||||
#
|
||||
# Removes an entity from the hash of entities.
|
||||
#
|
||||
def delete_entity(entity)
|
||||
self._entity_hash.delete(entity)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the hash of entities to the caller.
|
||||
#
|
||||
def entities
|
||||
_entity_list
|
||||
_entity_hash
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
# The protected entity list itself.
|
||||
# The protected entity hash itself.
|
||||
#
|
||||
attr_accessor :_entity_list
|
||||
#
|
||||
# The hash of entity sub-containers.
|
||||
#
|
||||
attr_accessor :_entity_sub_containers
|
||||
attr_accessor :_entity_hash
|
||||
|
||||
end
|
||||
|
||||
|
@ -49,7 +49,7 @@ class Host < Entity
|
||||
|
||||
# Holds the address of the host that this entity instance is associated
|
||||
# with.
|
||||
self.address = address;
|
||||
self.address = address
|
||||
|
||||
# Add an attribute group that will contain system information for this
|
||||
# host.
|
||||
|
@ -0,0 +1,53 @@
|
||||
module Msf
|
||||
class Recon
|
||||
class Entity
|
||||
|
||||
###
|
||||
#
|
||||
# Service
|
||||
# -------
|
||||
#
|
||||
# This class represents a logical service entity. Services symbolize remote
|
||||
# functionality provided by a host by means of some network-based protocol,
|
||||
# such as TCP over IP. Information about a service, such as its protocol,
|
||||
# port, banner, and other information is conveyed through attributes of the
|
||||
# service entity.
|
||||
#
|
||||
###
|
||||
class Service < Entity
|
||||
|
||||
def initialize(proto, port = nil)
|
||||
super()
|
||||
|
||||
#
|
||||
# Initialize the local attributes
|
||||
#
|
||||
self.proto = proto
|
||||
self.port = port
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns a pretty string representation of the service.
|
||||
#
|
||||
def pretty
|
||||
"#{port} (#{proto})"
|
||||
end
|
||||
|
||||
#
|
||||
# The protocol this service is using, such as 'tcp'.
|
||||
#
|
||||
attr_reader :proto
|
||||
#
|
||||
# The port this service is listening on, if applicable.
|
||||
#
|
||||
attr_reader :port
|
||||
|
||||
protected
|
||||
|
||||
attr_writer :proto, :port # :nodoc:
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
@ -26,6 +26,30 @@ module HostState
|
||||
Unknown = "unknown"
|
||||
end
|
||||
|
||||
###
|
||||
#
|
||||
# ServiceState
|
||||
# ---------
|
||||
#
|
||||
# The states that a service can be in.
|
||||
#
|
||||
###
|
||||
module ServiceState
|
||||
#
|
||||
# The service is alive.
|
||||
#
|
||||
Up = "up"
|
||||
#
|
||||
# The service is dead.
|
||||
#
|
||||
Dead = "down"
|
||||
#
|
||||
# The service state is unknown.
|
||||
#
|
||||
Unknown = "unknown"
|
||||
end
|
||||
|
||||
|
||||
###
|
||||
#
|
||||
# ReconManager
|
||||
@ -76,7 +100,7 @@ class ReconManager
|
||||
# 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
|
||||
hash_key = host_hash_key(address)
|
||||
|
||||
# If a host already exists with this information, then check to see what
|
||||
# status we received.
|
||||
@ -99,8 +123,58 @@ class ReconManager
|
||||
# dead
|
||||
end
|
||||
|
||||
#
|
||||
# This method reports a host's service state.
|
||||
#
|
||||
def report_service_state(mod, host, proto, port, state, context = nil)
|
||||
|
||||
# If the supplied host object has not yet been registered, do so now.
|
||||
# This occurs when a service module happens to discover a host that was
|
||||
# not originally thought to have existed
|
||||
if (host.needs_register != false and
|
||||
state == ServiceState::Up)
|
||||
new_host(host_hash_key(host.address), host, context)
|
||||
end
|
||||
|
||||
# Define the service entity name
|
||||
ename = "port_#{port}"
|
||||
|
||||
# Get the proto subcontainer for this entity, or add it if it isn't
|
||||
# already defined.
|
||||
p = host.services.add_entity_subcontainer(proto.downcase)
|
||||
|
||||
# Now that we have the protocol subcontainer, get the service instance
|
||||
# associated witht he port (if one has been defined).
|
||||
if (service = p.get_entity(ename))
|
||||
# TODO: update
|
||||
elsif (state == ServiceState::Up)
|
||||
service = Recon::Entity::Service.new(proto, port)
|
||||
|
||||
p.add_entity("port_#{ename}", service)
|
||||
|
||||
# TODO: Notify
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# This method returns the host object associated with the supplied address.
|
||||
# If one does not exist, it is created.
|
||||
#
|
||||
def get_host(address)
|
||||
host_hash[host_hash_key(address)]
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
#
|
||||
# This method returns the hash key to use with the supplied address.
|
||||
#
|
||||
# TODO: make this use comm info
|
||||
#
|
||||
def host_hash_key(address)
|
||||
address
|
||||
end
|
||||
|
||||
#
|
||||
# Called when a new host is detected.
|
||||
#
|
||||
@ -118,6 +192,9 @@ protected
|
||||
ilog("recon: New host discoverered: #{host.pretty}", "core",
|
||||
LEV_1)
|
||||
|
||||
# Now that the host has registered, we can't flag it up.
|
||||
host.needs_register = false
|
||||
|
||||
# Notify any host event subscribes of our new found fate.
|
||||
framework.events.on_host_changed(
|
||||
context, host, ReconEvent::EntityChangeType::Add)
|
||||
|
70
modules/recon/service/port_scanner/nmap.rb
Normal file
70
modules/recon/service/port_scanner/nmap.rb
Normal file
@ -0,0 +1,70 @@
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# Nmap
|
||||
# ----
|
||||
#
|
||||
# This recon modules uses nmap to detect the services that are running on a
|
||||
# given host.
|
||||
#
|
||||
###
|
||||
class Recon::Service::PortScanner::Nmap < Msf::Recon::Discoverer::Service
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Nmap port scanner',
|
||||
'Description' => %q{
|
||||
This module uses nmap to detect the services that are running
|
||||
on a given host.
|
||||
},
|
||||
'Author' => 'skape',
|
||||
'Version' => '$Revision$'))
|
||||
end
|
||||
|
||||
def probe_host(host)
|
||||
# If we are running as root, use nmap to do a SYN scan
|
||||
if (Process.euid == 0)
|
||||
cmd = "nmap -sS #{host.address}"
|
||||
# Otherwise, if we're non-root, use the standard tcp connect() scan
|
||||
else
|
||||
cmd = "nmap -sT #{host.address}"
|
||||
end
|
||||
|
||||
# Fire it off...
|
||||
p = IO.popen(cmd)
|
||||
|
||||
begin
|
||||
# Read each line, extracting the ones that contain open port
|
||||
# information
|
||||
while (buf = p.gets)
|
||||
if (buf =~ /^(\d+)\/(tcp|udp)\s+open/i)
|
||||
report_service_state(host, $2, $1, ServiceState::Up)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
p.close
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Automated launching
|
||||
#
|
||||
##
|
||||
|
||||
include Msf::ReconEvent::HostSubscriber
|
||||
|
||||
#
|
||||
# This method is automatically called when a new host is found.
|
||||
#
|
||||
def on_new_host(context, host)
|
||||
# TODO: check if auto-service-probe should be enabled
|
||||
# TODO: precedence of who should be able to search for services
|
||||
# TODO: evasion qualifications
|
||||
probe_host(host)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue
Block a user