086f657c56
This commit fixes an issue, where auxiliary/scanner/dcerpc/hidden terminates directly, once an endpoint can't be reached or access is denied. Instead the next endpoint in list should be checked, instead of terminating directly.
126 lines
3.3 KiB
Ruby
126 lines
3.3 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('RHOST', 'RPORT')
|
|
end
|
|
|
|
# Obtain information about a single host
|
|
def run_host(ip)
|
|
begin
|
|
|
|
epm = dcerpc_endpoint_list()
|
|
if(not epm)
|
|
print_status("Could not contact the endpoint mapper on #{ip}")
|
|
return
|
|
end
|
|
|
|
eports = {}
|
|
|
|
epm.each do |ep|
|
|
next if !(ep[:port] and ep[:prot] and 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 not ids
|
|
|
|
ids.each do |id|
|
|
if (not servs.has_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
|
|
|
|
res = dcerpc.call(0, NDR.long(0) * 128)
|
|
call = true
|
|
|
|
if (dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil)
|
|
data = dcerpc.last_response.stub_data
|
|
end
|
|
|
|
rescue ::Interrupt
|
|
raise $!
|
|
rescue ::Exception => e
|
|
error = e.to_s
|
|
end
|
|
|
|
if (error and error =~ /DCERPC FAULT/ and error !~ /nca_s_fault_access_denied/)
|
|
call = true
|
|
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
|
|
end
|
|
|
|
rescue ::Interrupt
|
|
raise $!
|
|
rescue ::Exception => e
|
|
print_status("Error: #{e}")
|
|
end
|
|
end
|
|
|
|
|
|
end
|