bettercap 1.1.9 → 1.1.10
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 +4 -4
- data/CONTRIBUTING.md +2 -2
- data/TODO.md +5 -2
- data/bin/bettercap +19 -11
- data/lib/bettercap.rb +5 -1
- data/lib/bettercap/base/ifirewall.rb +2 -0
- data/lib/bettercap/base/ispoofer.rb +2 -0
- data/lib/bettercap/context.rb +5 -2
- data/lib/bettercap/discovery/{arp.rb → agents/arp.rb} +15 -14
- data/lib/bettercap/discovery/{base.rb → agents/base.rb} +4 -4
- data/lib/bettercap/discovery/{icmp.rb → agents/icmp.rb} +2 -3
- data/lib/bettercap/discovery/{udp.rb → agents/udp.rb} +2 -2
- data/lib/bettercap/{discovery.rb → discovery/discovery.rb} +8 -1
- data/lib/bettercap/factories/firewall_factory.rb +2 -0
- data/lib/bettercap/factories/parser_factory.rb +11 -5
- data/lib/bettercap/factories/spoofer_factory.rb +3 -1
- data/lib/bettercap/firewalls/linux.rb +2 -0
- data/lib/bettercap/firewalls/osx.rb +2 -0
- data/lib/bettercap/firewalls/redirection.rb +2 -1
- data/lib/bettercap/httpd/server.rb +2 -3
- data/lib/bettercap/logger.rb +27 -10
- data/lib/bettercap/monkey/packetfu/utils.rb +5 -5
- data/lib/bettercap/network.rb +26 -16
- data/lib/bettercap/options.rb +27 -6
- data/lib/bettercap/proxy/certstore.rb +4 -3
- data/lib/bettercap/proxy/module.rb +2 -2
- data/lib/bettercap/proxy/proxy.rb +5 -5
- data/lib/bettercap/proxy/request.rb +2 -2
- data/lib/bettercap/proxy/response.rb +2 -0
- data/lib/bettercap/proxy/stream_logger.rb +15 -3
- data/lib/bettercap/proxy/streamer.rb +3 -1
- data/lib/bettercap/proxy/thread_pool.rb +4 -2
- data/lib/bettercap/shell.rb +2 -0
- data/lib/bettercap/sniffer/parsers/base.rb +3 -12
- data/lib/bettercap/sniffer/parsers/custom.rb +21 -0
- data/lib/bettercap/sniffer/parsers/ftp.rb +2 -0
- data/lib/bettercap/sniffer/parsers/httpauth.rb +4 -5
- data/lib/bettercap/sniffer/parsers/https.rb +3 -4
- data/lib/bettercap/sniffer/parsers/irc.rb +2 -0
- data/lib/bettercap/sniffer/parsers/mail.rb +2 -0
- data/lib/bettercap/sniffer/parsers/ntlmss.rb +3 -3
- data/lib/bettercap/sniffer/parsers/post.rb +7 -7
- data/lib/bettercap/sniffer/parsers/url.rb +11 -11
- data/lib/bettercap/sniffer/sniffer.rb +8 -2
- data/lib/bettercap/spoofers/arp.rb +15 -5
- data/lib/bettercap/spoofers/none.rb +2 -0
- data/lib/bettercap/target.rb +29 -10
- data/lib/bettercap/update_checker.rb +2 -0
- data/lib/bettercap/version.rb +1 -1
- metadata +8 -40
- data/Rakefile +0 -7
- data/test/factories/firewall_factory_test.rb +0 -54
- data/test/factories/parser_factory_test.rb +0 -36
- data/test/factories/spoofer_factory_test.rb +0 -15
- data/test/firewalls/linux_firewall_test.rb +0 -72
- data/test/firewalls/osx_firewall_test.rb +0 -72
- data/test/helpers/mock_shell.rb +0 -17
- data/test/logger_test.rb +0 -12
- data/test/network_test.rb +0 -14
- data/test/pcap/ftp.pcap +0 -0
- data/test/pcap/http.pcap +0 -0
- data/test/pcap/packets.pcap +0 -0
- data/test/proxy/response_test.rb +0 -56
- data/test/shell_test.rb +0 -15
- data/test/sniffer/parsers/base_parser_test.rb +0 -20
- data/test/sniffer/parsers/ftp_parser_test.rb +0 -27
- data/test/sniffer/parsers/url_parser_test.rb +0 -25
- data/test/target_test.rb +0 -24
- data/test/test_helper.rb +0 -47
@@ -9,6 +9,7 @@ Blog : http://www.evilsocket.net/
|
|
9
9
|
This project is released under the GPL 3 license.
|
10
10
|
|
11
11
|
=end
|
12
|
+
module BetterCap
|
12
13
|
class Redirection
|
13
14
|
attr_reader :interface, :protocol, :src_port, :dst_address, :dst_port
|
14
15
|
|
@@ -20,4 +21,4 @@ class Redirection
|
|
20
21
|
@dst_port = dst_port
|
21
22
|
end
|
22
23
|
end
|
23
|
-
|
24
|
+
end
|
@@ -13,8 +13,8 @@ require 'webrick'
|
|
13
13
|
|
14
14
|
require 'bettercap/logger'
|
15
15
|
|
16
|
+
module BetterCap
|
16
17
|
module HTTPD
|
17
|
-
|
18
18
|
class Server
|
19
19
|
def initialize( port = 8081, path = './' )
|
20
20
|
@port = port
|
@@ -41,6 +41,5 @@ class Server
|
|
41
41
|
@thread.join
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
45
44
|
end
|
46
|
-
|
45
|
+
end
|
data/lib/bettercap/logger.rb
CHANGED
@@ -9,13 +9,21 @@ Blog : http://www.evilsocket.net/
|
|
9
9
|
This project is released under the GPL 3 license.
|
10
10
|
|
11
11
|
=end
|
12
|
+
module BetterCap
|
12
13
|
module Logger
|
13
14
|
class << self
|
14
|
-
|
15
|
+
@@queue = Queue.new
|
16
|
+
@@debug = false
|
17
|
+
@@silent = false
|
18
|
+
@@logfile = nil
|
19
|
+
@@thread = nil
|
20
|
+
|
21
|
+
def init( debug, logfile, silent )
|
15
22
|
@@debug = debug
|
16
23
|
@@logfile = logfile
|
17
|
-
@@queue = Queue.new
|
18
24
|
@@thread = Thread.new { worker }
|
25
|
+
@@silent = silent
|
26
|
+
@@ctx = Context.get
|
19
27
|
end
|
20
28
|
|
21
29
|
def error(message)
|
@@ -23,7 +31,7 @@ module Logger
|
|
23
31
|
end
|
24
32
|
|
25
33
|
def info(message)
|
26
|
-
@@queue.push formatted_message(message, 'I')
|
34
|
+
@@queue.push( formatted_message(message, 'I') ) unless @@silent
|
27
35
|
end
|
28
36
|
|
29
37
|
def warn(message)
|
@@ -31,13 +39,19 @@ module Logger
|
|
31
39
|
end
|
32
40
|
|
33
41
|
def debug(message)
|
34
|
-
if @@debug
|
42
|
+
if @@debug and not @@silent
|
35
43
|
@@queue.push formatted_message(message, 'D').light_black
|
36
44
|
end
|
37
45
|
end
|
38
46
|
|
39
47
|
def raw(message)
|
40
|
-
@@queue.push message
|
48
|
+
@@queue.push( message )
|
49
|
+
end
|
50
|
+
|
51
|
+
def wait!
|
52
|
+
while not @@queue.empty?
|
53
|
+
sleep 0.3
|
54
|
+
end
|
41
55
|
end
|
42
56
|
|
43
57
|
private
|
@@ -45,11 +59,13 @@ module Logger
|
|
45
59
|
def worker
|
46
60
|
loop do
|
47
61
|
message = @@queue.pop
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
62
|
+
if @@ctx.running
|
63
|
+
puts message
|
64
|
+
unless @@logfile.nil?
|
65
|
+
f = File.open( @@logfile, 'a+t' )
|
66
|
+
f.puts( message.gsub( /\e\[(\d+)(;\d+)*m/, '') + "\n")
|
67
|
+
f.close
|
68
|
+
end
|
53
69
|
end
|
54
70
|
end
|
55
71
|
end
|
@@ -59,3 +75,4 @@ module Logger
|
|
59
75
|
end
|
60
76
|
end
|
61
77
|
end
|
78
|
+
end
|
@@ -23,9 +23,9 @@ module PacketFu
|
|
23
23
|
ret = {}
|
24
24
|
iface = iface.to_s.scan(/[0-9A-Za-z]/).join
|
25
25
|
|
26
|
-
Logger.debug "ifconfig #{iface}"
|
27
|
-
|
28
|
-
ifconfig_data = Shell.ifconfig(iface)
|
26
|
+
BetterCap::Logger.debug "ifconfig #{iface}"
|
27
|
+
|
28
|
+
ifconfig_data = BetterCap::Shell.ifconfig(iface)
|
29
29
|
if ifconfig_data =~ /#{iface}/i
|
30
30
|
ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
|
31
31
|
else
|
@@ -45,7 +45,7 @@ module PacketFu
|
|
45
45
|
private
|
46
46
|
|
47
47
|
def self.linux_ifconfig(iface='eth0',ifconfig_data)
|
48
|
-
Logger.debug "Linux ifconfig #{iface}:\n#{ifconfig_data}"
|
48
|
+
BetterCap::Logger.debug "Linux ifconfig #{iface}:\n#{ifconfig_data}"
|
49
49
|
|
50
50
|
ret = {}
|
51
51
|
real_iface = ifconfig_data.first
|
@@ -81,7 +81,7 @@ module PacketFu
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def self.darwin_ifconfig(iface='eth0',ifconfig_data)
|
84
|
-
Logger.debug "OSX ifconfig #{iface}:\n#{ifconfig_data}"
|
84
|
+
BetterCap::Logger.debug "OSX ifconfig #{iface}:\n#{ifconfig_data}"
|
85
85
|
|
86
86
|
ret = {}
|
87
87
|
real_iface = ifconfig_data.first
|
data/lib/bettercap/network.rb
CHANGED
@@ -11,15 +11,7 @@ This project is released under the GPL 3 license.
|
|
11
11
|
=end
|
12
12
|
require 'thread'
|
13
13
|
|
14
|
-
|
15
|
-
require 'bettercap/logger'
|
16
|
-
require 'bettercap/shell'
|
17
|
-
require 'bettercap/target'
|
18
|
-
require 'bettercap/factories/firewall_factory'
|
19
|
-
require 'bettercap/discovery/icmp'
|
20
|
-
require 'bettercap/discovery/udp'
|
21
|
-
require 'bettercap/discovery/arp'
|
22
|
-
|
14
|
+
module BetterCap
|
23
15
|
class Network
|
24
16
|
class << self
|
25
17
|
def is_ip?(ip)
|
@@ -29,6 +21,10 @@ class Network
|
|
29
21
|
false
|
30
22
|
end
|
31
23
|
|
24
|
+
def is_mac?(mac)
|
25
|
+
( /^[a-f0-9]{1,2}\:[a-f0-9]{1,2}\:[a-f0-9]{1,2}\:[a-f0-9]{1,2}\:[a-f0-9]{1,2}\:[a-f0-9]{1,2}$/i =~ mac.to_s )
|
26
|
+
end
|
27
|
+
|
32
28
|
def get_gateway
|
33
29
|
nstat = Shell.execute('netstat -nr')
|
34
30
|
|
@@ -62,13 +58,7 @@ class Network
|
|
62
58
|
|
63
59
|
def get_alive_targets( ctx, timeout = 5 )
|
64
60
|
if ctx.options.should_discover_hosts?
|
65
|
-
|
66
|
-
udp = UdpAgent.new ctx.ifconfig, ctx.gateway, ctx.ifconfig[:ip_saddr]
|
67
|
-
arp = ArpAgent.new ctx.ifconfig, ctx.gateway, ctx.ifconfig[:ip_saddr]
|
68
|
-
|
69
|
-
icmp.wait
|
70
|
-
arp.wait
|
71
|
-
udp.wait
|
61
|
+
start_agents( ctx, timeout )
|
72
62
|
else
|
73
63
|
Logger.debug 'Using current ARP cache.'
|
74
64
|
end
|
@@ -76,6 +66,15 @@ class Network
|
|
76
66
|
ArpAgent.parse ctx
|
77
67
|
end
|
78
68
|
|
69
|
+
def get_ip_address( ctx, mac, timeout = 5 )
|
70
|
+
ip = ArpAgent.find_mac( mac )
|
71
|
+
if ip.nil?
|
72
|
+
start_agents( ctx, timeout )
|
73
|
+
ip = ArpAgent.find_mac( mac )
|
74
|
+
end
|
75
|
+
ip
|
76
|
+
end
|
77
|
+
|
79
78
|
=begin
|
80
79
|
Apparently on Mac OSX the gem pcaprub ( or libpcap itself ) has
|
81
80
|
a bug, so we can't use 'PacketFu::Utils::arp' since the funtion
|
@@ -132,6 +131,16 @@ class Network
|
|
132
131
|
|
133
132
|
private
|
134
133
|
|
134
|
+
def start_agents( ctx, timeout )
|
135
|
+
icmp = IcmpAgent.new timeout
|
136
|
+
udp = UdpAgent.new ctx.ifconfig, ctx.gateway, ctx.ifconfig[:ip_saddr]
|
137
|
+
arp = ArpAgent.new ctx.ifconfig, ctx.gateway, ctx.ifconfig[:ip_saddr]
|
138
|
+
|
139
|
+
icmp.wait
|
140
|
+
arp.wait
|
141
|
+
udp.wait
|
142
|
+
end
|
143
|
+
|
135
144
|
def get_mac_from_capture( cap, ip_address )
|
136
145
|
cap.stream.each do |p|
|
137
146
|
arp_response = PacketFu::Packet.parse(p)
|
@@ -141,3 +150,4 @@ class Network
|
|
141
150
|
end
|
142
151
|
end
|
143
152
|
end
|
153
|
+
end
|
data/lib/bettercap/options.rb
CHANGED
@@ -9,7 +9,7 @@ Blog : http://www.evilsocket.net/
|
|
9
9
|
This project is released under the GPL 3 license.
|
10
10
|
|
11
11
|
=end
|
12
|
-
|
12
|
+
module BetterCap
|
13
13
|
class Options
|
14
14
|
attr_accessor :gateway,
|
15
15
|
:iface,
|
@@ -17,6 +17,7 @@ class Options
|
|
17
17
|
:half_duplex,
|
18
18
|
:target,
|
19
19
|
:logfile,
|
20
|
+
:silent,
|
20
21
|
:debug,
|
21
22
|
:arpcache,
|
22
23
|
:ignore,
|
@@ -25,6 +26,7 @@ class Options
|
|
25
26
|
:sniffer_filter,
|
26
27
|
:sniffer_src,
|
27
28
|
:parsers,
|
29
|
+
:custom_parser,
|
28
30
|
:local,
|
29
31
|
:proxy,
|
30
32
|
:proxy_https,
|
@@ -39,7 +41,8 @@ class Options
|
|
39
41
|
:httpd,
|
40
42
|
:httpd_port,
|
41
43
|
:httpd_path,
|
42
|
-
:check_updates
|
44
|
+
:check_updates,
|
45
|
+
:no_target_nbns
|
43
46
|
|
44
47
|
def initialize( iface )
|
45
48
|
@gateway = nil
|
@@ -48,8 +51,10 @@ class Options
|
|
48
51
|
@half_duplex = false
|
49
52
|
@target = nil
|
50
53
|
@logfile = nil
|
54
|
+
@silent = false
|
51
55
|
@debug = false
|
52
56
|
@arpcache = false
|
57
|
+
@no_target_nbns = false
|
53
58
|
|
54
59
|
@ignore = nil
|
55
60
|
|
@@ -58,6 +63,7 @@ class Options
|
|
58
63
|
@sniffer_filter = nil
|
59
64
|
@sniffer_src = nil
|
60
65
|
@parsers = ['*']
|
66
|
+
@custom_parser = nil
|
61
67
|
@local = false
|
62
68
|
|
63
69
|
@proxy = false
|
@@ -144,6 +150,16 @@ class Options
|
|
144
150
|
ctx.options.parsers = ParserFactory.from_cmdline(v)
|
145
151
|
end
|
146
152
|
|
153
|
+
opts.on( '--custom-parser EXPRESSION', 'Use a custom regular expression in order to capture and show sniffed data ( NOTE: Will set -X to true ).' ) do |v|
|
154
|
+
ctx.options.sniffer = true
|
155
|
+
ctx.options.parsers = ['CUSTOM']
|
156
|
+
ctx.options.custom_parser = Regexp.new(v)
|
157
|
+
end
|
158
|
+
|
159
|
+
opts.on( '--silent', 'Suppress every message which is not an error or a warning, default to false.' ) do
|
160
|
+
ctx.options.silent = true
|
161
|
+
end
|
162
|
+
|
147
163
|
opts.on( '--no-discovery', 'Do not actively search for hosts, just use the current ARP cache, default to false.' ) do
|
148
164
|
ctx.options.arpcache = true
|
149
165
|
end
|
@@ -152,6 +168,10 @@ class Options
|
|
152
168
|
ctx.options.spoofer = 'NONE'
|
153
169
|
end
|
154
170
|
|
171
|
+
opts.on( '--no-target-nbns', 'Disable target NBNS hostname resolution.' ) do
|
172
|
+
ctx.options.no_target_nbns = true
|
173
|
+
end
|
174
|
+
|
155
175
|
opts.on( '--half-duplex', 'Enable half-duplex MITM, this will make bettercap work in those cases when the router is not vulnerable.' ) do
|
156
176
|
ctx.options.half_duplex = true
|
157
177
|
end
|
@@ -228,7 +248,7 @@ class Options
|
|
228
248
|
end
|
229
249
|
end.parse!
|
230
250
|
|
231
|
-
Logger.init( ctx.options.debug, ctx.options.logfile )
|
251
|
+
Logger.init( ctx.options.debug, ctx.options.logfile, ctx.options.silent )
|
232
252
|
|
233
253
|
Logger.warn "You are running an unstable/beta version of this software, please" \
|
234
254
|
" update to a stable one if available." if BetterCap::VERSION =~ /[\d\.+]b/
|
@@ -309,13 +329,13 @@ class Options
|
|
309
329
|
|
310
330
|
def to_targets
|
311
331
|
targets = @target.split(",")
|
312
|
-
valid_targets = targets.select { |target| Network.is_ip?(target) }
|
332
|
+
valid_targets = targets.select { |target| Network.is_ip?(target) or Network.is_mac?(target) }
|
313
333
|
|
314
|
-
raise BetterCap::Error, "Invalid target" if valid_targets.empty?
|
334
|
+
raise BetterCap::Error, "Invalid target specified." if valid_targets.empty?
|
315
335
|
|
316
336
|
invalid_targets = targets - valid_targets
|
317
337
|
invalid_targets.each do |target|
|
318
|
-
Logger.warn "Invalid target #{target}"
|
338
|
+
Logger.warn "Invalid target specified: #{target}"
|
319
339
|
end
|
320
340
|
|
321
341
|
valid_targets.map { |target| Target.new(target) }
|
@@ -368,3 +388,4 @@ class Options
|
|
368
388
|
redirections
|
369
389
|
end
|
370
390
|
end
|
391
|
+
end
|
@@ -12,13 +12,14 @@ This project is released under the GPL 3 license.
|
|
12
12
|
require 'bettercap/logger'
|
13
13
|
require 'openssl'
|
14
14
|
|
15
|
+
module BetterCap
|
15
16
|
module Proxy
|
16
17
|
class CertStore
|
17
18
|
@@selfsigned = {}
|
18
19
|
@@frompems = {}
|
19
20
|
|
20
21
|
def self.from_file( filename )
|
21
|
-
|
22
|
+
unless @@frompems.has_key? filename
|
22
23
|
Logger.info "Loading self signed HTTPS certificate from '#{filename}' ..."
|
23
24
|
|
24
25
|
pem = File.read filename
|
@@ -30,7 +31,7 @@ module Proxy
|
|
30
31
|
end
|
31
32
|
|
32
33
|
def self.get_selfsigned( subject = '/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com' )
|
33
|
-
|
34
|
+
unless @@selfsigned.has_key? subject
|
34
35
|
Logger.info "Generating self signed HTTPS certificate for subject '#{subject}' ..."
|
35
36
|
|
36
37
|
key = OpenSSL::PKey::RSA.new(2048)
|
@@ -63,5 +64,5 @@ module Proxy
|
|
63
64
|
@@selfsigned[subject]
|
64
65
|
end
|
65
66
|
end
|
66
|
-
|
67
|
+
end
|
67
68
|
end
|
@@ -16,6 +16,7 @@ require 'uri'
|
|
16
16
|
require 'bettercap/logger'
|
17
17
|
require 'bettercap/network'
|
18
18
|
|
19
|
+
module BetterCap
|
19
20
|
module Proxy
|
20
21
|
|
21
22
|
class Proxy
|
@@ -93,8 +94,7 @@ class Proxy
|
|
93
94
|
begin
|
94
95
|
@pool << @server.accept
|
95
96
|
rescue Exception => e
|
96
|
-
Logger.warn("Error while accepting #{@type} connection: #{e.inspect}")
|
97
|
-
unless !@running
|
97
|
+
Logger.warn("Error while accepting #{@type} connection: #{e.inspect}") if @running
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
@@ -122,7 +122,7 @@ class Proxy
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def get_client_details( client )
|
125
|
-
|
125
|
+
unless @is_https
|
126
126
|
client_port, client_ip = Socket.unpack_sockaddr_in(client.getpeername)
|
127
127
|
else
|
128
128
|
_, client_port, _, client_ip = client.peeraddr
|
@@ -179,7 +179,7 @@ class Proxy
|
|
179
179
|
response = Response.from_socket server
|
180
180
|
|
181
181
|
if response.textual?
|
182
|
-
StreamLogger.
|
182
|
+
StreamLogger.log_http( @is_https, client_ip, request, response )
|
183
183
|
|
184
184
|
Logger.debug 'Detected textual response'
|
185
185
|
|
@@ -207,5 +207,5 @@ class Proxy
|
|
207
207
|
end
|
208
208
|
end
|
209
209
|
|
210
|
-
|
210
|
+
end
|
211
211
|
end
|
@@ -10,8 +10,8 @@ This project is released under the GPL 3 license.
|
|
10
10
|
|
11
11
|
=end
|
12
12
|
|
13
|
+
module BetterCap
|
13
14
|
module Proxy
|
14
|
-
|
15
15
|
class Request
|
16
16
|
attr_reader :lines, :verb, :url, :host, :port, :content_length
|
17
17
|
|
@@ -94,5 +94,5 @@ class Request
|
|
94
94
|
@lines.join("\n") + "\n"
|
95
95
|
end
|
96
96
|
end
|
97
|
-
|
97
|
+
end
|
98
98
|
end
|