xettercap 1.5.7xerob

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/bin/xettercap +61 -0
  3. data/lib/bettercap/banner +2 -0
  4. data/lib/bettercap/context.rb +259 -0
  5. data/lib/bettercap/discovery/agents/arp.rb +37 -0
  6. data/lib/bettercap/discovery/agents/base.rb +73 -0
  7. data/lib/bettercap/discovery/agents/icmp.rb +44 -0
  8. data/lib/bettercap/discovery/agents/udp.rb +30 -0
  9. data/lib/bettercap/discovery/thread.rb +128 -0
  10. data/lib/bettercap/error.rb +16 -0
  11. data/lib/bettercap/firewalls/base.rb +103 -0
  12. data/lib/bettercap/firewalls/bsd.rb +74 -0
  13. data/lib/bettercap/firewalls/linux.rb +65 -0
  14. data/lib/bettercap/firewalls/redirection.rb +42 -0
  15. data/lib/bettercap/loader.rb +27 -0
  16. data/lib/bettercap/logger.rb +131 -0
  17. data/lib/bettercap/memory.rb +56 -0
  18. data/lib/bettercap/monkey/celluloid/actor.rb +23 -0
  19. data/lib/bettercap/monkey/celluloid/io/udp_socket.rb +26 -0
  20. data/lib/bettercap/monkey/em-proxy/proxy.rb +23 -0
  21. data/lib/bettercap/monkey/openssl/server.rb +35 -0
  22. data/lib/bettercap/monkey/packetfu/pcap.rb +51 -0
  23. data/lib/bettercap/monkey/packetfu/utils.rb +210 -0
  24. data/lib/bettercap/monkey/system.rb +25 -0
  25. data/lib/bettercap/network/arp_reader.rb +91 -0
  26. data/lib/bettercap/network/hw-prefixes +21326 -0
  27. data/lib/bettercap/network/network.rb +102 -0
  28. data/lib/bettercap/network/packet_queue.rb +129 -0
  29. data/lib/bettercap/network/protos/base.rb +154 -0
  30. data/lib/bettercap/network/protos/dhcp.rb +227 -0
  31. data/lib/bettercap/network/protos/mysql.rb +40 -0
  32. data/lib/bettercap/network/protos/ntlm.rb +97 -0
  33. data/lib/bettercap/network/protos/snmp.rb +49 -0
  34. data/lib/bettercap/network/protos/teamviewer.rb +119 -0
  35. data/lib/bettercap/network/servers/dnsd.rb +152 -0
  36. data/lib/bettercap/network/servers/httpd.rb +55 -0
  37. data/lib/bettercap/network/services +2182 -0
  38. data/lib/bettercap/network/target.rb +168 -0
  39. data/lib/bettercap/network/validator.rb +96 -0
  40. data/lib/bettercap/options/core_options.rb +197 -0
  41. data/lib/bettercap/options/options.rb +165 -0
  42. data/lib/bettercap/options/proxy_options.rb +314 -0
  43. data/lib/bettercap/options/server_options.rb +73 -0
  44. data/lib/bettercap/options/sniff_options.rb +90 -0
  45. data/lib/bettercap/options/spoof_options.rb +71 -0
  46. data/lib/bettercap/pluggable.rb +37 -0
  47. data/lib/bettercap/proxy/http/module.rb +105 -0
  48. data/lib/bettercap/proxy/http/modules/injectcss.rb +79 -0
  49. data/lib/bettercap/proxy/http/modules/injecthtml.rb +80 -0
  50. data/lib/bettercap/proxy/http/modules/injectjs.rb +79 -0
  51. data/lib/bettercap/proxy/http/proxy.rb +184 -0
  52. data/lib/bettercap/proxy/http/request.rb +192 -0
  53. data/lib/bettercap/proxy/http/response.rb +226 -0
  54. data/lib/bettercap/proxy/http/ssl/authority.rb +182 -0
  55. data/lib/bettercap/proxy/http/ssl/bettercap-ca.pem +49 -0
  56. data/lib/bettercap/proxy/http/ssl/server.rb +63 -0
  57. data/lib/bettercap/proxy/http/sslstrip/cookiemonitor.rb +67 -0
  58. data/lib/bettercap/proxy/http/sslstrip/lock.ico +0 -0
  59. data/lib/bettercap/proxy/http/sslstrip/strip.rb +325 -0
  60. data/lib/bettercap/proxy/http/streamer.rb +225 -0
  61. data/lib/bettercap/proxy/stream_logger.rb +181 -0
  62. data/lib/bettercap/proxy/tcp/module.rb +75 -0
  63. data/lib/bettercap/proxy/tcp/proxy.rb +123 -0
  64. data/lib/bettercap/proxy/thread_pool.rb +194 -0
  65. data/lib/bettercap/shell.rb +70 -0
  66. data/lib/bettercap/sniffer/parsers/base.rb +87 -0
  67. data/lib/bettercap/sniffer/parsers/cookie.rb +45 -0
  68. data/lib/bettercap/sniffer/parsers/creditcard.rb +62 -0
  69. data/lib/bettercap/sniffer/parsers/custom.rb +26 -0
  70. data/lib/bettercap/sniffer/parsers/dhcp.rb +45 -0
  71. data/lib/bettercap/sniffer/parsers/dict.rb +37 -0
  72. data/lib/bettercap/sniffer/parsers/ftp.rb +24 -0
  73. data/lib/bettercap/sniffer/parsers/httpauth.rb +44 -0
  74. data/lib/bettercap/sniffer/parsers/https.rb +42 -0
  75. data/lib/bettercap/sniffer/parsers/irc.rb +24 -0
  76. data/lib/bettercap/sniffer/parsers/mail.rb +24 -0
  77. data/lib/bettercap/sniffer/parsers/mpd.rb +36 -0
  78. data/lib/bettercap/sniffer/parsers/mysql.rb +27 -0
  79. data/lib/bettercap/sniffer/parsers/nntp.rb +24 -0
  80. data/lib/bettercap/sniffer/parsers/ntlmss.rb +34 -0
  81. data/lib/bettercap/sniffer/parsers/pgsql.rb +36 -0
  82. data/lib/bettercap/sniffer/parsers/post.rb +33 -0
  83. data/lib/bettercap/sniffer/parsers/redis.rb +39 -0
  84. data/lib/bettercap/sniffer/parsers/rlogin.rb +45 -0
  85. data/lib/bettercap/sniffer/parsers/snmp.rb +44 -0
  86. data/lib/bettercap/sniffer/parsers/snpp.rb +37 -0
  87. data/lib/bettercap/sniffer/parsers/teamviewer.rb +30 -0
  88. data/lib/bettercap/sniffer/parsers/url.rb +30 -0
  89. data/lib/bettercap/sniffer/parsers/whatsapp.rb +33 -0
  90. data/lib/bettercap/sniffer/sniffer.rb +142 -0
  91. data/lib/bettercap/spoofers/arp.rb +150 -0
  92. data/lib/bettercap/spoofers/base.rb +152 -0
  93. data/lib/bettercap/spoofers/icmp.rb +202 -0
  94. data/lib/bettercap/spoofers/none.rb +57 -0
  95. data/lib/bettercap/update_checker.rb +57 -0
  96. data/lib/bettercap/version.rb +18 -0
  97. data/lib/bettercap.rb +70 -0
  98. metadata +276 -0
