class Rex::Post::Meterpreter::Tlv
Base TLV (Type-Length-Value) class
Attributes
compress[RW]
type[RW]
value[RW]
Public Class Methods
new(type, value = nil, compress=false)
click to toggle source
Returns an instance of a TLV.
# File lib/rex/post/meterpreter/packet.rb, line 113 def initialize(type, value = nil, compress=false) @type = type @compress = compress if (value != nil) if (type & TLV_META_TYPE_STRING == TLV_META_TYPE_STRING) if (value.kind_of?(Fixnum)) @value = value.to_s else @value = value.dup end else @value = value end end end
Public Instance Methods
from_r(raw)
click to toggle source
Translates the raw format of the TLV into a sanitize version.
# File lib/rex/post/meterpreter/packet.rb, line 285 def from_r(raw) self.value = nil length, self.type = raw.unpack("NN"); # check if the tlv value has been compressed... if( self.type & TLV_META_TYPE_COMPRESSED == TLV_META_TYPE_COMPRESSED ) # set this TLV as using compression @compress = true # remove the TLV_META_TYPE_COMPRESSED flag from the tlv type to restore the # tlv type to its origional, allowing for transparent data compression. self.type = self.type ^ TLV_META_TYPE_COMPRESSED # decompress the compressed data (skipping the length and type DWORD's) raw_decompressed = Rex::Text.zlib_inflate( raw[8..length-1] ) # update the length to reflect the decompressed data length (+8 for the length and type DWORD's) length = raw_decompressed.length + 8 # update the raw buffer with the new length, decompressed data and updated type. raw = [length, self.type].pack("NN") + raw_decompressed end if (self.type & TLV_META_TYPE_STRING == TLV_META_TYPE_STRING) if (raw.length > 0) self.value = raw[8..length-2] else self.value = nil end elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT) self.value = raw.unpack("NNN")[2] elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD) self.value = raw.unpack("NNQ<")[2] self.value = self.ntohq( self.value ) elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL) self.value = raw.unpack("NNc")[2] if (self.value == 1) self.value = true else self.value = false end else self.value = raw[8..length-1] end return length; end
inspect()
click to toggle source
# File lib/rex/post/meterpreter/packet.rb, line 130 def inspect utype = type ^ TLV_META_TYPE_COMPRESSED group = false meta = case (utype & TLV_META_MASK) when TLV_META_TYPE_STRING; "STRING" when TLV_META_TYPE_UINT; "INT" when TLV_META_TYPE_RAW; "RAW" when TLV_META_TYPE_BOOL; "BOOL" when TLV_META_TYPE_QWORD; "QWORD" when TLV_META_TYPE_GROUP; group=true; "GROUP" when TLV_META_TYPE_COMPLEX; "COMPLEX" else; 'unknown-meta-type' end stype = case type when PACKET_TYPE_REQUEST; "Request" when PACKET_TYPE_RESPONSE; "Response" when TLV_TYPE_REQUEST_ID; "REQUEST-ID" when TLV_TYPE_METHOD; "METHOD" when TLV_TYPE_RESULT; "RESULT" when TLV_TYPE_EXCEPTION; "EXCEPTION" when TLV_TYPE_STRING; "STRING" when TLV_TYPE_UINT; "UINT" when TLV_TYPE_BOOL; "BOOL" when TLV_TYPE_LENGTH; "LENGTH" when TLV_TYPE_DATA; "DATA" when TLV_TYPE_FLAGS; "FLAGS" when TLV_TYPE_CHANNEL_ID; "CHANNEL-ID" when TLV_TYPE_CHANNEL_TYPE; "CHANNEL-TYPE" when TLV_TYPE_CHANNEL_DATA; "CHANNEL-DATA" when TLV_TYPE_CHANNEL_DATA_GROUP; "CHANNEL-DATA-GROUP" when TLV_TYPE_CHANNEL_CLASS; "CHANNEL-CLASS" when TLV_TYPE_CHANNEL_PARENTID; "CHANNEL-PARENTID" when TLV_TYPE_SEEK_WHENCE; "SEEK-WHENCE" when TLV_TYPE_SEEK_OFFSET; "SEEK-OFFSET" when TLV_TYPE_SEEK_POS; "SEEK-POS" when TLV_TYPE_EXCEPTION_CODE; "EXCEPTION-CODE" when TLV_TYPE_EXCEPTION_STRING; "EXCEPTION-STRING" when TLV_TYPE_LIBRARY_PATH; "LIBRARY-PATH" when TLV_TYPE_TARGET_PATH; "TARGET-PATH" when TLV_TYPE_MIGRATE_PID; "MIGRATE-PID" when TLV_TYPE_MIGRATE_LEN; "MIGRATE-LEN" when TLV_TYPE_MIGRATE_PAYLOAD; "MIGRATE-PAYLOAD" when TLV_TYPE_MIGRATE_ARCH; "MIGRATE-ARCH" #when Extensions::Stdapi::TLV_TYPE_NETWORK_INTERFACE; 'network-interface' #when Extensions::Stdapi::TLV_TYPE_IP; 'ip-address' #when Extensions::Stdapi::TLV_TYPE_NETMASK; 'netmask' #when Extensions::Stdapi::TLV_TYPE_MAC_ADDRESS; 'mac-address' #when Extensions::Stdapi::TLV_TYPE_MAC_NAME; 'interface-name' #when Extensions::Stdapi::TLV_TYPE_IP6_SCOPE; 'address-scope' #when Extensions::Stdapi::TLV_TYPE_INTERFACE_MTU; 'interface-mtu' #when Extensions::Stdapi::TLV_TYPE_INTERFACE_FLAGS; 'interface-flags' #when Extensions::Stdapi::TLV_TYPE_INTERFACE_INDEX; 'interface-index' else; "unknown-#{type}" end val = value.inspect if val.length > 50 val = val[0,50] + ' ..."' end group ||= (self.class.to_s =~ /Packet/) if group tlvs_inspect = "tlvs=[\n" @tlvs.each { |t| tlvs_inspect << " #{t.inspect}\n" } tlvs_inspect << "]" else tlvs_inspect = "meta=#{meta.ljust 10} value=#{val}" end "#<#{self.class} type=#{stype.ljust 15} #{tlvs_inspect}>" end
meta_type?(meta)
click to toggle source
Checks to see if a TLVs meta type is equivalent to the meta type passed.
# File lib/rex/post/meterpreter/packet.rb, line 217 def meta_type?(meta) return (self.type & meta == meta) end
to_r()
click to toggle source
Converts the TLV to raw.
# File lib/rex/post/meterpreter/packet.rb, line 244 def to_r # Forcibly convert to ASCII-8BIT encoding raw = value.to_s.unpack("C*").pack("C*") if (self.type & TLV_META_TYPE_STRING == TLV_META_TYPE_STRING) raw += "\x00" elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT) raw = [value].pack("N") elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD) raw = [ self.htonq( value.to_i ) ].pack("Q<") elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL) if (value == true) raw = [1].pack("c") else raw = [0].pack("c") end end # check if the tlv is to be compressed... if( @compress ) raw_uncompressed = raw # compress the raw data raw_compressed = Rex::Text.zlib_deflate( raw_uncompressed ) # check we have actually made the raw data smaller... # (small blobs often compress slightly larger then the origional) # if the compressed data is not smaller, we dont use the compressed data if( raw_compressed.length < raw_uncompressed.length ) # if so, set the TLV's type to indicate compression is used self.type = self.type | TLV_META_TYPE_COMPRESSED # update the raw data with the uncompressed data length + compressed data # (we include the uncompressed data length as the C side will need to know this for decompression) raw = [ raw_uncompressed.length ].pack("N") + raw_compressed end end return [raw.length + 8, self.type].pack("NN") + raw end
type?(type)
click to toggle source
Checks to see if the TLVs type is equivalent to the type passed.
# File lib/rex/post/meterpreter/packet.rb, line 224 def type?(type) return self.type == type end
value?(value)
click to toggle source
Checks to see if the TLVs value is equivalent to the value passed.
# File lib/rex/post/meterpreter/packet.rb, line 231 def value?(value) return self.value == value end
Protected Instance Methods
htonq( value )
click to toggle source
# File lib/rex/post/meterpreter/packet.rb, line 333 def htonq( value ) if( [1].pack( 's' ) == [1].pack( 'n' ) ) return value end return [ value ].pack( 'Q<' ).reverse.unpack( 'Q<' ).first end
ntohq( value )
click to toggle source
# File lib/rex/post/meterpreter/packet.rb, line 340 def ntohq( value ) return htonq( value ) end