Module: Rex::Encoder::XDR

Defined in:
lib/rex/encoder/xdr.rb

Overview

This class implements basic XDR encoding.

Constant Summary collapse

MAX_ARG =
0xffffffff

Class Method Summary collapse

Class Method Details

.decode!(buf, *data) ⇒ Object

decode(buf, Integer, String, [Integer], [String]) does: [decode_int!(buf), decode_string!(buf),

decode_varray!(buf) { |i| XDR.decode_int!(i) },
decode_varray!(buf) { |s| XDR.decode_string(s) }]


91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rex/encoder/xdr.rb', line 91

def XDR.decode!(buf, *data)
  return *data.collect do |var|
    if data.length == 0
    elsif var.kind_of?(Array) && var[0] == String
      decode_varray!(buf) { |s| XDR.decode_string!(s) }
    elsif var.kind_of?(Array) && var[0] == Integer
      decode_varray!(buf) { |i| XDR.decode_int!(i) }
    elsif var == String
      decode_string!(buf)
    elsif var == Integer
      decode_int!(buf)
    end
  end
end

.decode_int!(data) ⇒ Object

Raises:



18
19
20
21
22
# File 'lib/rex/encoder/xdr.rb', line 18

def XDR.decode_int!(data)
  raise ArgumentError, 'XDR: No Integer data to decode' unless data
  raise ArgumentError, "XDR: Too little data to decode (#{data.size})" if data.size < 4
  return data.slice!(0..3).unpack('N')[0]
end

.decode_lchar!(data) ⇒ Object



29
30
31
# File 'lib/rex/encoder/xdr.rb', line 29

def XDR.decode_lchar!(data)
  return (decode_int!(data) & 0xff).chr
end

.decode_string!(data) ⇒ Object



41
42
43
44
45
46
# File 'lib/rex/encoder/xdr.rb', line 41

def XDR.decode_string!(data)
  real_len = decode_int!(data)
  return "" if real_len == 0
  align_len = (real_len + 3) & ~3
  return data.slice!(0..align_len-1).slice(0..real_len-1)
end

.decode_varray!(data) ⇒ Object



53
54
55
56
57
# File 'lib/rex/encoder/xdr.rb', line 53

def XDR.decode_varray!(data)
  buf = []
  1.upto(decode_int!(data)) { buf.push(yield(data)) }
  return buf
end

.encode(*data) ⇒ Object

encode(0, [0, 1], “foo”, [“bar”, 4]) does:

encode_int(0) +
encode_varray([0, 1]) { |i| XDR.encode_int(i) } +
encode_string("foo") +
encode_string("bar", 4)


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/rex/encoder/xdr.rb', line 64

def XDR.encode(*data)
  data.collect do |var|
    if var.kind_of?(String)
      encode_string(var)
    elsif var.kind_of?(Integer)
      encode_int(var)
    elsif var.kind_of?(Array) && var[0].kind_of?(String)
      raise ArgumentError, 'XDR: Incorrect string array arguments' if var.length != 2
      encode_string(var[0], var[1])
    elsif var.kind_of?(Array) && var[0].kind_of?(Integer)
      encode_varray(var) { |i| XDR.encode_int(i) }
    # 0 means an empty array index in the case of Integer and an empty string in
    #   the case of String so we get the best of both worlds
    elsif var.kind_of?(Array) && var[0].nil?
      encode_int(0)
    else
      type = var.class
      type = var[0].class if var.kind_of?(Array)
      raise TypeError, "XDR: encode does not support #{type}"
    end
  end.join(nil)
end

.encode_int(int) ⇒ Object

Also: unsigned int, bool, enum



14
15
16
# File 'lib/rex/encoder/xdr.rb', line 14

def XDR.encode_int(int)
  return [int].pack('N')
end

.encode_lchar(char) ⇒ Object



24
25
26
27
# File 'lib/rex/encoder/xdr.rb', line 24

def XDR.encode_lchar(char)
  char |= 0xffffff00 if char & 0x80 != 0
  return encode_int(char)
end

.encode_string(str, max = MAX_ARG) ⇒ Object

Also: Variable length opaque

Raises:



34
35
36
37
38
39
# File 'lib/rex/encoder/xdr.rb', line 34

def XDR.encode_string(str, max=MAX_ARG)
  raise ArgumentError, 'XDR: String too long' if str.length > max
  len = str.length
  str << "\x00" * ((4 - (len & 3)) & 3)
  return encode_int(len) + str
end

.encode_varray(arr, max = MAX_ARG, &block) ⇒ Object

Raises:



48
49
50
51
# File 'lib/rex/encoder/xdr.rb', line 48

def XDR.encode_varray(arr, max=MAX_ARG, &block)
  raise ArgumentError, 'XDR: Too many array elements' if arr.length > max
  return encode_int(arr.length) + arr.collect(&block).join(nil)
end