bettercap 1.4.6 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bettercap +1 -1
  3. data/lib/bettercap.rb +1 -0
  4. data/lib/bettercap/context.rb +63 -70
  5. data/lib/bettercap/discovery/agents/base.rb +2 -2
  6. data/lib/bettercap/discovery/thread.rb +5 -4
  7. data/lib/bettercap/firewalls/base.rb +2 -4
  8. data/lib/bettercap/firewalls/{osx.rb → bsd.rb} +3 -3
  9. data/lib/bettercap/firewalls/linux.rb +2 -2
  10. data/lib/bettercap/firewalls/redirection.rb +5 -2
  11. data/lib/bettercap/logger.rb +6 -11
  12. data/lib/bettercap/memory.rb +56 -0
  13. data/lib/bettercap/monkey/em-proxy/proxy.rb +23 -0
  14. data/lib/bettercap/monkey/packetfu/pcap.rb +51 -0
  15. data/lib/bettercap/network/arp_reader.rb +2 -2
  16. data/lib/bettercap/network/network.rb +2 -2
  17. data/lib/bettercap/network/packet_queue.rb +2 -2
  18. data/lib/bettercap/network/protos/base.rb +8 -5
  19. data/lib/bettercap/network/protos/dhcp.rb +5 -124
  20. data/lib/bettercap/network/target.rb +7 -2
  21. data/lib/bettercap/options/core_options.rb +189 -0
  22. data/lib/bettercap/options/options.rb +167 -0
  23. data/lib/bettercap/options/proxy_options.rb +258 -0
  24. data/lib/bettercap/options/server_options.rb +71 -0
  25. data/lib/bettercap/options/sniff_options.rb +90 -0
  26. data/lib/bettercap/options/spoof_options.rb +71 -0
  27. data/lib/bettercap/proxy/{module.rb → http/module.rb} +8 -4
  28. data/lib/bettercap/proxy/{modules → http/modules}/injectcss.rb +2 -2
  29. data/lib/bettercap/proxy/{modules → http/modules}/injecthtml.rb +2 -2
  30. data/lib/bettercap/proxy/{modules → http/modules}/injectjs.rb +2 -2
  31. data/lib/bettercap/proxy/{proxy.rb → http/proxy.rb} +5 -2
  32. data/lib/bettercap/proxy/{request.rb → http/request.rb} +4 -0
  33. data/lib/bettercap/proxy/{response.rb → http/response.rb} +3 -0
  34. data/lib/bettercap/proxy/{ssl → http/ssl}/authority.rb +3 -1
  35. data/lib/bettercap/proxy/{ssl → http/ssl}/bettercap-ca.pem +0 -0
  36. data/lib/bettercap/proxy/{ssl → http/ssl}/server.rb +3 -1
  37. data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/cookiemonitor.rb +2 -0
  38. data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/lock.ico +0 -0
  39. data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/strip.rb +4 -2
  40. data/lib/bettercap/proxy/{streamer.rb → http/streamer.rb} +7 -4
  41. data/lib/bettercap/proxy/stream_logger.rb +25 -9
  42. data/lib/bettercap/proxy/tcp/module.rb +75 -0
  43. data/lib/bettercap/proxy/tcp/proxy.rb +123 -0
  44. data/lib/bettercap/proxy/thread_pool.rb +1 -1
  45. data/lib/bettercap/sniffer/parsers/post.rb +1 -1
  46. data/lib/bettercap/sniffer/parsers/url.rb +1 -1
  47. data/lib/bettercap/sniffer/sniffer.rb +23 -17
  48. data/lib/bettercap/spoofers/arp.rb +21 -9
  49. data/lib/bettercap/spoofers/base.rb +12 -16
  50. data/lib/bettercap/spoofers/icmp.rb +4 -5
  51. data/lib/bettercap/spoofers/none.rb +0 -1
  52. data/lib/bettercap/version.rb +1 -1
  53. metadata +48 -19
  54. data/lib/bettercap/firewalls/openbsd.rb +0 -77
  55. data/lib/bettercap/options.rb +0 -600
