Finalised MSF-side of AES key negotiation over RSA

bug/bundler_fix
OJ 2017-06-25 10:24:00 +10:00
parent a9e03c1efd
commit 67b1a19aa1
No known key found for this signature in database
GPG Key ID: D5DC61FB93260597
5 changed files with 26 additions and 25 deletions

View File

@ -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)

View File

@ -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

View File

@ -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
#

View File

@ -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

View File

@ -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