Module: RubySMB::Dcerpc::Ndr::ArrayPlugin

Includes:
ConstructedTypePlugin
Defined in:
lib/ruby_smb/dcerpc/ndr.rb

Instance Method Summary collapse

Methods included from ConstructedTypePlugin

#defer_ptr, #do_num_bytes_ptr, #get_top_level_constructed_type, #has_deferred_ptrs?, #initialize_instance, #is_deferring, #read_ptr, #write_ptr

Instance Method Details

#align_element_size(offset) ⇒ Object



200
201
202
203
# File 'lib/ruby_smb/dcerpc/ndr.rb', line 200

def align_element_size(offset)
  align = eval_parameter(:type).instance_variable_get(:@obj_params)[:byte_align]
  align ? (align - (offset % align)) % align : 0
end

#do_num_bytes(struct_offset = 0) ⇒ Object



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/ruby_smb/dcerpc/ndr.rb', line 278

def do_num_bytes(struct_offset = 0)
  sum = 0

  if is_a?(ConfPlugin) && should_process_max_count?
    sum += 4
  end

  if is_a?(VarPlugin)
    sum += 8
  end

  unless empty?
    sum += align_element_size(struct_offset + sum)
    sum += super()
  end

  if has_deferred_ptrs?
    sum += do_num_bytes_ptr(struct_offset + sum)
  end
  sum
end

#do_read(io) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/ruby_smb/dcerpc/ndr.rb', line 248

def do_read(io)
  if is_a?(ConfPlugin) && should_process_max_count?
    max_count = io.readbytes(4).unpack1('L<')
    BinData.trace_message do |tracer|
      tracer.trace_obj("#{debug_name}.max_count", max_count.to_s)
    end
    set_max_count(max_count)
  end

  if is_a?(VarPlugin)
    @offset = io.readbytes(4).unpack('L<').first
    BinData.trace_message do |tracer|
      tracer.trace_obj("#{debug_name}.offset", @offset.to_s)
    end
    @actual_count = @read_until_index = io.readbytes(4).unpack('L<').first
    BinData.trace_message do |tracer|
      tracer.trace_obj("#{debug_name}.actual_count", @actual_count.to_s)
    end
  end

  if has_elements_to_read?
    io.seekbytes(align_element_size(io.offset))
    super
  end

  if has_deferred_ptrs?
    read_ptr(io)
  end
end

#do_write(io) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/ruby_smb/dcerpc/ndr.rb', line 211

def do_write(io)
  if is_a?(ConfPlugin) && should_process_max_count?
    io.writebytes([@max_count].pack('L<'))
  end

  if is_a?(VarPlugin)
    io.writebytes([@offset].pack('L<'))
    io.writebytes([@actual_count].pack('L<'))
  end

  unless empty?
    io.writebytes("\x00" * align_element_size(io.offset))
    super
  end

  if has_deferred_ptrs?
    write_ptr(io)
  end
end

#has_elements_to_read?Boolean

Returns:

  • (Boolean)


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/ruby_smb/dcerpc/ndr.rb', line 231

def has_elements_to_read?
  # When reading a binary stream, the only elements that indicate the array
  # has elements to read are :actual_count, :max_count or :initial_length
  # parameter, depending on the type of NDR Array:
  # 1. When :actual_count is present (NdrVarArray and NdrConfVarArray), it
  #    indicates the actual number of elements passed
  # 2. When only :max_count is present (NdrConfArray), we're assuming the
  #    maximum number of elements is the actual number of elements in this
  #    array
  # 3. None of them are present, but :initial_length parameter has been
  #    set, meaning we are delaing with a fixed array without any embedded
  #    size information (NdrFixArray)
  (@actual_count&.> 0) ||
  @actual_count.nil? && (@max_count&.> 0) ||
  @actual_count.nil? && @max_count.nil? && (eval_parameter(:initial_length)&.> 0)
end

#should_process_max_count?Boolean

Returns:

  • (Boolean)


205
206
207
208
209
# File 'lib/ruby_smb/dcerpc/ndr.rb', line 205

def should_process_max_count?
  # :max_count has already been processed if the parent structure is an
  # NdrStruct, but this is not the case if we are dealing with a pointer
  !parent.is_a?(NdrStruct) || self.is_a?(PointerPlugin)
end

#sum_num_bytes_below_index(index) ⇒ Object



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/ruby_smb/dcerpc/ndr.rb', line 300

def sum_num_bytes_below_index(index)
  (0...index).inject(0) do |sum, i|
    nbytes = 0
    if elements[i].has_parameter?(:byte_align) && elements[i].respond_to?(:bytes_to_align)
      nbytes = elements[i].bytes_to_align(elements[i], sum.ceil)
    end
    nbytes += elements[i].do_num_bytes

    if nbytes.is_a?(Integer)
      sum.ceil + nbytes
    else
      sum + nbytes
    end
  end
end