mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-05 14:57:30 +01:00
XDR-fu j0!
git-svn-id: file:///home/svn/incoming/trunk@2331 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
parent
cedab15c8f
commit
77d1ffb488
102
lib/rex/proto/rpc/xdr.rb
Executable file
102
lib/rex/proto/rpc/xdr.rb
Executable file
@ -0,0 +1,102 @@
|
||||
module Rex
|
||||
|
||||
class XDR
|
||||
MAX_ARG = 0xffffffff
|
||||
private_class_method :new
|
||||
|
||||
# Also: unsigned int, bool, enum
|
||||
def XDR.encode_int(int)
|
||||
return [int].pack('N')
|
||||
end
|
||||
|
||||
def XDR.decode_int!(data)
|
||||
return data.slice!(0..3).unpack('N')[0]
|
||||
end
|
||||
|
||||
|
||||
def XDR.encode_lchar(char)
|
||||
char |= 0xffffff00 if char & 0x80 != 0
|
||||
return encode_int(char)
|
||||
end
|
||||
|
||||
def XDR.decode_lchar!(data)
|
||||
return (decode_int!(data) & 0xff).chr
|
||||
end
|
||||
|
||||
|
||||
# Also: Variable length opaque
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
def XDR.decode_varray!(data)
|
||||
buf = []
|
||||
1.upto(decode_int!(data)) { buf.push(yield(data)) }
|
||||
return buf
|
||||
end
|
||||
|
||||
|
||||
|
||||
# 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)
|
||||
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
|
||||
|
||||
# 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) }]
|
||||
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
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue
Block a user