CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/base/sessions/encrypted_shell.rb
Views: 1904
1
# -*- coding: binary -*-
2
require 'securerandom'
3
4
module Msf
5
module Sessions
6
7
class EncryptedShell < Msf::Sessions::CommandShell
8
9
include Msf::Session::Basic
10
include Msf::Session::Provider::SingleCommandShell
11
include Msf::Payload::Windows::PayloadDBConf
12
13
attr_accessor :arch
14
attr_accessor :platform
15
16
attr_accessor :iv
17
attr_accessor :key
18
attr_accessor :staged
19
20
attr_accessor :chacha_cipher
21
22
# define some sort of method that checks for
23
# the existence of payload in the db before
24
# using datastore
25
def initialize(rstream, opts={})
26
self.arch ||= ""
27
self.platform = "windows"
28
@staged = opts[:datastore][:staged]
29
super
30
end
31
32
def type
33
"Encrypted"
34
end
35
36
def desc
37
"Encrypted reverse shell"
38
end
39
40
def self.type
41
self.class.type = "Encrypted"
42
end
43
44
def bootstrap(datastore = {}, handler = nil)
45
@key = datastore[:key] || datastore['ChachaKey']
46
nonce = datastore[:nonce] || datastore['ChachaNonce']
47
@iv = nonce
48
49
# staged payloads retrieve UUID via
50
# handle_connection() in stager.rb
51
unless @staged
52
curr_uuid = rstream.get_once(16, 1)
53
@key, @nonce = retrieve_chacha_creds(curr_uuid)
54
@iv = @nonce ? @nonce : "\0" * 12
55
56
unless @key && @nonce
57
print_status('Failed to retrieve key/nonce for uuid. Resorting to datastore')
58
@key = datastore['ChachaKey']
59
@iv = datastore['ChachaNonce']
60
end
61
end
62
63
new_nonce = SecureRandom.hex(6)
64
new_key = SecureRandom.hex(16)
65
66
@chacha_cipher = Rex::Crypto::Chacha20.new(@key, @iv)
67
new_cipher = @chacha_cipher.chacha20_crypt(new_nonce + new_key)
68
rstream.write(new_cipher)
69
70
@key = new_key
71
@iv = new_nonce
72
@chacha_cipher.reset_cipher(@key, @iv)
73
74
super(datastore, handler)
75
end
76
77
##
78
# Overridden from Msf::Sessions::CommandShell#shell_read
79
#
80
# Read encrypted data from console and decrypt it
81
#
82
def shell_read(length=-1, timeout=1)
83
rv = rstream.get_once(length, timeout)
84
# Needed to avoid crashing the +chacha20_crypt+ method
85
return nil unless rv
86
decrypted = @chacha_cipher.chacha20_crypt(rv)
87
framework.events.on_session_output(self, decrypted) if decrypted
88
89
return decrypted
90
rescue ::Rex::SocketError, ::EOFError, ::IOError, ::Errno::EPIPE => e
91
shell_close
92
raise e
93
end
94
95
##
96
# Overridden from Msf::Sessions::CommandShell#shell_write
97
#
98
# Encrypt data then write it to the console
99
#
100
def shell_write(buf)
101
return unless buf
102
103
framework.events.on_session_command(self, buf.strip)
104
encrypted = @chacha_cipher.chacha20_crypt(buf)
105
rstream.write(encrypted)
106
rescue ::Rex::SocketError, ::EOFError, ::IOError, ::Errno::EPIPE => e
107
shell_close
108
raise e
109
end
110
111
end
112
end
113
end
114
115