2013-01-31 19:53:37 +00:00
|
|
|
# -*- coding: binary -*-
|
|
|
|
module Rex
|
|
|
|
module Proto
|
|
|
|
module DCERPC
|
|
|
|
module WDSCP
|
|
|
|
class Packet
|
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
WDS_CONST = Rex::Proto::DCERPC::WDSCP::Constants
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
def initialize(packet_type, opcode)
|
|
|
|
if opcode.nil? || packet_type.nil?
|
|
|
|
raise(ArgumentError, "Packet arguments cannot be nil")
|
|
|
|
end
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
@variables = []
|
|
|
|
@packet_type = WDS_CONST::PACKET_TYPE[packet_type]
|
|
|
|
@opcode = WDS_CONST::OPCODE[opcode]
|
|
|
|
end
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
def add_var(name, type_mod=0, value_length=nil, array_size=0, value)
|
|
|
|
padding = 0
|
|
|
|
value_type = WDS_CONST::BASE_TYPE[WDS_CONST::VAR_TYPE_LOOKUP[name]]
|
|
|
|
name = Rex::Text.to_unicode(name).unpack('H*')[0]
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
value_length ||= value.length
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
# Variable block total size should be evenly divisible by 16.
|
|
|
|
len = 16 * (1 + (value_length/16))
|
|
|
|
@variables <<
|
|
|
|
[ name,
|
|
|
|
padding,
|
|
|
|
value_type,
|
|
|
|
type_mod,
|
|
|
|
value_length,
|
|
|
|
array_size,
|
|
|
|
value
|
|
|
|
].pack('H132vvvVVa%i' % len)
|
|
|
|
end
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
def create
|
|
|
|
packet = []
|
|
|
|
var_count = @variables.count
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
packet_size = 0
|
|
|
|
@variables.each do |var|
|
|
|
|
packet_size += var.length
|
|
|
|
end
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
# variables + operation
|
|
|
|
packet_size += 16
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
# These bytes are not part of the spec but are not part of DCERPC according to Wireshark
|
|
|
|
# Perhaps something from MSRPC specific? Basically length of the WDSCP packet twice...
|
|
|
|
packet << Rex::Text.pack_int64le(packet_size+40)*2
|
|
|
|
packet << create_endpoint_header(packet_size)
|
|
|
|
packet << create_operation_header(packet_size, var_count, @packet_type, @opcode)
|
|
|
|
packet.concat(@variables)
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
return packet.join
|
|
|
|
end
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
def create_operation_header(packet_size, var_count, packet_type=:REQUEST, opcode)
|
|
|
|
return [ packet_size, # PacketSize
|
|
|
|
256, # Version
|
|
|
|
packet_type, # Packet_Type
|
|
|
|
0, # Padding
|
|
|
|
opcode, # Opcode
|
|
|
|
var_count, # Variable Count
|
|
|
|
].pack('VvCCVV')
|
|
|
|
end
|
2013-01-31 19:53:37 +00:00
|
|
|
|
2013-09-05 21:21:26 +00:00
|
|
|
def create_endpoint_header(packet_size)
|
|
|
|
return [ 40, # Header_Size
|
|
|
|
256, # Version
|
|
|
|
packet_size, # Packet_Size - This doesn't differ from operation header despite the spec...
|
|
|
|
WDS_CONST::OS_DEPLOYMENT_GUID, # GUID
|
|
|
|
"\x00"*16, # Reserved
|
|
|
|
].pack('vvVa16a16')
|
|
|
|
end
|
2013-01-31 19:53:37 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|