rex 2.0.8 → 2.0.9

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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rex.rb +1 -0
  3. data/lib/rex/arch.rb +5 -0
  4. data/lib/rex/arch/x86.rb +19 -5
  5. data/lib/rex/arch/zarch.rb +17 -0
  6. data/lib/rex/compat.rb +5 -4
  7. data/lib/rex/constants.rb +3 -1
  8. data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
  9. data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
  10. data/lib/rex/exploitation/cmdstager.rb +1 -0
  11. data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
  12. data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
  13. data/lib/rex/exploitation/egghunter.rb +1 -1
  14. data/lib/rex/google/geolocation.rb +68 -0
  15. data/lib/rex/io/bidirectional_pipe.rb +0 -4
  16. data/lib/rex/java/serialization.rb +2 -0
  17. data/lib/rex/java/serialization/decode_error.rb +11 -0
  18. data/lib/rex/java/serialization/encode_error.rb +11 -0
  19. data/lib/rex/java/serialization/model.rb +2 -0
  20. data/lib/rex/java/serialization/model/annotation.rb +3 -3
  21. data/lib/rex/java/serialization/model/block_data.rb +3 -3
  22. data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
  23. data/lib/rex/java/serialization/model/class_desc.rb +6 -6
  24. data/lib/rex/java/serialization/model/contents.rb +17 -10
  25. data/lib/rex/java/serialization/model/field.rb +12 -11
  26. data/lib/rex/java/serialization/model/long_utf.rb +3 -3
  27. data/lib/rex/java/serialization/model/new_array.rb +22 -23
  28. data/lib/rex/java/serialization/model/new_class.rb +57 -0
  29. data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
  30. data/lib/rex/java/serialization/model/new_enum.rb +5 -5
  31. data/lib/rex/java/serialization/model/new_object.rb +22 -17
  32. data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
  33. data/lib/rex/java/serialization/model/reference.rb +4 -4
  34. data/lib/rex/java/serialization/model/stream.rb +7 -7
  35. data/lib/rex/java/serialization/model/utf.rb +3 -3
  36. data/lib/rex/json_hash_file.rb +94 -0
  37. data/lib/rex/logging/log_sink.rb +1 -0
  38. data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
  39. data/lib/rex/parser/appscan_nokogiri.rb +13 -23
  40. data/lib/rex/parser/fs/ntfs.rb +10 -5
  41. data/lib/rex/parser/nmap_nokogiri.rb +3 -1
  42. data/lib/rex/parser/openvas_nokogiri.rb +70 -73
  43. data/lib/rex/parser/winscp.rb +108 -0
  44. data/lib/rex/parser/x509_certificate.rb +92 -0
  45. data/lib/rex/payloads.rb +0 -1
  46. data/lib/rex/payloads/meterpreter/config.rb +154 -0
  47. data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
  48. data/lib/rex/post/meterpreter.rb +1 -1
  49. data/lib/rex/post/meterpreter/client.rb +26 -3
  50. data/lib/rex/post/meterpreter/client_core.rb +387 -75
  51. data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
  52. data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
  53. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
  54. data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
  55. data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
  56. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
  57. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
  58. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
  59. data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
  60. data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
  61. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
  62. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
  63. data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
  64. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
  65. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
  66. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
  67. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
  68. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
  69. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
  70. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
  71. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
  72. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
  73. data/lib/rex/post/meterpreter/packet.rb +29 -0
  74. data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
  75. data/lib/rex/post/meterpreter/ui/console.rb +1 -0
  76. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
  77. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
  78. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
  79. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
  80. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
  81. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
  82. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
  83. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
  84. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
  85. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
  86. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
  87. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
  88. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
  89. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
  90. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
  91. data/lib/rex/powershell.rb +62 -0
  92. data/lib/rex/powershell/command.rb +359 -0
  93. data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
  94. data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
  95. data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
  96. data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
  97. data/lib/rex/powershell/parser.rb +182 -0
  98. data/lib/rex/powershell/payload.rb +78 -0
  99. data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
  100. data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
  101. data/lib/rex/proto/dcerpc/client.rb +6 -6
  102. data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
  103. data/lib/rex/proto/http/client.rb +3 -3
  104. data/lib/rex/proto/http/client_request.rb +0 -5
  105. data/lib/rex/proto/http/response.rb +86 -0
  106. data/lib/rex/proto/ipmi/utils.rb +30 -26
  107. data/lib/rex/proto/kerberos/client.rb +1 -1
  108. data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
  109. data/lib/rex/proto/rfb/client.rb +8 -3
  110. data/lib/rex/proto/rfb/constants.rb +1 -1
  111. data/lib/rex/proto/rmi.rb +2 -0
  112. data/lib/rex/proto/rmi/decode_error.rb +10 -0
  113. data/lib/rex/proto/rmi/exception.rb +10 -0
  114. data/lib/rex/proto/rmi/model.rb +5 -0
  115. data/lib/rex/proto/rmi/model/call.rb +4 -4
  116. data/lib/rex/proto/rmi/model/call_data.rb +137 -0
  117. data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
  118. data/lib/rex/proto/rmi/model/element.rb +26 -11
  119. data/lib/rex/proto/rmi/model/output_header.rb +4 -4
  120. data/lib/rex/proto/rmi/model/ping.rb +2 -2
  121. data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
  122. data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
  123. data/lib/rex/proto/rmi/model/return_data.rb +5 -5
  124. data/lib/rex/proto/rmi/model/return_value.rb +124 -0
  125. data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
  126. data/lib/rex/proto/steam.rb +3 -0
  127. data/lib/rex/proto/steam/message.rb +125 -0
  128. data/lib/rex/proto/tftp/client.rb +35 -14
  129. data/lib/rex/random_identifier_generator.rb +2 -0
  130. data/lib/rex/ropbuilder.rb +1 -1
  131. data/lib/rex/socket/parameters.rb +9 -0
  132. data/lib/rex/socket/ssl_tcp.rb +25 -41
  133. data/lib/rex/socket/ssl_tcp_server.rb +10 -21
  134. data/lib/rex/sslscan/result.rb +20 -1
  135. data/lib/rex/text.rb +241 -55
  136. data/lib/rex/ui/output.rb +0 -3
  137. data/lib/rex/ui/subscriber.rb +0 -10
  138. data/lib/rex/ui/text/color.rb +9 -0
  139. data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
  140. data/lib/rex/ui/text/output.rb +15 -4
  141. data/lib/rex/ui/text/output/file.rb +1 -0
  142. data/lib/rex/ui/text/output/stdio.rb +0 -16
  143. data/lib/rex/ui/text/shell.rb +3 -0
  144. data/lib/rex/ui/text/table.rb +85 -19
  145. data/lib/rex/user_agent.rb +118 -0
  146. data/rex.gemspec +2 -2
  147. metadata +41 -14
  148. data/lib/rex/exploitation/powershell.rb +0 -62
  149. data/lib/rex/exploitation/powershell/parser.rb +0 -183
  150. data/lib/rex/payloads/meterpreter.rb +0 -2
  151. data/lib/rex/payloads/meterpreter/patch.rb +0 -136
