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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/TODO.md +8 -7
  3. data/bin/bettercap +8 -2
  4. data/lib/bettercap.rb +5 -4
  5. data/lib/bettercap/context.rb +54 -8
  6. data/lib/bettercap/discovery/agents/arp.rb +17 -4
  7. data/lib/bettercap/discovery/agents/base.rb +16 -52
  8. data/lib/bettercap/discovery/agents/icmp.rb +25 -17
  9. data/lib/bettercap/discovery/agents/udp.rb +9 -20
  10. data/lib/bettercap/discovery/{discovery.rb → thread.rb} +10 -9
  11. data/lib/bettercap/error.rb +1 -2
  12. data/lib/bettercap/factories/{firewall_factory.rb → firewall.rb} +11 -7
  13. data/lib/bettercap/factories/{parser_factory.rb → parser.rb} +13 -3
  14. data/lib/bettercap/factories/{spoofer_factory.rb → spoofer.rb} +10 -3
  15. data/lib/bettercap/firewalls/base.rb +76 -0
  16. data/lib/bettercap/firewalls/linux.rb +26 -16
  17. data/lib/bettercap/firewalls/osx.rb +22 -13
  18. data/lib/bettercap/firewalls/redirection.rb +15 -1
  19. data/lib/bettercap/httpd/server.rb +5 -0
  20. data/lib/bettercap/logger.rb +29 -8
  21. data/lib/bettercap/network.rb +105 -105
  22. data/lib/bettercap/options.rb +99 -41
  23. data/lib/bettercap/packet_queue.rb +92 -0
  24. data/lib/bettercap/proxy/certstore.rb +49 -43
  25. data/lib/bettercap/proxy/module.rb +4 -2
  26. data/lib/bettercap/proxy/proxy.rb +7 -2
  27. data/lib/bettercap/proxy/request.rb +28 -16
  28. data/lib/bettercap/proxy/response.rb +23 -2
  29. data/lib/bettercap/proxy/stream_logger.rb +6 -0
  30. data/lib/bettercap/proxy/streamer.rb +13 -5
  31. data/lib/bettercap/proxy/thread_pool.rb +6 -14
  32. data/lib/bettercap/shell.rb +5 -3
  33. data/lib/bettercap/sniffer/parsers/base.rb +7 -1
  34. data/lib/bettercap/sniffer/parsers/custom.rb +6 -1
  35. data/lib/bettercap/sniffer/parsers/ftp.rb +8 -5
  36. data/lib/bettercap/sniffer/parsers/httpauth.rb +4 -1
  37. data/lib/bettercap/sniffer/parsers/https.rb +4 -1
  38. data/lib/bettercap/sniffer/parsers/irc.rb +8 -5
  39. data/lib/bettercap/sniffer/parsers/mail.rb +8 -5
  40. data/lib/bettercap/sniffer/parsers/ntlmss.rb +21 -18
  41. data/lib/bettercap/sniffer/parsers/post.rb +4 -1
  42. data/lib/bettercap/sniffer/parsers/url.rb +4 -1
  43. data/lib/bettercap/sniffer/sniffer.rb +7 -3
  44. data/lib/bettercap/spoofers/arp.rb +69 -94
  45. data/lib/bettercap/spoofers/base.rb +132 -0
  46. data/lib/bettercap/spoofers/icmp.rb +200 -0
  47. data/lib/bettercap/spoofers/none.rb +8 -2
  48. data/lib/bettercap/target.rb +117 -90
  49. data/lib/bettercap/update_checker.rb +6 -0
  50. data/lib/bettercap/version.rb +3 -1
  51. metadata +24 -8
  52. data/lib/bettercap/base/ifirewall.rb +0 -46
  53. 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
- class Discovery
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
- empty_list = @ctx.targets.empty?
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 empty_list and not @ctx.targets.empty?
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
@@ -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
- class FirewallFactory
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.get_firewall
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 = OSXFirewall.new
27
+ @@instance = Firewalls::OSX.new
25
28
  elsif RUBY_PLATFORM =~ /linux/
26
- @@instance = LinuxFirewall.new
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 FirewallFactory.clear_firewall
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
- class ParserFactory
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}Parser").new
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::CustomParser.new(expression) ]
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
- class SpooferFactory
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}Spoofer").new
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/ifirewall'
12
+ require 'bettercap/firewalls/base'
13
13
  require 'bettercap/shell'
14
14
 
15
15
  module BetterCap
16
- class LinuxFirewall < IFirewall
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
- shell.execute("echo #{enabled ? 1 : 0} > /proc/sys/net/ipv4/ip_forward")
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
- shell.execute('cat /proc/sys/net/ipv4/ip_forward').strip == '1'
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
- shell.execute("echo #{enabled ? 0 : 1} > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts")
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
- shell.execute('iptables -t nat -I POSTROUTING -s 0/0 -j MASQUERADE')
45
+ Shell.execute('iptables -t nat -I POSTROUTING -s 0/0 -j MASQUERADE')
32
46
  # accept all
33
- shell.execute('iptables -P FORWARD ACCEPT')
47
+ Shell.execute('iptables -P FORWARD ACCEPT')
34
48
  # add redirection
35
- 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}")
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
- shell.execute('iptables -t nat -D POSTROUTING -s 0/0 -j MASQUERADE')
55
+ Shell.execute('iptables -t nat -D POSTROUTING -s 0/0 -j MASQUERADE')
41
56
  # remove redirection
42
- 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}")
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/ifirewall'
12
+ require 'bettercap/firewalls/base'
13
13
  require 'bettercap/shell'
14
14
 
15
15
  module BetterCap
16
- class OSXFirewall < IFirewall
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
- shell.execute("sysctl -w net.inet.ip.forwarding=#{enabled ? 1 : 0}")
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
- shell.execute("sysctl -w net.inet.icmp.bmcastecho=#{enabled ? 1 : 0}")
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
- shell.execute('sysctl net.inet.ip.forwarding').strip.split(' ')[1] == '1'
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
- shell.execute("pfctl -#{enabled ? 'e' : 'd'} >/dev/null 2>&1")
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
- shell.execute("pfctl -f #{config_file} >/dev/null 2>&1")
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
- attr_reader :interface, :protocol, :src_port, :dst_address, :dst_port
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