Initial working version of AES encryption of TLVs
parent
2129959d2d
commit
a9e03c1efd
|
@ -43,6 +43,8 @@ module MeterpreterOptions
|
|||
|
||||
valid = true
|
||||
|
||||
session.aes_key = session.core.negotiate_aes
|
||||
|
||||
if datastore['AutoVerifySession']
|
||||
if not session.is_valid_session?(datastore['AutoVerifySessionTimeout'].to_i)
|
||||
print_error("Meterpreter session #{session.sid} is not valid and will be closed")
|
||||
|
@ -52,14 +54,14 @@ module MeterpreterOptions
|
|||
|
||||
if valid
|
||||
# always make sure that the new session has a new guid if it's not already known
|
||||
guid = session.core.get_session_guid
|
||||
guid = session.session_guid
|
||||
STDERR.puts("Session GUID is #{guid}\n")
|
||||
if guid == '00000000-0000-0000-0000-000000000000'
|
||||
guid = SecureRandom.uuid
|
||||
session.core.set_session_guid(guid)
|
||||
session.guid = guid
|
||||
session.session_guid = guid
|
||||
# TODO: New statgeless session, do some account in the DB so we can track it later.
|
||||
else
|
||||
session.guid = guid
|
||||
# TODO: This session was either staged or previously known, and so we shold do some accounting here!
|
||||
end
|
||||
|
||||
|
|
|
@ -385,10 +385,6 @@ module Session
|
|||
#
|
||||
attr_accessor :machine_id
|
||||
#
|
||||
# The guid that identifies an active Meterpreter session
|
||||
#
|
||||
attr_accessor :guid
|
||||
#
|
||||
# The actual exploit module instance that created this session
|
||||
#
|
||||
attr_accessor :exploit
|
||||
|
|
|
@ -77,7 +77,7 @@ class Client
|
|||
# Initializes the client context with the supplied socket through
|
||||
# which communication with the server will be performed.
|
||||
#
|
||||
def initialize(sock,opts={})
|
||||
def initialize(sock, opts={})
|
||||
init_meterpreter(sock, opts)
|
||||
end
|
||||
|
||||
|
@ -130,6 +130,9 @@ class Client
|
|||
# self.encode_unicode = opts.has_key?(:encode_unicode) ? opts[:encode_unicode] : true
|
||||
self.encode_unicode = false
|
||||
|
||||
self.aes_key = nil
|
||||
self.session_guid = '00000000-0000-0000-0000-000000000000'
|
||||
|
||||
# The SSL certificate is being passed down as a file path
|
||||
if opts[:ssl_cert]
|
||||
if ! ::File.exist? opts[:ssl_cert]
|
||||
|
|
|
@ -75,6 +75,7 @@ class ClientCore < Extension
|
|||
begin
|
||||
response = self.client.send_packet_wait_response(request, self.client.response_timeout)
|
||||
rescue
|
||||
STDERR.puts("Getting ext commands for #{extension_name} failed with an exception\n")
|
||||
# In the case where orphaned shells call back with OLD copies of the meterpreter
|
||||
# binaries, we end up with a case where this fails. So here we just return the
|
||||
# empty list of supported commands.
|
||||
|
@ -210,7 +211,8 @@ class ClientCore < Extension
|
|||
image = f.read
|
||||
}
|
||||
|
||||
if !image.nil?
|
||||
if image
|
||||
STDERR.puts("Capabilities zlib: #{client.capabilities[:zlib]}\n")
|
||||
request.add_tlv(TLV_TYPE_DATA, image, false, client.capabilities[:zlib])
|
||||
else
|
||||
raise RuntimeError, "Failed to serialize library #{library_path}.", caller
|
||||
|
@ -287,6 +289,8 @@ class ClientCore < Extension
|
|||
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller
|
||||
end
|
||||
|
||||
STDERR.puts("Going to try to load #{mod} from #{path}\n")
|
||||
|
||||
# Load the extension DLL
|
||||
commands = load_library(
|
||||
'LibraryFilePath' => path,
|
||||
|
@ -680,10 +684,13 @@ class ClientCore < Extension
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Negotiates the use of AES256 encryption over the TLV packets.
|
||||
#
|
||||
def negotiate_aes
|
||||
request = Packet.create_request('core_negotiate_aes')
|
||||
response = client.send_request(request)
|
||||
response
|
||||
response.get_tlv_value(TLV_TYPE_AES_KEY)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'openssl'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
|
@ -109,7 +110,6 @@ TLV_TYPE_SESSION_GUID = TLV_META_TYPE_RAW | 462
|
|||
|
||||
TLV_TYPE_CIPHER_NAME = TLV_META_TYPE_STRING | 500
|
||||
TLV_TYPE_CIPHER_PARAMETERS = TLV_META_TYPE_GROUP | 501
|
||||
|
||||
TLV_TYPE_AES_KEY = TLV_META_TYPE_RAW | 550
|
||||
|
||||
#
|
||||
|
@ -127,6 +127,8 @@ LOAD_LIBRARY_FLAG_LOCAL = (1 << 2)
|
|||
class Tlv
|
||||
attr_accessor :type, :value, :compress
|
||||
|
||||
HEADER_SIZE = 8
|
||||
|
||||
##
|
||||
#
|
||||
# Constructor
|
||||
|
@ -321,7 +323,7 @@ class Tlv
|
|||
end
|
||||
end
|
||||
|
||||
return [raw.length + 8, self.type].pack("NN") + raw
|
||||
[raw.length + HEADER_SIZE, self.type].pack("NN") + raw
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -340,16 +342,16 @@ class Tlv
|
|||
# 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
|
||||
raw_decompressed = Rex::Text.zlib_inflate( raw[HEADER_SIZE..length-1] )
|
||||
# update the length to reflect the decompressed data length (+HEADER_SIZE for the length and type DWORD's)
|
||||
length = raw_decompressed.length + HEADER_SIZE
|
||||
# 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]
|
||||
self.value = raw[HEADER_SIZE..length-2]
|
||||
else
|
||||
self.value = nil
|
||||
end
|
||||
|
@ -367,23 +369,24 @@ class Tlv
|
|||
self.value = false
|
||||
end
|
||||
else
|
||||
self.value = raw[8..length-1]
|
||||
self.value = raw[HEADER_SIZE..length-1]
|
||||
end
|
||||
|
||||
return length;
|
||||
length
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def htonq( value )
|
||||
if( [1].pack( 's' ) == [1].pack( 'n' ) )
|
||||
def htonq(value)
|
||||
if [1].pack( 's' ) == [1].pack('n')
|
||||
return value
|
||||
else
|
||||
[value].pack('Q<').reverse.unpack('Q<').first
|
||||
end
|
||||
return [ value ].pack( 'Q<' ).reverse.unpack( 'Q<' ).first
|
||||
end
|
||||
|
||||
def ntohq( value )
|
||||
return htonq( value )
|
||||
def ntohq(value)
|
||||
htonq(value)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -409,7 +412,7 @@ class GroupTlv < Tlv
|
|||
def initialize(type)
|
||||
super(type)
|
||||
|
||||
self.tlvs = [ ]
|
||||
self.tlvs = []
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -450,8 +453,8 @@ class GroupTlv < Tlv
|
|||
# Returns an array of TLVs for the given type.
|
||||
#
|
||||
def get_tlvs(type)
|
||||
if (type == TLV_TYPE_ANY)
|
||||
return self.tlvs
|
||||
if type == TLV_TYPE_ANY
|
||||
self.tlvs
|
||||
else
|
||||
type_tlvs = []
|
||||
|
||||
|
@ -461,7 +464,7 @@ class GroupTlv < Tlv
|
|||
end
|
||||
}
|
||||
|
||||
return type_tlvs
|
||||
type_tlvs
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -477,7 +480,7 @@ class GroupTlv < Tlv
|
|||
def add_tlv(type, value = nil, replace = false, compress=false)
|
||||
|
||||
# If we should replace any TLVs with the same type...remove them first
|
||||
if (replace)
|
||||
if replace
|
||||
each(type) { |tlv|
|
||||
if (tlv.type == type)
|
||||
self.tlvs.delete(tlv)
|
||||
|
@ -493,14 +496,14 @@ class GroupTlv < Tlv
|
|||
|
||||
self.tlvs << tlv
|
||||
|
||||
return tlv
|
||||
tlv
|
||||
end
|
||||
|
||||
#
|
||||
# Adds zero or more TLVs to the packet.
|
||||
#
|
||||
def add_tlvs(tlvs)
|
||||
if (tlvs != nil)
|
||||
if tlvs
|
||||
tlvs.each { |tlv|
|
||||
add_tlv(tlv['type'], tlv['value'])
|
||||
}
|
||||
|
@ -513,11 +516,12 @@ class GroupTlv < Tlv
|
|||
def get_tlv(type, index = 0)
|
||||
type_tlvs = get_tlvs(type)
|
||||
|
||||
if (type_tlvs.length > index)
|
||||
return type_tlvs[index]
|
||||
if type_tlvs.length > index
|
||||
type_tlvs[index]
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -526,7 +530,7 @@ class GroupTlv < Tlv
|
|||
def get_tlv_value(type, index = 0)
|
||||
tlv = get_tlv(type, index)
|
||||
|
||||
return (tlv != nil) ? tlv.value : nil
|
||||
(tlv != nil) ? tlv.value : nil
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -540,7 +544,7 @@ class GroupTlv < Tlv
|
|||
# Checks to see if the container has a TLV of a given type.
|
||||
#
|
||||
def has_tlv?(type)
|
||||
return get_tlv(type) != nil
|
||||
get_tlv(type) != nil
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -567,7 +571,7 @@ class GroupTlv < Tlv
|
|||
raw << tlv.to_r
|
||||
}
|
||||
|
||||
return [raw.length + 8, self.type].pack("NN") + raw
|
||||
[raw.length + HEADER_SIZE, self.type].pack("NN") + raw
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -575,19 +579,19 @@ class GroupTlv < Tlv
|
|||
# TLVs.
|
||||
#
|
||||
def from_r(raw)
|
||||
offset = 8
|
||||
offset = HEADER_SIZE
|
||||
|
||||
# Reset the TLVs array
|
||||
self.tlvs = []
|
||||
self.type = raw.unpack("NN")[1]
|
||||
|
||||
# Enumerate all of the TLVs
|
||||
while (offset < raw.length-1)
|
||||
while offset < raw.length-1
|
||||
|
||||
tlv = nil
|
||||
|
||||
# Get the length and type
|
||||
length, type = raw[offset..offset+8].unpack("NN")
|
||||
length, type = raw[offset..offset+HEADER_SIZE].unpack("NN")
|
||||
|
||||
if (type & TLV_META_TYPE_GROUP == TLV_META_TYPE_GROUP)
|
||||
tlv = GroupTlv.new(type)
|
||||
|
@ -615,6 +619,56 @@ end
|
|||
class Packet < GroupTlv
|
||||
attr_accessor :created_at
|
||||
attr_accessor :raw
|
||||
attr_accessor :session_guid
|
||||
|
||||
##
|
||||
#
|
||||
# The Packet container itself has a custom header that is slightly different to the
|
||||
# typical TLV packets. The header contains the following:
|
||||
#
|
||||
# XOR KEY - 4 bytes
|
||||
# Session GUID - 16 bytes
|
||||
# Encrypted flag - 1 byte
|
||||
# Packet length - 4 bytes
|
||||
# Packet type - 4 bytes
|
||||
# Packet data - X bytes
|
||||
#
|
||||
# If the encrypted flag is NOT set, then the Packet data is just straight TLV values as
|
||||
# per the normal TLV packet structure.
|
||||
#
|
||||
# If the encrypted flag IS set, then the Packet data is an AES256 encrypted block with
|
||||
# the following format:
|
||||
#
|
||||
# IV - 16 bytes
|
||||
# Encrypted data - X bytes
|
||||
#
|
||||
# The key that is required to decrypt the data is stored alongside the session data,
|
||||
# and hence when the packet is initially parsed, only the header is accessed. The
|
||||
# packet itself will need to be decrypted on the fly at the point that it is required
|
||||
# and at that point the decryption key needs to be provided.
|
||||
#
|
||||
###
|
||||
|
||||
XOR_KEY_OFF = 0
|
||||
XOR_KEY_SIZE = 4
|
||||
|
||||
SESSION_GUID_OFF = XOR_KEY_OFF + XOR_KEY_SIZE
|
||||
SESSION_GUID_SIZE = 16
|
||||
|
||||
ENCRYPTED_FLAG_OFF = SESSION_GUID_OFF + SESSION_GUID_SIZE
|
||||
ENCRYPTED_FLAG_SIZE = 1
|
||||
|
||||
PACKET_LENGTH_OFF = ENCRYPTED_FLAG_OFF + ENCRYPTED_FLAG_SIZE
|
||||
PACKET_LENGTH_SIZE = 4
|
||||
|
||||
PACKET_TYPE_OFF = PACKET_LENGTH_OFF + PACKET_LENGTH_SIZE
|
||||
PACKET_TYPE_SIZE = 4
|
||||
|
||||
PACKET_DATA_OFF = PACKET_TYPE_OFF + PACKET_TYPE_SIZE
|
||||
|
||||
REQUIRED_PREFIX_SIZE = XOR_KEY_SIZE + SESSION_GUID_SIZE + ENCRYPTED_FLAG_SIZE + PACKET_LENGTH_SIZE
|
||||
|
||||
AES_IV_SIZE = 16
|
||||
|
||||
##
|
||||
#
|
||||
|
@ -626,7 +680,7 @@ class Packet < GroupTlv
|
|||
# Creates a request with the supplied method.
|
||||
#
|
||||
def Packet.create_request(method = nil)
|
||||
return Packet.new(PACKET_TYPE_REQUEST, method)
|
||||
Packet.new(PACKET_TYPE_REQUEST, method)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -644,7 +698,7 @@ class Packet < GroupTlv
|
|||
method = request.method
|
||||
end
|
||||
|
||||
return Packet.new(response_type, method)
|
||||
Packet.new(response_type, method)
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -661,7 +715,7 @@ class Packet < GroupTlv
|
|||
def initialize(type = nil, method = nil)
|
||||
super(type)
|
||||
|
||||
if (method)
|
||||
if method
|
||||
self.method = method
|
||||
end
|
||||
|
||||
|
@ -685,33 +739,86 @@ class Packet < GroupTlv
|
|||
|
||||
def raw_bytes_required
|
||||
# if we have the xor bytes and length ...
|
||||
if self.raw.length >= 8
|
||||
if self.raw.length >= REQUIRED_PREFIX_SIZE
|
||||
p = [ self.raw[0,4].unpack('H*')[0],
|
||||
self.raw[4,16].unpack('H*')[0],
|
||||
self.raw[20].unpack('H*')[0],
|
||||
self.raw[21,4].unpack('H*')[0] ].join('-')
|
||||
STDERR.puts("Incoming packet: #{p}\n")
|
||||
|
||||
# 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
|
||||
xor_key = self.raw[XOR_KEY_OFF, XOR_KEY_SIZE]
|
||||
decoded_bytes = xor_bytes(xor_key, raw[0, REQUIRED_PREFIX_SIZE])
|
||||
length_bytes = decoded_bytes[PACKET_LENGTH_OFF, PACKET_LENGTH_SIZE]
|
||||
length_bytes.unpack("N")[0] + PACKET_DATA_OFF - HEADER_SIZE - self.raw.length
|
||||
else
|
||||
# Otherwise ask for the remaining 8 bytes for the xor/length
|
||||
# Otherwise ask for the remaining bytes for the metadata to get the packet length
|
||||
# So we can do the rest of the calculation next time
|
||||
8 - self.raw.length
|
||||
REQUIRED_PREFIX_SIZE - self.raw.length
|
||||
end
|
||||
end
|
||||
|
||||
def aes_encrypt(aes_key, data)
|
||||
# Create the required cipher instance
|
||||
aes = OpenSSL::Cipher.new('AES-256-CBC')
|
||||
# Generate a truly random IV
|
||||
iv = aes.random_iv
|
||||
|
||||
# set up the encryption
|
||||
aes.encrypt
|
||||
aes.key = aes_key
|
||||
aes.iv = iv
|
||||
|
||||
# encrypt and return the IV along with the result
|
||||
return iv, aes.update(data) + aes.final
|
||||
end
|
||||
|
||||
def aes_decrypt(aes_key, iv, data)
|
||||
# Create the required cipher instance
|
||||
aes = OpenSSL::Cipher.new('AES-256-CBC')
|
||||
# Generate a truly random IV
|
||||
|
||||
# set up the encryption
|
||||
aes.decrypt
|
||||
aes.key = aes_key
|
||||
aes.iv = iv
|
||||
|
||||
# decrypt!
|
||||
aes.update(data) + aes.final
|
||||
end
|
||||
|
||||
#
|
||||
# Override the function that creates the raw byte stream for
|
||||
# sending so that it generates an XOR key, uses it to scramble
|
||||
# the serialized TLV content, and then returns the key plus the
|
||||
# scrambled data as the payload.
|
||||
#
|
||||
def to_r
|
||||
raw = super
|
||||
def to_r(session_guid, aes_key=nil)
|
||||
STDERR.puts("AES key: #{aes_key.inspect}\n")
|
||||
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
|
||||
|
||||
raw = [session_guid.gsub(/-/, '')].pack('H*')
|
||||
tlv_data = GroupTlv.instance_method(:to_r).bind(self).call
|
||||
|
||||
if aes_key
|
||||
raw << "\x01"
|
||||
STDERR.puts("Doing the encryption!\n")
|
||||
# encrypt the data, but not include the length and type
|
||||
iv, ciphertext = aes_encrypt(aes_key, tlv_data[HEADER_SIZE, tlv_data.length - HEADER_SIZE])
|
||||
STDERR.puts("Encryption done! IV is #{iv.unpack('H*')[0]}\n")
|
||||
# now manually add the length/type/iv/ciphertext
|
||||
STDERR.puts("len/type: #{[iv.length + ciphertext.length + HEADER_SIZE, self.type].inspect}\n")
|
||||
raw << [iv.length + ciphertext.length + HEADER_SIZE, self.type].pack('NN')
|
||||
raw << iv
|
||||
raw << ciphertext
|
||||
else
|
||||
raw << "\x00"
|
||||
raw << tlv_data
|
||||
end
|
||||
|
||||
# return the xor'd result with the key
|
||||
xor_key + xor_bytes(xor_key, raw)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -720,10 +827,26 @@ class Packet < GroupTlv
|
|||
# passing it on to the default functionality that can parse
|
||||
# the TLV values.
|
||||
#
|
||||
def from_r(bytes=nil)
|
||||
bytes ||= self.raw
|
||||
xor_key = bytes[0,4]
|
||||
super(xor_bytes(xor_key, bytes[4, bytes.length]))
|
||||
def from_r(aes_key=nil)
|
||||
xor_key = self.raw[XOR_KEY_OFF, XOR_KEY_SIZE]
|
||||
data = xor_key + xor_bytes(xor_key, self.raw[SESSION_GUID_OFF, self.raw.length - SESSION_GUID_OFF])
|
||||
self.session_guid = data[SESSION_GUID_OFF, SESSION_GUID_SIZE]
|
||||
encrypted_flag = data[ENCRYPTED_FLAG_OFF, ENCRYPTED_FLAG_SIZE] == "\x01"
|
||||
packet_length = data[PACKET_LENGTH_OFF, PACKET_LENGTH_SIZE]
|
||||
packet_type = data[PACKET_TYPE_OFF, PACKET_TYPE_SIZE]
|
||||
self.type = packet_type.unpack('N')[0]
|
||||
if encrypted_flag
|
||||
STDERR.puts("Packet is encrypted\n")
|
||||
# TODO error when there's no aes key
|
||||
iv = data[PACKET_DATA_OFF, AES_IV_SIZE]
|
||||
raw = aes_decrypt(aes_key, iv, data[PACKET_DATA_OFF + AES_IV_SIZE, data.length - PACKET_DATA_OFF - AES_IV_SIZE])
|
||||
else
|
||||
STDERR.puts("Packet isn't encrypted\n")
|
||||
raw = data[PACKET_DATA_OFF, data.length - PACKET_DATA_OFF]
|
||||
end
|
||||
|
||||
super(packet_length + packet_type + raw)
|
||||
STDERR.puts("Received packet: #{self.inspect}\n")
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -57,6 +57,12 @@ module PacketDispatcher
|
|||
# active migration. Unused if this is a passive dispatcher
|
||||
attr_accessor :comm_mutex
|
||||
|
||||
# The guid that identifies an active Meterpreter session
|
||||
attr_accessor :session_guid
|
||||
|
||||
# This contains the AES key to use when handling TLV packet comms in an
|
||||
# encrypted context
|
||||
attr_accessor :aes_key
|
||||
|
||||
# Passive Dispatching
|
||||
#
|
||||
|
@ -131,7 +137,7 @@ module PacketDispatcher
|
|||
resp.body = ""
|
||||
if req.body and req.body.length > 0
|
||||
packet = Packet.new(0)
|
||||
packet.from_r(req.body)
|
||||
packet.add_raw(req.body)
|
||||
dispatch_inbound_packet(packet)
|
||||
end
|
||||
cli.send_response(resp)
|
||||
|
@ -156,8 +162,10 @@ module PacketDispatcher
|
|||
add_response_waiter(packet, completion_routine, completion_param)
|
||||
end
|
||||
|
||||
STDERR.puts("Sending packet: #{packet.inspect}\n")
|
||||
|
||||
bytes = 0
|
||||
raw = packet.to_r
|
||||
raw = packet.to_r(self.session_guid, self.aes_key)
|
||||
err = nil
|
||||
|
||||
# Short-circuit send when using a passive dispatcher
|
||||
|
@ -166,8 +174,7 @@ module PacketDispatcher
|
|||
return raw.size # Lie!
|
||||
end
|
||||
|
||||
if (raw)
|
||||
|
||||
if raw
|
||||
self.comm_mutex.synchronize do
|
||||
begin
|
||||
bytes = self.sock.write(raw)
|
||||
|
@ -420,7 +427,17 @@ module PacketDispatcher
|
|||
# once a full packet has been received.
|
||||
#
|
||||
def receive_packet
|
||||
return parser.recv(self.sock)
|
||||
packet = parser.recv(self.sock)
|
||||
if packet
|
||||
packet.from_r(self.aes_key)
|
||||
STDERR.puts("Current GUID in packet dispatcher: #{self.session_guid}\n")
|
||||
if self.session_guid == '00000000-0000-0000-0000-000000000000'
|
||||
STDERR.puts("Packet Session GUID : #{packet.session_guid.inspect}\n")
|
||||
parts = packet.session_guid.unpack('H*')[0]
|
||||
self.session_guid = [parts[0, 8], parts[8, 4], parts[12, 4], parts[16, 4], parts[20, 12]].join('-')
|
||||
end
|
||||
end
|
||||
packet
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -31,6 +31,7 @@ class PacketParser
|
|||
#
|
||||
def recv(sock)
|
||||
bytes_left = self.packet.raw_bytes_required
|
||||
STDERR.puts("Waiting for bytes: #{bytes_left}\n")
|
||||
|
||||
if bytes_left > 0
|
||||
raw = sock.read(bytes_left)
|
||||
|
@ -42,8 +43,8 @@ class PacketParser
|
|||
end
|
||||
|
||||
if self.packet.raw_bytes_required == 0
|
||||
STDERR.puts("Packet is ready ...\n")
|
||||
packet = self.packet
|
||||
packet.from_r
|
||||
reset
|
||||
return packet
|
||||
end
|
||||
|
|
|
@ -469,8 +469,9 @@ class Console::CommandDispatcher::Core
|
|||
# Get the session GUID
|
||||
#
|
||||
def cmd_guid(*args)
|
||||
client.guid = client.core.get_session_guid unless client.guid
|
||||
print_good("Session GUID: #{client.guid}")
|
||||
parts = client.session_guid.unpack('H*')[0]
|
||||
guid = [parts[0, 8], parts[8, 4], parts[12, 4], parts[16, 4], parts[20, 12]].join('-')
|
||||
print_good("Session GUID: #{guid}")
|
||||
end
|
||||
|
||||
#
|
||||
|
|
Loading…
Reference in New Issue