bettercap 1.3.5 → 1.3.6

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -10
  3. data/lib/bettercap.rb +28 -3
  4. data/lib/bettercap/context.rb +2 -2
  5. data/lib/bettercap/discovery/agents/icmp.rb +1 -1
  6. data/lib/bettercap/firewalls/base.rb +25 -0
  7. data/lib/bettercap/monkey/packetfu/utils.rb +70 -10
  8. data/lib/bettercap/network/network.rb +11 -3
  9. data/lib/bettercap/network/packet_queue.rb +1 -1
  10. data/lib/bettercap/network/protos/base.rb +97 -0
  11. data/lib/bettercap/network/protos/dhcp.rb +350 -0
  12. data/lib/bettercap/options.rb +4 -4
  13. data/lib/bettercap/proxy/stream_logger.rb +7 -3
  14. data/lib/bettercap/shell.rb +23 -1
  15. data/lib/bettercap/sniffer/parsers/base.rb +52 -0
  16. data/lib/bettercap/sniffer/parsers/cookie.rb +45 -0
  17. data/lib/bettercap/sniffer/parsers/custom.rb +0 -1
  18. data/lib/bettercap/sniffer/parsers/dhcp.rb +48 -0
  19. data/lib/bettercap/sniffer/parsers/dict.rb +0 -1
  20. data/lib/bettercap/sniffer/parsers/ftp.rb +0 -1
  21. data/lib/bettercap/sniffer/parsers/httpauth.rb +0 -2
  22. data/lib/bettercap/sniffer/parsers/https.rb +0 -2
  23. data/lib/bettercap/sniffer/parsers/irc.rb +0 -1
  24. data/lib/bettercap/sniffer/parsers/mail.rb +0 -1
  25. data/lib/bettercap/sniffer/parsers/mpd.rb +0 -1
  26. data/lib/bettercap/sniffer/parsers/nntp.rb +0 -1
  27. data/lib/bettercap/sniffer/parsers/ntlmss.rb +0 -2
  28. data/lib/bettercap/sniffer/parsers/post.rb +5 -3
  29. data/lib/bettercap/sniffer/parsers/redis.rb +0 -1
  30. data/lib/bettercap/sniffer/parsers/rlogin.rb +0 -1
  31. data/lib/bettercap/sniffer/parsers/snpp.rb +0 -1
  32. data/lib/bettercap/sniffer/parsers/url.rb +0 -2
  33. data/lib/bettercap/sniffer/parsers/whatsapp.rb +33 -0
  34. data/lib/bettercap/sniffer/sniffer.rb +6 -6
  35. data/lib/bettercap/spoofers/base.rb +23 -0
  36. data/lib/bettercap/version.rb +1 -1
  37. metadata +7 -5
  38. data/lib/bettercap/factories/firewall.rb +0 -43
  39. data/lib/bettercap/factories/parser.rb +0 -74
  40. data/lib/bettercap/factories/spoofer.rb +0 -53
@@ -175,7 +175,7 @@ class Options
175
175
  ctx.options.iface = v
176
176
  end
177
177
 
178
- opts.on( '-S', '--spoofer NAME', 'Spoofer module to use, available: ' + Factories::Spoofer.available.join(', ') + ' - default: ' + ctx.options.spoofer ) do |v|
178
+ opts.on( '-S', '--spoofer NAME', 'Spoofer module to use, available: ' + Spoofers::Base.available.join(', ') + ' - default: ' + ctx.options.spoofer ) do |v|
179
179
  ctx.options.spoofer = v
180
180
  end
181
181
 
@@ -223,9 +223,9 @@ class Options
223
223
  ctx.options.sniffer_filter = v
224
224
  end
225
225
 
226
- opts.on( '-P', '--parsers PARSERS', 'Comma separated list of packet parsers to enable, "*" for all ( NOTE: Will set -X to true ), available: ' + Factories::Parser.available.join(', ') + ' - default: *' ) do |v|
226
+ opts.on( '-P', '--parsers PARSERS', 'Comma separated list of packet parsers to enable, "*" for all ( NOTE: Will set -X to true ), available: ' + Parsers::Base.available.join(', ') + ' - default: *' ) do |v|
227
227
  ctx.options.sniffer = true
228
- ctx.options.parsers = Factories::Parser.from_cmdline(v)
228
+ ctx.options.parsers = Parsers::Base.from_cmdline(v)
229
229
  end
230
230
 
231
231
  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|
@@ -492,7 +492,7 @@ class Options
492
492
  spoofers = []
