Files
metasploit-gs/lib/msf/core/exploit/dcerpc_epm.rb
T
Tod Beardsley ac1fb2d1da Just use a straight RPORT, don't sneak 593.
Incidentally, the endmap scanner doesn't appear to work at all for
http-rpc-epmap, so no harm done anyway (tested against Windows 2008
server).

It looks like a bigger change than it realy is, thanks to the indentaton
changes by removing the itertor. Diff this without whitespace changes to
get a better idea of what's actually different.
2013-11-19 13:29:02 -06:00

223 lines
5.2 KiB
Ruby

# -*- coding: binary -*-
module Msf
###
#
# This module provides service-specific methods for the DCERPC exploit mixin
#
###
module Exploit::Remote::DCERPC_EPM
# Contact the endpoint mapper of the target host and find the transport
def dcerpc_endpoint_find_tcp(host, uuid, vers, transport)
res = dcerpc_endpoint_list()
return nil if not res
res.each do |ent|
if (ent[:uuid] == uuid and ent[:vers] == vers and ent[:prot] == 'tcp')
return ent[:port]
end
end
nil
end
# Contact the endpoint mapper of the target host and find the transport
def dcerpc_endpoint_find_udp(host, uuid, vers, transport)
res = dcerpc_endpoint_list()
return nil if not res
res.each do |ent|
if (ent[:uuid] == uuid and ent[:vers] == vers and ent[:prot] == 'udp')
return ent[:port]
end
end
nil
end
# Contact the endpoint mapper and create a hash of all endpoints
def dcerpc_endpoint_list
res = []
print_status("Connecting to the endpoint mapper service...")
begin
eps = nil
dport = datastore['RPORT'] || 135
begin
eps = Rex::Socket::Tcp.create(
'PeerHost' => rhost,
'PeerPort' => dport,
'Proxies' => proxies,
'Context' =>
{
'Msf' => framework,
'MsfExploit' => self,
}
)
rescue ::Exception
end
if (not eps)
print_status("Could not connect to the endpoint mapper service")
return nil
end
eph = dcerpc_handle('e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0', 'ncacn_ip_tcp', [dport])
opt = { 'Msf' => framework, 'MsfExploit' => self }
dce = Rex::Proto::DCERPC::Client.new(eph, eps, opt)
hnd = nil
while(true)
# Placeholders
info =
{
:type => nil,
:port => nil,
:host => nil,
:pipe => nil,
:prot => nil,
:uuid => nil,
:vers => nil,
:note => nil
}
data = nil
if(not hnd)
# NULL handle to start with
data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 1].pack("V*")
else
# Break the loop early if we get another NULL handle
break if hnd == [0, 0, 0, 0, 1].pack("V*")
# Use the existing handle if we already have one
data = [0, 0, 0, 0, 0].pack("V*") + hnd
end
ret = dce.call(2, data)
if (
dce.last_response == nil or
dce.last_response.stub_data == nil or
dce.last_response.stub_data.length < 40 or
dce.last_response.stub_data[36,4] == "\xd6\xa0\xc9\x16"
)
# break from the parsing loop
break
end
# Record the response data
buf = dce.last_response.stub_data
# Record the handle if needed
hnd = buf[4, 20] if not hnd
# Parse the response data
nlen = buf[60, 4].unpack('V')[0]
if (nlen > 1)
info[:note] = buf[64, nlen - 1]
end
# Align the stub offset
soff = nlen + 72
while (soff % 4 != 0)
soff += 1
end
# Determine number of records
rcnt = buf[soff, 2].unpack('v')[0]
soff += 2
# Parse the data from the stack
1.upto(rcnt) do |i|
rlen = buf[soff, 2].unpack('v')[0]
soff += 2
if (i == 1)
info[:uuid] = Rex::Proto::DCERPC::UUID.uuid_unpack(buf[soff+1, 16])
info[:vers] = buf[soff+17,2].unpack('CC').map{|s| s.to_s}.join(".")
end
if (i > 3)
info[:type] = buf[soff, 1].unpack("C*")[0]
end
soff += rlen
xlen = buf[soff, 2].unpack('v')[0]
soff += 2
case info[:type]
when nil
# TCP
when 7
info[:prot] = 'tcp'
info[:port] = buf[soff, 2].unpack('n')[0]
# UDP
when 8
info[:prot] = 'udp'
info[:port] = buf[soff, 2].unpack('n')[0]
# ADDR
when 9
info[:host] = buf[soff, 4].unpack('C4').join('.')
# PIPE
when 15
info[:prot] = 'pipe'
info[:pipe] = buf[soff, xlen].unpack("a*")[0]
# LRPC
when 16
info[:prot] = 'lrpc'
info[:pipe] = buf[soff, xlen].unpack("a*")[0]
# NETBIOS
when 17,24
info[:host] = buf[soff, xlen].unpack("a*")[0]
# HTTP
when 31
info[:prot] = 'http'
info[:port] = buf[soff, 2].unpack('n')[0]
# DYNAMIC?
when 22
# not parsed
else
print_status("EPM unknown type: #{info[:type]} #{buf[soff, xlen].unpack("H*")[0]}")
end
soff += xlen
end
info[:pipe].gsub!("\x00", '') if info[:pipe]
info[:host].gsub!("\x00", '') if info[:host]
res << info
# Handle a buggy response from a Likewise server that can result in a loop otherwise
break if hnd == [0, 0, 0, 0, 0, 0, 0, 0, 0, 1].pack("V*")
end
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_status("Could not obtain the endpoint list: #{e}")
res = nil
end
res
end
end
end