bettercap 1.1.10 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|