493
493
  spoofer_modules_names = @spoofer.split(",")
494
494
  spoofer_modules_names.each do |module_name|
495
- spoofers << Factories::Spoofer.get_by_name( module_name )
495
+ spoofers << Spoofers::Base.get_by_name( module_name )
496
496
  end
497
497
  spoofers
498
498
  end
@@ -26,7 +26,7 @@ class StreamLogger
26
26
 
27
27
  # Search for the +addr+ IP address inside the list of collected targets and return
28
28
  # its compact string representation ( @see BetterCap::Target#to_s_compact ).
29
- def self.addr2s( addr )
29
+ def self.addr2s( addr, alt = nil )
30
30
  ctx = Context.get
31
31
 
32
32
  return 'local' if addr == ctx.ifconfig[:ip_saddr]
@@ -34,6 +34,10 @@ class StreamLogger
34
34
  target = ctx.find_target addr, nil
35
35
  return target.to_s_compact unless target.nil?
36
36
 
37
+ if addr == '0.0.0.0' and !alt.nil?
38
+ return alt
39
+ end
40
+
37
41
  addr
38
42
  end
39
43
 
@@ -41,8 +45,8 @@ class StreamLogger
41
45
  def self.log_raw( pkt, label, payload )
42
46
  nl = if label.include?"\n" then "\n" else " " end
43
47
  label = label.strip
44
- Logger.raw( "[#{self.addr2s(pkt.ip_saddr)} > #{self.addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst}] " \
45
- "[#{label.green}]#{nl}#{payload.strip.yellow}" )
48
+ Logger.raw( "[#{self.addr2s(pkt.ip_saddr, pkt.eth2s(:src))} > #{self.addr2s(pkt.ip_daddr,pkt.eth2s(:dst))}#{pkt.respond_to?('tcp_dst') ? ':' + pkt.tcp_dst.to_s : ''}] " \
49
+ "[#{label.green}]#{nl}#{payload.strip}" )
46
50
  end
47
51
 
48
52
  # Log a HTTP ( HTTPS if +is_https+ is true ) stream performed by the +client+
@@ -35,11 +35,33 @@ module Shell
35
35
  r
36
36
  end
37
37
 
38
- # Get the +iface+ network interface configuration.
38
+ # Cross-platform way of finding an executable in the $PATH.
39
+ def which(cmd)
40
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
41
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
42
+ exts.each { |ext|
43
+ exe = File.join(path, "#{cmd}#{ext}")
44
+ return exe if File.executable?(exe) && !File.directory?(exe)
45
+ }
46
+ end
47
+ return nil
48
+ end
49
+
50
+ # Cross-platform way of finding an executable in the $PATH.
51
+ def available?(cmd)
52
+ !which(cmd).nil?
53
+ end
54
+
55
+ # Get the +iface+ network interface configuration ( using ifconfig ).
39
56
  def ifconfig(iface = '')
40
57
  self.execute( "LANG=en && ifconfig #{iface}" )
41
58
  end
42
59
 
60
+ # Get the +iface+ network interface configuration ( using iproute2 ).
61
+ def ip(iface = '')
62
+ self.execute( "LANG=en && ip addr show #{iface}" )
63
+ end
64
+
43
65
  # Get the ARP table cached on this computer.
44
66
  def arp
45
67
  self.execute( 'LANG=en && arp -a -n' )
@@ -14,6 +14,58 @@ module BetterCap
14
14
  module Parsers
15
15
  # Base class for BetterCap::Parsers.
16
16
  class Base
