bettercap 1.4.6 → 1.5.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.
- checksums.yaml +4 -4
- data/bin/bettercap +1 -1
- data/lib/bettercap.rb +1 -0
- data/lib/bettercap/context.rb +63 -70
- data/lib/bettercap/discovery/agents/base.rb +2 -2
- data/lib/bettercap/discovery/thread.rb +5 -4
- data/lib/bettercap/firewalls/base.rb +2 -4
- data/lib/bettercap/firewalls/{osx.rb → bsd.rb} +3 -3
- data/lib/bettercap/firewalls/linux.rb +2 -2
- data/lib/bettercap/firewalls/redirection.rb +5 -2
- data/lib/bettercap/logger.rb +6 -11
- data/lib/bettercap/memory.rb +56 -0
- data/lib/bettercap/monkey/em-proxy/proxy.rb +23 -0
- data/lib/bettercap/monkey/packetfu/pcap.rb +51 -0
- data/lib/bettercap/network/arp_reader.rb +2 -2
- data/lib/bettercap/network/network.rb +2 -2
- data/lib/bettercap/network/packet_queue.rb +2 -2
- data/lib/bettercap/network/protos/base.rb +8 -5
- data/lib/bettercap/network/protos/dhcp.rb +5 -124
- data/lib/bettercap/network/target.rb +7 -2
- data/lib/bettercap/options/core_options.rb +189 -0
- data/lib/bettercap/options/options.rb +167 -0
- data/lib/bettercap/options/proxy_options.rb +258 -0
- data/lib/bettercap/options/server_options.rb +71 -0
- data/lib/bettercap/options/sniff_options.rb +90 -0
- data/lib/bettercap/options/spoof_options.rb +71 -0
- data/lib/bettercap/proxy/{module.rb → http/module.rb} +8 -4
- data/lib/bettercap/proxy/{modules → http/modules}/injectcss.rb +2 -2
- data/lib/bettercap/proxy/{modules → http/modules}/injecthtml.rb +2 -2
- data/lib/bettercap/proxy/{modules → http/modules}/injectjs.rb +2 -2
- data/lib/bettercap/proxy/{proxy.rb → http/proxy.rb} +5 -2
- data/lib/bettercap/proxy/{request.rb → http/request.rb} +4 -0
- data/lib/bettercap/proxy/{response.rb → http/response.rb} +3 -0
- data/lib/bettercap/proxy/{ssl → http/ssl}/authority.rb +3 -1
- data/lib/bettercap/proxy/{ssl → http/ssl}/bettercap-ca.pem +0 -0
- data/lib/bettercap/proxy/{ssl → http/ssl}/server.rb +3 -1
- data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/cookiemonitor.rb +2 -0
- data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/lock.ico +0 -0
- data/lib/bettercap/proxy/{sslstrip → http/sslstrip}/strip.rb +4 -2
- data/lib/bettercap/proxy/{streamer.rb → http/streamer.rb} +7 -4
- data/lib/bettercap/proxy/stream_logger.rb +25 -9
- 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 +1 -1
- data/lib/bettercap/sniffer/parsers/post.rb +1 -1
- data/lib/bettercap/sniffer/parsers/url.rb +1 -1
- data/lib/bettercap/sniffer/sniffer.rb +23 -17
- data/lib/bettercap/spoofers/arp.rb +21 -9
- data/lib/bettercap/spoofers/base.rb +12 -16
- data/lib/bettercap/spoofers/icmp.rb +4 -5
- data/lib/bettercap/spoofers/none.rb +0 -1
- data/lib/bettercap/version.rb +1 -1
- metadata +48 -19
- data/lib/bettercap/firewalls/openbsd.rb +0 -77
- data/lib/bettercap/options.rb +0 -600
data/lib/bettercap/version.rb
CHANGED
@@ -12,7 +12,7 @@ This project is released under the GPL 3 license.
|
|
12
12
|
=end
|
13
13
|
module BetterCap
|
14
14
|
# Current version of bettercap.
|
15
|
-
VERSION = '1.
|
15
|
+
VERSION = '1.5.0'
|
16
16
|
# Program banner.
|
17
17
|
BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
|
18
18
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bettercap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simone Margaritelli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -130,6 +130,26 @@ dependencies:
|
|
130
130
|
- - ">="
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: 1.0.3
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: em-proxy
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.1'
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.1.8
|
143
|
+
type: :runtime
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - "~>"
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0.1'
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.1.8
|
133
153
|
description: BetterCap is the state of the art, modular, portable and easily extensible
|
134
154
|
MITM framework featuring ARP, DNS and ICMP spoofing, sslstripping, credentials harvesting
|
135
155
|
and more.
|
@@ -152,14 +172,16 @@ files:
|
|
152
172
|
- lib/bettercap/discovery/thread.rb
|
153
173
|
- lib/bettercap/error.rb
|
154
174
|
- lib/bettercap/firewalls/base.rb
|
175
|
+
- lib/bettercap/firewalls/bsd.rb
|
155
176
|
- lib/bettercap/firewalls/linux.rb
|
156
|
-
- lib/bettercap/firewalls/openbsd.rb
|
157
|
-
- lib/bettercap/firewalls/osx.rb
|
158
177
|
- lib/bettercap/firewalls/redirection.rb
|
159
178
|
- lib/bettercap/loader.rb
|
160
179
|
- lib/bettercap/logger.rb
|
180
|
+
- lib/bettercap/memory.rb
|
161
181
|
- lib/bettercap/monkey/celluloid/io/udp_socket.rb
|
182
|
+
- lib/bettercap/monkey/em-proxy/proxy.rb
|
162
183
|
- lib/bettercap/monkey/openssl/server.rb
|
184
|
+
- lib/bettercap/monkey/packetfu/pcap.rb
|
163
185
|
- lib/bettercap/monkey/packetfu/utils.rb
|
164
186
|
- lib/bettercap/monkey/system.rb
|
165
187
|
- lib/bettercap/network/arp_reader.rb
|
@@ -176,22 +198,29 @@ files:
|
|
176
198
|
- lib/bettercap/network/services
|
177
199
|
- lib/bettercap/network/target.rb
|
178
200
|
- lib/bettercap/network/validator.rb
|
179
|
-
- lib/bettercap/options.rb
|
180
|
-
- lib/bettercap/
|
181
|
-
- lib/bettercap/
|
182
|
-
- lib/bettercap/
|
183
|
-
- lib/bettercap/
|
184
|
-
- lib/bettercap/
|
185
|
-
- lib/bettercap/proxy/
|
186
|
-
- lib/bettercap/proxy/
|
187
|
-
- lib/bettercap/proxy/
|
188
|
-
- lib/bettercap/proxy/
|
189
|
-
- lib/bettercap/proxy/
|
190
|
-
- lib/bettercap/proxy/
|
191
|
-
- lib/bettercap/proxy/
|
192
|
-
- lib/bettercap/proxy/
|
201
|
+
- lib/bettercap/options/core_options.rb
|
202
|
+
- lib/bettercap/options/options.rb
|
203
|
+
- lib/bettercap/options/proxy_options.rb
|
204
|
+
- lib/bettercap/options/server_options.rb
|
205
|
+
- lib/bettercap/options/sniff_options.rb
|
206
|
+
- lib/bettercap/options/spoof_options.rb
|
207
|
+
- lib/bettercap/proxy/http/module.rb
|
208
|
+
- lib/bettercap/proxy/http/modules/injectcss.rb
|
209
|
+
- lib/bettercap/proxy/http/modules/injecthtml.rb
|
210
|
+
- lib/bettercap/proxy/http/modules/injectjs.rb
|
211
|
+
- lib/bettercap/proxy/http/proxy.rb
|
212
|
+
- lib/bettercap/proxy/http/request.rb
|
213
|
+
- lib/bettercap/proxy/http/response.rb
|
214
|
+
- lib/bettercap/proxy/http/ssl/authority.rb
|
215
|
+
- lib/bettercap/proxy/http/ssl/bettercap-ca.pem
|
216
|
+
- lib/bettercap/proxy/http/ssl/server.rb
|
217
|
+
- lib/bettercap/proxy/http/sslstrip/cookiemonitor.rb
|
218
|
+
- lib/bettercap/proxy/http/sslstrip/lock.ico
|
219
|
+
- lib/bettercap/proxy/http/sslstrip/strip.rb
|
220
|
+
- lib/bettercap/proxy/http/streamer.rb
|
193
221
|
- lib/bettercap/proxy/stream_logger.rb
|
194
|
-
- lib/bettercap/proxy/
|
222
|
+
- lib/bettercap/proxy/tcp/module.rb
|
223
|
+
- lib/bettercap/proxy/tcp/proxy.rb
|
195
224
|
- lib/bettercap/proxy/thread_pool.rb
|
196
225
|
- lib/bettercap/shell.rb
|
197
226
|
- lib/bettercap/sniffer/parsers/base.rb
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
=begin
|
3
|
-
|
4
|
-
BETTERCAP
|
5
|
-
|
6
|
-
Author : Angelos D. Keromytis
|
7
|
-
Email : angelos@cs.columbia.edu
|
8
|
-
|
9
|
-
This project is released under the GPL 3 license.
|
10
|
-
|
11
|
-
=end
|
12
|
-
|
13
|
-
module BetterCap
|
14
|
-
module Firewalls
|
15
|
-
# OpenBSD Firewall class; for now, it's a direct copy of the OSX firewall
|
16
|
-
class OpenBSD < Base
|
17
|
-
# If +enabled+ is true will enable packet forwarding, otherwise it will
|
18
|
-
# disable it.
|
19
|
-
def enable_forwarding(enabled)
|
20
|
-
Shell.execute("sysctl -w net.inet.ip.forwarding=#{enabled ? 1 : 0}")
|
21
|
-
end
|
22
|
-
|
23
|
-
# If +enabled+ is true will enable packet icmp_echo_ignore_broadcasts, otherwise it will
|
24
|
-
# disable it.
|
25
|
-
def enable_icmp_bcast(enabled)
|
26
|
-
Shell.execute("sysctl -w net.inet.icmp.bmcastecho=#{enabled ? 1 : 0}")
|
27
|
-
end
|
28
|
-
|
29
|
-
# Return true if packet forwarding is currently enabled, otherwise false.
|
30
|
-
def forwarding_enabled?
|
31
|
-
Shell.execute('sysctl net.inet.ip.forwarding').strip.split(' ')[1] == '1'
|
32
|
-
end
|
33
|
-
|
34
|
-
# This method is ignored on OpenBSD.
|
35
|
-
def enable_send_redirects(enabled); end
|
36
|
-
|
37
|
-
# If +enabled+ is true, the PF firewall will be enabled, otherwise it will
|
38
|
-
# be disabled.
|
39
|
-
def enable(enabled)
|
40
|
-
begin
|
41
|
-
Shell.execute("pfctl -#{enabled ? 'e' : 'd'} >/dev/null 2>&1")
|
42
|
-
rescue; end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Apply the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
46
|
-
def add_port_redirection( r )
|
47
|
-
# create the pf config file
|
48
|
-
config_file = "/tmp/bettercap_pf_#{Process.pid}.conf"
|
49
|
-
|
50
|
-
File.open( config_file, 'a+t' ) do |f|
|
51
|
-
f.write "rdr pass on #{r.interface} proto #{r.protocol} from any to any port #{r.src_port} -> #{r.dst_address} port #{r.dst_port}\n"
|
52
|
-
end
|
53
|
-
|
54
|
-
# load the rule
|
55
|
-
Shell.execute("pfctl -f #{config_file} >/dev/null 2>&1")
|
56
|
-
# enable pf
|
57
|
-
enable true
|
58
|
-
end
|
59
|
-
|
60
|
-
# Remove the +r+ BetterCap::Firewalls::Redirection port redirection object.
|
61
|
-
def del_port_redirection( r )
|
62
|
-
# FIXME: This should search for multiple rules inside the
|
63
|
-
# file and remove only this one.
|
64
|
-
|
65
|
-
# disable pf
|
66
|
-
enable false
|
67
|
-
|
68
|
-
begin
|
69
|
-
# remove the pf config file
|
70
|
-
File.delete( "/tmp/bettercap_pf_#{Process.pid}.conf" )
|
71
|
-
rescue
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
data/lib/bettercap/options.rb
DELETED
@@ -1,600 +0,0 @@
|
|
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
|
-
# Gateway IP address.
|
19
|
-
attr_accessor :gateway
|
20
|
-
# Network interface.
|
21
|
-
attr_accessor :iface
|
22
|
-
# Name of the spoofer to use.
|
23
|
-
attr_accessor :spoofer
|
24
|
-
# If true half duplex mode is enabled.
|
25
|
-
attr_accessor :half_duplex
|
26
|
-
# Comma separated list of targets.
|
27
|
-
attr_accessor :target
|
28
|
-
# Log file name.
|
29
|
-
attr_accessor :logfile
|
30
|
-
# If true the Logger will prepend timestamps to each line.
|
31
|
-
attr_accessor :log_timestamp
|
32
|
-
# If true will suppress every log message which is not an error or a warning.
|
33
|
-
attr_accessor :silent
|
34
|
-
# If true will enable debug messages.
|
35
|
-
attr_accessor :debug
|
36
|
-
# If true will disable active network discovery, the program will just use
|
37
|
-
# the current ARP cache.
|
38
|
-
attr_accessor :arpcache
|
39
|
-
# Comma separated list of ip addresses to ignore.
|
40
|
-
attr_accessor :ignore
|
41
|
-
# If true the BetterCap::Sniffer will be enabled.
|
42
|
-
attr_accessor :sniffer
|
43
|
-
# PCAP file name to save captured packets to.
|
44
|
-
attr_accessor :sniffer_pcap
|
45
|
-
# BPF filter to apply to sniffed packets.
|
46
|
-
attr_accessor :sniffer_filter
|
47
|
-
# Input PCAP file, if specified the BetterCap::Sniffer will read packets
|
48
|
-
# from it instead of the network.
|
49
|
-
attr_accessor :sniffer_src
|
50
|
-
# Comma separated list of BetterCap::Parsers to enable.
|
51
|
-
attr_accessor :parsers
|
52
|
-
# Regular expression to use with the BetterCap::Parsers::Custom parser.
|
53
|
-
attr_accessor :custom_parser
|
54
|
-
# If true, bettercap will sniff packets from the local interface as well.
|
55
|
-
attr_accessor :local
|
56
|
-
# If true, HTTP transparent proxy will be enabled.
|
57
|
-
attr_accessor :proxy
|
58
|
-
# If true, HTTPS transparent proxy will be enabled.
|
59
|
-
attr_accessor :proxy_https
|
60
|
-
# HTTP proxy port.
|
61
|
-
attr_accessor :proxy_port
|
62
|
-
# List of HTTP ports, [ 80 ] by default.
|
63
|
-
attr_accessor :http_ports
|
64
|
-
# HTTPS proxy port.
|
65
|
-
attr_accessor :proxy_https_port
|
66
|
-
# List of HTTPS ports, [ 443 ] by default.
|
67
|
-
attr_accessor :https_ports
|
68
|
-
# File name of the PEM certificate to use for the HTTPS proxy.
|
69
|
-
attr_accessor :proxy_pem_file
|
70
|
-
# File name of the transparent proxy module to load.
|
71
|
-
attr_accessor :proxy_module
|
72
|
-
# If true, sslstrip is enabled.
|
73
|
-
attr_accessor :sslstrip
|
74
|
-
# Custom HTTP transparent proxy address.
|
75
|
-
attr_accessor :custom_proxy
|
76
|
-
# Custom HTTP transparent proxy port.
|
77
|
-
attr_accessor :custom_proxy_port
|
78
|
-
# Custom HTTPS transparent proxy address.
|
79
|
-
attr_accessor :custom_https_proxy
|
80
|
-
# Custom HTTPS transparent proxy port.
|
81
|
-
attr_accessor :custom_https_proxy_port
|
82
|
-
# Custom list of redirections.
|
83
|
-
attr_accessor :custom_redirections
|
84
|
-
# If true, BetterCap::Network::Servers::HTTPD will be enabled.
|
85
|
-
attr_accessor :httpd
|
86
|
-
# The port to bind HTTP server to.
|
87
|
-
attr_accessor :httpd_port
|
88
|
-
# Web root of the HTTP server.
|
89
|
-
attr_accessor :httpd_path
|
90
|
-
# If true, BetterCap::Network::Servers::DNSD will be enabled.
|
91
|
-
attr_accessor :dnsd
|
92
|
-
# The port to bind DNS server to.
|
93
|
-
attr_accessor :dnsd_port
|
94
|
-
# The host resolution file to use with the DNS server.
|
95
|
-
attr_accessor :dnsd_file
|
96
|
-
# If true, bettercap will check for updates then exit.
|
97
|
-
attr_accessor :check_updates
|
98
|
-
# If true, targets NBNS hostname resolution won't be performed.
|
99
|
-
attr_accessor :no_target_nbns
|
100
|
-
# If true, bettercap won't forward packets for any target, causing
|
101
|
-
# connections to be killed.
|
102
|
-
attr_accessor :kill
|
103
|
-
# If different than 0, this time will be used as a delay while sending packets.
|
104
|
-
attr_accessor :packet_throttle
|
105
|
-
|
106
|
-
# Create a BetterCap::Options class instance using the specified network interface.
|
107
|
-
def initialize( iface )
|
108
|
-
@gateway = nil
|
109
|
-
@iface = iface
|
110
|
-
@spoofer = 'ARP'
|
111
|
-
@half_duplex = false
|
112
|
-
@target = nil
|
113
|
-
@logfile = nil
|
114
|
-
@log_timestamp = false
|
115
|
-
@silent = false
|
116
|
-
@debug = false
|
117
|
-
@arpcache = false
|
118
|
-
@no_target_nbns = false
|
119
|
-
@kill = false
|
120
|
-
@packet_throttle = 0.0
|
121
|
-
@http_ports = [ 80 ]
|
122
|
-
@https_ports = [ 443 ]
|
123
|
-
@ignore = nil
|
124
|
-
|
125
|
-
@dnsd = false
|
126
|
-
@dnsd_port = 5300
|
127
|
-
@dnsd_file = nil
|
128
|
-
|
129
|
-
@sniffer = false
|
130
|
-
@sniffer_pcap = nil
|
131
|
-
@sniffer_filter = nil
|
132
|
-
@sniffer_src = nil
|
133
|
-
@parsers = ['*']
|
134
|
-
@custom_parser = nil
|
135
|
-
@local = false
|
136
|
-
|
137
|
-
@proxy = false
|
138
|
-
@proxy_https = false
|
139
|
-
@proxy_port = 8080
|
140
|
-
@proxy_https_port = 8083
|
141
|
-
@proxy_pem_file = nil
|
142
|
-
@proxy_module = nil
|
143
|
-
|
144
|
-
@custom_proxy = nil
|
145
|
-
@custom_proxy_port = 8080
|
146
|
-
|
147
|
-
@custom_https_proxy = nil
|
148
|
-
@custom_https_proxy_port = 8083
|
149
|
-
|
150
|
-
@custom_redirections = []
|
151
|
-
|
152
|
-
@sslstrip = true
|
153
|
-
|
154
|
-
@httpd = false
|
155
|
-
@httpd_port = 8081
|
156
|
-
@httpd_path = './'
|
157
|
-
|
158
|
-
@check_updates = false
|
159
|
-
end
|
160
|
-
|
161
|
-
# Initialize the BetterCap::Context, parse command line arguments and update program
|
162
|
-
# state accordingly.
|
163
|
-
# Will rise a BetterCap::Error if errors occurred.
|
164
|
-
def self.parse!
|
165
|
-
ctx = Context.get
|
166
|
-
|
167
|
-
OptionParser.new do |opts|
|
168
|
-
opts.version = BetterCap::VERSION
|
169
|
-
opts.banner = "Usage: bettercap [options]"
|
170
|
-
opts.separator ""
|
171
|
-
opts.separator "Specific options:"
|
172
|
-
opts.separator ""
|
173
|
-
|
174
|
-
opts.on( '-G', '--gateway ADDRESS', 'Manually specify the gateway address, if not specified the current gateway will be retrieved and used. ' ) do |v|
|
175
|
-
ctx.options.gateway = v
|
176
|
-
end
|
177
|
-
|
178
|
-
opts.on( '-I', '--interface IFACE', 'Network interface name - default: ' + ctx.options.iface.to_s.yellow ) do |v|
|
179
|
-
ctx.options.iface = v
|
180
|
-
end
|
181
|
-
|
182
|
-
opts.on( '-S', '--spoofer NAME', "Spoofer module to use, available: #{Spoofers::Base.available.map{|x| x.yellow }.join(', ')} - default: #{ctx.options.spoofer.yellow}." ) do |v|
|
183
|
-
ctx.options.spoofer = v
|
184
|
-
end
|
185
|
-
|
186
|
-
opts.on( '-T', '--target ADDRESS1,ADDRESS2', 'Target IP addresses, if not specified the whole subnet will be targeted.' ) do |v|
|
187
|
-
ctx.options.target = v
|
188
|
-
end
|
189
|
-
|
190
|
-
opts.on( '--ignore ADDRESS1,ADDRESS2', 'Ignore these addresses if found while searching for targets.' ) do |v|
|
191
|
-
ctx.options.parse_ignore!(v)
|
192
|
-
end
|
193
|
-
|
194
|
-
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|
|
195
|
-
ctx.options.logfile = v
|
196
|
-
end
|
197
|
-
|
198
|
-
opts.on( '--log-timestamp', 'Enable logging with timestamps for each line, disabled by default.' ) do
|
199
|
-
ctx.options.log_timestamp = true
|
200
|
-
end
|
201
|
-
|
202
|
-
opts.on( '-D', '--debug', 'Enable debug logging.' ) do
|
203
|
-
ctx.options.debug = true
|
204
|
-
end
|
205
|
-
|
206
|
-
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
|
207
|
-
ctx.options.local = true
|
208
|
-
ctx.options.sniffer = true
|
209
|
-
end
|
210
|
-
|
211
|
-
opts.on( '-X', '--sniffer', 'Enable sniffer.' ) do
|
212
|
-
ctx.options.sniffer = true
|
213
|
-
end
|
214
|
-
|
215
|
-
opts.on( '--sniffer-source FILE', 'Load packets from the specified PCAP file instead of the interface ( will enable sniffer ).' ) do |v|
|
216
|
-
ctx.options.sniffer = true
|
217
|
-
ctx.options.sniffer_src = File.expand_path v
|
218
|
-
end
|
219
|
-
|
220
|
-
opts.on( '--sniffer-pcap FILE', 'Save all packets to the specified PCAP file ( will enable sniffer ).' ) do |v|
|
221
|
-
ctx.options.sniffer = true
|
222
|
-
ctx.options.sniffer_pcap = File.expand_path v
|
223
|
-
end
|
224
|
-
|
225
|
-
opts.on( '--sniffer-filter EXPRESSION', 'Configure the sniffer to use this BPF filter ( will enable sniffer ).' ) do |v|
|
226
|
-
ctx.options.sniffer = true
|
227
|
-
ctx.options.sniffer_filter = v
|
228
|
-
end
|
229
|
-
|
230
|
-
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|
|
231
|
-
ctx.options.sniffer = true
|
232
|
-
ctx.options.parsers = Parsers::Base.from_cmdline(v)
|
233
|
-
end
|
234
|
-
|
235
|
-
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|
|
236
|
-
ctx.options.sniffer = true
|
237
|
-
ctx.options.parsers = ['CUSTOM']
|
238
|
-
ctx.options.custom_parser = Regexp.new(v)
|
239
|
-
end
|
240
|
-
|
241
|
-
opts.on( '--silent', "Suppress every message which is not an error or a warning, default to #{'false'.yellow}." ) do
|
242
|
-
ctx.options.silent = true
|
243
|
-
end
|
244
|
-
|
245
|
-
opts.on( '--no-discovery', "Do not actively search for hosts, just use the current ARP cache, default to #{'false'.yellow}." ) do
|
246
|
-
ctx.options.arpcache = true
|
247
|
-
end
|
248
|
-
|
249
|
-
opts.on( '--no-spoofing', "Disable spoofing, alias for #{'--spoofer NONE'.yellow}." ) do
|
250
|
-
ctx.options.spoofer = 'NONE'
|
251
|
-
end
|
252
|
-
|
253
|
-
opts.on( '--no-target-nbns', 'Disable target NBNS hostname resolution.' ) do
|
254
|
-
ctx.options.no_target_nbns = true
|
255
|
-
end
|
256
|
-
|
257
|
-
opts.on( '--half-duplex', 'Enable half-duplex MITM, this will make bettercap work in those cases when the router is not vulnerable.' ) do
|
258
|
-
ctx.options.half_duplex = true
|
259
|
-
end
|
260
|
-
|
261
|
-
opts.on( '--proxy', "Enable HTTP proxy and redirects all HTTP requests to it, default to #{'false'.yellow}." ) do
|
262
|
-
ctx.options.proxy = true
|
263
|
-
end
|
264
|
-
|
265
|
-
opts.on( '--proxy-https', "Enable HTTPS proxy and redirects all HTTPS requests to it, default to #{'false'.yellow}." ) do
|
266
|
-
ctx.options.proxy_https = true
|
267
|
-
end
|
268
|
-
|
269
|
-
opts.on( '--proxy-port PORT', "Set HTTP proxy port, default to #{ctx.options.proxy_port.to_s.yellow}." ) do |v|
|
270
|
-
ctx.options.proxy = true
|
271
|
-
ctx.options.proxy_port = v.to_i
|
272
|
-
end
|
273
|
-
|
274
|
-
opts.on( '--http-ports PORT1,PORT2', "Comma separated list of HTTP ports to redirect to the proxy, default to #{ctx.options.http_ports.map{|x| x.to_s.yellow }.join(', ')}." ) do |v|
|
275
|
-
ctx.options.http_ports = ctx.options.parse_ports( v )
|
276
|
-
end
|
277
|
-
|
278
|
-
opts.on( '--https-ports PORT1,PORT2', "Comma separated list of HTTPS ports to redirect to the proxy, default to #{ctx.options.https_ports.map{|x| x.to_s.yellow }.join(', ')}." ) do |v|
|
279
|
-
ctx.options.https_ports = ctx.options.parse_ports( v )
|
280
|
-
end
|
281
|
-
|
282
|
-
opts.on( '--proxy-https-port PORT', "Set HTTPS proxy port, default to #{ctx.options.proxy_https_port.to_s.yellow}." ) do |v|
|
283
|
-
ctx.options.proxy_https = true
|
284
|
-
ctx.options.proxy_https_port = v.to_i
|
285
|
-
end
|
286
|
-
|
287
|
-
opts.on( '--proxy-pem FILE', "Use a custom PEM CA certificate file for the HTTPS proxy, default to #{Proxy::SSL::Authority::DEFAULT.yellow} ." ) do |v|
|
288
|
-
ctx.options.proxy_https = true
|
289
|
-
ctx.options.proxy_pem_file = File.expand_path v
|
290
|
-
end
|
291
|
-
|
292
|
-
opts.on( '--proxy-module MODULE', "Ruby proxy module to load, either a custom file or one of the following: #{Proxy::Module.available.map{|x| x.yellow}.join(', ')}." ) do |v|
|
293
|
-
Proxy::Module.load(ctx, opts, v)
|
294
|
-
end
|
295
|
-
|
296
|
-
opts.on( '--custom-proxy ADDRESS', 'Use a custom HTTP upstream proxy instead of the builtin one.' ) do |v|
|
297
|
-
ctx.options.parse_custom_proxy!(v)
|
298
|
-
end
|
299
|
-
|
300
|
-
opts.on( '--custom-proxy-port PORT', "Specify a port for the custom HTTP upstream proxy, default to #{ctx.options.custom_proxy_port.to_s.yellow}." ) do |v|
|
301
|
-
ctx.options.custom_proxy_port = v.to_i
|
302
|
-
end
|
303
|
-
|
304
|
-
opts.on( '--no-sslstrip', 'Disable SSLStrip.' ) do
|
305
|
-
ctx.options.sslstrip = false
|
306
|
-
end
|
307
|
-
|
308
|
-
opts.on( '--custom-https-proxy ADDRESS', 'Use a custom HTTPS upstream proxy instead of the builtin one.' ) do |v|
|
309
|
-
ctx.options.parse_custom_proxy!( v, true )
|
310
|
-
end
|
311
|
-
|
312
|
-
opts.on( '--custom-https-proxy-port PORT', "Specify a port for the custom HTTPS upstream proxy, default to #{ctx.options.custom_https_proxy_port.to_s.yellow}." ) do |v|
|
313
|
-
ctx.options.custom_https_proxy_port = v.to_i
|
314
|
-
end
|
315
|
-
|
316
|
-
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|
|
317
|
-
ctx.options.parse_redirection!( v )
|
318
|
-
end
|
319
|
-
|
320
|
-
opts.on( '--httpd', "Enable HTTP server, default to #{'false'.yellow}." ) do
|
321
|
-
ctx.options.httpd = true
|
322
|
-
end
|
323
|
-
|
324
|
-
opts.on( '--httpd-port PORT', "Set HTTP server port, default to #{ctx.options.httpd_port.to_s.yellow}." ) do |v|
|
325
|
-
ctx.options.httpd = true
|
326
|
-
ctx.options.httpd_port = v.to_i
|
327
|
-
end
|
328
|
-
|
329
|
-
opts.on( '--dns FILE', 'Enable DNS server and use this file as a hosts resolution table.' ) do |v|
|
330
|
-
ctx.options.dnsd = true
|
331
|
-
ctx.options.dnsd_file = File.expand_path v
|
332
|
-
end
|
333
|
-
|
334
|
-
opts.on( '--dns-port PORT', "Set DNS server port, default to #{ctx.options.dnsd_port.to_s.yellow}." ) do |v|
|
335
|
-
ctx.options.dnsd_port = v.to_i
|
336
|
-
end
|
337
|
-
|
338
|
-
opts.on( '--httpd-path PATH', "Set HTTP server path, default to #{ctx.options.httpd_path.yellow} ." ) do |v|
|
339
|
-
ctx.options.httpd = true
|
340
|
-
ctx.options.httpd_path = v
|
341
|
-
end
|
342
|
-
|
343
|
-
opts.on( '--kill', 'Instead of forwarding packets, this switch will make targets connections to be killed.' ) do
|
344
|
-
ctx.options.kill = true
|
345
|
-
end
|
346
|
-
|
347
|
-
opts.on( '--packet-throttle NUMBER', 'Number of seconds ( can be a decimal number ) to wait between each packet to be sent.' ) do |v|
|
348
|
-
ctx.options.packet_throttle = v.to_f
|
349
|
-
raise BetterCap::Error, "Invalid packet throttle value specified." if ctx.options.packet_throttle <= 0.0
|
350
|
-
end
|
351
|
-
|
352
|
-
opts.on( '--check-updates', 'Will check if any update is available and then exit.' ) do
|
353
|
-
ctx.options.check_updates = true
|
354
|
-
end
|
355
|
-
|
356
|
-
opts.on('-h', '--help', 'Display the available options.') do
|
357
|
-
puts opts
|
358
|
-
puts "\nFor examples & docs please visit " + "http://bettercap.org/docs/".bold
|
359
|
-
exit
|
360
|
-
end
|
361
|
-
end.parse!
|
362
|
-
|
363
|
-
Logger.init( ctx.options.debug, ctx.options.logfile, ctx.options.silent, ctx.options.log_timestamp )
|
364
|
-
|
365
|
-
if ctx.options.check_updates
|
366
|
-
UpdateChecker.check
|
367
|
-
exit
|
368
|
-
end
|
369
|
-
|
370
|
-
raise BetterCap::Error, 'This software must run as root.' unless Process.uid == 0
|
371
|
-
raise BetterCap::Error, 'No default interface found, please specify one with the -I argument.' if ctx.options.iface.nil?
|
372
|
-
|
373
|
-
ctx.options.starting_message
|
374
|
-
|
375
|
-
if ctx.options.sslstrip and ctx.options.dnsd
|
376
|
-
raise BetterCap::Error, "SSL Stripping and builtin DNS server are mutually exclusive features, " \
|
377
|
-
"either use the --no-sslstrip option or remove the --dns option."
|
378
|
-
end
|
379
|
-
|
380
|
-
if ctx.options.has_proxy_module? and ( !ctx.options.proxy and !ctx.options.proxy_https )
|
381
|
-
raise BetterCap::Error, "A proxy module was specified but none of the HTTP or HTTPS proxies are " \
|
382
|
-
"enabled, specify --proxy or --proxy-https options."
|
383
|
-
end
|
384
|
-
|
385
|
-
unless ctx.options.gateway.nil?
|
386
|
-
raise BetterCap::Error, "The specified gateway '#{ctx.options.gateway}' is not a valid IPv4 address." unless Network::Validator.is_ip?(ctx.options.gateway)
|
387
|
-
ctx.gateway = ctx.options.gateway
|
388
|
-
Logger.debug("Targetting manually specified gateway #{ctx.gateway}")
|
389
|
-
end
|
390
|
-
|
391
|
-
unless ctx.options.target.nil?
|
392
|
-
ctx.targets = ctx.options.parse_targets
|
393
|
-
end
|
394
|
-
|
395
|
-
# Load firewall instance, network interface informations and detect the
|
396
|
-
# gateway address.
|
397
|
-
ctx.update!
|
398
|
-
|
399
|
-
# Spoofers need the context network data to be initialized.
|
400
|
-
ctx.spoofer = ctx.options.parse_spoofers
|
401
|
-
|
402
|
-
ctx
|
403
|
-
end
|
404
|
-
|
405
|
-
# Return true if active host discovery is enabled, otherwise false.
|
406
|
-
def should_discover_hosts?
|
407
|
-
!@arpcache
|
408
|
-
end
|
409
|
-
|
410
|
-
# Return true if a proxy module was specified, otherwise false.
|
411
|
-
def has_proxy_module?
|
412
|
-
!@proxy_module.nil?
|
413
|
-
end
|
414
|
-
|
415
|
-
# Return true if a spoofer module was specified, otherwise false.
|
416
|
-
def has_spoofer?
|
417
|
-
@spoofer != 'NONE' and @spoofer != 'none'
|
418
|
-
end
|
419
|
-
|
420
|
-
# Return true if the BetterCap::Parsers::URL is enabled, otherwise false.
|
421
|
-
def has_http_sniffer_enabled?
|
422
|
-
@sniffer and ( @parsers.include?'*' or @parsers.include?'URL' )
|
423
|
-
end
|
424
|
-
|
425
|
-
# Return true if the +ip+ address needs to be ignored, otherwise false.
|
426
|
-
def ignore_ip?(ip)
|
427
|
-
!@ignore.nil? and @ignore.include?(ip)
|
428
|
-
end
|
429
|
-
|
430
|
-
# Parsing Routines
|
431
|
-
|
432
|
-
# Setter for the #ignore attribute, will raise a BetterCap::Error if one
|
433
|
-
# or more invalid IP addresses are specified.
|
434
|
-
def parse_ignore!(value)
|
435
|
-
@ignore = value.split(",")
|
436
|
-
valid = @ignore.select { |target| Network::Validator.is_ip?(target) }
|
437
|
-
|
438
|
-
raise BetterCap::Error, "Invalid ignore addresses specified." if valid.empty?
|
439
|
-
|
440
|
-
invalid = @ignore - valid
|
441
|
-
invalid.each do |target|
|
442
|
-
Logger.warn "Not a valid address: #{target}"
|
443
|
-
end
|
444
|
-
|
445
|
-
@ignore = valid
|
446
|
-
|
447
|
-
Logger.warn "Ignoring #{valid.join(", ")} ."
|
448
|
-
end
|
449
|
-
|
450
|
-
# Setter for the #custom_proxy or #custom_https_proxy attribute, will raise a
|
451
|
-
# BetterCap::Error if +value+ is not a valid IP address.
|
452
|
-
def parse_custom_proxy!(value, https=false)
|
453
|
-
raise BetterCap::Error, 'Invalid custom HTTP upstream proxy address specified.' unless Network::Validator.is_ip?(value)
|
454
|
-
if https
|
455
|
-
@custom_https_proxy = value
|
456
|
-
else
|
457
|
-
@custom_proxy = value
|
458
|
-
end
|
459
|
-
end
|
460
|
-
|
461
|
-
# Parse a custom redirection rule.
|
462
|
-
def parse_redirection!(rule)
|
463
|
-
if rule =~ /^((TCP)|(UDP))\s+(\d+)\s+(\d+)$/i
|
464
|
-
@custom_redirections << {
|
465
|
-
:proto => $1.upcase,
|
466
|
-
:from => $4.to_i,
|
467
|
-
:to => $5.to_i
|
468
|
-
}
|
469
|
-
else
|
470
|
-
raise BetterCap::Error, 'Invalid custom redirection rule specified.'
|
471
|
-
end
|
472
|
-
end
|
473
|
-
|
474
|
-
# Parse a comma separated list of ports and return an array containing only
|
475
|
-
# valid ports, raise BetterCap::Error if that array is empty.
|
476
|
-
def parse_ports(value)
|
477
|
-
ports = []
|
478
|
-
value.split(",").each do |v|
|
479
|
-
v = v.strip.to_i
|
480
|
-
if v > 0 and v <= 65535
|
481
|
-
ports << v
|
482
|
-
end
|
483
|
-
end
|
484
|
-
raise BetterCap::Error, 'Invalid ports specified.' if ports.empty?
|
485
|
-
ports
|
486
|
-
end
|
487
|
-
|
488
|
-
# Split specified targets and parse them ( either as IP or MAC ), will raise a
|
489
|
-
# BetterCap::Error if one or more invalid addresses are specified.
|
490
|
-
def parse_targets
|
491
|
-
valid = []
|
492
|
-
targets = @target.split(",")
|
493
|
-
|
494
|
-
targets.each do |t|
|
495
|
-
if Network::Validator.is_ip?(t) or Network::Validator.is_mac?(t)
|
496
|
-
valid << Network::Target.new(t)
|
497
|
-
|
498
|
-
elsif Network::Validator.is_range?(t)
|
499
|
-
Network::Validator.each_in_range( t ) do |address|
|
500
|
-
valid << Network::Target.new(address)
|
501
|
-
end
|
502
|
-
|
503
|
-
elsif Network::Validator.is_netmask?(t)
|
504
|
-
Network::Validator.each_in_netmask(t) do |address|
|
505
|
-
valid << Network::Target.new(address)
|
506
|
-
end
|
507
|
-
|
508
|
-
else
|
509
|
-
raise BetterCap::Error, "Invalid target specified '#{t}', valid formats are IP addresses, "\
|
510
|
-
"MAC addresses, IP ranges ( 192.168.1.1-30 ) or netmasks ( 192.168.1.1/24 ) ."
|
511
|
-
end
|
512
|
-
end
|
513
|
-
|
514
|
-
valid
|
515
|
-
end
|
516
|
-
|
517
|
-
# Parse spoofers and return a list of BetterCap::Spoofers objects. Raise a
|
518
|
-
# BetterCap::Error if an invalid spoofer name was specified.
|
519
|
-
def parse_spoofers
|
520
|
-
spoofers = []
|
521
|
-
@spoofer.split(",").each do |module_name|
|
522
|
-
spoofers << Spoofers::Base.get_by_name( module_name )
|
523
|
-
end
|
524
|
-
spoofers
|
525
|
-
end
|
526
|
-
|
527
|
-
# Helper method to create a Firewalls::Redirection object.
|
528
|
-
def redir( address, port, to, proto = 'TCP' )
|
529
|
-
Firewalls::Redirection.new( @iface, proto, port, address, to )
|
530
|
-
end
|
531
|
-
|
532
|
-
# Create a list of BetterCap::Firewalls::Redirection objects which are needed
|
533
|
-
# given the specified command line arguments.
|
534
|
-
def get_redirections ifconfig
|
535
|
-
redirections = []
|
536
|
-
|
537
|
-
if @dnsd or ( @proxy and @sslstrip )
|
538
|
-
redirections << redir( ifconfig[:ip_saddr], 53, @dnsd_port )
|
539
|
-
redirections << redir( ifconfig[:ip_saddr], 53, @dnsd_port, 'UDP' )
|
540
|
-
end
|
541
|
-
|
542
|
-
if @proxy
|
543
|
-
@http_ports.each do |port|
|
544
|
-
redirections << redir( ifconfig[:ip_saddr], port, @proxy_port )
|
545
|
-
end
|
546
|
-
end
|
547
|
-
|
548
|
-
if @proxy_https
|
549
|
-
@https_ports.each do |port|
|
550
|
-
redirections << redir( ifconfig[:ip_saddr], port, @proxy_https_port )
|
551
|
-
end
|
552
|
-
end
|
553
|
-
|
554
|
-
if @custom_proxy
|
555
|
-
@http_ports.each do |port|
|
556
|
-
redirections << redir( @custom_proxy, port, @custom_proxy_port )
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
if @custom_https_proxy
|
561
|
-
@https_ports.each do |port|
|
562
|
-
redirections << redir( @custom_https_proxy, port, @custom_https_proxy_port )
|
563
|
-
end
|
564
|
-
end
|
565
|
-
|
566
|
-
@custom_redirections.each do |r|
|
567
|
-
redirections << redir( ifconfig[:ip_saddr], r[:from], r[:to], r[:proto] )
|
568
|
-
end
|
569
|
-
|
570
|
-
redirections
|
571
|
-
end
|
572
|
-
|
573
|
-
# Print the starting status message.
|
574
|
-
def starting_message
|
575
|
-
on = '✔'.green
|
576
|
-
off = '✘'.red
|
577
|
-
status = {
|
578
|
-
'spoofing' => ( has_spoofer? ? on : off ),
|
579
|
-
'discovery' => ( ( !target.nil? or arpcache ) ? off : on ),
|
580
|
-
'sniffer' => ( sniffer ? on : off ),
|
581
|
-
'http-proxy' => ( proxy ? on : off ),
|
582
|
-
'https-proxy' => ( proxy_https ? on : off ),
|
583
|
-
'sslstrip' => ( ( proxy and sslstrip ) ? on : off ),
|
584
|
-
'http-server' => ( httpd ? on : off ),
|
585
|
-
'dns-server' => ( ( ( proxy and sslstrip ) or dnsd ) ? on : off )
|
586
|
-
}
|
587
|
-
|
588
|
-
msg = "Starting [ "
|
589
|
-
status.each do |k,v|
|
590
|
-
msg += "#{k}:#{v} "
|
591
|
-
end
|
592
|
-
msg += "] ...\n\n"
|
593
|
-
|
594
|
-
Logger.info msg
|
595
|
-
|
596
|
-
Logger.warn "You are running an unstable/beta version of this software, please" \
|
597
|
-
" update to a stable one if available." if BetterCap::VERSION =~ /[\d\.+]b/
|
598
|
-
end
|
599
|
-
end
|
600
|
-
end
|