2019-07-16 11:31:10 -05:00
|
|
|
# -*- coding: binary -*-
|
2019-10-28 16:25:28 -05:00
|
|
|
require 'securerandom'
|
2019-07-15 12:16:33 -05:00
|
|
|
|
|
|
|
|
module Msf
|
|
|
|
|
module Sessions
|
|
|
|
|
|
2019-07-16 11:31:10 -05:00
|
|
|
class EncryptedShell < Msf::Sessions::CommandShell
|
|
|
|
|
|
|
|
|
|
include Msf::Session::Basic
|
|
|
|
|
include Msf::Session::Provider::SingleCommandShell
|
2019-11-18 13:41:01 -06:00
|
|
|
include Msf::Payload::Windows::PayloadDBConf
|
2019-07-15 12:16:33 -05:00
|
|
|
|
|
|
|
|
attr_accessor :arch
|
|
|
|
|
attr_accessor :platform
|
|
|
|
|
|
2019-09-30 15:05:07 -05:00
|
|
|
attr_accessor :iv
|
|
|
|
|
attr_accessor :key
|
2019-10-11 12:24:56 -05:00
|
|
|
attr_accessor :staged
|
2019-07-15 12:16:33 -05:00
|
|
|
|
2019-11-20 11:24:23 -06:00
|
|
|
attr_accessor :chacha_cipher
|
|
|
|
|
|
2019-10-10 12:14:11 -05:00
|
|
|
# define some sort of method that checks for
|
|
|
|
|
# the existence of payload in the db before
|
|
|
|
|
# using datastore
|
2019-10-03 13:31:30 -05:00
|
|
|
def initialize(rstream, opts={})
|
2019-07-15 12:16:33 -05:00
|
|
|
self.arch ||= ""
|
2019-07-16 11:31:10 -05:00
|
|
|
self.platform = "windows"
|
2019-10-11 12:24:56 -05:00
|
|
|
@staged = opts[:datastore][:staged]
|
|
|
|
|
super
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def type
|
|
|
|
|
"Encrypted"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def desc
|
|
|
|
|
"Encrypted reverse shell"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def self.type
|
|
|
|
|
self.class.type = "Encrypted"
|
|
|
|
|
end
|
|
|
|
|
|
2021-08-17 16:58:51 +01:00
|
|
|
def bootstrap(datastore = {}, handler = nil)
|
2019-10-11 12:24:56 -05:00
|
|
|
@key = datastore[:key] || datastore['ChachaKey']
|
|
|
|
|
nonce = datastore[:nonce] || datastore['ChachaNonce']
|
2019-11-14 10:29:58 -06:00
|
|
|
@iv = nonce
|
2019-10-10 12:14:11 -05:00
|
|
|
|
2019-10-11 12:24:56 -05:00
|
|
|
# staged payloads retrieve UUID via
|
|
|
|
|
# handle_connection() in stager.rb
|
|
|
|
|
unless @staged
|
|
|
|
|
curr_uuid = rstream.get_once(16, 1)
|
2019-11-18 13:41:01 -06:00
|
|
|
@key, @nonce = retrieve_chacha_creds(curr_uuid)
|
2019-11-14 10:29:58 -06:00
|
|
|
@iv = @nonce ? @nonce : "\0" * 12
|
2019-10-10 12:14:11 -05:00
|
|
|
|
|
|
|
|
unless @key && @nonce
|
2019-10-11 12:24:56 -05:00
|
|
|
print_status('Failed to retrieve key/nonce for uuid. Resorting to datastore')
|
2019-10-10 12:14:11 -05:00
|
|
|
@key = datastore['ChachaKey']
|
2019-11-14 10:29:58 -06:00
|
|
|
@iv = datastore['ChachaNonce']
|
2019-10-10 12:14:11 -05:00
|
|
|
end
|
|
|
|
|
end
|
2019-10-03 13:31:30 -05:00
|
|
|
|
2019-10-28 16:25:28 -05:00
|
|
|
new_nonce = SecureRandom.hex(6)
|
2019-11-14 10:29:58 -06:00
|
|
|
new_key = SecureRandom.hex(16)
|
2019-11-20 11:24:23 -06:00
|
|
|
|
|
|
|
|
@chacha_cipher = Rex::Crypto::Chacha20.new(@key, @iv)
|
|
|
|
|
new_cipher = @chacha_cipher.chacha20_crypt(new_nonce + new_key)
|
2019-10-03 13:31:30 -05:00
|
|
|
rstream.write(new_cipher)
|
|
|
|
|
|
2019-10-07 08:44:48 -05:00
|
|
|
@key = new_key
|
2019-11-14 10:29:58 -06:00
|
|
|
@iv = new_nonce
|
2019-11-20 11:24:23 -06:00
|
|
|
@chacha_cipher.reset_cipher(@key, @iv)
|
2021-08-17 16:58:51 +01:00
|
|
|
|
|
|
|
|
super(datastore, handler)
|
2019-07-15 12:16:33 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
# Overridden from Msf::Sessions::CommandShell#shell_read
|
|
|
|
|
#
|
|
|
|
|
# Read encrypted data from console and decrypt it
|
|
|
|
|
#
|
|
|
|
|
def shell_read(length=-1, timeout=1)
|
|
|
|
|
rv = rstream.get_once(length, timeout)
|
2021-08-17 16:58:51 +01:00
|
|
|
# Needed to avoid crashing the +chacha20_crypt+ method
|
|
|
|
|
return nil unless rv
|
2019-11-20 11:24:23 -06:00
|
|
|
decrypted = @chacha_cipher.chacha20_crypt(rv)
|
2019-07-15 12:16:33 -05:00
|
|
|
framework.events.on_session_output(self, decrypted) if decrypted
|
2019-11-20 11:24:23 -06:00
|
|
|
|
2019-07-16 11:31:10 -05:00
|
|
|
return decrypted
|
2019-07-15 12:16:33 -05:00
|
|
|
rescue ::Rex::SocketError, ::EOFError, ::IOError, ::Errno::EPIPE => e
|
|
|
|
|
shell_close
|
|
|
|
|
raise e
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
# Overridden from Msf::Sessions::CommandShell#shell_write
|
2019-11-14 10:29:58 -06:00
|
|
|
#
|
2019-07-15 12:16:33 -05:00
|
|
|
# Encrypt data then write it to the console
|
|
|
|
|
#
|
|
|
|
|
def shell_write(buf)
|
|
|
|
|
return unless buf
|
|
|
|
|
|
|
|
|
|
framework.events.on_session_command(self, buf.strip)
|
2019-11-20 11:24:23 -06:00
|
|
|
encrypted = @chacha_cipher.chacha20_crypt(buf)
|
2019-07-15 12:16:33 -05:00
|
|
|
rstream.write(encrypted)
|
|
|
|
|
rescue ::Rex::SocketError, ::EOFError, ::IOError, ::Errno::EPIPE => e
|
|
|
|
|
shell_close
|
|
|
|
|
raise e
|
|
|
|
|
end
|
|
|
|
|
|
2019-07-16 11:31:10 -05:00
|
|
|
end
|
2019-07-15 12:16:33 -05:00
|
|
|
end
|
|
|
|
|
end
|