138 lines
2.9 KiB
Ruby
138 lines
2.9 KiB
Ruby
require 'rex/proto/dcerpc'
|
|
|
|
module Msf
|
|
|
|
###
|
|
#
|
|
# This mixin provides utility methods for interacting with a DCERPC service on
|
|
# a remote machine. These methods may generally be useful in the context of
|
|
# exploitation. This mixin extends the Tcp exploit mixin. Only one DCERPC
|
|
# service can be accessed at a time using this class.
|
|
#
|
|
###
|
|
module Exploit::Remote::DCERPC
|
|
include Exploit::Remote::Tcp
|
|
|
|
# Alias over the Rex DCERPC protocol modules
|
|
DCERPCPacket = Rex::Proto::DCERPC::Packet
|
|
DCERPCClient = Rex::Proto::DCERPC::Client
|
|
DCERPCResponse = Rex::Proto::DCERPC::Response
|
|
DCERPCUUID = Rex::Proto::DCERPC::UUID
|
|
|
|
def initialize(info = {})
|
|
super
|
|
|
|
register_advanced_options(
|
|
[
|
|
OptInt.new('DCEFragSize', [ 1, 'Set the DCERPC packet fragmentation size', 127]),
|
|
OptBool.new('DCEMultiBind', [ 0, 'Use multi-context bind calls', 'T' ])
|
|
], Msf::Exploit::Remote::DCERPC)
|
|
|
|
register_options(
|
|
[
|
|
Opt::RHOST,
|
|
Opt::RPORT(135),
|
|
], Msf::Exploit::Remote::DCERPC)
|
|
end
|
|
|
|
#
|
|
# Generate a DCERPC bind request and send it on the default socket
|
|
#
|
|
def dcerpc_bind (uuid, vers = nil)
|
|
|
|
# Create the bind request
|
|
bind, ctx = dcerpc_make_bind(uuid, vers)
|
|
if (bind == nil)
|
|
return
|
|
end
|
|
|
|
# Verify that the socket exists
|
|
if (sock == nil)
|
|
return
|
|
end
|
|
|
|
# Send the bind request
|
|
sock.put(bind)
|
|
|
|
# Parse the response
|
|
resp = DCERPCClient.read_response(sock)
|
|
if (resp.ack_result[ctx] != 0)
|
|
print_status("Failed to bind to UUID " + uuid)
|
|
return
|
|
end
|
|
|
|
return resp
|
|
end
|
|
|
|
#
|
|
# Generate DCERPC request packets and send them on the default socket
|
|
#
|
|
def dcerpc_call (func, stub)
|
|
|
|
# Create the request packets
|
|
pkts = dcerpc_make_call(func, stub)
|
|
if (pkts == nil)
|
|
return
|
|
end
|
|
|
|
# Verify that the socket exists
|
|
if (sock == nil)
|
|
return
|
|
end
|
|
|
|
print_status("Sending " + pkts.size.to_s + " DCERPC fragments...")
|
|
pkts.each { |chunk| sock.put(chunk) }
|
|
resp = DCERPCClient.read_response(sock)
|
|
return resp
|
|
end
|
|
|
|
#
|
|
# Generate the DCERPC bind request packet
|
|
#
|
|
def dcerpc_make_bind (uuid, vers = nil)
|
|
# Resolve the UUID if only the name was supplied
|
|
if (vers == nil)
|
|
vers = DCERPCUUID.vers_by_name(uuid)
|
|
uuid = DCERPCUUID.uuid_by_name(uuid)
|
|
end
|
|
|
|
|
|
# Verify that the uuid was resolved and is valid
|
|
if (uuid == nil)
|
|
print_status("Invalid UUID")
|
|
return
|
|
end
|
|
|
|
bind, ctx = nil, nil
|
|
|
|
if (datastore['DCEMultiBind'])
|
|
bind, ctx = DCERPCPacket.make_bind_fake_multi(uuid, vers, 10, 4)
|
|
else
|
|
bind, ctx = DCERPCPacket.make_bind(uuid, vers)
|
|
end
|
|
|
|
# Cache the context value for future requests
|
|
self.dcerpc_bind_context = ctx
|
|
|
|
return bind, ctx
|
|
end
|
|
|
|
#
|
|
# Generate the DCERPC request packets, broken up into DCEFragSize chunks
|
|
#
|
|
def dcerpc_make_call (func, stub, ctx = self.dcerpc_bind_context)
|
|
DCERPCPacket.make_request(
|
|
func,
|
|
stub,
|
|
datastore['DCEFragSize'].to_i || stub.length,
|
|
ctx
|
|
)
|
|
end
|
|
|
|
# Used to track the last DCERPC context
|
|
attr_accessor :dcerpc_bind_context
|
|
|
|
end
|
|
|
|
end
|