bettercap 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/bettercap/context.rb +1 -2
- data/lib/bettercap/discovery/thread.rb +13 -5
- data/lib/bettercap/memory.rb +1 -1
- data/lib/bettercap/network/network.rb +1 -1
- data/lib/bettercap/network/packet_queue.rb +3 -1
- data/lib/bettercap/network/validator.rb +9 -0
- data/lib/bettercap/options/core_options.rb +12 -16
- data/lib/bettercap/options/options.rb +1 -1
- data/lib/bettercap/options/proxy_options.rb +37 -1
- data/lib/bettercap/options/server_options.rb +6 -4
- data/lib/bettercap/options/sniff_options.rb +6 -6
- data/lib/bettercap/options/spoof_options.rb +2 -2
- data/lib/bettercap/proxy/http/module.rb +2 -2
- data/lib/bettercap/proxy/tcp/module.rb +2 -2
- data/lib/bettercap/spoofers/base.rb +1 -1
- data/lib/bettercap/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1fb03c684e4f5c63193e20fa8d8cd226f619059
|
4
|
+
data.tar.gz: 02c684a36e92f414fb1ba06095e6690309320d60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f0b04d7769d9d27a02c53bdf7af45024a417bd67fae18a3fa67b7b47af51454a8246e222df3d38657ab519af3dfa7d3e947406916ac963d6735f5514e7bc831
|
7
|
+
data.tar.gz: 9a145c4ecb97d929433b5411657d551145f3e1e4c642a42c54c5d6deba673556e53aae746647e1c82d713f0d7bb7bb049aec3648bd3ab00dcf85d5f5ae227ee5
|
data/lib/bettercap/context.rb
CHANGED
@@ -121,12 +121,11 @@ class Context
|
|
121
121
|
# Start everything!
|
122
122
|
def start!
|
123
123
|
# Start targets auto discovery.
|
124
|
-
BetterCap::Logger.info( "Targeting the whole subnet #{@ifconfig[:ip4_obj].to_range} ..." ) unless @options.spoof.enabled? or @options.core.arpcache
|
125
124
|
@discovery.start
|
126
125
|
# give some time to the discovery thread to spawn its workers,
|
127
126
|
# this will prevent 'Too many open files' errors to delay host
|
128
127
|
# discovery.
|
129
|
-
sleep(1.5)
|
128
|
+
sleep(1.5) if @options.core.discovery?
|
130
129
|
|
131
130
|
# Start network spoofers if any.
|
132
131
|
@spoofer.each do |spoofer|
|
@@ -23,6 +23,10 @@ class Thread
|
|
23
23
|
|
24
24
|
# Start the active network discovery thread.
|
25
25
|
def start
|
26
|
+
if @ctx.options.core.discovery?
|
27
|
+
Logger.info "[#{'DISCOVERY'.green}] Targeting the whole subnet #{@ctx.ifconfig[:ip4_obj].to_range} ..."
|
28
|
+
end
|
29
|
+
|
26
30
|
@running = true
|
27
31
|
@thread = ::Thread.new { worker }
|
28
32
|
end
|
@@ -31,7 +35,6 @@ class Thread
|
|
31
35
|
def stop
|
32
36
|
@running = false
|
33
37
|
if @thread != nil
|
34
|
-
Logger.info( 'Stopping network discovery thread ...' ) unless @ctx.options.core.arpcache
|
35
38
|
begin
|
36
39
|
@thread.exit
|
37
40
|
rescue
|
@@ -97,18 +100,23 @@ class Thread
|
|
97
100
|
# This method implements the main discovery logic, it will be executed within
|
98
101
|
# the spawned thread.
|
99
102
|
def worker
|
100
|
-
Logger.debug( 'Network discovery thread started.' )
|
103
|
+
Logger.debug( 'Network discovery thread started.' ) if @ctx.options.core.discovery?
|
101
104
|
|
102
105
|
prev = []
|
103
106
|
while @running
|
104
|
-
|
107
|
+
# No targets specified.
|
108
|
+
if @ctx.options.core.targets.nil?
|
109
|
+
@ctx.targets = Network.get_alive_targets(@ctx).sort_by {
|
110
|
+
|t| t.sortable_ip
|
111
|
+
}
|
112
|
+
end
|
105
113
|
|
106
|
-
print_differences( prev )
|
114
|
+
print_differences( prev ) if @ctx.options.core.discovery?
|
107
115
|
|
108
116
|
prev = @ctx.targets
|
109
117
|
|
110
118
|
@ctx.memory.optimize!
|
111
|
-
sleep(1) if @ctx.options.core.
|
119
|
+
sleep(1) if @ctx.options.core.discovery?
|
112
120
|
end
|
113
121
|
end
|
114
122
|
end
|
data/lib/bettercap/memory.rb
CHANGED
@@ -46,7 +46,7 @@ class Memory
|
|
46
46
|
freed_d = new_freed
|
47
47
|
end
|
48
48
|
|
49
|
-
Logger.debug "GC: allocd objects: #{allocs_d} freed objects: #{freed_d}"
|
49
|
+
# Logger.debug "GC: allocd objects: #{allocs_d} freed objects: #{freed_d}"
|
50
50
|
|
51
51
|
@total_allocs = new_allocs
|
52
52
|
@total_freed = new_freed
|
@@ -54,7 +54,7 @@ class << self
|
|
54
54
|
# Return a list of BetterCap::Target objects found on the network, given a
|
55
55
|
# BetterCap::Context ( +ctx+ ) and a +timeout+ in seconds for the operation.
|
56
56
|
def get_alive_targets( ctx )
|
57
|
-
if ctx.options.core.
|
57
|
+
if ctx.options.core.discovery?
|
58
58
|
start_agents( ctx )
|
59
59
|
else
|
60
60
|
Logger.debug 'Using current ARP cache.'
|
@@ -100,7 +100,9 @@ class PacketQueue
|
|
100
100
|
sleep(@throttle) if @throttle != 0.0
|
101
101
|
|
102
102
|
rescue Exception => e
|
103
|
-
|
103
|
+
if !e.message.include?('Host is down') and !e.message.include?('Permission denied') and !e.message.include?('No route to host')
|
104
|
+
Logger.debug "#{self.class.name} ( #{packet.class.name} ) : #{e.message}"
|
105
|
+
end
|
104
106
|
|
105
107
|
# If we've got an error message such as:
|
106
108
|
# (cannot open BPF device) /dev/bpf0: Too many open files
|
@@ -27,6 +27,15 @@ class Validator
|
|
27
27
|
false
|
28
28
|
end
|
29
29
|
|
30
|
+
# Return true if +port+ is a valid port, otherwise false.
|
31
|
+
def self.is_valid_port?(port)
|
32
|
+
port ||= ""
|
33
|
+
return false if port.strip.empty?
|
34
|
+
return false unless port =~ /^[0-9]+$/
|
35
|
+
port = port.to_i
|
36
|
+
return ( port > 0 and port <= 65535 )
|
37
|
+
end
|
38
|
+
|
30
39
|
# Extract valid IP addresses from +data+ and yields each one of them.
|
31
40
|
def self.each_ip(data)
|
32
41
|
data.scan(/(#{IP_ADDRESS_REGEX})/).each do |m|
|
@@ -41,18 +41,18 @@ class CoreOptions
|
|
41
41
|
attr_accessor :check_updates
|
42
42
|
|
43
43
|
def initialize( iface )
|
44
|
-
@iface
|
45
|
-
@gateway
|
46
|
-
@targets
|
47
|
-
@logfile
|
48
|
-
@log_timestamp
|
49
|
-
@silent
|
50
|
-
@debug
|
51
|
-
@ignore
|
52
|
-
@arpcache
|
53
|
-
@no_target_nbns
|
44
|
+
@iface = iface
|
45
|
+
@gateway = nil
|
46
|
+
@targets = nil
|
47
|
+
@logfile = nil
|
48
|
+
@log_timestamp = false
|
49
|
+
@silent = false
|
50
|
+
@debug = false
|
51
|
+
@ignore = nil
|
52
|
+
@arpcache = false
|
53
|
+
@no_target_nbns = false
|
54
54
|
@packet_throttle = 0.0
|
55
|
-
@check_updates
|
55
|
+
@check_updates = false
|
56
56
|
end
|
57
57
|
|
58
58
|
def parse!( ctx, opts )
|
@@ -127,6 +127,7 @@ class CoreOptions
|
|
127
127
|
raise BetterCap::Error, 'No default interface found, please specify one with the -I argument.' if @iface.nil?
|
128
128
|
end
|
129
129
|
|
130
|
+
# Return true if active host discovery is enabled, otherwise false.
|
130
131
|
def discovery?
|
131
132
|
( @targets.nil? and !@arpcache )
|
132
133
|
end
|
@@ -179,11 +180,6 @@ class CoreOptions
|
|
179
180
|
def ignore_ip?(ip)
|
180
181
|
!@ignore.nil? and @ignore.include?(ip)
|
181
182
|
end
|
182
|
-
|
183
|
-
# Return true if active host discovery is enabled, otherwise false.
|
184
|
-
def should_discover_hosts?
|
185
|
-
!@arpcache
|
186
|
-
end
|
187
183
|
end
|
188
184
|
|
189
185
|
end
|
@@ -98,17 +98,35 @@ class ProxyOptions
|
|
98
98
|
end
|
99
99
|
|
100
100
|
opts.on( '--tcp-proxy-port PORT', "Set local TCP proxy port, default to #{@tcp_proxy_port.to_s.yellow} ." ) do |v|
|
101
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
101
102
|
@tcp_proxy = true
|
102
103
|
@tcp_proxy_port = v.to_i
|
103
104
|
end
|
104
105
|
|
106
|
+
opts.on( '--tcp-proxy-upstream ADDRESS:PORT', 'Set TCP proxy upstream server address and port.' ) do |v|
|
107
|
+
if v =~ /^(.+):(\d+)$/
|
108
|
+
address = $1
|
109
|
+
port = $2
|
110
|
+
else
|
111
|
+
raise BetterCap::Error, "Invalid address and port specified, the correct syntax is ADDRESS:PORT ( i.e. 192.168.1.2:22 )."
|
112
|
+
end
|
113
|
+
|
114
|
+
address, port = validate_address address, port
|
115
|
+
|
116
|
+
@tcp_proxy = true
|
117
|
+
@tcp_proxy_upstream_address = address
|
118
|
+
@tcp_proxy_upstream_port = port.to_i
|
119
|
+
end
|
120
|
+
|
105
121
|
opts.on( '--tcp-proxy-upstream-address ADDRESS', 'Set TCP proxy upstream server address.' ) do |v|
|
106
|
-
|
122
|
+
v, _ = validate_address v
|
123
|
+
|
107
124
|
@tcp_proxy = true
|
108
125
|
@tcp_proxy_upstream_address = v
|
109
126
|
end
|
110
127
|
|
111
128
|
opts.on( '--tcp-proxy-upstream-port PORT', 'Set TCP proxy upstream server port.' ) do |v|
|
129
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
112
130
|
@tcp_proxy = true
|
113
131
|
@tcp_proxy_upstream_port = v.to_i
|
114
132
|
end
|
@@ -121,6 +139,7 @@ class ProxyOptions
|
|
121
139
|
end
|
122
140
|
|
123
141
|
opts.on( '--proxy-port PORT', "Set HTTP proxy port, default to #{@proxy_port.to_s.yellow}." ) do |v|
|
142
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
124
143
|
@proxy = true
|
125
144
|
@proxy_port = v.to_i
|
126
145
|
end
|
@@ -146,6 +165,7 @@ class ProxyOptions
|
|
146
165
|
end
|
147
166
|
|
148
167
|
opts.on( '--proxy-https-port PORT', "Set HTTPS proxy port, default to #{@proxy_https_port.to_s.yellow}." ) do |v|
|
168
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
149
169
|
@proxy_https = true
|
150
170
|
@proxy_https_port = v.to_i
|
151
171
|
end
|
@@ -168,6 +188,7 @@ class ProxyOptions
|
|
168
188
|
end
|
169
189
|
|
170
190
|
opts.on( '--custom-proxy-port PORT', "Specify a port for the custom HTTP upstream proxy, default to #{@custom_proxy_port.to_s.yellow}." ) do |v|
|
191
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
171
192
|
@custom_proxy_port = v.to_i
|
172
193
|
end
|
173
194
|
|
@@ -176,6 +197,7 @@ class ProxyOptions
|
|
176
197
|
end
|
177
198
|
|
178
199
|
opts.on( '--custom-https-proxy-port PORT', "Specify a port for the custom HTTPS upstream proxy, default to #{@custom_https_proxy_port.to_s.yellow}." ) do |v|
|
200
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
179
201
|
@custom_https_proxy_port = v.to_i
|
180
202
|
end
|
181
203
|
|
@@ -253,6 +275,20 @@ class ProxyOptions
|
|
253
275
|
def any?
|
254
276
|
@proxy or @proxy_https or @tcp_proxy or @custom_proxy
|
255
277
|
end
|
278
|
+
|
279
|
+
def validate_address( address, port = nil )
|
280
|
+
unless Network::Validator.is_ip?(address)
|
281
|
+
begin
|
282
|
+
address = IPSocket.getaddress address
|
283
|
+
rescue SocketError
|
284
|
+
raise BetterCap::Error, "Could not resolve '#{address}' to a valid ip address."
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
raise BetterCap::Error, "Invalid port '#{port}' specified." unless port.nil? or Network::Validator.is_valid_port?(port)
|
289
|
+
|
290
|
+
[ address, port ]
|
291
|
+
end
|
256
292
|
end
|
257
293
|
|
258
294
|
end
|
@@ -28,12 +28,12 @@ class ServerOptions
|
|
28
28
|
attr_accessor :dnsd_file
|
29
29
|
|
30
30
|
def initialize
|
31
|
-
@httpd
|
31
|
+
@httpd = false
|
32
32
|
@httpd_port = 8081
|
33
33
|
@httpd_path = './'
|
34
|
-
@dnsd
|
35
|
-
@dnsd_port
|
36
|
-
@dnsd_file
|
34
|
+
@dnsd = false
|
35
|
+
@dnsd_port = 5300
|
36
|
+
@dnsd_file = nil
|
37
37
|
end
|
38
38
|
|
39
39
|
def parse!( ctx, opts )
|
@@ -46,6 +46,7 @@ class ServerOptions
|
|
46
46
|
end
|
47
47
|
|
48
48
|
opts.on( '--httpd-port PORT', "Set HTTP server port, default to #{@httpd_port.to_s.yellow}." ) do |v|
|
49
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
49
50
|
@httpd = true
|
50
51
|
@httpd_port = v.to_i
|
51
52
|
end
|
@@ -61,6 +62,7 @@ class ServerOptions
|
|
61
62
|
end
|
62
63
|
|
63
64
|
opts.on( '--dns-port PORT', "Set DNS server port, default to #{@dnsd_port.to_s.yellow}." ) do |v|
|
65
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
64
66
|
@dnsd_port = v.to_i
|
65
67
|
end
|
66
68
|
|
@@ -31,13 +31,13 @@ class SniffOptions
|
|
31
31
|
attr_accessor :local
|
32
32
|
|
33
33
|
def initialize
|
34
|
-
@enabled
|
35
|
-
@output
|
36
|
-
@filter
|
37
|
-
@src
|
38
|
-
@parsers
|
34
|
+
@enabled = false
|
35
|
+
@output = nil
|
36
|
+
@filter = nil
|
37
|
+
@src = nil
|
38
|
+
@parsers = ['*']
|
39
39
|
@custom_parser = nil
|
40
|
-
@local
|
40
|
+
@local = false
|
41
41
|
end
|
42
42
|
|
43
43
|
def parse!( ctx, opts )
|
@@ -51,8 +51,8 @@ class Module
|
|
51
51
|
require ctx.options.proxies.proxy_module
|
52
52
|
|
53
53
|
self.register_options(opts)
|
54
|
-
rescue LoadError
|
55
|
-
raise BetterCap::Error, "Invalid proxy module name '#{name}' ."
|
54
|
+
rescue LoadError => e
|
55
|
+
raise BetterCap::Error, "Invalid proxy module name '#{name}': #{e.message}"
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -51,8 +51,8 @@ class Module
|
|
51
51
|
def load( file )
|
52
52
|
begin
|
53
53
|
require file
|
54
|
-
rescue LoadError
|
55
|
-
raise BetterCap::Error, "Invalid TCP proxy module specified."
|
54
|
+
rescue LoadError => e
|
55
|
+
raise BetterCap::Error, "Invalid TCP proxy module specified: #{e.message}"
|
56
56
|
end
|
57
57
|
|
58
58
|
@@loaded.each do |name,mod|
|
data/lib/bettercap/version.rb
CHANGED
@@ -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.5.
|
15
|
+
VERSION = '1.5.1'
|
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.5.
|
4
|
+
version: 1.5.1
|
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-03-
|
11
|
+
date: 2016-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|