xettercap 1.5.7xerob
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/xettercap +61 -0
- data/lib/bettercap/banner +2 -0
- data/lib/bettercap/context.rb +259 -0
- data/lib/bettercap/discovery/agents/arp.rb +37 -0
- data/lib/bettercap/discovery/agents/base.rb +73 -0
- data/lib/bettercap/discovery/agents/icmp.rb +44 -0
- data/lib/bettercap/discovery/agents/udp.rb +30 -0
- data/lib/bettercap/discovery/thread.rb +128 -0
- data/lib/bettercap/error.rb +16 -0
- data/lib/bettercap/firewalls/base.rb +103 -0
- data/lib/bettercap/firewalls/bsd.rb +74 -0
- data/lib/bettercap/firewalls/linux.rb +65 -0
- data/lib/bettercap/firewalls/redirection.rb +42 -0
- data/lib/bettercap/loader.rb +27 -0
- data/lib/bettercap/logger.rb +131 -0
- data/lib/bettercap/memory.rb +56 -0
- data/lib/bettercap/monkey/celluloid/actor.rb +23 -0
- data/lib/bettercap/monkey/celluloid/io/udp_socket.rb +26 -0
- data/lib/bettercap/monkey/em-proxy/proxy.rb +23 -0
- data/lib/bettercap/monkey/openssl/server.rb +35 -0
- data/lib/bettercap/monkey/packetfu/pcap.rb +51 -0
- data/lib/bettercap/monkey/packetfu/utils.rb +210 -0
- data/lib/bettercap/monkey/system.rb +25 -0
- data/lib/bettercap/network/arp_reader.rb +91 -0
- data/lib/bettercap/network/hw-prefixes +21326 -0
- data/lib/bettercap/network/network.rb +102 -0
- data/lib/bettercap/network/packet_queue.rb +129 -0
- data/lib/bettercap/network/protos/base.rb +154 -0
- data/lib/bettercap/network/protos/dhcp.rb +227 -0
- data/lib/bettercap/network/protos/mysql.rb +40 -0
- data/lib/bettercap/network/protos/ntlm.rb +97 -0
- data/lib/bettercap/network/protos/snmp.rb +49 -0
- data/lib/bettercap/network/protos/teamviewer.rb +119 -0
- data/lib/bettercap/network/servers/dnsd.rb +152 -0
- data/lib/bettercap/network/servers/httpd.rb +55 -0
- data/lib/bettercap/network/services +2182 -0
- data/lib/bettercap/network/target.rb +168 -0
- data/lib/bettercap/network/validator.rb +96 -0
- data/lib/bettercap/options/core_options.rb +197 -0
- data/lib/bettercap/options/options.rb +165 -0
- data/lib/bettercap/options/proxy_options.rb +314 -0
- data/lib/bettercap/options/server_options.rb +73 -0
- data/lib/bettercap/options/sniff_options.rb +90 -0
- data/lib/bettercap/options/spoof_options.rb +71 -0
- data/lib/bettercap/pluggable.rb +37 -0
- data/lib/bettercap/proxy/http/module.rb +105 -0
- data/lib/bettercap/proxy/http/modules/injectcss.rb +79 -0
- data/lib/bettercap/proxy/http/modules/injecthtml.rb +80 -0
- data/lib/bettercap/proxy/http/modules/injectjs.rb +79 -0
- data/lib/bettercap/proxy/http/proxy.rb +184 -0
- data/lib/bettercap/proxy/http/request.rb +192 -0
- data/lib/bettercap/proxy/http/response.rb +226 -0
- data/lib/bettercap/proxy/http/ssl/authority.rb +182 -0
- data/lib/bettercap/proxy/http/ssl/bettercap-ca.pem +49 -0
- data/lib/bettercap/proxy/http/ssl/server.rb +63 -0
- data/lib/bettercap/proxy/http/sslstrip/cookiemonitor.rb +67 -0
- data/lib/bettercap/proxy/http/sslstrip/lock.ico +0 -0
- data/lib/bettercap/proxy/http/sslstrip/strip.rb +325 -0
- data/lib/bettercap/proxy/http/streamer.rb +225 -0
- data/lib/bettercap/proxy/stream_logger.rb +181 -0
- data/lib/bettercap/proxy/tcp/module.rb +75 -0
- data/lib/bettercap/proxy/tcp/proxy.rb +123 -0
- data/lib/bettercap/proxy/thread_pool.rb +194 -0
- data/lib/bettercap/shell.rb +70 -0
- data/lib/bettercap/sniffer/parsers/base.rb +87 -0
- data/lib/bettercap/sniffer/parsers/cookie.rb +45 -0
- data/lib/bettercap/sniffer/parsers/creditcard.rb +62 -0
- data/lib/bettercap/sniffer/parsers/custom.rb +26 -0
- data/lib/bettercap/sniffer/parsers/dhcp.rb +45 -0
- data/lib/bettercap/sniffer/parsers/dict.rb +37 -0
- data/lib/bettercap/sniffer/parsers/ftp.rb +24 -0
- data/lib/bettercap/sniffer/parsers/httpauth.rb +44 -0
- data/lib/bettercap/sniffer/parsers/https.rb +42 -0
- data/lib/bettercap/sniffer/parsers/irc.rb +24 -0
- data/lib/bettercap/sniffer/parsers/mail.rb +24 -0
- data/lib/bettercap/sniffer/parsers/mpd.rb +36 -0
- data/lib/bettercap/sniffer/parsers/mysql.rb +27 -0
- data/lib/bettercap/sniffer/parsers/nntp.rb +24 -0
- data/lib/bettercap/sniffer/parsers/ntlmss.rb +34 -0
- data/lib/bettercap/sniffer/parsers/pgsql.rb +36 -0
- data/lib/bettercap/sniffer/parsers/post.rb +33 -0
- data/lib/bettercap/sniffer/parsers/redis.rb +39 -0
- data/lib/bettercap/sniffer/parsers/rlogin.rb +45 -0
- data/lib/bettercap/sniffer/parsers/snmp.rb +44 -0
- data/lib/bettercap/sniffer/parsers/snpp.rb +37 -0
- data/lib/bettercap/sniffer/parsers/teamviewer.rb +30 -0
- data/lib/bettercap/sniffer/parsers/url.rb +30 -0
- data/lib/bettercap/sniffer/parsers/whatsapp.rb +33 -0
- data/lib/bettercap/sniffer/sniffer.rb +142 -0
- data/lib/bettercap/spoofers/arp.rb +150 -0
- data/lib/bettercap/spoofers/base.rb +152 -0
- data/lib/bettercap/spoofers/icmp.rb +202 -0
- data/lib/bettercap/spoofers/none.rb +57 -0
- data/lib/bettercap/update_checker.rb +57 -0
- data/lib/bettercap/version.rb +18 -0
- data/lib/bettercap.rb +70 -0
- metadata +276 -0
@@ -0,0 +1,314 @@
|
|
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
|
+
# If set, only this address will be redirected to the HTTP(S) proxiy.
|
22
|
+
attr_accessor :proxy_upstream_address
|
23
|
+
# HTTP proxy port.
|
24
|
+
attr_accessor :proxy_port
|
25
|
+
# List of HTTP ports, [ 80 ] by default.
|
26
|
+
attr_accessor :http_ports
|
27
|
+
# HTTPS proxy port.
|
28
|
+
attr_accessor :proxy_https_port
|
29
|
+
# List of HTTPS ports, [ 443 ] by default.
|
30
|
+
attr_accessor :https_ports
|
31
|
+
# File name of the PEM certificate to use for the HTTPS proxy.
|
32
|
+
attr_accessor :proxy_pem_file
|
33
|
+
# File name of the transparent proxy module to load.
|
34
|
+
attr_accessor :proxy_module
|
35
|
+
# If true, sslstrip is enabled.
|
36
|
+
attr_accessor :sslstrip
|
37
|
+
# If true, direct connections to the IP of this machine will be allowed.
|
38
|
+
attr_accessor :allow_local_connections
|
39
|
+
# If true, TCP proxy will be enabled.
|
40
|
+
attr_accessor :tcp_proxy
|
41
|
+
# TCP proxy local port.
|
42
|
+
attr_accessor :tcp_proxy_port
|
43
|
+
# TCP proxy upstream server address.
|
44
|
+
attr_accessor :tcp_proxy_upstream_address
|
45
|
+
# TCP proxy upstream server port.
|
46
|
+
attr_accessor :tcp_proxy_upstream_port
|
47
|
+
# TCP proxy module to load.
|
48
|
+
attr_accessor :tcp_proxy_module
|
49
|
+
# Custom HTTP transparent proxy address.
|
50
|
+
attr_accessor :custom_proxy
|
51
|
+
# Custom HTTP transparent proxy port.
|
52
|
+
attr_accessor :custom_proxy_port
|
53
|
+
# Custom HTTPS transparent proxy address.
|
54
|
+
attr_accessor :custom_https_proxy
|
55
|
+
# Custom HTTPS transparent proxy port.
|
56
|
+
attr_accessor :custom_https_proxy_port
|
57
|
+
# Custom list of redirections.
|
58
|
+
attr_accessor :custom_redirections
|
59
|
+
|
60
|
+
def initialize
|
61
|
+
@http_ports = [ 80 ]
|
62
|
+
@https_ports = [ 443 ]
|
63
|
+
@proxy = false
|
64
|
+
@proxy_https = false
|
65
|
+
@proxy_upstream_address = nil
|
66
|
+
@proxy_port = 8080
|
67
|
+
@proxy_https_port = 8083
|
68
|
+
@proxy_pem_file = nil
|
69
|
+
@proxy_module = nil
|
70
|
+
@sslstrip = true
|
71
|
+
@allow_local_connections = false
|
72
|
+
|
73
|
+
@tcp_proxy = false
|
74
|
+
@tcp_proxy_port = 2222
|
75
|
+
@tcp_proxy_upstream_address = nil
|
76
|
+
@tcp_proxy_upstream_port = nil
|
77
|
+
@tcp_proxy_module = nil
|
78
|
+
|
79
|
+
@custom_proxy = nil
|
80
|
+
@custom_proxy_port = 8080
|
81
|
+
|
82
|
+
@custom_https_proxy = nil
|
83
|
+
@custom_https_proxy_port = 8083
|
84
|
+
|
85
|
+
@custom_redirections = []
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse!( ctx, opts )
|
89
|
+
opts.separator ""
|
90
|
+
opts.separator "PROXYING:".bold
|
91
|
+
opts.separator ""
|
92
|
+
|
93
|
+
opts.separator ""
|
94
|
+
opts.separator " TCP:"
|
95
|
+
opts.separator ""
|
96
|
+
|
97
|
+
opts.on( '--tcp-proxy', 'Enable TCP proxy ( requires other --tcp-proxy-* options to be specified ).' ) do
|
98
|
+
@tcp_proxy = true
|
99
|
+
end
|
100
|
+
|
101
|
+
opts.on( '--tcp-proxy-module MODULE', "Ruby TCP proxy module to load." ) do |v|
|
102
|
+
@tcp_proxy_module = File.expand_path(v)
|
103
|
+
Proxy::TCP::Module.load( @tcp_proxy_module )
|
104
|
+
end
|
105
|
+
|
106
|
+
opts.on( '--tcp-proxy-port PORT', "Set local TCP proxy port, default to #{@tcp_proxy_port.to_s.yellow} ." ) do |v|
|
107
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
108
|
+
@tcp_proxy = true
|
109
|
+
@tcp_proxy_port = v.to_i
|
110
|
+
end
|
111
|
+
|
112
|
+
opts.on( '--tcp-proxy-upstream ADDRESS:PORT', 'Set TCP proxy upstream server address and port.' ) do |v|
|
113
|
+
if v =~ /^(.+):(\d+)$/
|
114
|
+
address = $1
|
115
|
+
port = $2
|
116
|
+
else
|
117
|
+
raise BetterCap::Error, "Invalid address and port specified, the correct syntax is ADDRESS:PORT ( i.e. 192.168.1.2:22 )."
|
118
|
+
end
|
119
|
+
|
120
|
+
address, port = validate_address address, port
|
121
|
+
|
122
|
+
@tcp_proxy = true
|
123
|
+
@tcp_proxy_upstream_address = address
|
124
|
+
@tcp_proxy_upstream_port = port.to_i
|
125
|
+
end
|
126
|
+
|
127
|
+
opts.on( '--tcp-proxy-upstream-address ADDRESS', 'Set TCP proxy upstream server address.' ) do |v|
|
128
|
+
v, _ = validate_address v
|
129
|
+
|
130
|
+
@tcp_proxy = true
|
131
|
+
@tcp_proxy_upstream_address = v
|
132
|
+
end
|
133
|
+
|
134
|
+
opts.on( '--tcp-proxy-upstream-port PORT', 'Set TCP proxy upstream server port.' ) do |v|
|
135
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
136
|
+
@tcp_proxy = true
|
137
|
+
@tcp_proxy_upstream_port = v.to_i
|
138
|
+
end
|
139
|
+
|
140
|
+
opts.separator " HTTP:"
|
141
|
+
opts.separator ""
|
142
|
+
|
143
|
+
opts.on( '--proxy', "Enable HTTP proxy and redirects all HTTP requests to it, default to #{'false'.yellow}." ) do
|
144
|
+
@proxy = true
|
145
|
+
end
|
146
|
+
|
147
|
+
opts.on( '--proxy-port PORT', "Set HTTP proxy port, default to #{@proxy_port.to_s.yellow}." ) do |v|
|
148
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
149
|
+
@proxy = true
|
150
|
+
@proxy_port = v.to_i
|
151
|
+
end
|
152
|
+
|
153
|
+
opts.on( '--allow-local-connections', "Allow direct connections to the proxy instance, default to #{@allow_local_connections.to_s.yellow}." ) do |v|
|
154
|
+
@proxy = true
|
155
|
+
@allow_local_connections = true
|
156
|
+
end
|
157
|
+
|
158
|
+
opts.on( '--no-sslstrip', 'Disable SSLStrip.' ) do
|
159
|
+
@proxy = true
|
160
|
+
@sslstrip = false
|
161
|
+
end
|
162
|
+
|
163
|
+
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|
|
164
|
+
Proxy::HTTP::Module.load(ctx, opts, v)
|
165
|
+
@proxy = true
|
166
|
+
end
|
167
|
+
|
168
|
+
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|
|
169
|
+
@http_ports = ProxyOptions.parse_ports( v )
|
170
|
+
@proxy = true
|
171
|
+
end
|
172
|
+
|
173
|
+
opts.on( '--proxy-upstream-address ADDRESS', 'If set, only requests coming from this server address will be redirected to the HTTP/HTTPS proxies.' ) do |v|
|
174
|
+
v, _ = validate_address v
|
175
|
+
@proxy_upstream_address = v
|
176
|
+
end
|
177
|
+
|
178
|
+
opts.separator ""
|
179
|
+
opts.separator " HTTPS:"
|
180
|
+
opts.separator ""
|
181
|
+
|
182
|
+
opts.on( '--proxy-https', "Enable HTTPS proxy and redirects all HTTPS requests to it, default to #{'false'.yellow}." ) do
|
183
|
+
@proxy_https = true
|
184
|
+
end
|
185
|
+
|
186
|
+
opts.on( '--proxy-https-port PORT', "Set HTTPS proxy port, default to #{@proxy_https_port.to_s.yellow}." ) do |v|
|
187
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
188
|
+
@proxy_https = true
|
189
|
+
@proxy_https_port = v.to_i
|
190
|
+
end
|
191
|
+
|
192
|
+
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|
|
193
|
+
@proxy_https = true
|
194
|
+
@proxy_pem_file = File.expand_path v
|
195
|
+
end
|
196
|
+
|
197
|
+
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|
|
198
|
+
@https_ports = ProxyOptions.parse_ports( v )
|
199
|
+
@proxy_https = true
|
200
|
+
end
|
201
|
+
|
202
|
+
opts.separator ""
|
203
|
+
opts.separator " CUSTOM:"
|
204
|
+
opts.separator ""
|
205
|
+
|
206
|
+
opts.on( '--custom-proxy ADDRESS', 'Use a custom HTTP upstream proxy instead of the builtin one.' ) do |v|
|
207
|
+
parse_custom_proxy!(v)
|
208
|
+
end
|
209
|
+
|
210
|
+
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|
|
211
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
212
|
+
@custom_proxy_port = v.to_i
|
213
|
+
end
|
214
|
+
|
215
|
+
opts.on( '--custom-https-proxy ADDRESS', 'Use a custom HTTPS upstream proxy instead of the builtin one.' ) do |v|
|
216
|
+
parse_custom_proxy!( v, true )
|
217
|
+
end
|
218
|
+
|
219
|
+
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|
|
220
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
221
|
+
@custom_https_proxy_port = v.to_i
|
222
|
+
end
|
223
|
+
|
224
|
+
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|
|
225
|
+
parse_redirection!( v )
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def validate!( ctx )
|
230
|
+
if @tcp_proxy
|
231
|
+
raise BetterCap::Error, "No TCP proxy port specified ( --tcp-proxy-port PORT )." if @tcp_proxy_port.nil?
|
232
|
+
raise BetterCap::Error, "No TCP proxy upstream server address specified ( --tcp-proxy-upstream-address ADDRESS )." if @tcp_proxy_upstream_address.nil?
|
233
|
+
raise BetterCap::Error, "No TCP proxy upstream server port specified ( --tcp-proxy-upstream-port PORT )." if @tcp_proxy_upstream_port.nil?
|
234
|
+
end
|
235
|
+
|
236
|
+
if @proxy and @sslstrip and ctx.options.servers.dnsd
|
237
|
+
raise BetterCap::Error, "SSL Stripping and builtin DNS server are mutually exclusive features, " \
|
238
|
+
"either use the --no-sslstrip option or remove the --dns option."
|
239
|
+
end
|
240
|
+
|
241
|
+
if has_proxy_module? and ( !@proxy and !@proxy_https )
|
242
|
+
raise BetterCap::Error, "A proxy module was specified but none of the HTTP or HTTPS proxies are " \
|
243
|
+
"enabled, specify --proxy or --proxy-https options."
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
# Parse a comma separated list of ports and return an array containing only
|
249
|
+
# valid ports, raise BetterCap::Error if that array is empty.
|
250
|
+
def self.parse_ports(value)
|
251
|
+
ports = []
|
252
|
+
value.split(",").each do |v|
|
253
|
+
v = v.strip.to_i
|
254
|
+
if v > 0 and v <= 65535
|
255
|
+
ports << v
|
256
|
+
end
|
257
|
+
end
|
258
|
+
raise BetterCap::Error, 'Invalid ports specified.' if ports.empty?
|
259
|
+
ports
|
260
|
+
end
|
261
|
+
|
262
|
+
# Setter for the #custom_proxy or #custom_https_proxy attribute, will raise a
|
263
|
+
# BetterCap::Error if +value+ is not a valid IP address.
|
264
|
+
def parse_custom_proxy!(value, https=false)
|
265
|
+
raise BetterCap::Error, 'Invalid custom HTTP upstream proxy address specified.' unless Network::Validator.is_ip?(value)
|
266
|
+
if https
|
267
|
+
@custom_https_proxy = value
|
268
|
+
else
|
269
|
+
@custom_proxy = value
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Parse a custom redirection rule.
|
274
|
+
def parse_redirection!(rule)
|
275
|
+
if rule =~ /^((TCP)|(UDP))\s+(\d+)\s+(\d+)$/i
|
276
|
+
@custom_redirections << {
|
277
|
+
:proto => $1.upcase,
|
278
|
+
:from => $4.to_i,
|
279
|
+
:to => $5.to_i
|
280
|
+
}
|
281
|
+
else
|
282
|
+
raise BetterCap::Error, 'Invalid custom redirection rule specified.'
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Return true if a proxy module was specified, otherwise false.
|
287
|
+
def has_proxy_module?
|
288
|
+
!@proxy_module.nil?
|
289
|
+
end
|
290
|
+
|
291
|
+
def sslstrip?
|
292
|
+
@proxy and @sslstrip
|
293
|
+
end
|
294
|
+
|
295
|
+
def any?
|
296
|
+
@proxy or @proxy_https or @tcp_proxy or @custom_proxy
|
297
|
+
end
|
298
|
+
|
299
|
+
def validate_address( address, port = nil )
|
300
|
+
unless Network::Validator.is_ip?(address)
|
301
|
+
begin
|
302
|
+
address = IPSocket.getaddress address
|
303
|
+
rescue SocketError
|
304
|
+
raise BetterCap::Error, "Could not resolve '#{address}' to a valid ip address."
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
raise BetterCap::Error, "Invalid port '#{port}' specified." unless port.nil? or Network::Validator.is_valid_port?(port)
|
309
|
+
|
310
|
+
[ address, port ]
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
@@ -0,0 +1,73 @@
|
|
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
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
50
|
+
@httpd = true
|
51
|
+
@httpd_port = v.to_i
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on( '--httpd-path PATH', "Set HTTP server path, default to #{@httpd_path.yellow} ." ) do |v|
|
55
|
+
@httpd = true
|
56
|
+
@httpd_path = v
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on( '--dns FILE', 'Enable DNS server and use this file as a hosts resolution table.' ) do |v|
|
60
|
+
@dnsd = true
|
61
|
+
@dnsd_file = File.expand_path v
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on( '--dns-port PORT', "Set DNS server port, default to #{@dnsd_port.to_s.yellow}." ) do |v|
|
65
|
+
raise BetterCap::Error, "Invalid port '#{v}' specified." unless Network::Validator.is_valid_port?(v)
|
66
|
+
@dnsd_port = v.to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,90 @@
|
|
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 SniffOptions
|
17
|
+
# If true the BetterCap::Sniffer will be enabled.
|
18
|
+
attr_accessor :enabled
|
19
|
+
# PCAP file name to save captured packets to.
|
20
|
+
attr_accessor :output
|
21
|
+
# BPF filter to apply to sniffed packets.
|
22
|
+
attr_accessor :filter
|
23
|
+
# Input PCAP file, if specified the BetterCap::Sniffer will read packets
|
24
|
+
# from it instead of the network.
|
25
|
+
attr_accessor :src
|
26
|
+
# Comma separated list of BetterCap::Parsers to enable.
|
27
|
+
attr_accessor :parsers
|
28
|
+
# Regular expression to use with the BetterCap::Parsers::Custom parser.
|
29
|
+
attr_accessor :custom_parser
|
30
|
+
# If true, bettercap will sniff packets from the local interface as well.
|
31
|
+
attr_accessor :local
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@enabled = false
|
35
|
+
@output = nil
|
36
|
+
@filter = nil
|
37
|
+
@src = nil
|
38
|
+
@parsers = ['*']
|
39
|
+
@custom_parser = nil
|
40
|
+
@local = false
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse!( ctx, opts )
|
44
|
+
opts.separator ""
|
45
|
+
opts.separator "SNIFFING:".bold
|
46
|
+
opts.separator ""
|
47
|
+
|
48
|
+
opts.on( '-X', '--sniffer', 'Enable sniffer.' ) do
|
49
|
+
@enabled = true
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on( '-L', '--local', "Parse packets coming from/to the address of this computer ( NOTE: Will set -X to true ), default to #{'false'.yellow}." ) do
|
53
|
+
@enabled = true
|
54
|
+
@local = true
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on( '--sniffer-source FILE', 'Load packets from the specified PCAP file instead of the interface ( will enable sniffer ).' ) do |v|
|
58
|
+
@enabled = true
|
59
|
+
@src = File.expand_path v
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on( '--sniffer-output FILE', 'Save all packets to the specified PCAP file ( will enable sniffer ).' ) do |v|
|
63
|
+
@enabled = true
|
64
|
+
@output = File.expand_path v
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on( '--sniffer-filter EXPRESSION', 'Configure the sniffer to use this BPF filter ( will enable sniffer ).' ) do |v|
|
68
|
+
@enabled = true
|
69
|
+
@filter = v
|
70
|
+
end
|
71
|
+
|
72
|
+
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.map { |x| x.yellow }.join(', ')} - default: #{'*'.yellow}" ) do |v|
|
73
|
+
@enabled = true
|
74
|
+
@parsers = Parsers::Base.from_cmdline(v)
|
75
|
+
end
|
76
|
+
|
77
|
+
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|
|
78
|
+
@enabled = true
|
79
|
+
@parsers = ['CUSTOM']
|
80
|
+
@custom_parser = Regexp.new(v)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Return true if the specified +parser+ is enabled, otherwise false.
|
85
|
+
def enabled?( parser = nil )
|
86
|
+
@enabled and ( parser.nil? or ( @parsers.include?('*') or @parsers.include?(parser.upcase) ) )
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
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 SpoofOptions
|
17
|
+
# Name of the spoofer to use.
|
18
|
+
attr_accessor :spoofer
|
19
|
+
# If true half duplex mode is enabled.
|
20
|
+
attr_accessor :half_duplex
|
21
|
+
# If true, bettercap won't forward packets for any target, causing
|
22
|
+
# connections to be killed.
|
23
|
+
attr_accessor :kill
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@spoofer = 'ARP'
|
27
|
+
@half_duplex = false
|
28
|
+
@kill = false
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse!( ctx, opts )
|
32
|
+
opts.separator ""
|
33
|
+
opts.separator "SPOOFING:".bold
|
34
|
+
opts.separator ""
|
35
|
+
|
36
|
+
opts.on( '-S', '--spoofer NAME', "Spoofer module to use, available: #{Spoofers::Base.available.map{|x| x.yellow }.join(', ')} - default: #{@spoofer.yellow}." ) do |v|
|
37
|
+
@spoofer = v
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on( '--no-spoofing', "Disable spoofing, alias for #{'--spoofer NONE'.yellow}." ) do
|
41
|
+
@spoofer = 'NONE'
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on( '--half-duplex', 'Enable half-duplex MITM, this will make bettercap work in those cases when the router is not vulnerable.' ) do
|
45
|
+
@half_duplex = true
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on( '--kill', 'Instead of forwarding packets, this switch will make targets connections to be killed.' ) do
|
49
|
+
@kill = true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return true if a spoofer module was specified, otherwise false.
|
54
|
+
def enabled?
|
55
|
+
@spoofer.upcase != 'NONE'
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Parse spoofers and return a list of BetterCap::Spoofers objects. Raise a
|
60
|
+
# BetterCap::Error if an invalid spoofer name was specified.
|
61
|
+
def parse_spoofers
|
62
|
+
valid = []
|
63
|
+
@spoofer.split(",").each do |module_name|
|
64
|
+
valid << Spoofers::Base.get_by_name( module_name )
|
65
|
+
end
|
66
|
+
valid
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,37 @@
|
|
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
|
+
# Simple base class for modules and plugins of various types.
|
16
|
+
class Pluggable
|
17
|
+
@@metadata = {
|
18
|
+
'Name' => '',
|
19
|
+
'Version' => '',
|
20
|
+
'Author' => "Simone 'evilsocket' Margaritelli",
|
21
|
+
'License' => 'GPL3',
|
22
|
+
'Description' => ''
|
23
|
+
}
|
24
|
+
|
25
|
+
# Define the metadata for this module.
|
26
|
+
def self.meta(meta = {})
|
27
|
+
meta.each do |key,value|
|
28
|
+
@@metadata[key] = value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get the metadata of this module.
|
33
|
+
def self.metadata
|
34
|
+
@@metadata
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,105 @@
|
|
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 Proxy
|
16
|
+
module HTTP
|
17
|
+
|
18
|
+
# Base class for transparent proxy modules.
|
19
|
+
class Module < BetterCap::Pluggable
|
20
|
+
@@path = File.dirname(__FILE__) + '/modules/'
|
21
|
+
@@modules = []
|
22
|
+
|
23
|
+
def on_pre_request( request ); end
|
24
|
+
def on_request( request, response ); end
|
25
|
+
|
26
|
+
# Return a list of available builtin proxy module names.
|
27
|
+
def self.available
|
28
|
+
avail = []
|
29
|
+
Dir.foreach( @@path ) do |file|
|
30
|
+
if file =~ /.rb/
|
31
|
+
avail << file.gsub('.rb','')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
avail
|
35
|
+
end
|
36
|
+
|
37
|
+
# Check if the module with +name+ is within the builtin ones.
|
38
|
+
def self.is_builtin?(name)
|
39
|
+
self.available.include?(name)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Load the module with +name+.
|
43
|
+
def self.load(ctx, opts, name)
|
44
|
+
if self.is_builtin?(name)
|
45
|
+
ctx.options.proxies.proxy_module = "#{@@path}/#{name}.rb"
|
46
|
+
else
|
47
|
+
ctx.options.proxies.proxy_module = File.expand_path(name)
|
48
|
+
end
|
49
|
+
|
50
|
+
begin
|
51
|
+
require ctx.options.proxies.proxy_module
|
52
|
+
|
53
|
+
self.register_options(opts)
|
54
|
+
rescue LoadError => e
|
55
|
+
raise BetterCap::Error, "Invalid proxy module name '#{name}': #{e.message}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Return a list of registered modules.
|
60
|
+
def self.modules
|
61
|
+
@@modules
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return true if the module is enabled, otherwise false.
|
65
|
+
def enabled?
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
# Register custom options for each available module.
|
70
|
+
def self.register_options(opts)
|
71
|
+
self.each_module do |const|
|
72
|
+
if const.respond_to?(:on_options)
|
73
|
+
const.on_options(opts)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Register available proxy modules into the system.
|
79
|
+
def self.register_modules
|
80
|
+
self.each_module do |const|
|
81
|
+
Logger.debug "Registering module #{const}"
|
82
|
+
@@modules << const.new
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Loop each available BetterCap::Proxy::HTTP::Proxy module and yield each
|
89
|
+
# one of them for the given code block.
|
90
|
+
def self.each_module
|
91
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
92
|
+
Object.constants.each do |klass|
|
93
|
+
const = Kernel.const_get(klass.to_s)
|
94
|
+
if const.respond_to?(:superclass) and const.superclass == self
|
95
|
+
yield const
|
96
|
+
end
|
97
|
+
end
|
98
|
+
ensure
|
99
|
+
$VERBOSE = old_verbose
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|