metasploit-framework/lib/rex/proto/dcerpc/packet.rb

253 lines
6.6 KiB
Ruby

module Rex
module Proto
module DCERPC
class Packet
require 'rex/proto/dcerpc/uuid'
require 'rex/proto/dcerpc/response'
require 'rex/text'
UUID = Rex::Proto::DCERPC::UUID
# Create a standard DCERPC BIND request packet
def self.make_bind(uuid, vers)
# Process the version strings ("1.0", 1.0, "1", 1)
bind_vers_maj, bind_vers_min = UUID.vers_to_nums(vers)
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(UUID.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
UUID.uuid_pack(uuid), # interface uuid
bind_vers_maj, # interface major version
bind_vers_min, # interface minor version
UUID.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=0, bind_tail=0)
bind_head = rand(6)+10 if bind_head == 0
bind_tail = rand(4)+1 if bind_head == 0
u = Rex::Proto::DCERPC::UUID
# Process the version strings ("1.0", 1.0, "1", 1)
bind_vers_maj, bind_vers_min = UUID.vers_to_nums(vers)
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(UUID.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
UUID.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
UUID.uuid_pack(uuid), # interface uuid
bind_vers_maj, # interface major version
bind_vers_min, # interface minor version
UUID.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
UUID.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 = UUID.vers_to_nums(vers)
xfer_vers_maj, xfer_vers_min = UUID.vers_to_nums(UUID.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
UUID.uuid_pack(uuid), # interface uuid
bind_vers_maj, # interface major version
bind_vers_min, # interface minor version
UUID.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, object_id = '')
dlen = data.length
flen = dlen + 24
use_object = 0
object_str = ''
if object_id.size > 0
flags |= 0x80
flen = flen + 16
object_str = UUID.uuid_pack(object_id)
end
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') + object_str + data
end
# Used to create standard DCERPC REQUEST packet(s)
def self.make_request(opnum=0, data="", size=data.length, ctx=0, object_id = '')
if size > 4000
size = 4000
end
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, object_id) )
return frags
end
# Process requests with only one fragment
if chunks.length == 1
frags.push( make_request_chunk(3, opnum, chunks[0], ctx, object_id) )
return frags
end
# Create the first fragment of the request
frags.push( make_request_chunk(1, opnum, chunks.shift, ctx, object_id) )
# Create all of the middle fragments
while chunks.length != 1
frags.push( make_request_chunk(0, opnum, chunks.shift, ctx, object_id) )
end
# Create the last fragment of the request
frags.push( make_request_chunk(2, opnum, chunks.shift, ctx, object_id) )
return frags
end
end
end
end
end