Begin rework of packet handling

This moves some of the packet-specific stuff to the packet class itself
bug/bundler_fix
OJ 2017-06-20 19:18:37 +10:00
parent cec87a3e4f
commit 2129959d2d
No known key found for this signature in database
GPG Key ID: D5DC61FB93260597
2 changed files with 46 additions and 66 deletions

View File

@ -305,7 +305,7 @@ class Tlv
end
# check if the tlv is to be compressed...
if( @compress )
if @compress
raw_uncompressed = raw
# compress the raw data
raw_compressed = Rex::Text.zlib_deflate( raw_uncompressed )
@ -614,6 +614,7 @@ end
###
class Packet < GroupTlv
attr_accessor :created_at
attr_accessor :raw
##
#
@ -665,6 +666,7 @@ class Packet < GroupTlv
end
self.created_at = ::Time.now
self.raw = ''
# If it's a request, generate a random request identifier
if ((type == PACKET_TYPE_REQUEST) ||
@ -677,6 +679,28 @@ class Packet < GroupTlv
end
end
def add_raw(bytes)
self.raw << bytes
end
def raw_bytes_required
# if we have the xor bytes and length ...
if self.raw.length >= 8
# return a value based on the length of the data indicated by
# the header
xor_key = self.raw[0, 4]
length_bytes = xor_bytes(xor_key, raw[4, 4])
length = length_bytes.unpack("N")[0]
# the raw buffer will always be 4 bytes longer than the length value
# given because of the xor key, so the number of bytes we need is ...
length - self.raw.length + 4
else
# Otherwise ask for the remaining 8 bytes for the xor/length
# So we can do the rest of the calculation next time
8 - self.raw.length
end
end
#
# Override the function that creates the raw byte stream for
# sending so that it generates an XOR key, uses it to scramble
@ -685,11 +709,8 @@ class Packet < GroupTlv
#
def to_r
raw = super
xor_key = rand(254) + 1
xor_key |= (rand(254) + 1) << 8
xor_key |= (rand(254) + 1) << 16
xor_key |= (rand(254) + 1) << 24
result = [xor_key].pack('N') + xor_bytes(xor_key, raw)
xor_key = (rand(254) + 1).chr + (rand(254) + 1).chr + (rand(254) + 1).chr + (rand(254) + 1).chr
result = xor_key + xor_bytes(xor_key, raw)
result
end
@ -699,17 +720,18 @@ class Packet < GroupTlv
# passing it on to the default functionality that can parse
# the TLV values.
#
def from_r(bytes)
xor_key = bytes[0,4].unpack('N')[0]
def from_r(bytes=nil)
bytes ||= self.raw
xor_key = bytes[0,4]
super(xor_bytes(xor_key, bytes[4, bytes.length]))
end
#
# Xor a set of bytes with a given DWORD xor key.
# Xor a set of bytes with a given XOR key.
#
def xor_bytes(xor_key, bytes)
result = ''
bytes.bytes.zip([xor_key].pack('V').bytes.cycle).each do |b|
bytes.bytes.zip(xor_key.bytes.cycle).each do |b|
result << (b[0].ord ^ b[1].ord).chr
end
result

View File

@ -12,17 +12,10 @@ module Meterpreter
###
class PacketParser
# 4 byte xor
# 4 byte length
# 4 byte type
HEADER_SIZE = 12
#
# Initializes the packet parser context with an optional cipher.
# Initializes the packet parser context.
#
def initialize(cipher = nil)
self.cipher = cipher
def initialize
reset
end
@ -30,71 +23,36 @@ class PacketParser
# Resets the parser state so that a new packet can begin being parsed.
#
def reset
self.raw = ''
self.hdr_length_left = HEADER_SIZE
self.payload_length_left = 0
self.packet = Packet.new(0)
end
#
# Reads data from the wire and parse as much of the packet as possible.
#
def recv(sock)
# Create a typeless packet
packet = Packet.new(0)
bytes_left = self.packet.raw_bytes_required
if (self.hdr_length_left > 0)
buf = sock.read(self.hdr_length_left)
if (buf)
self.raw << buf
self.hdr_length_left -= buf.length
else
raise EOFError
end
# If we've finished reading the header, set the
# payload length left to the number of bytes
# specified in the length
if (self.hdr_length_left == 0)
xor_key = raw[0, 4].unpack('N')[0]
length_bytes = packet.xor_bytes(xor_key, raw[4, 4])
# header size doesn't include the xor key, which is always tacked on the front
self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4)
end
end
if (self.payload_length_left > 0)
buf = sock.read(self.payload_length_left)
if (buf)
self.raw << buf
self.payload_length_left -= buf.length
if bytes_left > 0
raw = sock.read(bytes_left)
if raw
self.packet.add_raw(raw)
else
raise EOFError
end
end
# If we've finished reading the entire packet
if ((self.hdr_length_left == 0) &&
(self.payload_length_left == 0))
# TODO: cipher decryption
if (cipher)
end
# Deserialize the packet from the raw buffer
packet.from_r(self.raw)
# Reset our state
if self.packet.raw_bytes_required == 0
packet = self.packet
packet.from_r
reset
return packet
end
nil
end
protected
attr_accessor :cipher, :raw, :hdr_length_left, :payload_length_left # :nodoc:
attr_accessor :cipher, :packet # :nodoc:
end