bettercap 1.1.10 → 1.2.0
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/TODO.md +8 -7
- data/bin/bettercap +8 -2
- data/lib/bettercap.rb +5 -4
- data/lib/bettercap/context.rb +54 -8
- data/lib/bettercap/discovery/agents/arp.rb +17 -4
- data/lib/bettercap/discovery/agents/base.rb +16 -52
- data/lib/bettercap/discovery/agents/icmp.rb +25 -17
- data/lib/bettercap/discovery/agents/udp.rb +9 -20
- data/lib/bettercap/discovery/{discovery.rb → thread.rb} +10 -9
- data/lib/bettercap/error.rb +1 -2
- data/lib/bettercap/factories/{firewall_factory.rb → firewall.rb} +11 -7
- data/lib/bettercap/factories/{parser_factory.rb → parser.rb} +13 -3
- data/lib/bettercap/factories/{spoofer_factory.rb → spoofer.rb} +10 -3
- data/lib/bettercap/firewalls/base.rb +76 -0
- data/lib/bettercap/firewalls/linux.rb +26 -16
- data/lib/bettercap/firewalls/osx.rb +22 -13
- data/lib/bettercap/firewalls/redirection.rb +15 -1
- data/lib/bettercap/httpd/server.rb +5 -0
- data/lib/bettercap/logger.rb +29 -8
- data/lib/bettercap/network.rb +105 -105
- data/lib/bettercap/options.rb +99 -41
- data/lib/bettercap/packet_queue.rb +92 -0
- data/lib/bettercap/proxy/certstore.rb +49 -43
- data/lib/bettercap/proxy/module.rb +4 -2
- data/lib/bettercap/proxy/proxy.rb +7 -2
- data/lib/bettercap/proxy/request.rb +28 -16
- data/lib/bettercap/proxy/response.rb +23 -2
- data/lib/bettercap/proxy/stream_logger.rb +6 -0
- data/lib/bettercap/proxy/streamer.rb +13 -5
- data/lib/bettercap/proxy/thread_pool.rb +6 -14
- data/lib/bettercap/shell.rb +5 -3
- data/lib/bettercap/sniffer/parsers/base.rb +7 -1
- data/lib/bettercap/sniffer/parsers/custom.rb +6 -1
- data/lib/bettercap/sniffer/parsers/ftp.rb +8 -5
- data/lib/bettercap/sniffer/parsers/httpauth.rb +4 -1
- data/lib/bettercap/sniffer/parsers/https.rb +4 -1
- data/lib/bettercap/sniffer/parsers/irc.rb +8 -5
- data/lib/bettercap/sniffer/parsers/mail.rb +8 -5
- data/lib/bettercap/sniffer/parsers/ntlmss.rb +21 -18
- data/lib/bettercap/sniffer/parsers/post.rb +4 -1
- data/lib/bettercap/sniffer/parsers/url.rb +4 -1
- data/lib/bettercap/sniffer/sniffer.rb +7 -3
- data/lib/bettercap/spoofers/arp.rb +69 -94
- data/lib/bettercap/spoofers/base.rb +132 -0
- data/lib/bettercap/spoofers/icmp.rb +200 -0
- data/lib/bettercap/spoofers/none.rb +8 -2
- data/lib/bettercap/target.rb +117 -90
- data/lib/bettercap/update_checker.rb +6 -0
- data/lib/bettercap/version.rb +3 -1
- metadata +24 -8
- data/lib/bettercap/base/ifirewall.rb +0 -46
- data/lib/bettercap/base/ispoofer.rb +0 -32
@@ -10,18 +10,23 @@ This project is released under the GPL 3 license.
|
|
10
10
|
|
11
11
|
=end
|
12
12
|
module BetterCap
|
13
|
-
|
13
|
+
module Discovery
|
14
|
+
# Class responsible to actively discover targets on the network.
|
15
|
+
class Thread
|
16
|
+
# Initialize the class using the +ctx+ BetterCap::Context instance.
|
14
17
|
def initialize( ctx )
|
15
18
|
@ctx = ctx
|
16
19
|
@running = false
|
17
20
|
@thread = nil
|
18
21
|
end
|
19
22
|
|
23
|
+
# Start the active network discovery thread.
|
20
24
|
def start
|
21
25
|
@running = true
|
22
|
-
@thread = Thread.new { worker }
|
26
|
+
@thread = ::Thread.new { worker }
|
23
27
|
end
|
24
28
|
|
29
|
+
# Stop the active network discovery thread.
|
25
30
|
def stop
|
26
31
|
@running = false
|
27
32
|
if @thread != nil
|
@@ -39,15 +44,10 @@ class Discovery
|
|
39
44
|
Logger.debug( 'Network discovery thread started.' ) unless @ctx.options.arpcache
|
40
45
|
|
41
46
|
while @running
|
42
|
-
|
43
|
-
|
44
|
-
if @ctx.options.should_discover_hosts?
|
45
|
-
Logger.info 'Searching for targets ...' if empty_list
|
46
|
-
end
|
47
|
-
|
47
|
+
was_empty = @ctx.targets.empty?
|
48
48
|
@ctx.targets = Network.get_alive_targets(@ctx).sort_by { |t| t.sortable_ip }
|
49
49
|
|
50
|
-
if
|
50
|
+
if was_empty and not @ctx.targets.empty?
|
51
51
|
Logger.info "Collected #{@ctx.targets.size} total targets."
|
52
52
|
|
53
53
|
msg = "\n"
|
@@ -62,3 +62,4 @@ class Discovery
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
65
|
+
end
|
data/lib/bettercap/error.rb
CHANGED
@@ -9,8 +9,7 @@ Blog : http://www.evilsocket.net/
|
|
9
9
|
This project is released under the GPL 3 license.
|
10
10
|
|
11
11
|
=end
|
12
|
-
|
13
|
-
# class used to distinghuish between handled and unhandled exceptions
|
14
12
|
module BetterCap
|
13
|
+
# Class used to distinghuish between handled and unhandled exceptions.
|
15
14
|
class Error < StandardError; end
|
16
15
|
end
|
@@ -14,25 +14,29 @@ require 'bettercap/firewalls/osx'
|
|
14
14
|
require 'bettercap/firewalls/linux'
|
15
15
|
|
16
16
|
module BetterCap
|
17
|
-
|
17
|
+
module Factories
|
18
|
+
# Factory class responsible of creating the correct object for the current
|
19
|
+
# operating system of the user.
|
20
|
+
class Firewall
|
18
21
|
@@instance = nil
|
19
|
-
|
20
|
-
def self.
|
22
|
+
# Save and return an instance of the appropriate BetterCap::Firewalls object.
|
23
|
+
def self.get
|
21
24
|
return @@instance unless @@instance.nil?
|
22
25
|
|
23
26
|
if RUBY_PLATFORM =~ /darwin/
|
24
|
-
@@instance =
|
27
|
+
@@instance = Firewalls::OSX.new
|
25
28
|
elsif RUBY_PLATFORM =~ /linux/
|
26
|
-
@@instance =
|
29
|
+
@@instance = Firewalls::Linux.new
|
27
30
|
else
|
28
31
|
raise BetterCap::Error, 'Unsupported operating system'
|
29
32
|
end
|
30
33
|
|
31
34
|
@@instance
|
32
35
|
end
|
33
|
-
|
34
|
-
def
|
36
|
+
# Clear the instance of the BetterCap::Firewalls object.
|
37
|
+
def self.clear
|
35
38
|
@@instance = nil
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
42
|
+
end
|
@@ -14,10 +14,14 @@ require 'bettercap/error'
|
|
14
14
|
require 'bettercap/logger'
|
15
15
|
|
16
16
|
module BetterCap
|
17
|
-
|
17
|
+
module Factories
|
18
|
+
# Factory class responsible for listing, parsing and creating BetterCap::Parsers
|
19
|
+
# object instances.
|
20
|
+
class Parser
|
18
21
|
@@path = File.dirname(__FILE__) + '/../sniffer/parsers/'
|
19
22
|
|
20
23
|
class << self
|
24
|
+
# Return a list of available parsers.
|
21
25
|
def available
|
22
26
|
avail = []
|
23
27
|
Dir.foreach( @@path ) do |file|
|
@@ -28,6 +32,8 @@ class ParserFactory
|
|
28
32
|
avail
|
29
33
|
end
|
30
34
|
|
35
|
+
# Parse the +v+ command line argument and return a list of parser names.
|
36
|
+
# Will raise BetterCap::Error if one or more parser names are not valid.
|
31
37
|
def from_cmdline(v)
|
32
38
|
raise BetterCap::Error, "No parser names provided" if v.nil?
|
33
39
|
|
@@ -39,6 +45,7 @@ class ParserFactory
|
|
39
45
|
list
|
40
46
|
end
|
41
47
|
|
48
|
+
# Return a list of BetterCap::Parsers instances by their +parsers+ names.
|
42
49
|
def load_by_names(parsers)
|
43
50
|
loaded = []
|
44
51
|
Dir.foreach( @@path ) do |file|
|
@@ -48,16 +55,19 @@ class ParserFactory
|
|
48
55
|
|
49
56
|
require_relative "#{@@path}#{file}"
|
50
57
|
|
51
|
-
loaded << Kernel.const_get("BetterCap::#{cname.capitalize}
|
58
|
+
loaded << Kernel.const_get("BetterCap::Parsers::#{cname.capitalize}").new
|
52
59
|
end
|
53
60
|
end
|
54
61
|
loaded
|
55
62
|
end
|
56
63
|
|
64
|
+
# Load and return an instance of the BetterCap::Parsers::Custom parser
|
65
|
+
# given the +expression+ Regex object.
|
57
66
|
def load_custom(expression)
|
58
67
|
require_relative "#{@@path}custom.rb"
|
59
|
-
[ BetterCap::
|
68
|
+
[ BetterCap::Parsers::Custom.new(expression) ]
|
60
69
|
end
|
61
70
|
end
|
62
71
|
end
|
63
72
|
end
|
73
|
+
end
|
@@ -12,18 +12,24 @@ This project is released under the GPL 3 license.
|
|
12
12
|
require 'bettercap/error'
|
13
13
|
|
14
14
|
module BetterCap
|
15
|
-
|
15
|
+
module Factories
|
16
|
+
# Factory class responsible for listing, parsing and creating BetterCap::Spoofers
|
17
|
+
# object instances.
|
18
|
+
class Spoofer
|
16
19
|
class << self
|
20
|
+
# Return a list of available spoofers.
|
17
21
|
def available
|
18
22
|
avail = []
|
19
23
|
Dir.foreach( File.dirname(__FILE__) + '/../spoofers/') do |file|
|
20
|
-
if file =~ /.rb/
|
24
|
+
if file =~ /.rb/ and file != 'base.rb'
|
21
25
|
avail << file.gsub('.rb','').upcase
|
22
26
|
end
|
23
27
|
end
|
24
28
|
avail
|
25
29
|
end
|
26
30
|
|
31
|
+
# Create an instance of a BetterCap::Spoofers object given its +name+.
|
32
|
+
# Will raise a BetterCap::Error if +name+ is not valid.
|
27
33
|
def get_by_name(name)
|
28
34
|
raise BetterCap::Error, "Invalid spoofer name '#{name}'!" unless available? name
|
29
35
|
|
@@ -31,7 +37,7 @@ class SpooferFactory
|
|
31
37
|
|
32
38
|
require_relative "../spoofers/#{name}"
|
33
39
|
|
34
|
-
Kernel.const_get("BetterCap::#{name.capitalize}
|
40
|
+
Kernel.const_get("BetterCap::Spoofers::#{name.capitalize}").new
|
35
41
|
end
|
36
42
|
|
37
43
|
private
|
@@ -42,3 +48,4 @@ class SpooferFactory
|
|
42
48
|
end
|
43
49
|
end
|
44
50
|
end
|
51
|
+
end
|
@@ -0,0 +1,76 @@
|
|
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
|
+
module BetterCap
|
13
|
+
module Firewalls
|
14
|
+
# Base class for BetterCap::Firewalls objects.
|
15
|
+
class Base
|
16
|
+
# Initialize the firewall object.
|
17
|
+
# Raise NotImplementedError
|
18
|
+
def initialize
|
19
|
+
@frwd_initial_state = forwarding_enabled?
|
20
|
+
end
|
21
|
+
|
22
|
+
# If +enabled+ is true will enable packet forwarding, otherwise it will
|
23
|
+
# disable it.
|
24
|
+
# Raise NotImplementedError
|
25
|
+
def enable_forwarding(enabled)
|
26
|
+
not_implemented_method!
|
27
|
+
end
|
28
|
+
|
29
|
+
# If +enabled+ is true will enable icmp_echo_ignore_broadcasts, otherwise it will
|
30
|
+
# disable it.
|
31
|
+
# Raise NotImplementedError
|
32
|
+
def enable_icmp_bcast(enabled)
|
33
|
+
not_implemented_method!
|
34
|
+
end
|
35
|
+
|
36
|
+
# If +enabled+ is true will enable send_redirects, otherwise it will
|
37
|
+
# disable it.
|
38
|
+
# Raise NotImplementedError
|
39
|
+
def enable_send_redirects(enabled)
|
40
|
+
not_implemented_method!
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return true if packet forwarding is currently enabled, otherwise false.
|
44
|
+
# Raise NotImplementedError
|
45
|
+
def forwarding_enabled?
|
46
|
+
not_implemented_method!
|
47
|
+
end
|
48
|
+
|
49
|
+
# Apply the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
50
|
+
# Raise NotImplementedError
|
51
|
+
def add_port_redirection( r )
|
52
|
+
not_implemented_method!
|
53
|
+
end
|
54
|
+
|
55
|
+
# Remove the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
56
|
+
# Raise NotImplementedError
|
57
|
+
def del_port_redirection( r )
|
58
|
+
not_implemented_method!
|
59
|
+
end
|
60
|
+
|
61
|
+
# Restore the system's original packet forwarding state.
|
62
|
+
# Raise NotImplementedError
|
63
|
+
def restore
|
64
|
+
if forwarding_enabled? != @frwd_initial_state
|
65
|
+
enable_forwarding @frwd_initial_state
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def not_implemented_method!
|
72
|
+
raise NotImplementedError, 'Firewalls::Base: Unimplemented method!'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -9,43 +9,53 @@ Blog : http://www.evilsocket.net/
|
|
9
9
|
This project is released under the GPL 3 license.
|
10
10
|
|
11
11
|
=end
|
12
|
-
require 'bettercap/base
|
12
|
+
require 'bettercap/firewalls/base'
|
13
13
|
require 'bettercap/shell'
|
14
14
|
|
15
15
|
module BetterCap
|
16
|
-
|
16
|
+
module Firewalls
|
17
|
+
# Linux firewall class.
|
18
|
+
class Linux < Base
|
19
|
+
# If +enabled+ is true will enable packet forwarding, otherwise it will
|
20
|
+
# disable it.
|
17
21
|
def enable_forwarding(enabled)
|
18
|
-
|
22
|
+
Shell.execute("echo #{enabled ? 1 : 0} > /proc/sys/net/ipv4/ip_forward")
|
19
23
|
end
|
20
24
|
|
25
|
+
# Return true if packet forwarding is currently enabled, otherwise false.
|
21
26
|
def forwarding_enabled?
|
22
|
-
|
27
|
+
Shell.execute('cat /proc/sys/net/ipv4/ip_forward').strip == '1'
|
23
28
|
end
|
24
29
|
|
30
|
+
# If +enabled+ is true will enable packet icmp_echo_ignore_broadcasts, otherwise it will
|
31
|
+
# disable it.
|
25
32
|
def enable_icmp_bcast(enabled)
|
26
|
-
|
33
|
+
Shell.execute("echo #{enabled ? 0 : 1} > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts")
|
27
34
|
end
|
28
35
|
|
36
|
+
# If +enabled+ is true will enable send_redirects, otherwise it will
|
37
|
+
# disable it.
|
38
|
+
def enable_send_redirects(enabled)
|
39
|
+
Shell.execute("echo #{enabled ? 0 : 1} > /proc/sys/net/ipv4/conf/all/send_redirects")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Apply the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
29
43
|
def add_port_redirection( r )
|
30
44
|
# post route
|
31
|
-
|
45
|
+
Shell.execute('iptables -t nat -I POSTROUTING -s 0/0 -j MASQUERADE')
|
32
46
|
# accept all
|
33
|
-
|
47
|
+
Shell.execute('iptables -P FORWARD ACCEPT')
|
34
48
|
# add redirection
|
35
|
-
|
49
|
+
Shell.execute("iptables -t nat -A PREROUTING -i #{r.interface} -p #{r.protocol} --dport #{r.src_port} -j DNAT --to #{r.dst_address}:#{r.dst_port}")
|
36
50
|
end
|
37
51
|
|
52
|
+
# Remove the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
38
53
|
def del_port_redirection( r )
|
39
54
|
# remove post route
|
40
|
-
|
55
|
+
Shell.execute('iptables -t nat -D POSTROUTING -s 0/0 -j MASQUERADE')
|
41
56
|
# remove redirection
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def shell
|
48
|
-
Shell
|
57
|
+
Shell.execute("iptables -t nat -D PREROUTING -i #{r.interface} -p #{r.protocol} --dport #{r.src_port} -j DNAT --to #{r.dst_address}:#{r.dst_port}")
|
49
58
|
end
|
50
59
|
end
|
51
60
|
end
|
61
|
+
end
|
@@ -9,29 +9,42 @@ Blog : http://www.evilsocket.net/
|
|
9
9
|
This project is released under the GPL 3 license.
|
10
10
|
|
11
11
|
=end
|
12
|
-
require 'bettercap/base
|
12
|
+
require 'bettercap/firewalls/base'
|
13
13
|
require 'bettercap/shell'
|
14
14
|
|
15
15
|
module BetterCap
|
16
|
-
|
16
|
+
module Firewalls
|
17
|
+
# OSX Firewall class.
|
18
|
+
class OSX < Base
|
19
|
+
# If +enabled+ is true will enable packet forwarding, otherwise it will
|
20
|
+
# disable it.
|
17
21
|
def enable_forwarding(enabled)
|
18
|
-
|
22
|
+
Shell.execute("sysctl -w net.inet.ip.forwarding=#{enabled ? 1 : 0}")
|
19
23
|
end
|
20
24
|
|
25
|
+
# If +enabled+ is true will enable packet icmp_echo_ignore_broadcasts, otherwise it will
|
26
|
+
# disable it.
|
21
27
|
def enable_icmp_bcast(enabled)
|
22
|
-
|
28
|
+
Shell.execute("sysctl -w net.inet.icmp.bmcastecho=#{enabled ? 1 : 0}")
|
23
29
|
end
|
24
30
|
|
31
|
+
# Return true if packet forwarding is currently enabled, otherwise false.
|
25
32
|
def forwarding_enabled?
|
26
|
-
|
33
|
+
Shell.execute('sysctl net.inet.ip.forwarding').strip.split(' ')[1] == '1'
|
27
34
|
end
|
28
35
|
|
36
|
+
# This method is ignored on OSX.
|
37
|
+
def enable_send_redirects(enabled); end
|
38
|
+
|
39
|
+
# If +enabled+ is true, the PF firewall will be enabled, otherwise it will
|
40
|
+
# be disabled.
|
29
41
|
def enable(enabled)
|
30
42
|
begin
|
31
|
-
|
43
|
+
Shell.execute("pfctl -#{enabled ? 'e' : 'd'} >/dev/null 2>&1")
|
32
44
|
rescue; end
|
33
45
|
end
|
34
46
|
|
47
|
+
# Apply the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
35
48
|
def add_port_redirection( r )
|
36
49
|
# create the pf config file
|
37
50
|
config_file = "/tmp/bettercap_pf_#{Process.pid}.conf"
|
@@ -41,11 +54,12 @@ class OSXFirewall < IFirewall
|
|
41
54
|
end
|
42
55
|
|
43
56
|
# load the rule
|
44
|
-
|
57
|
+
Shell.execute("pfctl -f #{config_file} >/dev/null 2>&1")
|
45
58
|
# enable pf
|
46
59
|
enable true
|
47
60
|
end
|
48
61
|
|
62
|
+
# Remove the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
49
63
|
def del_port_redirection( r )
|
50
64
|
# FIXME: This should search for multiple rules inside the
|
51
65
|
# file and remove only this one.
|
@@ -60,11 +74,6 @@ class OSXFirewall < IFirewall
|
|
60
74
|
end
|
61
75
|
|
62
76
|
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def shell
|
67
|
-
Shell
|
68
|
-
end
|
77
|
+
end
|
69
78
|
end
|
70
79
|
end
|
@@ -10,9 +10,22 @@ This project is released under the GPL 3 license.
|
|
10
10
|
|
11
11
|
=end
|
12
12
|
module BetterCap
|
13
|
+
module Firewalls
|
14
|
+
# This class represents a firewall port redirection rule.
|
13
15
|
class Redirection
|
14
|
-
|
16
|
+
# Network interface name.
|
17
|
+
attr_reader :interface
|
18
|
+
# Protocol name.
|
19
|
+
attr_reader :protocol
|
20
|
+
# Source port.
|
21
|
+
attr_reader :src_port
|
22
|
+
# Destination address.
|
23
|
+
attr_reader :dst_address
|
24
|
+
# Destionation port.
|
25
|
+
attr_reader :dst_port
|
15
26
|
|
27
|
+
# Create the redirection rule for the specified +interface+ and +protocol+.
|
28
|
+
# Redirect *:+src_port+ to +dst_address+:+dst_port+
|
16
29
|
def initialize( interface, protocol, src_port, dst_address, dst_port )
|
17
30
|
@interface = interface
|
18
31
|
@protocol = protocol
|
@@ -22,3 +35,4 @@ class Redirection
|
|
22
35
|
end
|
23
36
|
end
|
24
37
|
end
|
38
|
+
end
|
@@ -15,7 +15,10 @@ require 'bettercap/logger'
|
|
15
15
|
|
16
16
|
module BetterCap
|
17
17
|
module HTTPD
|
18
|
+
# Simple HTTP server class used to serve static assets when needed.
|
18
19
|
class Server
|
20
|
+
# Initialize the HTTP server with the specified tcp +port+ using
|
21
|
+
# +path+ as the document root.
|
19
22
|
def initialize( port = 8081, path = './' )
|
20
23
|
@port = port
|
21
24
|
@path = path
|
@@ -27,6 +30,7 @@ class Server
|
|
27
30
|
)
|
28
31
|
end
|
29
32
|
|
33
|
+
# Start the server.
|
30
34
|
def start
|
31
35
|
Logger.info "Starting HTTPD on port #{@port} and path #{@path} ..."
|
32
36
|
@thread = Thread.new {
|
@@ -34,6 +38,7 @@ class Server
|
|
34
38
|
}
|
35
39
|
end
|
36
40
|
|
41
|
+
# Stop the server.
|
37
42
|
def stop
|
38
43
|
Logger.info 'Stopping HTTPD ...'
|
39
44
|
|