Fixes, tweaks, etc
git-svn-id: file:///home/svn/incoming/trunk@2783 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
48b59caeff
commit
5049896454
|
@ -15,34 +15,30 @@ require 'rex/proto/dcerpc/uuid'
|
|||
require 'rex/proto/dcerpc/response'
|
||||
require 'rex/text'
|
||||
|
||||
#
|
||||
# Process a DCERPC response packet from a socket
|
||||
#
|
||||
def read_response (socket)
|
||||
|
||||
head = socket.timed_read(10, 5)
|
||||
if (! head or head.length() != 10)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
resp = Rex::Proto::DCERPC::Response.new(head)
|
||||
|
||||
if (! resp.frag_len)
|
||||
return resp
|
||||
end
|
||||
|
||||
body = socket.timed_read(resp.frag_len, 10)
|
||||
if (! body or body.length() != resp.frag_len)
|
||||
|
||||
body = socket.timed_read(resp.frag_len - 10, 10)
|
||||
if (body.nil? or body.length() != resp.frag_len - 10)
|
||||
return resp
|
||||
end
|
||||
|
||||
|
||||
resp.parse(body)
|
||||
return resp
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Create a standard DCERPC BIND request packet
|
||||
#
|
||||
def make_bind (uuid, vers)
|
||||
u = Rex::Proto::DCERPC::UUID.new()
|
||||
|
||||
|
@ -74,12 +70,12 @@ require 'rex/text'
|
|||
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(3)+1)
|
||||
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)
|
||||
|
@ -87,7 +83,7 @@ require 'rex/text'
|
|||
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 * 40) + 32
|
||||
bind_size = (bind_total * 44) + 28
|
||||
real_ctx, ctx = 0, 0
|
||||
|
||||
# Create the header of the bind request
|
||||
|
@ -104,8 +100,7 @@ require 'rex/text'
|
|||
5840, # max xmit frag
|
||||
5840, # max recv frag
|
||||
0, # assoc group
|
||||
1, # num ctx items
|
||||
bind_total, # context id
|
||||
bind_total, # num ctx items
|
||||
].pack('CCCCNvvVvvVV')
|
||||
|
||||
# Generate the fake UUIDs prior to the real one
|
||||
|
@ -117,7 +112,7 @@ require 'rex/text'
|
|||
|
||||
data +=
|
||||
[
|
||||
ctx += 1, # context id
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
rand_uuid, # interface uuid
|
||||
rand_imaj, # interface major version
|
||||
|
@ -126,13 +121,14 @@ require 'rex/text'
|
|||
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 += 1, # context id
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
u.uuid_pack(uuid), # interface uuid
|
||||
bind_vers_maj, # interface major version
|
||||
|
@ -141,7 +137,9 @@ require 'rex/text'
|
|||
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
|
||||
|
@ -151,7 +149,7 @@ require 'rex/text'
|
|||
|
||||
data +=
|
||||
[
|
||||
ctx += 1, # context id
|
||||
ctx, # context id
|
||||
1, # num trans items
|
||||
rand_uuid, # interface uuid
|
||||
rand_imaj, # interface major version
|
||||
|
@ -160,15 +158,14 @@ require 'rex/text'
|
|||
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()
|
||||
|
||||
|
@ -202,9 +199,7 @@ require 'rex/text'
|
|||
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
|
||||
|
@ -226,9 +221,7 @@ require 'rex/text'
|
|||
].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
|
||||
|
@ -253,7 +246,6 @@ require 'rex/text'
|
|||
return frags
|
||||
end
|
||||
|
||||
|
||||
# Create the first fragment of the request
|
||||
frags.push( make_request_chunk(1, opnum, chunks.shift, ctx) )
|
||||
|
||||
|
|
|
@ -15,23 +15,29 @@ class DCERPC::Response
|
|||
|
||||
attr_accessor :frag_len, :auth_len, :type, :vers_major, :vers_minor
|
||||
attr_accessor :flags, :data_rep, :call_id, :max_frag_xmit, :max_frag_recv
|
||||
attr_accessor :assoc_group, :sec_addr_len, :sec_addr, :num_results, :ack_result
|
||||
attr_accessor :ack_reason, :xfer_syntax_uuid, :xfer_syntax_vers
|
||||
|
||||
attr_accessor :assoc_group, :sec_addr_len, :sec_addr, :num_results
|
||||
attr_accessor :nack_reason, :xfer_syntax_uuid, :xfer_syntax_vers
|
||||
attr_accessor :ack_reason, :ack_result, :ack_xfer_syntax_uuid, :ack_xfer_syntax_vers
|
||||
attr_accessor :alloc_hint, :context_id, :cancel_cnt, :status, :stub_data
|
||||
|
||||
# Create a new DCERPC::Response object, using the first 10 bytes of the packet
|
||||
def initialize (head)
|
||||
self.frag_len = head[8,2].unpack('v')
|
||||
self.frag_len = head[8,2].unpack('v')[0]
|
||||
self.raw = head
|
||||
self.ack_result = []
|
||||
self.ack_reason = []
|
||||
self.ack_xfer_syntax_uuid = []
|
||||
self.ack_xfer_syntax_vers = []
|
||||
end
|
||||
|
||||
# Parse the contents of a DCERPC response packet and fill out all the fields
|
||||
def parse (body)
|
||||
self.raw = self.raw + body
|
||||
self.type = self.raw[2,1].unpack('C')
|
||||
self.type = self.raw[2,1].unpack('C')[0]
|
||||
|
||||
uuid = Rex::Proto::DCERPC::UUID.new()
|
||||
data = self.raw
|
||||
|
||||
|
||||
# BIND_ACK == 12, ALTER_CONTEXT_RESP == 15
|
||||
if (self.type == 12 or self.type == 15)
|
||||
|
||||
|
@ -49,29 +55,51 @@ class DCERPC::Response
|
|||
self.assoc_group,
|
||||
self.sec_addr_len = data.unpack('CCCCNvvVvvVv')
|
||||
|
||||
# Keep an offset into the packet handy
|
||||
x = 0
|
||||
|
||||
# XXX This is still somewhat broken (4 digit ports)
|
||||
self.sec_addr = data[26, self.sec_addr_len]
|
||||
|
||||
# Move the pointer into the packet forward
|
||||
data = data[26 + self.sec_addr_len, 0xffff]
|
||||
x += 26 + self.sec_addr_len + 2
|
||||
|
||||
self.num_results = data[2,1].unpack('C')
|
||||
self.ack_result = data[6,2].unpack('v')
|
||||
# Figure out how many results we have (multiple-context binds)
|
||||
self.num_results = data[ x, 4 ].unpack('V')[0]
|
||||
|
||||
# Move the pointer to the ack_result[0] offset
|
||||
x += 4
|
||||
|
||||
# Initialize the ack_result index
|
||||
ack = 0
|
||||
|
||||
if (self.ack_result != 0)
|
||||
self.ack_reason = data[8,2].unpack('v')
|
||||
data = data[2, 0xffff]
|
||||
# Scan through all results and add them to the result arrays
|
||||
while ack < self.num_results
|
||||
self.ack_result[ack] = data[ x + 0, 2 ].unpack('v')[0]
|
||||
self.ack_reason[ack] = data[ x + 2, 2 ].unpack('v')[0]
|
||||
self.ack_xfer_syntax_uuid[ack] = uuid.uuid_unpack(data[ x + 4, 16 ])
|
||||
self.ack_xfer_syntax_vers[ack] = data[ x + 20, 4 ].unpack('V')[0]
|
||||
x += 24
|
||||
ack += 1
|
||||
end
|
||||
|
||||
# Move it even further
|
||||
data = data[10, 0xffff]
|
||||
|
||||
self.xfer_syntax_uuid = uuid.uuid_unpack(data[0,16])
|
||||
self.xfer_syntax_vers = data[16,4].unpack('V')
|
||||
|
||||
# End of BIND_ACK || ALTER_CONTEXT_RESP
|
||||
end
|
||||
|
||||
|
||||
# BIND_NACK == 13
|
||||
if (self.type == 13)
|
||||
|
||||
# Decode most of the DCERPC header
|
||||
self.vers_major,
|
||||
self.vers_minor,
|
||||
trash,
|
||||
self.flags,
|
||||
self.data_rep,
|
||||
self.frag_len,
|
||||
self.auth_len,
|
||||
self.call_id,
|
||||
self.nack_reason = data.unpack('CCCCNvvVv')
|
||||
end
|
||||
|
||||
# RESPONSE == 2
|
||||
if (self.type == 2)
|
||||
|
@ -91,7 +119,7 @@ class DCERPC::Response
|
|||
|
||||
# Put the application data into self.stub_data
|
||||
self.stub_data = data[data.length - self.alloc_hint, 0xffff]
|
||||
|
||||
|
||||
# End of RESPONSE
|
||||
end
|
||||
|
||||
|
@ -114,8 +142,7 @@ class DCERPC::Response
|
|||
self.status = data.unpack('CCCCNvvVVvCCV')
|
||||
|
||||
# Put the application data into self.stub_data
|
||||
self.stub_data = data[data.length - self.alloc_hint, 0xffff]
|
||||
|
||||
self.stub_data = data[data.length - self.alloc_hint, 0xffff]
|
||||
# End of FAULT
|
||||
end
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ class DCERPC::UUID
|
|||
'SVCCTL' => [ '367abb81-9844-35f1-ad32-98f038001003', '2.0' ]
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
# Convert a UUID in binary format to the string representation
|
||||
def uuid_unpack(uuid_bin)
|
||||
sprintf("%.8x-%.4x-%.4x-%.4x-%s",
|
||||
uuid_bin[ 0, 4].unpack('V')[0],
|
||||
|
@ -35,31 +36,37 @@ class DCERPC::UUID
|
|||
)
|
||||
end
|
||||
|
||||
# Convert a UUID in string format to the binary representation
|
||||
def 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 ()
|
||||
self.uuid_pack('8a885d04-1ceb-11c9-9fe8-08002b104860')
|
||||
end
|
||||
|
||||
# Provide the common TransferSyntax version number
|
||||
def 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]
|
||||
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]
|
||||
end
|
||||
end
|
||||
|
||||
# Convert a string or number in float format to two unique numbers 2.0 => [2, 0]
|
||||
def vers_to_nums (vers)
|
||||
vers_maj = vers.to_i
|
||||
vers_min = ((vers.to_f - vers.to_i) * 10).to_i
|
||||
|
|
Loading…
Reference in New Issue