17
+ # Hash of available parsers ( parser name -> class name )
18
+ @@loaded = {}
19
+
20
+ class << self
21
+ # Called when this base class is inherited from one of the parsers.
22
+ def inherited(subclass)
23
+ name = subclass.name.split('::')[2].upcase
24
+ if name != 'CUSTOM'
25
+ @@loaded[name] = subclass.name
26
+ end
27
+ end
28
+
29
+ # Return a list of available parsers names.
30
+ def available
31
+ @@loaded.keys
32
+ end
33
+
34
+ # Parse the +v+ command line argument and return a list of parser names.
35
+ # Will raise BetterCap::Error if one or more parser names are not valid.
36
+ def from_cmdline(v)
37
+ raise BetterCap::Error, "No parser names provided" if v.nil?
38
+
39
+ avail = available
40
+ list = v.split(',').collect(&:strip).collect(&:upcase).reject{ |c| c.empty? }
41
+ list.each do |parser|
42
+ raise BetterCap::Error, "Invalid parser name '#{parser}'." unless avail.include?(parser) or parser == '*'
43
+ end
44
+ list
45
+ end
46
+
47
+ # Return a list of BetterCap::Parsers instances by their +parsers+ names.
48
+ def load_by_names(parsers)
49
+ loaded = []
50
+
51
+ @@loaded.each do |name,cname|
52
+ if parsers.include?(name) or parsers == ['*']
53
+ Logger.debug "Loading parser #{name} ( #{cname} ) ..."
54
+ loaded << BetterCap::Loader.load(cname).new
55
+ end
56
+ end
57
+
58
+ loaded
59
+ end
60
+
61
+ # Load and return an instance of the BetterCap::Parsers::Custom parser
62
+ # given the +expression+ Regex object.
63
+ def load_custom(expression)
64
+ Logger.debug "Loading custom parser: '#{expression}' ..."
65
+ [ BetterCap::Parsers::Custom.new(expression) ]
66
+ end
67
+ end
68
+
17
69
  # Initialize this parser.
18
70
  def initialize
19
71
  @filters = []
