metasploit-framework/modules/auxiliary/scanner/dcerpc/hidden.rb

123 lines
3.1 KiB
Ruby

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
# Exploit mixins should be called first
include Msf::Exploit::Remote::DCERPC
include Msf::Auxiliary::Report
# Scanner mixin should be near last
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Hidden DCERPC Service Discovery',
'Description' => %q{
This module will query the endpoint mapper and make a list
of all ncacn_tcp RPC services. It will then connect to each of
these services and use the management API to list all other
RPC services accessible on this port. Any RPC service found attached
to a TCP port, but not listed in the endpoint mapper, will be displayed
and analyzed to see whether anonymous access is permitted.
},
'Author' => 'hdm',
'License' => MSF_LICENSE
)
deregister_options('RPORT')
end
# Obtain information about a single host
def run_host(ip)
epm = dcerpc_endpoint_list
if !epm
print_status("Could not contact the endpoint mapper on #{ip}")
return
end
eports = {}
epm.each do |ep|
next if !(ep[:port] && ep[:prot] && (ep[:prot] == 'tcp'))
eports[ep[:port]] ||= {}
eports[ep[:port]][ep[:uuid] + '_' + ep[:vers]] = true
end
eports.each_pair do |eport, servs|
rport = eport
print_status("Looking for services on #{ip}:#{rport}...")
ids = dcerpc_mgmt_inq_if_ids(rport)
next if !ids
ids.each do |id|
next if servs.key?(id[0] + '_' + id[1])
print_status("\tHIDDEN: UUID #{id[0]} v#{id[1]}")
conn = nil
bind = nil
call = nil
data = nil
error = nil
begin
connect(true, { 'RPORT' => eport })
conn = true
handle = dcerpc_handle(id[0], id[1], 'ncacn_ip_tcp', [eport])
dcerpc_bind(handle)
bind = true
dcerpc.call(0, NDR.long(0) * 128)
call = true
if (!dcerpc.last_response.nil? && !dcerpc.last_response.stub_data.nil?)
data = dcerpc.last_response.stub_data
end
rescue ::Interrupt
raise $ERROR_INFO
rescue ::Exception => e
error = e.to_s
end
if error
if error =~ (/DCERPC FAULT/) && error !~ (/nca_s_fault_access_denied/)
call = true
else
elog(e)
end
end
status = "\t\t"
status << 'CONN ' if conn
status << 'BIND ' if bind
status << 'CALL ' if call
status << "DATA=#{data.unpack('H*')[0]} " if data
status << "ERROR=#{error} " if error
print_status(status)
print_status('')
## Add Report
report_note(
host: ip,
proto: 'tcp',
port: datastore['RPORT'],
type: "DCERPC HIDDEN: UUID #{id[0]} v#{id[1]}",
data: status
)
end
end
rescue ::Interrupt
raise $ERROR_INFO
rescue ::Exception => e
print_status("Error: #{e}")
end
end