@@ -295,6 +295,7 @@ class Client
295
295
  end
296
296
  sent_data = 0
297
297
  sent_blocks = 0
298
+ send_retries = 0
298
299
  expected_blocks = data_blocks.size
299
300
  expected_size = data_blocks.join.size
300
301
  if block_given?
@@ -302,24 +303,43 @@ class Client
302
303
  yield "Sending #{expected_size} bytes (#{expected_blocks} blocks)"
303
304
  end
304
305
  data_blocks.each_with_index do |data_block,idx|
305
- req = [OpData, (idx + 1), data_block].pack("nnA*")
306
- if self.server_sock.sendto(req, host, port) > 0
307
- sent_data += data_block.size
308
- end
309
- res = self.server_sock.recvfrom(65535)
310
- if res
311
- code, type, msg = parse_tftp_response(res[0])
312
- if code == 4
313
- sent_blocks += 1
314
- yield "Sent #{data_block.size} bytes in block #{sent_blocks}" if block_given?
315
- else
316
- if block_given?
317
- yield "Got an unexpected response: Code:%d, Type:%d, Message:'%s'. Aborting." % [code, type, msg]
306
+ loop do
307
+ req = [OpData, (idx + 1), data_block].pack("nnA*")
308
+ if self.server_sock.sendto(req, host, port) <= 0
309
+ send_retries += 1
310
+ if send_retries > 100
311
+ break
312
+ else
313
+ next
314
+ end
315
+ end
316
+ send_retries = 0
317
+ res = self.server_sock.recvfrom(65535)
318
+ if res
319
+ code, type, msg = parse_tftp_response(res[0])
320
+ if code == 4
321
+ if type == idx + 1
322
+ sent_blocks += 1
323
+ sent_data += data_block.size
324
+ yield "Sent #{data_block.size} bytes in block #{idx+1}" if block_given?
325
+ break
326
+ else
327
+ next
328
+ end
329
+ else
330
+ if block_given?
331
+ yield "Got an unexpected response: Code:%d, Type:%d, Message:'%s'. Aborting." % [code, type, msg]
332
+ end
333
+ break
318
334
  end
319
- break
320
335
  end
321
336
  end
322
337
  end
338
+
339
+ if send_retries > 100
340
+ yield "Too many send retries, aborted"
341
+ end
342
+
323
343
  if block_given?
324
344
  if(sent_data == expected_size)
325
345
  yield("Transferred #{sent_data} bytes in #{sent_blocks} blocks, upload complete!")
@@ -327,6 +347,7 @@ class Client
327
347
  yield "Upload complete, but with errors."
328
348
  end
329
349
  end
350
+
330
351
  if sent_data == expected_size
