Finalised MSF-side of AES key negotiation over RSA
parent
a9e03c1efd
commit
67b1a19aa1
|
@ -55,7 +55,6 @@ module MeterpreterOptions
|
|||
if valid
|
||||
# always make sure that the new session has a new guid if it's not already known
|
||||
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)
|
||||
|
|
|
@ -17,6 +17,8 @@ require 'rex/payloads/meterpreter/uri_checksum'
|
|||
# certificate hash checking
|
||||
require 'rex/socket/x509_certificate'
|
||||
|
||||
require 'openssl'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
|
@ -75,7 +77,6 @@ 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.
|
||||
|
@ -212,7 +213,6 @@ class ClientCore < Extension
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -289,8 +289,6 @@ 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,
|
||||
|
@ -688,9 +686,28 @@ class ClientCore < Extension
|
|||
# Negotiates the use of AES256 encryption over the TLV packets.
|
||||
#
|
||||
def negotiate_aes
|
||||
aes_key = nil
|
||||
rsa_key = OpenSSL::PKey::RSA.new(2048)
|
||||
rsa_pub_key = rsa_key.public_key
|
||||
|
||||
request = Packet.create_request('core_negotiate_aes')
|
||||
request.add_tlv(TLV_TYPE_RSA_PUB_KEY, rsa_pub_key.to_pem)
|
||||
|
||||
response = client.send_request(request)
|
||||
response.get_tlv_value(TLV_TYPE_AES_KEY)
|
||||
aes_key_enc = response.get_tlv_value(TLV_TYPE_ENC_AES_KEY)
|
||||
|
||||
if aes_key_enc
|
||||
begin
|
||||
aes_key = rsa_key.private_decrypt(aes_key_enc, OpenSSL::PKey::RSA::PKCS1_PADDING)
|
||||
rescue OpenSSL::PKey::RSAError
|
||||
# probably failed due to padding, everything else can be bubbled up, but
|
||||
# we'll stick with a blank key
|
||||
end
|
||||
else
|
||||
aes_key = response.get_tlv_value(TLV_TYPE_AES_KEY)
|
||||
end
|
||||
|
||||
aes_key
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -111,6 +111,8 @@ 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
|
||||
TLV_TYPE_ENC_AES_KEY = TLV_META_TYPE_RAW | 551
|
||||
TLV_TYPE_RSA_PUB_KEY = TLV_META_TYPE_STRING | 552
|
||||
|
||||
#
|
||||
# Core flags
|
||||
|
@ -222,6 +224,8 @@ class Tlv
|
|||
when TLV_TYPE_UUID; "UUID"
|
||||
when TLV_TYPE_SESSION_GUID; "SESSION-GUID"
|
||||
when TLV_TYPE_AES_KEY; "AES-KEY"
|
||||
when TLV_TYPE_ENC_AES_KEY; "ENC-AES-KEY"
|
||||
when TLV_TYPE_RSA_PUB_KEY; "RSA-PUB-KEY"
|
||||
|
||||
#when Extensions::Stdapi::TLV_TYPE_NETWORK_INTERFACE; 'network-interface'
|
||||
#when Extensions::Stdapi::TLV_TYPE_IP; 'ip-address'
|
||||
|
@ -740,12 +744,6 @@ class Packet < GroupTlv
|
|||
def raw_bytes_required
|
||||
# if we have the xor bytes and length ...
|
||||
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[XOR_KEY_OFF, XOR_KEY_SIZE]
|
||||
|
@ -795,7 +793,6 @@ class Packet < GroupTlv
|
|||
# scrambled data as the payload.
|
||||
#
|
||||
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
|
||||
|
||||
raw = [session_guid.gsub(/-/, '')].pack('H*')
|
||||
|
@ -803,12 +800,9 @@ class Packet < GroupTlv
|
|||
|
||||
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
|
||||
|
@ -836,17 +830,14 @@ class Packet < GroupTlv
|
|||
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
|
||||
|
||||
#
|
||||
|
|
|
@ -162,8 +162,6 @@ module PacketDispatcher
|
|||
add_response_waiter(packet, completion_routine, completion_param)
|
||||
end
|
||||
|
||||
STDERR.puts("Sending packet: #{packet.inspect}\n")
|
||||
|
||||
bytes = 0
|
||||
raw = packet.to_r(self.session_guid, self.aes_key)
|
||||
err = nil
|
||||
|
@ -430,9 +428,7 @@ module PacketDispatcher
|
|||
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
|
||||
|
|
|
@ -31,7 +31,6 @@ 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)
|
||||
|
@ -43,7 +42,6 @@ class PacketParser
|
|||
end
|
||||
|
||||
if self.packet.raw_bytes_required == 0
|
||||
STDERR.puts("Packet is ready ...\n")
|
||||
packet = self.packet
|
||||
reset
|
||||
return packet
|
||||
|
|
Loading…
Reference in New Issue