xettercap 1.5.7xerob
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 +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
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: bbfc85fac2603c848498feb4a8acd1ea7bba9ebecfbf22b053b374138db3a272
|
|
4
|
+
data.tar.gz: f45da6057ca6f78421932054270e47258643d68905d632d438e09c8874b637b7
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: b24afaa692025254897bd1aaa78759847f86e5a55d2b49507bd779965fc286a6d8298b26e44569ac6ce42b6cf739134116ee4678c6c589896a67a32cb9554ce8
|
|
7
|
+
data.tar.gz: 3615020fca5dff0349202c8355becf5fccc507edec430a6289c890221c439aea00f6aff6fc88f3caff9d23a5ef57d8f91541b341a8cf504d1bc98ac1a354b92d
|
data/bin/xettercap
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
=begin
|
|
5
|
+
|
|
6
|
+
BETTERCAP
|
|
7
|
+
|
|
8
|
+
Author : Simone 'evilsocket' Margaritelli
|
|
9
|
+
Email : evilsocket@gmail.com
|
|
10
|
+
Blog : http://www.evilsocket.net/
|
|
11
|
+
|
|
12
|
+
This project is released under the GPL 3 license.
|
|
13
|
+
|
|
14
|
+
=end
|
|
15
|
+
|
|
16
|
+
require 'bettercap'
|
|
17
|
+
begin
|
|
18
|
+
|
|
19
|
+
# We need this in order to report unhandled exceptions.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Create global context, parse command line arguments and perform basic
|
|
23
|
+
# error checking.
|
|
24
|
+
ctx = BetterCap::Options.parse!
|
|
25
|
+
|
|
26
|
+
ctx.start!
|
|
27
|
+
|
|
28
|
+
loop do
|
|
29
|
+
sleep 10
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
rescue SystemExit, Interrupt, SignalException
|
|
33
|
+
BetterCap::Logger.raw "\n"
|
|
34
|
+
|
|
35
|
+
rescue OptionParser::InvalidOption,
|
|
36
|
+
OptionParser::AmbiguousOption,
|
|
37
|
+
OptionParser::MissingArgument => e
|
|
38
|
+
BetterCap::Logger.error "'#{e.message.capitalize}', verify your command line arguments executing 'bettercap --help'."
|
|
39
|
+
|
|
40
|
+
rescue BetterCap::Error => e
|
|
41
|
+
BetterCap::Logger.error e.message
|
|
42
|
+
|
|
43
|
+
rescue Exception => e
|
|
44
|
+
puts "\n\n"
|
|
45
|
+
BetterCap::Logger.error "Oooops, seems like something weird occurred, please copy paste the following output " \
|
|
46
|
+
"and open a new issue on https://github.com/evilsocket/bettercap/issues :\n"
|
|
47
|
+
|
|
48
|
+
BetterCap::Logger.error "Platform : #{RUBY_PLATFORM}"
|
|
49
|
+
BetterCap::Logger.error "Ruby Version : #{RUBY_VERSION}"
|
|
50
|
+
BetterCap::Logger.error "BetterCap Version : #{BetterCap::VERSION}"
|
|
51
|
+
BetterCap::Logger.error "Command Line : #{original_argv.join(" ")}"
|
|
52
|
+
BetterCap::Logger.error "Exception : #{e.class}"
|
|
53
|
+
BetterCap::Logger.error "Message : #{e.message}"
|
|
54
|
+
BetterCap::Logger.error "Backtrace :\n\n #{e.backtrace.join("\n ")}\n"
|
|
55
|
+
|
|
56
|
+
ensure
|
|
57
|
+
# Make sure all the messages on the logger queue are printed.
|
|
58
|
+
BetterCap::Logger.wait!
|
|
59
|
+
|
|
60
|
+
ctx.finalize unless ctx.nil?
|
|
61
|
+
end
|
|
@@ -0,0 +1,259 @@
|
|
|
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
|
+
# This class holds global states and data, moreover it exposes high level
|
|
16
|
+
# methods to manipulate the program behaviour.
|
|
17
|
+
class Context
|
|
18
|
+
# Instance of BetterCap::Options class.
|
|
19
|
+
attr_accessor :options
|
|
20
|
+
# Instance of the current BetterCap::Firewalls class.
|
|
21
|
+
attr_accessor :firewall
|
|
22
|
+
# Local interface ( as an instance of BetterCap::Network::Target ).
|
|
23
|
+
attr_accessor :iface
|
|
24
|
+
# Network gateway ( as an instance of BetterCap::Network::Target ).
|
|
25
|
+
attr_accessor :gateway
|
|
26
|
+
# A list of BetterCap::Target objects which is periodically updated.
|
|
27
|
+
attr_accessor :targets
|
|
28
|
+
# Instance of BetterCap::Discovery::Thread class.
|
|
29
|
+
attr_accessor :discovery
|
|
30
|
+
# A list of BetterCap::Spoofers class instances.
|
|
31
|
+
attr_accessor :spoofer
|
|
32
|
+
# Instance of BetterCap::Network::Servers::HTTPD class.
|
|
33
|
+
attr_accessor :httpd
|
|
34
|
+
# Instance of BetterCap::Network::Servers::DNSD class.
|
|
35
|
+
attr_accessor :dnsd
|
|
36
|
+
# Set to true if the program is running, to false if a shutdown was
|
|
37
|
+
# scheduled by the user which pressed CTRL+C
|
|
38
|
+
attr_accessor :running
|
|
39
|
+
# Timeout for discovery operations.
|
|
40
|
+
attr_reader :timeout
|
|
41
|
+
# Instance of BetterCap::PacketQueue.
|
|
42
|
+
attr_reader :packets
|
|
43
|
+
# Instance of BetterCap::Memory.
|
|
44
|
+
attr_reader :memory
|
|
45
|
+
|
|
46
|
+
@@instance = nil
|
|
47
|
+
|
|
48
|
+
# Return the global instance of the program Context, if the instance
|
|
49
|
+
# was not yet created it will be initialized and returned.
|
|
50
|
+
def self.get
|
|
51
|
+
@@instance ||= self.new
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Initialize the global context object.
|
|
55
|
+
def initialize
|
|
56
|
+
begin
|
|
57
|
+
iface = PCAPRUB::Pcap.lookupdev
|
|
58
|
+
rescue Exception => e
|
|
59
|
+
iface = nil
|
|
60
|
+
Logger.exception e
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
@running = true
|
|
64
|
+
@timeout = 5
|
|
65
|
+
@options = Options.new iface
|
|
66
|
+
@discovery = Discovery::Thread.new self
|
|
67
|
+
@firewall = Firewalls::Base.get
|
|
68
|
+
@memory = Memory.new
|
|
69
|
+
@iface = nil
|
|
70
|
+
@original_mac = nil
|
|
71
|
+
@gateway = nil
|
|
72
|
+
@targets = []
|
|
73
|
+
@spoofer = nil
|
|
74
|
+
@httpd = nil
|
|
75
|
+
@dnsd = nil
|
|
76
|
+
@proxies = []
|
|
77
|
+
@redirections = []
|
|
78
|
+
@packets = nil
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Update the Context state parsing network related informations.
|
|
82
|
+
def update!
|
|
83
|
+
gw = @options.core.gateway || Network.get_gateway
|
|
84
|
+
raise BetterCap::Error, "Could not detect the gateway address for interface #{@options.core.iface}, "\
|
|
85
|
+
'make sure you\'ve specified the correct network interface to use and to have the '\
|
|
86
|
+
'correct network configuration, this could also happen if bettercap '\
|
|
87
|
+
'is launched from a virtual environment.' unless Network::Validator.is_ip?(gw)
|
|
88
|
+
|
|
89
|
+
unless @options.core.use_mac.nil?
|
|
90
|
+
cfg = PacketFu::Utils.ifconfig @options.core.iface
|
|
91
|
+
raise BetterCap::Error, "Could not determine IPv4 address of '#{@options.core.iface}', make sure this interface "\
|
|
92
|
+
'is active and connected.' if cfg[:ip4_obj].nil?
|
|
93
|
+
|
|
94
|
+
@original_mac = Network::Target.normalized_mac(cfg[:eth_saddr])
|
|
95
|
+
|
|
96
|
+
Logger.info "Changing interface MAC address to #{@options.core.use_mac}"
|
|
97
|
+
|
|
98
|
+
Shell.ifconfig( "#{@options.core.iface} ether #{@options.core.use_mac}")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
cfg = PacketFu::Utils.ifconfig @options.core.iface
|
|
102
|
+
raise BetterCap::Error, "Could not determine IPv4 address of '#{@options.core.iface}', make sure this interface "\
|
|
103
|
+
'is active and connected.' if cfg[:ip4_obj].nil?
|
|
104
|
+
|
|
105
|
+
@gateway = Network::Target.new gw
|
|
106
|
+
@targets = @options.core.targets unless @options.core.targets.nil?
|
|
107
|
+
@iface = Network::Target.new( cfg[:ip_saddr], cfg[:eth_saddr], cfg[:ip4_obj], cfg[:iface] )
|
|
108
|
+
|
|
109
|
+
###Logger.info "[#{@iface.name.green}] #{@iface.to_s(false)}"
|
|
110
|
+
|
|
111
|
+
Logger.debug '----- NETWORK INFORMATIONS -----'
|
|
112
|
+
Logger.debug " network = #{@iface.network} ( #{@iface.network.to_range.to_s.split('..').join( ' -> ')} )"
|
|
113
|
+
Logger.debug " gateway = #{@gateway.ip}"
|
|
114
|
+
Logger.debug " local_ip = #{@iface.ip}"
|
|
115
|
+
Logger.debug "--------------------------------\n"
|
|
116
|
+
|
|
117
|
+
@packets = Network::PacketQueue.new( @iface.name, @options.core.packet_throttle, 4 )
|
|
118
|
+
# Spoofers need the context network data to be initialized.
|
|
119
|
+
@spoofer = @options.spoof.parse_spoofers
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Find a target given its +ip+ and +mac+ addresses inside the #targets
|
|
123
|
+
# list, if not found return nil.
|
|
124
|
+
def find_target ip, mac
|
|
125
|
+
@targets.each do |target|
|
|
126
|
+
if target.equals?(ip,mac)
|
|
127
|
+
return target
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
nil
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Start everything!
|
|
134
|
+
def start!
|
|
135
|
+
# Start targets auto discovery.
|
|
136
|
+
@discovery.start
|
|
137
|
+
|
|
138
|
+
# Start network spoofers if any.
|
|
139
|
+
@spoofer.each do |spoofer|
|
|
140
|
+
spoofer.start
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Start proxies and setup port redirection.
|
|
144
|
+
if @options.proxies.any?
|
|
145
|
+
if ( @options.proxies.proxy or @options.proxies.proxy_https ) and @options.sniff.enabled?('URL')
|
|
146
|
+
BetterCap::Logger.warn "WARNING: Both HTTP transparent proxy and URL parser are enabled, you're gonna see duplicated logs."
|
|
147
|
+
end
|
|
148
|
+
create_proxies!
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
enable_port_redirection!
|
|
152
|
+
|
|
153
|
+
create_servers!
|
|
154
|
+
|
|
155
|
+
# Start network sniffer.
|
|
156
|
+
if @options.sniff.enabled?
|
|
157
|
+
Sniffer.start self
|
|
158
|
+
elsif @options.spoof.enabled? and !@options.proxies.any?
|
|
159
|
+
Logger.warn 'WARNING: Sniffer module was NOT enabled ( -X argument ), this '\
|
|
160
|
+
'will cause the MITM to run but no data to be collected.'
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Stop every running daemon that was started and reset system state.
|
|
165
|
+
def finalize
|
|
166
|
+
@running = false
|
|
167
|
+
|
|
168
|
+
# Logger is silent if @running == false
|
|
169
|
+
puts "\nStopping MITM attack ...\n"
|
|
170
|
+
|
|
171
|
+
Logger.debug 'Stopping target discovery manager ...'
|
|
172
|
+
@discovery.stop
|
|
173
|
+
|
|
174
|
+
Logger.debug 'Stopping spoofers ...'
|
|
175
|
+
@spoofer.each do |spoofer|
|
|
176
|
+
spoofer.stop
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Spoofer might be sending some last packets to restore the targets,
|
|
180
|
+
# the packet queue must be stopped here.
|
|
181
|
+
@packets.stop
|
|
182
|
+
|
|
183
|
+
Logger.debug 'Stopping proxies ...'
|
|
184
|
+
@proxies.each do |proxy|
|
|
185
|
+
proxy.stop
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
Logger.debug 'Disabling port redirections ...'
|
|
189
|
+
@redirections.each do |r|
|
|
190
|
+
@firewall.del_port_redirection( r )
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
Logger.debug 'Restoring firewall state ...'
|
|
194
|
+
@firewall.restore
|
|
195
|
+
|
|
196
|
+
@dnsd.stop unless @dnsd.nil?
|
|
197
|
+
@httpd.stop unless @httpd.nil?
|
|
198
|
+
|
|
199
|
+
Shell.ifconfig( "#{@options.core.iface} ether #{@original_mac}") unless @original_mac.nil?
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
private
|
|
203
|
+
|
|
204
|
+
# Apply needed BetterCap::Firewalls::Redirection objects.
|
|
205
|
+
def enable_port_redirection!
|
|
206
|
+
@redirections = @options.get_redirections(@iface)
|
|
207
|
+
@redirections.each do |r|
|
|
208
|
+
Logger.debug "Redirecting #{r.protocol} traffic from #{r.src_address.nil? ? '*' : r.src_address}:#{r.src_port} to #{r.dst_address}:#{r.dst_port}"
|
|
209
|
+
@firewall.add_port_redirection( r )
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Initialize the needed transparent proxies and the processor routined which
|
|
214
|
+
# is needed in order to run proxy modules.
|
|
215
|
+
def create_proxies!
|
|
216
|
+
if @options.proxies.has_proxy_module?
|
|
217
|
+
Proxy::HTTP::Module.register_modules
|
|
218
|
+
raise BetterCap::Error, "#{@options.proxies.proxy_module} is not a valid bettercap proxy module." if Proxy::HTTP::Module.modules.empty?
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# create HTTP proxy
|
|
222
|
+
if @options.proxies.proxy
|
|
223
|
+
@proxies << Proxy::HTTP::Proxy.new( @iface.ip, @options.proxies.proxy_port, false )
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# create HTTPS proxy
|
|
227
|
+
if @options.proxies.proxy_https
|
|
228
|
+
@proxies << Proxy::HTTP::Proxy.new( @iface.ip, @options.proxies.proxy_https_port, true )
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# create TCP proxy
|
|
232
|
+
if @options.proxies.tcp_proxy
|
|
233
|
+
@proxies << Proxy::TCP::Proxy.new( @iface.ip, @options.proxies.tcp_proxy_port, @options.proxies.tcp_proxy_upstream_address, @options.proxies.tcp_proxy_upstream_port )
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
@proxies.each do |proxy|
|
|
237
|
+
proxy.start
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Initialize and start the needed servers.
|
|
242
|
+
def create_servers!
|
|
243
|
+
# Start local DNS server.
|
|
244
|
+
if @options.servers.dnsd
|
|
245
|
+
Logger.warn "Starting DNS server with spoofing disabled, bettercap will only reply to local DNS queries." unless @options.spoof.enabled?
|
|
246
|
+
|
|
247
|
+
@dnsd = Network::Servers::DNSD.new( @options.servers.dnsd_file, @iface.ip, @options.servers.dnsd_port )
|
|
248
|
+
@dnsd.start
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Start local HTTP server.
|
|
252
|
+
if @options.servers.httpd
|
|
253
|
+
@httpd = Network::Servers::HTTPD.new( @options.servers.httpd_port, @options.servers.httpd_path )
|
|
254
|
+
@httpd.start
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
end
|
|
259
|
+
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
|
+
# Parse the ARP table searching for new hosts.
|
|
15
|
+
module BetterCap
|
|
16
|
+
module Discovery
|
|
17
|
+
module Agents
|
|
18
|
+
# Class responsible of sending ARP probes to each possible IP on the network.
|
|
19
|
+
class Arp < Discovery::Agents::Base
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# Build a PacketFu::ARPPacket instance for the specified +ip+ address.
|
|
23
|
+
def get_probe( ip )
|
|
24
|
+
pkt = PacketFu::ARPPacket.new
|
|
25
|
+
|
|
26
|
+
pkt.eth_saddr = pkt.arp_saddr_mac = @ctx.iface.mac
|
|
27
|
+
pkt.eth_daddr = 'ff:ff:ff:ff:ff:ff'
|
|
28
|
+
pkt.arp_daddr_mac = '00:00:00:00:00:00'
|
|
29
|
+
pkt.arp_saddr_ip = @ctx.iface.ip
|
|
30
|
+
pkt.arp_daddr_ip = ip.to_s
|
|
31
|
+
|
|
32
|
+
pkt
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
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
|
+
# Base class for discovery agents.
|
|
15
|
+
module BetterCap
|
|
16
|
+
module Discovery
|
|
17
|
+
module Agents
|
|
18
|
+
# Base class for BetterCap::Discovery::Agents.
|
|
19
|
+
class Base
|
|
20
|
+
# Initialize the agent using the +ctx+ BetterCap::Context instance.
|
|
21
|
+
# If +address+ is not nil only that ip will be probed.
|
|
22
|
+
def initialize( ctx, address = nil )
|
|
23
|
+
@ctx = ctx
|
|
24
|
+
@address = address
|
|
25
|
+
|
|
26
|
+
if @address.nil?
|
|
27
|
+
net = ip = @ctx.iface.network
|
|
28
|
+
# loop each ip in our subnet and push it to the queue
|
|
29
|
+
while net.include?ip
|
|
30
|
+
unless skip_address?(ip)
|
|
31
|
+
@ctx.packets.push( get_probe(ip) )
|
|
32
|
+
end
|
|
33
|
+
ip = ip.succ
|
|
34
|
+
end
|
|
35
|
+
else
|
|
36
|
+
if skip_address?(@address)
|
|
37
|
+
Logger.debug "Skipping #{@address} ..."
|
|
38
|
+
else
|
|
39
|
+
Logger.debug "Probing #{@address} ..."
|
|
40
|
+
@ctx.packets.push( get_probe(@address) )
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Return true if +ip+ must be skipped during discovery, otherwise false.
|
|
48
|
+
def skip_address?(ip)
|
|
49
|
+
# don't send probes to the gateway if we already have its MAC.
|
|
50
|
+
if ip == @ctx.gateway.ip
|
|
51
|
+
return !@ctx.gateway.mac.nil?
|
|
52
|
+
# don't send probes to our device
|
|
53
|
+
elsif ip == @ctx.iface.ip
|
|
54
|
+
return true
|
|
55
|
+
# don't stress endpoints we already discovered
|
|
56
|
+
else
|
|
57
|
+
target = @ctx.find_target( ip.to_s, nil )
|
|
58
|
+
# known target?
|
|
59
|
+
return false if target.nil?
|
|
60
|
+
# do we still need to get the mac for this target?
|
|
61
|
+
return ( target.mac.nil?? false : true )
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Each Discovery::Agent::Base derived class should implement this method.
|
|
67
|
+
def get_probe( ip )
|
|
68
|
+
Logger.warn "#{self.class.name}#get_probe not implemented!"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
# Send a broadcast ping trying to filling the ARP table.
|
|
15
|
+
module BetterCap
|
|
16
|
+
module Discovery
|
|
17
|
+
module Agents
|
|
18
|
+
# Class responsible to do a ping-sweep on the network.
|
|
19
|
+
class Icmp
|
|
20
|
+
# Create a thread which will perform a ping-sweep on the network in order
|
|
21
|
+
# to populate the ARP cache with active targets.
|
|
22
|
+
def initialize( ctx, address = nil )
|
|
23
|
+
Firewalls::Base.get.enable_icmp_bcast(true)
|
|
24
|
+
|
|
25
|
+
# TODO: Use the real broadcast address for this network.
|
|
26
|
+
3.times do
|
|
27
|
+
pkt = PacketFu::ICMPPacket.new
|
|
28
|
+
|
|
29
|
+
pkt.eth_saddr = ctx.iface.mac
|
|
30
|
+
pkt.eth_daddr = 'ff:ff:ff:ff:ff:ff'
|
|
31
|
+
pkt.ip_saddr = ctx.iface.ip
|
|
32
|
+
pkt.ip_daddr = '255.255.255.255'
|
|
33
|
+
pkt.icmp_type = 8
|
|
34
|
+
pkt.icmp_code = 0
|
|
35
|
+
pkt.payload = "ABCD"
|
|
36
|
+
pkt.recalc
|
|
37
|
+
|
|
38
|
+
ctx.packets.push(pkt)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
# Send UDP probes trying to filling the ARP table.
|
|
15
|
+
module BetterCap
|
|
16
|
+
module Discovery
|
|
17
|
+
module Agents
|
|
18
|
+
# Class responsible to send UDP probe packets to each possible IP on the network.
|
|
19
|
+
class Udp < Discovery::Agents::Base
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# Build an UDP packet for the specified +ip+ address.
|
|
23
|
+
def get_probe( ip )
|
|
24
|
+
# send dummy udp packet, just to fill ARP table
|
|
25
|
+
[ ip.to_s, 137, "\x10\x12\x85\x00\x00" ]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
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 Discovery
|
|
15
|
+
# Class responsible to actively discover targets on the network.
|
|
16
|
+
class Thread
|
|
17
|
+
# Initialize the class using the +ctx+ BetterCap::Context instance.
|
|
18
|
+
def initialize( ctx )
|
|
19
|
+
@ctx = ctx
|
|
20
|
+
@running = false
|
|
21
|
+
@thread = nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Start the active network discovery thread.
|
|
25
|
+
def start
|
|
26
|
+
@running = true
|
|
27
|
+
@thread = ::Thread.new { worker }
|
|
28
|
+
|
|
29
|
+
if @ctx.options.core.discovery?
|
|
30
|
+
###Logger.info "[#{'DISCOVERY'.green}] Targeting the whole subnet #{@ctx.iface.network.to_range} ..."
|
|
31
|
+
# give some time to the discovery thread to spawn its workers,
|
|
32
|
+
# this will prevent 'Too many open files' errors to delay host
|
|
33
|
+
# discovery.
|
|
34
|
+
sleep(1.5)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Stop the active network discovery thread.
|
|
39
|
+
def stop
|
|
40
|
+
@running = false
|
|
41
|
+
if @thread != nil
|
|
42
|
+
begin
|
|
43
|
+
@thread.exit
|
|
44
|
+
rescue
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
# Return true if the +list+ of targets includes +target+.
|
|
52
|
+
def list_include_target?( list, target )
|
|
53
|
+
list.each do |t|
|
|
54
|
+
if t.equals?(target.ip, target.mac)
|
|
55
|
+
return true
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Print informations about new and lost targets.
|
|
62
|
+
def print_differences( prev )
|
|
63
|
+
diff = { :new => [], :lost => [] }
|
|
64
|
+
|
|
65
|
+
@ctx.targets.each do |target|
|
|
66
|
+
unless list_include_target?( prev, target )
|
|
67
|
+
diff[:new] << target
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
prev.each do |target|
|
|
72
|
+
unless list_include_target?( @ctx.targets, target )
|
|
73
|
+
diff[:lost] << target
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
unless diff[:new].empty? and diff[:lost].empty?
|
|
78
|
+
if diff[:new].empty?
|
|
79
|
+
snew = ""
|
|
80
|
+
else
|
|
81
|
+
snew = "Acquired #{diff[:new].size} new target#{diff[:new].size > 1 ? "s" : ""}"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if diff[:lost].empty?
|
|
85
|
+
slost = ""
|
|
86
|
+
else
|
|
87
|
+
slost = "#{snew.empty?? 'L' : ', l'}ost #{diff[:lost].size} target#{diff[:lost].size > 1 ? "s" : ""}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
Logger.info "#{snew}#{slost} :"
|
|
91
|
+
|
|
92
|
+
msg = "\n"
|
|
93
|
+
diff[:new].each do |target|
|
|
94
|
+
msg += " [#{'NEW'.green}] #{target.to_s(false)}\n"
|
|
95
|
+
end
|
|
96
|
+
diff[:lost].each do |target|
|
|
97
|
+
msg += " [#{'LOST'.red}] #{target.to_s(false)}\n"
|
|
98
|
+
end
|
|
99
|
+
msg += "\n"
|
|
100
|
+
Logger.raw msg
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# This method implements the main discovery logic, it will be executed within
|
|
105
|
+
# the spawned thread.
|
|
106
|
+
def worker
|
|
107
|
+
Logger.debug( 'Network discovery thread started.' ) if @ctx.options.core.discovery?
|
|
108
|
+
|
|
109
|
+
prev = []
|
|
110
|
+
while @running
|
|
111
|
+
# No targets specified.
|
|
112
|
+
if @ctx.options.core.targets.nil?
|
|
113
|
+
@ctx.targets = Network.get_alive_targets(@ctx).sort_by {
|
|
114
|
+
|t| t.sortable_ip
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
print_differences( prev ) if @ctx.options.core.discovery?
|
|
119
|
+
|
|
120
|
+
prev = @ctx.targets
|
|
121
|
+
|
|
122
|
+
@ctx.memory.optimize!
|
|
123
|
+
sleep(1) if @ctx.options.core.discovery?
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
# Class used to distinghuish between handled and unhandled exceptions.
|
|
15
|
+
class Error < StandardError; end
|
|
16
|
+
end
|