331
352
  self.status = {:success => [
332
353
  self.local_file,
@@ -1,5 +1,7 @@
1
1
  # -*- coding: binary -*-
2
2
 
3
+ require 'rex/text'
4
+
3
5
  # A quick way to produce unique random strings that follow the rules of
4
6
  # identifiers, i.e., begin with a letter and contain only alphanumeric
5
7
  # characters and underscore.
@@ -3,6 +3,6 @@ module Rex
3
3
  module RopBuilder
4
4
 
5
5
  require 'rex/ropbuilder/rop'
6
- require 'metasm/metasm'
6
+ require 'metasm'
7
7
  end
8
8
  end
@@ -56,6 +56,7 @@ class Rex::Socket::Parameters
56
56
  # @option hash [Bool] 'Bool' Create a bare socket
57
57
  # @option hash [Bool] 'Server' Whether or not this should be a server
58
58
  # @option hash [Bool] 'SSL' Whether or not SSL should be used
59
+ # @option hash [OpenSSL::SSL::SSLContext] 'SSLContext' Use a pregenerated SSL Context
59
60
  # @option hash [String] 'SSLVersion' Specify Auto, SSL2, SSL3, or TLS1 (Auto is
60
61
  # default)
61
62
  # @option hash [String] 'SSLCert' A file containing an SSL certificate (for
@@ -117,6 +118,10 @@ class Rex::Socket::Parameters
117
118
  self.ssl = false
118
119
  end
119
120
 
121
+ if hash['SSLContext']
122
+ self.sslctx = hash['SSLContext']
123
+ end
124
+
120
125
  supported_ssl_versions = ['Auto', 'SSL2', 'SSL23', 'TLS1', 'SSL3', :Auto, :SSLv2, :SSLv3, :SSLv23, :TLSv1]
121
126
  if (hash['SSLVersion'] and supported_ssl_versions.include? hash['SSLVersion'])
122
127
  self.ssl_version = hash['SSLVersion']
@@ -324,6 +329,10 @@ class Rex::Socket::Parameters
324
329
  # @return [Bool]
325
330
  attr_accessor :ssl
326
331
 
332
+ # Pre configured SSL Context to use
333
+ # @return [OpenSSL::SSL::SSLContext]
334
+ attr_accessor :sslctx
335
+
327
336
  # What version of SSL to use (Auto, SSL2, SSL3, SSL23, TLS1)
328
337
  # @return [String,Symbol]
329
338
  attr_accessor :ssl_version
@@ -56,52 +56,39 @@ begin
56
56
  def initsock(params = nil)
57
57
  super
58
58
 
59
- # The autonegotiation preference for SSL/TLS versions
60
- versions = [:TLSv1, :SSLv3, :SSLv23, :SSLv2]
59
+ # Default to SSLv23 (automatically negotiate)
60
+ version = :SSLv23
61
61
 
62
- # Limit this to a specific SSL/TLS version if specified
62
+ # Let the caller specify a particular SSL/TLS version
63
63
  if params
64
64
  case params.ssl_version
65
65
  when 'SSL2', :SSLv2
66
- versions = [:SSLv2]
67
- when 'SSL23', :SSLv23
68
- versions = [:SSLv23]
66
+ version = :SSLv2
67
+ # 'TLS' will be the new name for autonegotation with newer versions of OpenSSL
68
+ when 'SSL23', :SSLv23, 'TLS'
69
+ version = :SSLv23
69
70
  when 'SSL3', :SSLv3
70
- versions = [:SSLv3]
71
- when 'TLS1', :TLSv1
72
- versions = [:TLSv1]
73
- else
74
- # Leave the version list as-is (Auto)
71
+ version = :SSLv3
72
+ when 'TLS1','TLS1.0', :TLSv1
73
+ version = :TLSv1
74
+ when 'TLS1.1', :TLSv1_1
75
+ version = :TLSv1_1
76
+ when 'TLS1.2', :TLSv1_2
77
+ version = :TLSv1_2
75
78
  end
76
79
  end
77
80
 
78
- # Limit our versions to those supported by the linked OpenSSL library
79
- versions = versions.select {|v| OpenSSL::SSL::SSLContext::METHODS.include? v }
80
-
81
81
  # Raise an error if no selected versions are supported
82
- if versions.length == 0
82
+ if ! OpenSSL::SSL::SSLContext::METHODS.include? version
83
83
  raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version'
84
84
  end
85
85
 
86
- last_error = nil
87
-
88
- # Iterate through SSL/TLS versions until we successfully negotiate
89
- versions.each do |version|
90
- begin
91
- # Try intializing the socket with this SSL/TLS version
92
- # This will throw an exception if it fails
93
- initsock_with_ssl_version(params, version)
94
-
95
- # Success! Record what method was used and return
96
- self.ssl_negotiated_version = version
97
- return
98
- rescue OpenSSL::SSL::SSLError => e
99
- last_error = e
100
- end
101
- end
86
+ # Try intializing the socket with this SSL/TLS version
87
+ # This will throw an exception if it fails
88
+ initsock_with_ssl_version(params, version)
102
89
 
103
- # No SSL/TLS versions succeeded, raise the last error
104
- raise last_error
90
+ # Track the SSL version
91
+ self.ssl_negotiated_version = version
105
92
  end
106
93
 
107
94
  def initsock_with_ssl_version(params, version)
@@ -137,9 +124,6 @@ begin
137
124
  # Tie the context to a socket
138
125
  self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx)
139
126
 
140
- # XXX - enabling this causes infinite recursion, so disable for now
141
- # self.sslsock.sync_close = true
142
-
143
127
  # Force a negotiation timeout
144
128
  begin
145
129
  Timeout.timeout(params.timeout) do
@@ -366,7 +350,11 @@ begin
366
350
 
367
351
  attr_reader :peer_verified # :nodoc:
368
352
  attr_reader :ssl_negotiated_version # :nodoc:
369
- attr_accessor :sslsock, :sslctx # :nodoc:
353
+ attr_accessor :sslsock, :sslctx, :sslhash # :nodoc:
354
+
355
+ def type?
356
+ return 'tcp-ssl'
357
+ end
370
358
 
371
359
  protected
372
360
 
@@ -377,9 +365,5 @@ protected
377
365
  rescue LoadError
378
366
  end
379
367
 
380
- def type?
381
- return 'tcp-ssl'
382
- end
383
-
384
368
  end
385
369
 
@@ -2,6 +2,7 @@
2
2
  require 'rex/socket'
3
3
  require 'rex/socket/tcp_server'
4
4
  require 'rex/io/stream_server'
5
+ require 'rex/parser/x509_certificate'
5
6
 
6
7
  ###
7
8
  #
@@ -47,8 +48,14 @@ module Rex::Socket::SslTcpServer
47
48
  end
48
49
 
49
50
  def initsock(params = nil)
50
- raise RuntimeError, "No OpenSSL support" if not @@loaded_openssl
51
- self.sslctx = makessl(params)
51
+ raise RuntimeError, 'No OpenSSL support' unless @@loaded_openssl
52
+
53
+ if params && params.sslctx && params.sslctx.kind_of?(OpenSSL::SSL::SSLContext)
54
+ self.sslctx = params.sslctx
55
+ else
56
+ self.sslctx = makessl(params)
57
+ end
58
+
52
59
  super
53
60
  end
54
61
 
@@ -108,25 +115,7 @@ module Rex::Socket::SslTcpServer
108
115
  # @param [String] ssl_cert
109
116
  # @return [String, String, Array]
110
117
  def self.ssl_parse_pem(ssl_cert)
111
- cert = nil
112
- key = nil
113
- chain = nil
114
-
115
- certs = []
116
- ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
117
- if pem =~ /PRIVATE KEY/
118
- key = OpenSSL::PKey::RSA.new(pem)
119
- elsif pem =~ /CERTIFICATE/
120
- certs << OpenSSL::X509::Certificate.new(pem)
121
- end
122
- end
123
-
124
- cert = certs.shift
125
- if certs.length > 0
126
- chain = certs
127
- end
128
-
129
- [key, cert, chain]
118
+ Rex::Parser::X509Certificate.parse_pem(ssl_cert)
130
119
  end
131
120
 
132
121
  #
@@ -15,6 +15,24 @@ class Result
15
15
  @cert = nil
16
16
  @ciphers = Set.new
17
17
  @supported_versions = [:SSLv2, :SSLv3, :TLSv1]
18
+ @deprecated_weak_ciphers = [
19
+ 'ECDHE-RSA-DES-CBC3-SHA',
20
+ 'ECDHE-ECDSA-DES-CBC3-SHA',
21
+ 'SRP-DSS-3DES-EDE-CBC-SHA',
22
+ 'SRP-RSA-3DES-EDE-CBC-SHA',
23
+ 'SRP-3DES-EDE-CBC-SHA',
24
+ 'EDH-RSA-DES-CBC3-SHA',
25
+ 'EDH-DSS-DES-CBC3-SHA',
26
+ 'ECDH-RSA-DES-CBC3-SHA',
27
+ 'ECDH-ECDSA-DES-CBC3-SHA',
28
+ 'DES-CBC3-SHA',
29
+ 'PSK-3DES-EDE-CBC-SHA',
30
+ 'EXP-EDH-RSA-DES-CBC-SHA',
31
+ 'EXP-EDH-DSS-DES-CBC-SHA',
32
+ 'EXP-DES-CBC-SHA',
33
+ 'EXP-RC2-CBC-MD5',
34
+ 'EXP-RC4-MD5'
35
+ ]
18
36
  end
19
37
 
20
38
  def cert
@@ -113,7 +131,8 @@ class Result
113
131
  unless @supported_versions.include? version
114
132
  raise ArgumentError, "Must be a supported SSL Version"
115
133
  end
116
- unless OpenSSL::SSL::SSLContext.new(version).ciphers.flatten.include? cipher
134
+ unless OpenSSL::SSL::SSLContext.new(version).ciphers.flatten.include?(cipher) \
135
+ || @deprecated_weak_ciphers.include?(cipher)
117
136
  raise ArgumentError, "Must be a valid SSL Cipher for #{version}!"
118
137
  end
119
138
  unless key_length.kind_of? Fixnum
data/lib/rex/text.rb CHANGED
@@ -3,18 +3,8 @@ require 'digest/md5'
3
3
  require 'digest/sha1'
4
4
  require 'stringio'
5
5
  require 'cgi'
6
- require 'rex/exploitation/powershell'
7
-
8
- %W{ iconv zlib }.each do |libname|
9
- begin
10
- old_verbose = $VERBOSE
11
- $VERBOSE = nil
12
- require libname
13
- rescue ::LoadError
14
- ensure
15
- $VERBOSE = old_verbose
16
- end
17
- end
6
+ require 'rex/powershell'
7
+ require 'zlib'
18
8
 
19
9
  module Rex
20
10
 
@@ -42,8 +32,10 @@ module Text
42
32
  UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
43
33
  LowerAlpha = "abcdefghijklmnopqrstuvwxyz"
44
34
  Numerals = "0123456789"
45
- Base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
46
- Alpha = UpperAlpha + LowerAlpha
35
+ Base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
36
+ Base64 = UpperAlpha + LowerAlpha + Numerals + '+/'
37
+ Base64Url = UpperAlpha + LowerAlpha + Numerals + '-_'
38
+ Alpha = UpperAlpha + LowerAlpha
47
39
  AlphaNumeric = Alpha + Numerals
48
40
  HighAscii = [*(0x80 .. 0xff)].pack("C*")
49
41
  LowAscii = [*(0x00 .. 0x1f)].pack("C*")
@@ -53,7 +45,95 @@ module Text
53
45
 
54
46
  DefaultPatternSets = [ Rex::Text::UpperAlpha, Rex::Text::LowerAlpha, Rex::Text::Numerals ]
55
47
 
56
- # In case Iconv isn't loaded
48
+ # The Iconv translation table for IBM's mainframe / System Z
49
+ # (z/os, s390, mvs, etc) - This is a different implementation
50
+ # of EBCDIC than the Iconv_EBCDIC below.
51
+ # It is technically referred to as Code Page IBM1047.
52
+ # This will be net new (until Ruby supports 1047 code page)
53
+ # for all Mainframe / SystemZ based modules
54
+ # that need to convert ASCII to EBCDIC
55
+ #
56
+ # The bytes are indexed by ASCII conversion number
57
+ # e.g. Iconv_IBM1047[0x41] == \xc1 for letter "A"
58
+ #
59
+ # Note the characters CANNOT be assumed to be in any logical
60
+ # order. Nor are the tables reversible. Lookups must be for each byte
61
+ # https://gist.github.com/bigendiansmalls/b08483ecedff52cc8fa3
62
+ #
63
+ Iconv_IBM1047 = [
64
+ "\x00","\x01","\x02","\x03","\x37","\x2d","\x2e","\x2f",
65
+ "\x16","\x05","\x15","\x0b","\x0c","\x0d","\x0e","\x0f","\x10",
66
+ "\x11","\x12","\x13","\x3c","\x3d","\x32","\x26","\x18","\x19",
67
+ "\x3f","\x27","\x1c","\x1d","\x1e","\x1f","\x40","\x5a","\x7f",
68
+ "\x7b","\x5b","\x6c","\x50","\x7d","\x4d","\x5d","\x5c","\x4e",
69
+ "\x6b","\x60","\x4b","\x61","\xf0","\xf1","\xf2","\xf3","\xf4",
70
+ "\xf5","\xf6","\xf7","\xf8","\xf9","\x7a","\x5e","\x4c","\x7e",
71
+ "\x6e","\x6f","\x7c","\xc1","\xc2","\xc3","\xc4","\xc5","\xc6",
72
+ "\xc7","\xc8","\xc9","\xd1","\xd2","\xd3","\xd4","\xd5","\xd6",
73
+ "\xd7","\xd8","\xd9","\xe2","\xe3","\xe4","\xe5","\xe6","\xe7",
74
+ "\xe8","\xe9","\xad","\xe0","\xbd","\x5f","\x6d","\x79","\x81",
75
+ "\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x91",
76
+ "\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\xa2",
77
+ "\xa3","\xa4","\xa5","\xa6","\xa7","\xa8","\xa9","\xc0","\x4f",
78
+ "\xd0","\xa1","\x07","\x20","\x21","\x22","\x23","\x24","\x25",
79
+ "\x06","\x17","\x28","\x29","\x2a","\x2b","\x2c","\x09","\x0a",
80
+ "\x1b","\x30","\x31","\x1a","\x33","\x34","\x35","\x36","\x08",
81
+ "\x38","\x39","\x3a","\x3b","\x04","\x14","\x3e","\xff","\x41",
82
+ "\xaa","\x4a","\xb1","\x9f","\xb2","\x6a","\xb5","\xbb","\xb4",
83
+ "\x9a","\x8a","\xb0","\xca","\xaf","\xbc","\x90","\x8f","\xea",
84
+ "\xfa","\xbe","\xa0","\xb6","\xb3","\x9d","\xda","\x9b","\x8b",
85
+ "\xb7","\xb8","\xb9","\xab","\x64","\x65","\x62","\x66","\x63",
86
+ "\x67","\x9e","\x68","\x74","\x71","\x72","\x73","\x78","\x75",
87
+ "\x76","\x77","\xac","\x69","\xed","\xee","\xeb","\xef","\xec",
88
+ "\xbf","\x80","\xfd","\xfe","\xfb","\xfc","\xba","\xae","\x59",
89
+ "\x44","\x45","\x42","\x46","\x43","\x47","\x9c","\x48","\x54",
90
+ "\x51","\x52","\x53","\x58","\x55","\x56","\x57","\x8c","\x49",
91
+ "\xcd","\xce","\xcb","\xcf","\xcc","\xe1","\x70","\xdd","\xde",
92
+ "\xdb","\xdc","\x8d","\x8e","\xdf"
93
+ ]
94
+
95
+ #
96
+ # This is the reverse of the above, converts EBCDIC -> ASCII
97
+ # The bytes are indexed by IBM1047(EBCDIC) conversion number
98
+ # e.g. Iconv_ISO8859_1[0xc1] = \x41 for letter "A"
99
+ #
100
+ # Note the characters CANNOT be assumed to be in any logical (e.g. sequential)
101
+ # order. Nor are the tables reversible. Lookups must be done byte by byte
102
+ #
103
+ Iconv_ISO8859_1 = [
104
+ "\x00","\x01","\x02","\x03","\x9c","\x09","\x86","\x7f",
105
+ "\x97","\x8d","\x8e","\x0b","\x0c","\x0d","\x0e","\x0f","\x10",
106
+ "\x11","\x12","\x13","\x9d","\x0a","\x08","\x87","\x18","\x19",
107
+ "\x92","\x8f","\x1c","\x1d","\x1e","\x1f","\x80","\x81","\x82",
108
+ "\x83","\x84","\x85","\x17","\x1b","\x88","\x89","\x8a","\x8b",
109
+ "\x8c","\x05","\x06","\x07","\x90","\x91","\x16","\x93","\x94",
110
+ "\x95","\x96","\x04","\x98","\x99","\x9a","\x9b","\x14","\x15",
111
+ "\x9e","\x1a","\x20","\xa0","\xe2","\xe4","\xe0","\xe1","\xe3",
112
+ "\xe5","\xe7","\xf1","\xa2","\x2e","\x3c","\x28","\x2b","\x7c",
113
+ "\x26","\xe9","\xea","\xeb","\xe8","\xed","\xee","\xef","\xec",
114
+ "\xdf","\x21","\x24","\x2a","\x29","\x3b","\x5e","\x2d","\x2f",
115
+ "\xc2","\xc4","\xc0","\xc1","\xc3","\xc5","\xc7","\xd1","\xa6",
116
+ "\x2c","\x25","\x5f","\x3e","\x3f","\xf8","\xc9","\xca","\xcb",
117
+ "\xc8","\xcd","\xce","\xcf","\xcc","\x60","\x3a","\x23","\x40",
118
+ "\x27","\x3d","\x22","\xd8","\x61","\x62","\x63","\x64","\x65",
119
+ "\x66","\x67","\x68","\x69","\xab","\xbb","\xf0","\xfd","\xfe",
120
+ "\xb1","\xb0","\x6a","\x6b","\x6c","\x6d","\x6e","\x6f","\x70",
121
+ "\x71","\x72","\xaa","\xba","\xe6","\xb8","\xc6","\xa4","\xb5",
122
+ "\x7e","\x73","\x74","\x75","\x76","\x77","\x78","\x79","\x7a",
123
+ "\xa1","\xbf","\xd0","\x5b","\xde","\xae","\xac","\xa3","\xa5",
124
+ "\xb7","\xa9","\xa7","\xb6","\xbc","\xbd","\xbe","\xdd","\xa8",
125
+ "\xaf","\x5d","\xb4","\xd7","\x7b","\x41","\x42","\x43","\x44",
126
+ "\x45","\x46","\x47","\x48","\x49","\xad","\xf4","\xf6","\xf2",
127
+ "\xf3","\xf5","\x7d","\x4a","\x4b","\x4c","\x4d","\x4e","\x4f",
128
+ "\x50","\x51","\x52","\xb9","\xfb","\xfc","\xf9","\xfa","\xff",
129
+ "\x5c","\xf7","\x53","\x54","\x55","\x56","\x57","\x58","\x59",
130
+ "\x5a","\xb2","\xd4","\xd6","\xd2","\xd3","\xd5","\x30","\x31",
131
+ "\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\xb3",
132
+ "\xdb","\xdc","\xd9","\xda","\x9f"
133
+ ]
134
+
135
+ # The Iconv translation table. The Iconv gem is deprecated in favor of
136
+ # String#encode, yet there is no encoding for EBCDIC. See #4525
57
137
  Iconv_EBCDIC = [
58
138
  "\x00", "\x01", "\x02", "\x03", "7", "-", ".", "/", "\x16", "\x05",
59
139
  "%", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13",
@@ -306,7 +386,7 @@ module Text
306
386
  # Converts a raw string to a powershell byte array
307
387
  #
308
388
  def self.to_powershell(str, name = "buf")
309
- return Rex::Exploitation::Powershell::Script.to_byte_array(str, name)
389
+ return Rex::Powershell::Script.to_byte_array(str, name)
310
390
  end
311
391
 
312
392
  #
@@ -372,31 +452,26 @@ module Text
372
452
  return str
373
453
  end
374
454
 
455
+ # Converts US-ASCII to UTF-8, skipping over any characters which don't
456
+ # convert cleanly. This is a convenience method that wraps
457
+ # String#encode with non-raising default paramaters.
375
458
  #
376
- # Converts ISO-8859-1 to UTF-8
377
- #
459
+ # @param str [String] An encodable ASCII string
460
+ # @return [String] a UTF-8 equivalent
461
+ # @note This method will discard invalid characters
378
462
  def self.to_utf8(str)
379
-
380
- if str.respond_to?(:encode)
381
- # Skip over any bytes that fail to convert to UTF-8
382
- return str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' })
383
- end
384
-
385
- begin
386
- Iconv.iconv("utf-8","iso-8859-1", str).join(" ")
387
- rescue
388
- raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
389
- end
463
+ str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' })
390
464
  end
391
465
 
392
- #
393
- # Converts ASCII to EBCDIC
394
- #
395
466
  class IllegalSequence < ArgumentError; end
396
467
 
397
- # A native implementation of the ASCII->EBCDIC table, used to fall back from using
398
- # Iconv
399
- def self.to_ebcdic_rex(str)
468
+ # A native implementation of the ASCII to EBCDIC conversion table, since
469
+ # EBCDIC isn't available to String#encode as of Ruby 2.1
470
+ #
471
+ # @param str [String] An encodable ASCII string
472
+ # @return [String] an EBCDIC encoded string
473
+ # @note This method will raise in the event of invalid characters
474
+ def self.to_ebcdic(str)
400
475
  new_str = []
401
476
  str.each_byte do |x|
402
477
  if Iconv_ASCII.index(x.chr)
@@ -408,9 +483,13 @@ module Text
408
483
  new_str.join
409
484
  end
410
485
 
411
- # A native implementation of the EBCDIC->ASCII table, used to fall back from using
412
- # Iconv
413
- def self.from_ebcdic_rex(str)
486
+ # A native implementation of the EBCDIC to ASCII conversion table, since
487
+ # EBCDIC isn't available to String#encode as of Ruby 2.1
488
+ #
489
+ # @param str [String] an EBCDIC encoded string
490
+ # @return [String] An encodable ASCII string
491
+ # @note This method will raise in the event of invalid characters
492
+ def self.from_ebcdic(str)
414
493
  new_str = []
415
494
  str.each_byte do |x|
416
495
  if Iconv_EBCDIC.index(x.chr)
@@ -422,27 +501,37 @@ module Text
422
501
  new_str.join
423
502
  end
424
503
 
425
- def self.to_ebcdic(str)
426
- begin
427
- Iconv.iconv("EBCDIC-US", "ASCII", str).first
428
- rescue ::Iconv::IllegalSequence => e
429
- raise e
430
- rescue
431
- self.to_ebcdic_rex(str)
504
+ #
505
+ # The next two are the same as the above, except strictly for z/os
506
+ # conversions
507
+ # strictly for IBM1047 -> ISO8859-1
508
+ # A native implementation of the IBM1047(EBCDIC) -> ISO8859-1(ASCII)
509
+ # conversion table, since EBCDIC isn't available to String#encode as of Ruby 2.1
510
+ # all 256 bytes are defined
511
+ #
512
+ def self.to_ibm1047(str)
513
+ return str if str.nil?
514
+ new_str = []
515
+ str.each_byte do |x|
516
+ new_str << Iconv_IBM1047[x.ord]
432
517
  end
518
+ new_str.join
433
519
  end
434
520
 
435
521
  #
436
- # Converts EBCIDC to ASCII
522
+ # The next two are the same as the above, except strictly for z/os
523
+ # conversions
524
+ # strictly for ISO8859-1 -> IBM1047
525
+ # A native implementation of the ISO8859-1(ASCII) -> IBM1047(EBCDIC)
526
+ # conversion table, since EBCDIC isn't available to String#encode as of Ruby 2.1
437
527
  #
438
- def self.from_ebcdic(str)
439
- begin
440
- Iconv.iconv("ASCII", "EBCDIC-US", str).first
441
- rescue ::Iconv::IllegalSequence => e
442
- raise e
443
- rescue
444
- self.from_ebcdic_rex(str)
528
+ def self.from_ibm1047(str)
529
+ return str if str.nil?
530
+ new_str = []
531
+ str.each_byte do |x|
532
+ new_str << Iconv_ISO8859_1[x.ord]
445
533
  end
534
+ new_str.join
446
535
  end
447
536
 
448
537
  #
@@ -1037,6 +1126,56 @@ module Text
1037
1126
  return output
1038
1127
  end
1039
1128
 
1129
+ #
1130
+ # Converts a string to one similar to what would be used by cowsay(1), a UNIX utility for
1131
+ # displaying text as if it was coming from an ASCII-cow's mouth:
1132
+ #
1133
+ # __________________
1134
+ # < the cow says moo >
1135
+ # ------------------
1136
+ # \ ^__^
1137
+ # \ (oo)\_______
1138
+ # (__)\ )\/\
1139
+ # ||----w |
1140
+ # || ||
1141
+ #
1142
+ # @param text [String] The string to cowsay
1143
+ # @param width [Fixnum] Width of the cow's cloud. Default's to cowsay(1)'s default, 39.
1144
+ def self.cowsay(text, width=39)
1145
+ # cowsay(1) chunks a message up into 39-byte chunks and wraps it in '| ' and ' |'
1146
+ # Rex::Text.wordwrap(text, 0, 39, ' |', '| ') almost does this, but won't
1147
+ # split a word that has > 39 characters in it which results in oddly formed
1148
+ # text in the cowsay banner, so just do it by hand. This big mess wraps
1149
+ # the provided text in an ASCII-cloud and then makes it look like the cloud
1150
+ # is a thought/word coming from the ASCII-cow. Each line in the
1151
+ # ASCII-cloud is no more than the specified number-characters long, and the
1152
+ # cloud corners are made to look rounded
1153
+ text_lines = text.scan(Regexp.new(".{1,#{width-4}}"))
1154
+ max_length = text_lines.map(&:size).sort.last
1155
+ cloud_parts = []
1156
+ cloud_parts << " #{'_' * (max_length + 2)}"
1157
+ if text_lines.size == 1
1158
+ cloud_parts << "< #{text} >"
1159
+ else
1160
+ cloud_parts << "/ #{text_lines.first.ljust(max_length, ' ')} \\"
1161
+ if text_lines.size > 2
1162
+ text_lines[1, text_lines.length - 2].each do |line|
1163
+ cloud_parts << "| #{line.ljust(max_length, ' ')} |"
1164
+ end
1165
+ end
1166
+ cloud_parts << "\\ #{text_lines.last.ljust(max_length, ' ')} /"
1167
+ end
1168
+ cloud_parts << " #{'-' * (max_length + 2)}"
1169
+ cloud_parts << <<EOS
1170
+ \\ ,__,
1171
+ \\ (oo)____
1172
+ (__) )\\
1173
+ ||--|| *
1174
+ EOS
1175
+ cloud_parts.join("\n")
1176
+ end
1177
+
1178
+
1040
1179
  ##
1041
1180
  #
1042
1181
  # Transforms
@@ -1134,6 +1273,24 @@ module Text
1134
1273
  str.to_s.unpack("m")[0]
1135
1274
  end
1136
1275
 
1276
+ #
1277
+ # Base64 encoder (URL-safe RFC6920)
1278
+ #
1279
+ def self.encode_base64url(str, delim='')
1280
+ encode_base64(str, delim).
1281
+ tr('+/', '-_').
1282
+ gsub('=', '')
1283
+ end
1284
+
1285
+ #
1286
+ # Base64 decoder (URL-safe RFC6920, ignores invalid characters)
1287
+ #
1288
+ def self.decode_base64url(str)
1289
+ decode_base64(
1290
+ str.gsub(/[^a-zA-Z0-9_\-]/, '').
1291
+ tr('-_', '+/'))
1292
+ end
1293
+
1137
1294
  #
1138
1295
  # Raw MD5 digest of the supplied string
1139
1296
  #
@@ -1274,6 +1431,18 @@ module Text
1274
1431
  rand_base(len, bad, *foo )
1275
1432
  end
1276
1433
 
1434
+ # Generate random bytes of base64 data
1435
+ def self.rand_text_base64(len, bad='')
1436
+ foo = Base64.unpack('C*').map{ |c| c.chr }
1437
+ rand_base(len, bad, *foo )
1438
+ end
1439
+
1440
+ # Generate random bytes of base64url data
1441
+ def self.rand_text_base64url(len, bad='')
1442
+ foo = Base64Url.unpack('C*').map{ |c| c.chr }
1443
+ rand_base(len, bad, *foo )
1444
+ end
1445
+
1277
1446
  # Generate a random GUID
1278
1447
  #
1279
1448
  # @example
@@ -1523,7 +1692,10 @@ module Text
1523
1692
  # @param data [#delete]
1524
1693
  # @param badchars [String] A list of characters considered to be bad
1525
1694
  def self.remove_badchars(data, badchars = '')
1526
- data.delete(badchars)
1695
+ return data if badchars.length == 0
1696
+ badchars_pat = badchars.unpack("C*").map{|c| "\\x%.2x" % c}.join
1697
+ data.gsub!(/[#{badchars_pat}]/n, '')
1698
+ data
1527
1699
  end
1528
1700
 
1529
1701
  #
@@ -1532,7 +1704,8 @@ module Text
1532
1704
  # @param keepers [String]
1533
1705
  # @return [String] All characters not contained in +keepers+
1534
1706
  def self.charset_exclude(keepers)
1535
- [*(0..255)].pack('C*').delete(keepers)
1707
+ excluded_bytes = [*(0..255)] - keepers.unpack("C*")
1708
+ excluded_bytes.pack("C*")
1536
1709
  end
1537
1710
 
1538
1711
  #
@@ -1643,6 +1816,19 @@ module Text
1643
1816
  mail_address << Rex::Text.rand_hostname
1644
1817
  end
1645
1818
 
1819
+ #
1820
+ # Calculate the block API hash for the given module/function
1821
+ #
1822
+ # @param mod [String] The name of the module containing the target function.
1823
+ # @param fun [String] The name of the function.
1824
+ #
1825
+ # @return [String] The hash of the mod/fun pair in string format
1826
+ def self.block_api_hash(mod, fun)
1827
+ unicode_mod = (mod.upcase + "\x00").unpack('C*').pack('v*')
1828
+ mod_hash = self.ror13_hash(unicode_mod)
1829
+ fun_hash = self.ror13_hash(fun + "\x00")
1830
+ "0x#{(mod_hash + fun_hash & 0xFFFFFFFF).to_s(16)}"
1831
+ end
1646
1832
 
1647
1833
  #
1648
1834
  # Calculate the ROR13 hash of a given string