Fixes, tweaks, etc

git-svn-id: file:///home/svn/incoming/trunk@2783 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2005-07-17 23:28:28 +00:00
parent 48b59caeff
commit 5049896454
3 changed files with 76 additions and 50 deletions

View File

@ -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) )

View File

@ -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

View File

@ -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