@@ -0,0 +1,168 @@
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 Network
16
+ # This class represents a target, namely a single endpoint device on the
17
+ # network.
18
+ class Target
19
+ # The IP address of this device.
20
+ attr_accessor :ip
21
+ # The MAC address of the device network interface.
22
+ attr_accessor :mac
23
+ # Network object.
24
+ attr_accessor :network
25
+ # Vendor of the device network interface if available.
26
+ attr_accessor :vendor
27
+ # NetBIOS hostname of the device if available OR interface name in case of
28
+ # local address.
29
+ attr_accessor :name
30
+ # True if the IP attribute of this target needs to be updated.
31
+ attr_accessor :ip_refresh
32
+
33
+ # Timeout in seconds for the NBNS hostname resolution request.
34
+ NBNS_TIMEOUT = 30
35
+ # UDP port for the NBNS hostname resolution request.
36
+ NBNS_PORT = 137
37
+ # Buffer size for the NBNS hostname resolution request.
38
+ NBNS_BUFSIZE = 65536
39
+ # NBNS hostname resolution request buffer.
40
+ NBNS_REQUEST = "\x82\x28\x0\x0\x0\x1\x0\x0\x0\x0\x0\x0\x20\x43\x4B\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x0\x0\x21\x0\x1"
41
+
42
+ @@prefixes = nil
43
+ @@lock = Mutex.new
44
+
45
+ # Create a +Target+ object given its +ip+ and (optional) +mac+ address.
46
+ # The +ip+ argument could also be a MAC address itself, in this case the
47
+ # ip address will be parsed from the computer ARP cache and updated
48
+ # accordingly.
49
+ def initialize( ip, mac=nil, network=nil, name=nil )
50
+ if Network::Validator.is_ip?(ip)
51
+ @ip = ip
52
+ @ip_refresh = false
53
+ elsif Network::Validator.is_mac?(ip)
54
+ @ip = nil
55
+ mac = ip
56
+ @ip_refresh = true
57
+ else
58
+ raise BetterCap::Error, "'#{ip}' is not a valid IP or MAC address."
59
+ end
60
+
61
+ @mac = Target.normalized_mac(mac) unless mac.nil?
62
+ @vendor = Target.lookup_vendor(@mac) unless mac.nil?
63
+ @name = name
64
+ @network = network
65
+ @resolver = Thread.new { resolve! } unless Context.get.options.core.no_target_nbns or @ip.nil? or !@network.nil?
66
+ end
67
+
68
+ # Return the integer representation of the +ip+ attribute which can be
69
+ # used for sorting a list of +Target+ objects+
70
+ def sortable_ip
71
+ @ip.split('.').inject(0) {|total,value| (total << 8 ) + value.to_i}
72
+ end
73
+
74
+ # Return true if both the ip and mac are not nil.
75
+ def spoofable?
76
+ ( !@ip.nil? and !@mac.nil? )
77
+ end
78
+
79
+ # +mac+ attribute setter, it will normalize the +value+ and perform
80
+ # a vendor lookup.
81
+ def mac=(value)
82
+ @mac = Target.normalized_mac(value)
83
+ @vendor = Target.lookup_vendor(@mac) unless @mac.nil?
84
+ end
85
+
86
+ # Return a verbose string representation of this object.
87
+ def to_s(padding=true)
88
+ address = @ip.nil?? '???' : @ip
89
+ fmt = padding ? '%-15s : %-17s' : '%s : %s'
90
+ vendor = @vendor.nil?? " ( ??? )" : " ( #{@vendor} )"
91
+
92
+ s = sprintf( fmt, address, @mac )
93
+ s += " / #{@name}" unless @name.nil?
94
+ s += vendor
95
+ s
96
+ end
97
+
98
+ # Return a compact string representation of this object.
99
+ def to_s_compact
100
+ return "#{@name}/#{@ip}" if @name
101
+ @ip
102
+ end
103
+
104
+ # Return true if this +Target+ is equal to the specified +ip+ and +mac+,
105
+ # otherwise return false.
106
+ def equals?(ip, mac = nil)
107
+ # compare by ip if no mac
108
+ return ( @ip == ip ) if mac.nil?
109
+ # false if no mac or if it's different
110
+ return false if @mac.nil? || ( @mac != mac )
111
+
112
+ ###Logger.info "Found IP #{ip} for target #{@mac}!" if @ip.nil?
113
+ @ip = ip
114
+ return true
115
+ end
116
+
117
+ def self.normalized_mac(v)
118
+ v.split(':').map { |e| e.size == 2 ? e.upcase : "0#{e.upcase}" }.join(':')
119
+ end
120
+
121
+ private
122
+
123
+ # Attempt to perform a NBNS name resolution for this target.
124
+ def resolve!
125
+ resp, sock = nil, nil
126
+ begin
127
+ sock = UDPSocket.open
128
+ sock.send( NBNS_REQUEST, 0, @ip, NBNS_PORT )
129
+ resp = if select([sock], nil, nil, NBNS_TIMEOUT)
130
+ sock.recvfrom(NBNS_BUFSIZE)
131
+ end
132
+ if resp
133
+ @name = parse_nbns_response resp
134
+ ###Logger.info "Found NetBIOS name '#{@name}' for address #{@ip}"
135
+ end
136
+ rescue Exception => e
137
+ Logger.debug e
138
+ ensure
139
+ sock.close if sock
140
+ end
141
+ end
142
+
143
+ # Given the +resp+ NBNS response, parse the hostname from it.
144
+ def parse_nbns_response resp
145
+ resp[0][57,15].to_s.strip
146
+ end
147
+
148
+ # Lookup the given +mac+ address in order to find its vendor.
149
+ def self.lookup_vendor( mac )
150
+ @@lock.synchronize {
151
+ if @@prefixes.nil?
152
+ Logger.debug 'Preloading hardware vendor prefixes ...'
153
+
154
+ @@prefixes = {}
155
+ filename = File.dirname(__FILE__) + '/hw-prefixes'
156
+ File.open( filename ).each do |line|
157
+ if line =~ /^([A-F0-9]{6})\s(.+)$/
158
+ @@prefixes[$1] = $2
159
+ end
160
+ end
161
+ end
162
+ }
163
+
164
+ @@prefixes[ mac.split(':')[0,3].join('').upcase ]
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,96 @@
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
+ module BetterCap
14
+ module Network
15
+ # Simple class to perform validation of various addresses, ranges, etc.
16
+ class Validator
17
+ # Basic expression to validate an IP address.
18
+ IP_ADDRESS_REGEX = '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})'
19
+ # Quite self explainatory :)
20
+ IP_OCTECT_MAX = 255
21
+
22
+ # Return true if +ip+ is a valid IP address, otherwise false.
23
+ def self.is_ip?(ip)
24
+ if /\A#{IP_ADDRESS_REGEX}\Z/ =~ ip.to_s
25
+ return $~.captures.all? { |i| i.to_i <= IP_OCTECT_MAX }
26
+ end
27
+ false
28
+ end
29
+
30
+ # Return true if +port+ is a valid port, otherwise false.
31
+ def self.is_valid_port?(port)
32
+ port ||= ""
33
+ return false if port.strip.empty?
34
+ return false unless port =~ /^[0-9]+$/
35
+ port = port.to_i
36
+ return ( port > 0 and port <= 65535 )
37
+ end
38
+
39
+ # Extract valid IP addresses from +data+ and yields each one of them.
40
+ def self.each_ip(data)
41
+ data.scan(/(#{IP_ADDRESS_REGEX})/).each do |m|
42
+ yield( m[0] ) if m[0] != '0.0.0.0'
43
+ end
44
+ end
45
+
46
+ # Return true if +r+ is a valid IP address range ( 192.168.1.1-93 ), otherwise false.
47
+ def self.is_range?(r)
48
+ if /\A#{IP_ADDRESS_REGEX}\-(\d{1,3})\Z/ =~ r.to_s
49
+ return $~.captures.all? { |i| i.to_i <= IP_OCTECT_MAX }
50
+ end
51
+ false
52
+ end
53
+
54
+ # Parse +r+ as an IP range and return the first and last IP.
55
+ def self.parse_range(r)
56
+ first, last_part = r.split('-')
57
+ last = first.split('.')[0..2].join('.') + ".#{last_part}"
58
+ first = IPAddr.new(first)
59
+ last = IPAddr.new(last)
60
+
61
+ [ first, last ]
62
+ end
63
+
64
+ # Parse +r+ as an IP range and yields each address in it.
65
+ def self.each_in_range(r)
66
+ first, last = self.parse_range(r)
67
+ loop do
68
+ yield first.to_s
69
+ break if first == last
70
+ first = first.succ
71
+ end
72
+ end
73
+
74
+ # Parse +m+ as a netmask and yields each address in it.
75
+ def self.each_in_netmask(m)
76
+ IPAddr.new(m).to_range.each do |o|
77
+ yield o.to_s
78
+ end
79
+ end
80
+
81
+ # Return true if +n+ is a valid IP netmask range ( 192.168.1.1/24 ), otherwise false.
82
+ def self.is_netmask?(n)
83
+ if /\A#{IP_ADDRESS_REGEX}\/(\d+)\Z/ =~ n.to_s
84
+ return $~.captures.all? { |i| i.to_i <= IP_OCTECT_MAX }
85
+ end
86
+ false
87
+ end
88
+
89
+ # Return true if +mac+ is a valid MAC address, otherwise false.
90
+ def self.is_mac?(mac)
91
+ ( /^[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 )
92
+ end
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,197 @@
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
+
16
+ class CoreOptions
17
+ # Network interface.
18
+ attr_accessor :iface
19
+ # Gateway IP address.
20
+ attr_accessor :gateway
21
+ # Comma separated list of targets.
22
+ attr_accessor :targets
23
+ # Comma separated list of ip addresses to ignore.
24
+ attr_accessor :ignore
25
+ # If false will disable active network discovery, the program will just use
26
+ # the current ARP cache.
27
+ attr_accessor :discovery
28
+ # If true, targets NBNS hostname resolution won't be performed.
29
+ attr_accessor :no_target_nbns
30
+ # Log file name.
31
+ attr_accessor :logfile
32
+ # If true the Logger will prepend timestamps to each line.
33
+ attr_accessor :log_timestamp
34
+ # If true will suppress every log message which is not an error or a warning.
35
+ attr_accessor :silent
36
+ # If true will enable debug messages.
37
+ attr_accessor :debug
38
+ # If different than 0, this time will be used as a delay while sending packets.
39
+ attr_accessor :packet_throttle
40
+ # If true, bettercap will check for updates then exit.
41
+ attr_accessor :check_updates
42
+ # If not nil, the interface MAC address will be changed to this value.
43
+ attr_accessor :use_mac
44
+
45
+ def initialize( iface )
46
+ @iface = iface
47
+ @gateway = nil
48
+ @targets = nil
49
+ @logfile = nil
50
+ @log_timestamp = false
51
+ @silent = false
52
+ @debug = false
53
+ @ignore = nil
54
+ @discovery = true
55
+ @no_target_nbns = false
56
+ @packet_throttle = 0.0
57
+ @check_updates = false
58
+ @use_mac = nil
59
+ end
60
+
61
+ def parse!( ctx, opts )
62
+ opts.separator ""
63
+ opts.separator "MAIN:".bold
64
+ opts.separator ""
65
+
66
+ opts.on( '-I', '--interface IFACE', 'Network interface name - default: ' + @iface.to_s.yellow ) do |v|
67
+ @iface = v
68
+ end
69
+
70
+ opts.on( '--use-mac ADDRESS', 'Change the interface MAC address to this value before performing the attack.' ) do |v|
71
+ @use_mac = v
72
+ raise BetterCap::Error, "Invalid MAC address specified." unless Network::Validator.is_mac?(@use_mac)
73
+ end
74
+
75
+ opts.on( '--random-mac', 'Change the interface MAC address to a random one before performing the attack.' ) do |v|
76
+ @use_mac = [format('%0.2x', rand(256) & ~1), (1..5).map { format('%0.2x', rand(256)) }].join(':')
77
+ end
78
+
79
+ opts.on( '-G', '--gateway ADDRESS', 'Manually specify the gateway address, if not specified the current gateway will be retrieved and used. ' ) do |v|
80
+ @gateway = v
81
+ raise BetterCap::Error, "The specified gateway '#{v}' is not a valid IPv4 address." unless Network::Validator.is_ip?(v)
82
+ end
83
+
84
+ opts.on( '-T', '--target ADDRESS1,ADDRESS2', 'Target IP addresses, if not specified the whole subnet will be targeted.' ) do |v|
85
+ self.targets = v
86
+ end
87
+
88
+ opts.on( '--ignore ADDRESS1,ADDRESS2', 'Ignore these addresses if found while searching for targets.' ) do |v|
89
+ self.ignore = v
90
+ end
91
+
92
+ opts.on( '--no-discovery', "Do not actively search for hosts, just use the current ARP cache, default to #{'false'.yellow}." ) do
93
+ @discovery = false
94
+ end
95
+
96
+ opts.on( '--no-target-nbns', 'Disable target NBNS hostname resolution.' ) do
97
+ @no_target_nbns = true
98
+ end
99
+
100
+ opts.on( '--packet-throttle NUMBER', 'Number of seconds ( can be a decimal number ) to wait between each packet to be sent.' ) do |v|
101
+ @packet_throttle = v.to_f
102
+ raise BetterCap::Error, "Invalid packet throttle value specified." if @packet_throttle <= 0.0
103
+ end
104
+
105
+ opts.on( '--check-updates', 'Will check if any update is available and then exit.' ) do
106
+ @check_updates = true
107
+ end
108
+
109
+ opts.on( '-h', '--help', 'Display the available options.') do
110
+ puts opts
111
+ puts "\nFor examples & docs please visit " + "http://bettercap.org/docs/".bold
112
+ exit
113
+ end
114
+
115
+ opts.separator ""
116
+ opts.separator "LOGGING:".bold
117
+ opts.separator ""
118
+
119
+ opts.on( '-O', '--log LOG_FILE', 'Log all messages into a file, if not specified the log messages will be only print into the shell.' ) do |v|
120
+ @logfile = v
121
+ end
122
+
123
+ opts.on( '--log-timestamp', 'Enable logging with timestamps for each line, disabled by default.' ) do
124
+ @log_timestamp = true
125
+ end
126
+
127
+ opts.on( '-D', '--debug', 'Enable debug logging.' ) do
128
+ @debug = true
129
+ end
130
+
131
+ opts.on( '--silent', "Suppress every message which is not an error or a warning, default to #{'false'.yellow}." ) do
132
+ @silent = true
133
+ end
134
+
135
+ end
136
+
137
+ def validate!
138
+ raise BetterCap::Error, 'This software must run as root.' unless Process.uid == 0
139
+ raise BetterCap::Error, 'No default interface found, please specify one with the -I argument.' if @iface.nil?
140
+ end
141
+
142
+ # Return true if active host discovery is enabled, otherwise false.
143
+ def discovery?
144
+ ( @discovery and @targets.nil? )
145
+ end
146
+
147
+ # Split specified targets and parse them ( either as IP or MAC ), will raise a
148
+ # BetterCap::Error if one or more invalid addresses are specified.
149
+ def targets=(value)
150
+ @targets = []
151
+
152
+ value.split(",").each do |t|
153
+ if Network::Validator.is_ip?(t) or Network::Validator.is_mac?(t)
154
+ @targets << Network::Target.new(t)
155
+
156
+ elsif Network::Validator.is_range?(t)
157
+ Network::Validator.each_in_range( t ) do |address|
158
+ @targets << Network::Target.new(address)
159
+ end
160
+
161
+ elsif Network::Validator.is_netmask?(t)
162
+ Network::Validator.each_in_netmask(t) do |address|
163
+ @targets << Network::Target.new(address)
164
+ end
165
+
166
+ else
167
+ raise BetterCap::Error, "Invalid target specified '#{t}', valid formats are IP addresses, "\
168
+ "MAC addresses, IP ranges ( 192.168.1.1-30 ) or netmasks ( 192.168.1.1/24 ) ."
169
+ end
170
+ end
171
+ end
172
+
173
+ # Setter for the #ignore attribute, will raise a BetterCap::Error if one
174
+ # or more invalid IP addresses are specified.
175
+ def ignore=(value)
176
+ @ignore = value.split(",")
177
+ valid = @ignore.select { |target| Network::Validator.is_ip?(target) }
178
+
179
+ raise BetterCap::Error, "Invalid ignore addresses specified." if valid.empty?
180
+
181
+ invalid = @ignore - valid
182
+ invalid.each do |target|
183
+ Logger.warn "Not a valid address: #{target}"
184
+ end
185
+
186
+ @ignore = valid
187
+
188
+ Logger.warn "Ignoring #{valid.join(", ")} ."
189
+ end
190
+
191
+ # Return true if the +ip+ address needs to be ignored, otherwise false.
192
+ def ignore_ip?(ip)
193
+ !@ignore.nil? and @ignore.include?(ip)
194
+ end
195
+ end
196
+
197
+ end
@@ -0,0 +1,165 @@
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
+ # Parse command line arguments, set options and initialize +Context+
16
+ # accordingly.
17
+ class Options
18
+ # Core options
19
+ attr_reader :core
20
+ # Spoofing related options.
21
+ attr_reader :spoof
22
+ # Sniffing related options.
23
+ attr_reader :sniff
24
+ # Proxies related options.
25
+ attr_reader :proxies
26
+ # Misc servers related options.
27
+ attr_reader :servers
28
+
29
+ # Create a BetterCap::Options class instance using the specified network interface.
30
+ def initialize( iface )
31
+ @core = CoreOptions.new iface
32
+ @spoof = SpoofOptions.new
33
+ @sniff = SniffOptions.new
34
+ @proxies = ProxyOptions.new
35
+ @servers = ServerOptions.new
36
+ end
37
+
38
+ # Initialize the BetterCap::Context, parse command line arguments and update program
39
+ # state accordingly.
40
+ # Will rise a BetterCap::Error if errors occurred.
41
+ def self.parse!
42
+ ctx = Context.get
43
+
44
+ OptionParser.new do |opts|
45
+ opts.version = BetterCap::VERSION
46
+ opts.banner = "Usage: bettercap [options]"
47
+
48
+ ctx.options.core.parse!( ctx, opts )
49
+ ctx.options.spoof.parse!( ctx, opts )
50
+ ctx.options.sniff.parse!( ctx, opts )
51
+ ctx.options.proxies.parse!( ctx, opts )
52
+ ctx.options.servers.parse!( ctx, opts )
53
+
54
+ end.parse!
55
+
56
+ # Initialize logging system.
57
+ Logger.init( ctx )
58
+
59
+ if ctx.options.core.check_updates
60
+ UpdateChecker.check
61
+ exit
62
+ end
63
+
64
+ # Validate options.
65
+ ctx.options.validate!( ctx )
66
+ # Load firewall instance, network interface informations and detect the
67
+ # gateway address.
68
+ ctx.update!
69
+
70
+ ctx
71
+ end
72
+
73
+ def validate!( ctx )
74
+ @core.validate!
75
+ @proxies.validate!( ctx )
76
+ # Print starting message.
77
+ starting_message
78
+ end
79
+
80
+ def need_gateway?
81
+ ( @core.discovery? or @spoof.enabled? )
82
+ end
83
+
84
+ # Helper method to create a Firewalls::Redirection object.
85
+ def redir( address, port, to, proto = 'TCP' )
86
+ Firewalls::Redirection.new( @core.iface, proto, nil, port, address, to )
87
+ end
88
+
89
+ # Helper method to create a Firewalls::Redirection object for a single address ( +from+ ).
90
+ def redir_single( from, address, port, to, proto = 'TCP' )
91
+ Firewalls::Redirection.new( @core.iface, proto, from, port, address, to )
92
+ end
93
+
94
+ # Create a list of BetterCap::Firewalls::Redirection objects which are needed
95
+ # given the specified command line arguments.
96
+ def get_redirections iface
97
+ redirections = []
98
+
99
+ if @servers.dnsd or @proxies.sslstrip?
100
+ redirections << redir( iface.ip, 53, @servers.dnsd_port )
101
+ redirections << redir( iface.ip, 53, @servers.dnsd_port, 'UDP' )
102
+ end
103
+
104
+ if @proxies.proxy
105
+ @proxies.http_ports.each do |port|
106
+ if @proxies.proxy_upstream_address.nil?
107
+ redirections << redir( iface.ip, port, @proxies.proxy_port )
108
+ else
109
+ redirections << redir_single( @proxies.proxy_upstream_address, iface.ip, port, @proxies.proxy_port )
110
+ end
111
+ end
112
+ end
113
+
114
+ if @proxies.proxy_https
115
+ @proxies.https_ports.each do |port|
116
+ if @proxies.proxy_upstream_address.nil?
117
+ redirections << redir( iface.ip, port, @proxies.proxy_https_port )
118
+ else
119
+ redirections << redir_single( @proxies.proxy_upstream_address, iface.ip, port, @proxies.proxy_port )
120
+ end
121
+ end
122
+ end
123
+
124
+ if @proxies.tcp_proxy
125
+ redirections << redir_single( @proxies.tcp_proxy_upstream_address, iface.ip, @proxies.tcp_proxy_upstream_port, @proxies.tcp_proxy_port )
126
+ end
127
+
128
+ if @proxies.custom_proxy
129
+ @proxies.http_ports.each do |port|
130
+ redirections << redir( @proxies.custom_proxy, port, @proxies.custom_proxy_port )
131
+ end
132
+ end
133
+
134
+ if @proxies.custom_https_proxy
135
+ @proxies.https_ports.each do |port|
136
+ redirections << redir( @proxies.custom_https_proxy, port, @proxies.custom_https_proxy_port )
137
+ end
138
+ end
139
+
140
+ @proxies.custom_redirections.each do |r|
141
+ redirections << redir( iface.ip, r[:from], r[:to], r[:proto] )
142
+ end
143
+
144
+ redirections
145
+ end
146
+
147
+ # Print the starting status message.
148
+ def starting_message
149
+ on = '✔'.green
150
+ off = '✘'.red
151
+ status = {
152
+ 'spoofing' => ( @spoof.enabled? ? on : off ),
153
+ 'discovery' => ( @core.discovery? ? on : off ),
154
+ 'sniffer' => ( @sniff.enabled? ? on : off ),
155
+ 'tcp-proxy' => ( @proxies.tcp_proxy ? on : off ),
156
+ 'http-proxy' => ( @proxies.proxy ? on : off ),
157
+ 'https-proxy' => ( @proxies.proxy_https ? on : off ),
158
+ 'sslstrip' => ( @proxies.sslstrip? ? on : off ),
159
+ 'http-server' => ( @servers.httpd ? on : off ),
160
+ 'dns-server' => ( @proxies.sslstrip? or @servers.dnsd ? on : off )
161
+ }
162
+
163
+ end
164
+ end
165
+ end