@@ -0,0 +1,167 @@
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.should_discover_hosts? 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 ifconfig
97
+ redirections = []
98
+
99
+ if @servers.dnsd or @proxies.sslstrip?
100
+ redirections << redir( ifconfig[:ip_saddr], 53, @servers.dnsd_port )
101
+ redirections << redir( ifconfig[:ip_saddr], 53, @servers.dnsd_port, 'UDP' )
102
+ end
103
+
104
+ if @proxies.proxy
105
+ @proxies.http_ports.each do |port|
106
+ redirections << redir( ifconfig[:ip_saddr], port, @proxies.proxy_port )
107
+ end
108
+ end
109
+
110
+ if @proxies.proxy_https
111
+ @proxies.https_ports.each do |port|
112
+ redirections << redir( ifconfig[:ip_saddr], port, @proxies.proxy_https_port )
113
+ end
114
+ end
115
+
116
+ if @proxies.tcp_proxy
117
+ redirections << redir_single( @proxies.tcp_proxy_upstream_address, ifconfig[:ip_saddr], @proxies.tcp_proxy_upstream_port, @proxies.tcp_proxy_port )
118
+ end
119
+
120
+ if @proxies.custom_proxy
121
+ @proxies.http_ports.each do |port|
122
+ redirections << redir( @proxies.custom_proxy, port, @proxies.custom_proxy_port )
123
+ end
124
+ end
125
+
126
+ if @proxies.custom_https_proxy
127
+ @proxies.https_ports.each do |port|
128
+ redirections << redir( @proxies.custom_https_proxy, port, @proxies.custom_https_proxy_port )
129
+ end
130
+ end
131
+
132
+ @proxies.custom_redirections.each do |r|
133
+ redirections << redir( ifconfig[:ip_saddr], r[:from], r[:to], r[:proto] )
134
+ end
135
+
136
+ redirections
137
+ end
138
+
139
+ # Print the starting status message.
140
+ def starting_message
141
+ on = '✔'.green
142
+ off = '✘'.red
143
+ status = {
144
+ 'spoofing' => ( @spoof.enabled? ? on : off ),
145
+ 'discovery' => ( @core.discovery? ? on : off ),
146
+ 'sniffer' => ( @sniff.enabled? ? on : off ),
147
+ 'tcp-proxy' => ( @proxies.tcp_proxy ? on : off ),
148
+ 'http-proxy' => ( @proxies.proxy ? on : off ),
149
+ 'https-proxy' => ( @proxies.proxy_https ? on : off ),
150
+ 'sslstrip' => ( @proxies.sslstrip? ? on : off ),
151
+ 'http-server' => ( @servers.httpd ? on : off ),
152
+ 'dns-server' => ( @proxies.sslstrip? or @servers.dnsd ? on : off )
153
+ }
154
+
155
+ msg = "Starting [ "
156
+ status.each do |k,v|
157
+ msg += "#{k}:#{v} "
158
+ end
159
+ msg += "] ...\n\n"
160
+
161
+ Logger.info msg
162
+
163
+ Logger.warn "You are running an unstable/beta version of this software, please" \
164
+ " update to a stable one if available." if BetterCap::VERSION =~ /[\d\.+]b/
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,258 @@
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 ProxyOptions
17
+ # If true, HTTP transparent proxy will be enabled.
18
+ attr_accessor :proxy
19
+ # If true, HTTPS transparent proxy will be enabled.
20
+ attr_accessor :proxy_https
21
+ # HTTP proxy port.
22
+ attr_accessor :proxy_port
23
+ # List of HTTP ports, [ 80 ] by default.
24
+ attr_accessor :http_ports
25
+ # HTTPS proxy port.
26
+ attr_accessor :proxy_https_port
27
+ # List of HTTPS ports, [ 443 ] by default.
28
+ attr_accessor :https_ports
29
+ # File name of the PEM certificate to use for the HTTPS proxy.
30
+ attr_accessor :proxy_pem_file
31
+ # File name of the transparent proxy module to load.
32
+ attr_accessor :proxy_module
33
+ # If true, sslstrip is enabled.
34
+ attr_accessor :sslstrip
35
+ # If true, TCP proxy will be enabled.
36
+ attr_accessor :tcp_proxy
37
+ # TCP proxy local port.
38
+ attr_accessor :tcp_proxy_port
39
+ # TCP proxy upstream server address.
40
+ attr_accessor :tcp_proxy_upstream_address
41
+ # TCP proxy upstream server port.
42
+ attr_accessor :tcp_proxy_upstream_port
43
+ # TCP proxy module to load.
44
+ attr_accessor :tcp_proxy_module
45
+ # Custom HTTP transparent proxy address.
46
+ attr_accessor :custom_proxy
47
+ # Custom HTTP transparent proxy port.
48
+ attr_accessor :custom_proxy_port
49
+ # Custom HTTPS transparent proxy address.
50
+ attr_accessor :custom_https_proxy
51
+ # Custom HTTPS transparent proxy port.
52
+ attr_accessor :custom_https_proxy_port
53
+ # Custom list of redirections.
54
+ attr_accessor :custom_redirections
55
+
56
+ def initialize
57
+ @http_ports = [ 80 ]
58
+ @https_ports = [ 443 ]
59
+ @proxy = false
60
+ @proxy_https = false
61
+ @proxy_port = 8080
62
+ @proxy_https_port = 8083
63
+ @proxy_pem_file = nil
64
+ @proxy_module = nil
65
+ @sslstrip = true
66
+
67
+ @tcp_proxy = false
68
+ @tcp_proxy_port = 2222
69
+ @tcp_proxy_upstream_address = nil
70
+ @tcp_proxy_upstream_port = nil
71
+ @tcp_proxy_module = nil
72
+
73
+ @custom_proxy = nil
74
+ @custom_proxy_port = 8080
75
+
76
+ @custom_https_proxy = nil
77
+ @custom_https_proxy_port = 8083
78
+
79
+ @custom_redirections = []
80
+ end
81
+
82
+ def parse!( ctx, opts )
83
+ opts.separator ""
84
+ opts.separator "PROXYING:".bold
85
+ opts.separator ""
86
+
87
+ opts.separator ""
88
+ opts.separator " TCP:"
89
+ opts.separator ""
90
+
91
+ opts.on( '--tcp-proxy', 'Enable TCP proxy ( requires other --tcp-proxy-* options to be specified ).' ) do
92
+ @tcp_proxy = true
93
+ end
94
+
95
+ opts.on( '--tcp-proxy-module MODULE', "Ruby TCP proxy module to load." ) do |v|
96
+ @tcp_proxy_module = File.expand_path(v)
97
+ Proxy::TCP::Module.load( @tcp_proxy_module )
98
+ end
99
+
100
+ opts.on( '--tcp-proxy-port PORT', "Set local TCP proxy port, default to #{@tcp_proxy_port.to_s.yellow} ." ) do |v|
101
+ @tcp_proxy = true
102
+ @tcp_proxy_port = v.to_i
103
+ end
104
+
105
+ opts.on( '--tcp-proxy-upstream-address ADDRESS', 'Set TCP proxy upstream server address.' ) do |v|
106
+ raise BetterCap::Error, 'Invalid TCP proxy upstream server address specified.' unless Network::Validator.is_ip?(v)
107
+ @tcp_proxy = true
108
+ @tcp_proxy_upstream_address = v
109
+ end
110
+
111
+ opts.on( '--tcp-proxy-upstream-port PORT', 'Set TCP proxy upstream server port.' ) do |v|
112
+ @tcp_proxy = true
113
+ @tcp_proxy_upstream_port = v.to_i
114
+ end
115
+
116
+ opts.separator " HTTP:"
117
+ opts.separator ""
118
+
119
+ opts.on( '--proxy', "Enable HTTP proxy and redirects all HTTP requests to it, default to #{'false'.yellow}." ) do
120
+ @proxy = true
121
+ end
122
+
123
+ opts.on( '--proxy-port PORT', "Set HTTP proxy port, default to #{@proxy_port.to_s.yellow}." ) do |v|
124
+ @proxy = true
125
+ @proxy_port = v.to_i
126
+ end
127
+
128
+ opts.on( '--no-sslstrip', 'Disable SSLStrip.' ) do
129
+ @sslstrip = false
130
+ end
131
+
132
+ opts.on( '--proxy-module MODULE', "Ruby proxy module to load, either a custom file or one of the following: #{Proxy::HTTP::Module.available.map{|x| x.yellow}.join(', ')}." ) do |v|
133
+ Proxy::HTTP::Module.load(ctx, opts, v)
134
+ end
135
+
136
+ opts.on( '--http-ports PORT1,PORT2', "Comma separated list of HTTP ports to redirect to the proxy, default to #{@http_ports.map{|x| x.to_s.yellow }.join(', ')}." ) do |v|
137
+ @http_ports = self.parse_ports( v )
138
+ end
139
+
140
+ opts.separator ""
141
+ opts.separator " HTTPS:"
142
+ opts.separator ""
143
+
144
+ opts.on( '--proxy-https', "Enable HTTPS proxy and redirects all HTTPS requests to it, default to #{'false'.yellow}." ) do
145
+ @proxy_https = true
146
+ end
147
+
148
+ opts.on( '--proxy-https-port PORT', "Set HTTPS proxy port, default to #{@proxy_https_port.to_s.yellow}." ) do |v|
149
+ @proxy_https = true
150
+ @proxy_https_port = v.to_i
151
+ end
152
+
153
+ opts.on( '--proxy-pem FILE', "Use a custom PEM CA certificate file for the HTTPS proxy, default to #{Proxy::HTTP::SSL::Authority::DEFAULT.yellow} ." ) do |v|
154
+ @proxy_https = true
155
+ @proxy_pem_file = File.expand_path v
156
+ end
157
+
158
+ opts.on( '--https-ports PORT1,PORT2', "Comma separated list of HTTPS ports to redirect to the proxy, default to #{@https_ports.map{|x| x.to_s.yellow }.join(', ')}." ) do |v|
159
+ @https_ports = self.parse_ports( v )
160
+ end
161
+
162
+ opts.separator ""
163
+ opts.separator " CUSTOM:"
164
+ opts.separator ""
165
+
166
+ opts.on( '--custom-proxy ADDRESS', 'Use a custom HTTP upstream proxy instead of the builtin one.' ) do |v|
167
+ parse_custom_proxy!(v)
168
+ end
169
+
170
+ opts.on( '--custom-proxy-port PORT', "Specify a port for the custom HTTP upstream proxy, default to #{@custom_proxy_port.to_s.yellow}." ) do |v|
171
+ @custom_proxy_port = v.to_i
172
+ end
173
+
174
+ opts.on( '--custom-https-proxy ADDRESS', 'Use a custom HTTPS upstream proxy instead of the builtin one.' ) do |v|
175
+ parse_custom_proxy!( v, true )
176
+ end
177
+
178
+ opts.on( '--custom-https-proxy-port PORT', "Specify a port for the custom HTTPS upstream proxy, default to #{@custom_https_proxy_port.to_s.yellow}." ) do |v|
179
+ @custom_https_proxy_port = v.to_i
180
+ end
181
+
182
+ opts.on( '--custom-redirection RULE', "Apply a custom port redirection, the format of the rule is #{'PROTOCOL ORIGINAL_PORT NEW_PORT'.yellow}. For instance #{'TCP 21 2100'.yellow} will redirect all TCP traffic going to port 21, to port 2100." ) do |v|
183
+ parse_redirection!( v )
184
+ end
185
+ end
186
+
187
+ def validate!( ctx )
188
+ if @tcp_proxy
189
+ raise BetterCap::Error, "No TCP proxy port specified ( --tcp-proxy-port PORT )." if @tcp_proxy_port.nil?
190
+ raise BetterCap::Error, "No TCP proxy upstream server address specified ( --tcp-proxy-upstream-address ADDRESS )." if @tcp_proxy_upstream_address.nil?
191
+ raise BetterCap::Error, "No TCP proxy upstream server port specified ( --tcp-proxy-upstream-port PORT )." if @tcp_proxy_upstream_port.nil?
192
+ end
193
+
194
+ if @sslstrip and ctx.options.servers.dnsd
195
+ raise BetterCap::Error, "SSL Stripping and builtin DNS server are mutually exclusive features, " \
196
+ "either use the --no-sslstrip option or remove the --dns option."
197
+ end
198
+
199
+ if has_proxy_module? and ( !@proxy and !@proxy_https )
200
+ raise BetterCap::Error, "A proxy module was specified but none of the HTTP or HTTPS proxies are " \
201
+ "enabled, specify --proxy or --proxy-https options."
202
+ end
203
+
204
+ end
205
+
206
+ # Parse a comma separated list of ports and return an array containing only
207
+ # valid ports, raise BetterCap::Error if that array is empty.
208
+ def self.parse_ports(value)
209
+ ports = []
210
+ value.split(",").each do |v|
211
+ v = v.strip.to_i
212
+ if v > 0 and v <= 65535
213
+ ports << v
214
+ end
215
+ end
216
+ raise BetterCap::Error, 'Invalid ports specified.' if ports.empty?
217
+ ports
218
+ end
219
+
220
+ # Setter for the #custom_proxy or #custom_https_proxy attribute, will raise a
221
+ # BetterCap::Error if +value+ is not a valid IP address.
222
+ def parse_custom_proxy!(value, https=false)
223
+ raise BetterCap::Error, 'Invalid custom HTTP upstream proxy address specified.' unless Network::Validator.is_ip?(value)
224
+ if https
225
+ @custom_https_proxy = value
226
+ else
227
+ @custom_proxy = value
228
+ end
229
+ end
230
+
231
+ # Parse a custom redirection rule.
232
+ def parse_redirection!(rule)
233
+ if rule =~ /^((TCP)|(UDP))\s+(\d+)\s+(\d+)$/i
234
+ @custom_redirections << {
235
+ :proto => $1.upcase,
236
+ :from => $4.to_i,
237
+ :to => $5.to_i
238
+ }
239
+ else
240
+ raise BetterCap::Error, 'Invalid custom redirection rule specified.'
241
+ end
242
+ end
243
+
244
+ # Return true if a proxy module was specified, otherwise false.
245
+ def has_proxy_module?
246
+ !@proxy_module.nil?
247
+ end
248
+
249
+ def sslstrip?
250
+ @proxy and @sslstrip
251
+ end
252
+
253
+ def any?
254
+ @proxy or @proxy_https or @tcp_proxy or @custom_proxy
255
+ end
256
+ end
257
+
258
+ end
@@ -0,0 +1,71 @@
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 ServerOptions
17
+ # If true, BetterCap::Network::Servers::HTTPD will be enabled.
18
+ attr_accessor :httpd
19
+ # The port to bind HTTP server to.
20
+ attr_accessor :httpd_port
21
+ # Web root of the HTTP server.
22
+ attr_accessor :httpd_path
23
+ # If true, BetterCap::Network::Servers::DNSD will be enabled.
24
+ attr_accessor :dnsd
25
+ # The port to bind DNS server to.
26
+ attr_accessor :dnsd_port
27
+ # The host resolution file to use with the DNS server.
28
+ attr_accessor :dnsd_file
29
+
30
+ def initialize
31
+ @httpd = false
32
+ @httpd_port = 8081
33
+ @httpd_path = './'
34
+ @dnsd = false
35
+ @dnsd_port = 5300
36
+ @dnsd_file = nil
37
+ end
38
+
39
+ def parse!( ctx, opts )
40
+ opts.separator ""
41
+ opts.separator "SERVERS:".bold
42
+ opts.separator ""
43
+
44
+ opts.on( '--httpd', "Enable HTTP server, default to #{'false'.yellow}." ) do
45
+ @httpd = true
46
+ end
47
+
48
+ opts.on( '--httpd-port PORT', "Set HTTP server port, default to #{@httpd_port.to_s.yellow}." ) do |v|
49
+ @httpd = true
50
+ @httpd_port = v.to_i
51
+ end
52
+
53
+ opts.on( '--httpd-path PATH', "Set HTTP server path, default to #{@httpd_path.yellow} ." ) do |v|
54
+ @httpd = true
55
+ @httpd_path = v
56
+ end
57
+
58
+ opts.on( '--dns FILE', 'Enable DNS server and use this file as a hosts resolution table.' ) do |v|
59
+ @dnsd = true
60
+ @dnsd_file = File.expand_path v
61
+ end
62
+
63
+ opts.on( '--dns-port PORT', "Set DNS server port, default to #{@dnsd_port.to_s.yellow}." ) do |v|
64
+ @dnsd_port = v.to_i
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+ end