rex 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
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