@@ -0,0 +1,45 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+ module Parsers
16
+ # HTTP cookies parser.
17
+ class Cookie < Base
18
+ # Cookies to ignore.
19
+ FILTER = [ '__cfduid', '_ga', '_gat' ].freeze
20
+
21
+ def on_packet( pkt )
22
+ hostname = nil
23
+ cookies = {}
24
+
25
+ pkt.to_s.split("\n").each do |line|
26
+ if line =~ /Host:\s*([^\s]+)/i
27
+ hostname = $1
28
+ elsif line =~ /.*Cookie:\s*(.+)/i
29
+ $1.strip.split(';').each do |v|
30
+ k, v = v.split('=').map(&:strip)
31
+ next if k.nil? or v.nil?
32
+ unless k.empty? or v.empty? or FILTER.include?(k)
33
+ cookies[k] = v
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ unless hostname.nil? or cookies.empty?
40
+ StreamLogger.log_raw( pkt, "COOKIE", "[#{hostname.yellow}] #{cookies.map{|k,v| "#{k.green}=#{v.yellow}"}.join('; ')}" )
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
13
 
15
14
  module BetterCap
16
15
  module Parsers
@@ -0,0 +1,48 @@
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
+
13
+ module BetterCap
14
+ module Parsers
15
+ # DHCP packets and authentication parser.
16
+ class DHCP < Base
17
+ def on_packet( pkt )
18
+ begin
19
+ if pkt.udp_dst == 67 or pkt.udp_dst == 68
20
+ packet = Network::Protos::DHCP::Packet.parse( pkt.payload )
21
+ unless packet.nil?
22
+ auth = packet.authentication
23
+ cid = auth.nil?? nil : packet.client_identifier
24
+ msg = "[#{packet.type.yellow}] #{'Transaction-ID'.green}=#{packet.transaction_id.yellow}"
25
+
26
+ unless cid.nil?
27
+ msg += " #{'Client-ID'.green}='#{cid.yellow}'"
28
+ end
29
+
30
+ unless auth.nil?
31
+ msg += "\n#{'AUTHENTICATION'.green}:\n\n"
32
+ auth.each do |k,v|
33
+ msg += " #{k.blue} : #{v.yellow}\n"
34
+ end
35
+ msg += "\n"
36
+ end
37
+
38
+ StreamLogger.log_raw( pkt, 'DHCP', msg )
39
+ end
40
+ end
41
+ rescue Exception => e
42
+ Logger.debug e.message
43
+ Logger.debug e.backtrace.join("\n")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -9,7 +9,6 @@ Blog : http://www.evilsocket.net/
9
9
  This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
- require 'bettercap/sniffer/parsers/base'
13
12
 
14
13
  module BetterCap
15
14
  module Parsers
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
13
 
15
14
  module BetterCap
16
15
  module Parsers
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
- require 'colorize'
15
13
  require 'base64'
16
14
 
17
15
  module BetterCap
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
- require 'colorize'
15
13
  require 'resolv'
16
14
 
17
15
  module BetterCap
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
13
 
15
14
  module BetterCap
16
15
  module Parsers
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
13
 
15
14
  module BetterCap
16
15
  module Parsers
@@ -9,7 +9,6 @@ Blog : http://www.evilsocket.net/
9
9
  This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
- require 'bettercap/sniffer/parsers/base'
13
12
 
14
13
  module BetterCap
15
14
  module Parsers
@@ -10,7 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
13
 
15
14
  module BetterCap
16
15
  module Parsers
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
- require 'colorize'
15
13
 
16
14
  module BetterCap
17
15
  module Parsers
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
- require 'colorize'
15
13
 
16
14
  module BetterCap
17
15
  module Parsers
@@ -32,7 +30,11 @@ class Post < Base
32
30
 
33
31
  req.body.split('&').each do |v|
34
32
  name, value = v.split('=')
35
- msg << " #{name.blue} : #{URI.unescape(value).yellow}\n"
33
+ if name.nil? or value.nil?
34
+ msg << " #{URI.unescape(v).yellow}\n"
35
+ else
36
+ msg << " #{name.blue} : #{URI.unescape(value).yellow}\n"
37
+ end
36
38
  end
37
39
 
38
40
  StreamLogger.log_raw( pkt, "POST", req.to_url(1000) )
@@ -9,7 +9,6 @@ Blog : http://www.evilsocket.net/
9
9
  This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
- require 'bettercap/sniffer/parsers/base'
13
12
 
14
13
  module BetterCap
15
14
  module Parsers
@@ -9,7 +9,6 @@ Blog : http://www.evilsocket.net/
9
9
  This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
- require 'bettercap/sniffer/parsers/base'
13
12
 
14
13
  module BetterCap
15
14
  module Parsers
@@ -9,7 +9,6 @@ Blog : http://www.evilsocket.net/
9
9
  This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
- require 'bettercap/sniffer/parsers/base'
13
12
 
14
13
  module BetterCap
15
14
  module Parsers
@@ -10,8 +10,6 @@ Blog : http://www.evilsocket.net/
10
10
  This project is released under the GPL 3 license.
11
11
 
12
12
  =end
13
- require 'bettercap/sniffer/parsers/base'
14
- require 'colorize'
15
13
 
16
14
  module BetterCap
17
15
  module Parsers
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ WhatsApp OS Parser:
11
+ Author : Gianluca Costa
12
+ Email : g.costa@xplico.org
13
+
14
+ This project is released under the GPL 3 license.
15
+
16
+ =end
17
+
18
+ module BetterCap
19
+ module Parsers
20
+ # WhatsApp traffic parser.
21
+ class Whatsapp < Base
22
+ def on_packet( pkt )
23
+ begin
24
+ if ( pkt.tcp_dst == 443 or pkt.tcp_dst == 5222 or pkt.tcp_dst == 5223 ) and pkt.payload =~ /^WA.*?([a-zA-Z\-\.0-9]+).*?([0-9]+)/
25
+ version = $1
26
+ phone = $2
27
+ StreamLogger.log_raw( pkt, 'WHATSAPP', "#{'phone'.green}=#{phone.yellow} #{'version'.green}=#{version.yellow}" )
28
+ end
29
+ rescue; end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -58,9 +58,9 @@ class Sniffer
58
58
  if @@ctx.options.sniffer_src.nil?
59
59
  @@cap.stream
60
60
  else
61
- Logger.info "Reading packets from #{@@ctx.options.sniffer_src} ..."
61
+ Logger.info "[#{'SNIFFER'.green}] Reading packets from #{@@ctx.options.sniffer_src} ..."
62
62
 
63
- PcapFile.file_to_array @@ctx.options.sniffer_src
63
+ PacketFu::PcapFile.file_to_array @@ctx.options.sniffer_src
64
64
  end
65
65
  end
66
66
 
@@ -99,14 +99,14 @@ class Sniffer
99
99
  @@ctx = ctx
100
100
 
101
101
  unless @@ctx.options.sniffer_pcap.nil?
102
- @@pcap = PcapFile.new
103
- Logger.warn "Saving packets to #{@@ctx.options.sniffer_pcap} ."
102
+ @@pcap = PacketFu::PcapFile.new
103
+ Logger.info "[#{'SNIFFER'.green}] Saving packets to #{@@ctx.options.sniffer_pcap} ."
104
104
  end
105
105
 
106
106
  if @@ctx.options.custom_parser.nil?
107
- @@parsers = Factories::Parser.load_by_names @@ctx.options.parsers
107
+ @@parsers = Parsers::Base.load_by_names @@ctx.options.parsers
108
108
  else
109
- @@parsers = Factories::Parser.load_custom @@ctx.options.custom_parser
109
+ @@parsers = Parsers::Base.load_custom @@ctx.options.custom_parser
110
110
  end
111
111
 
112
112
  @@cap = Capture.new(