bettercap 1.1.10 → 1.2.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/TODO.md +8 -7
- data/bin/bettercap +8 -2
- data/lib/bettercap.rb +5 -4
- data/lib/bettercap/context.rb +54 -8
- data/lib/bettercap/discovery/agents/arp.rb +17 -4
- data/lib/bettercap/discovery/agents/base.rb +16 -52
- data/lib/bettercap/discovery/agents/icmp.rb +25 -17
- data/lib/bettercap/discovery/agents/udp.rb +9 -20
- data/lib/bettercap/discovery/{discovery.rb → thread.rb} +10 -9
- data/lib/bettercap/error.rb +1 -2
- data/lib/bettercap/factories/{firewall_factory.rb → firewall.rb} +11 -7
- data/lib/bettercap/factories/{parser_factory.rb → parser.rb} +13 -3
- data/lib/bettercap/factories/{spoofer_factory.rb → spoofer.rb} +10 -3
- data/lib/bettercap/firewalls/base.rb +76 -0
- data/lib/bettercap/firewalls/linux.rb +26 -16
- data/lib/bettercap/firewalls/osx.rb +22 -13
- data/lib/bettercap/firewalls/redirection.rb +15 -1
- data/lib/bettercap/httpd/server.rb +5 -0
- data/lib/bettercap/logger.rb +29 -8
- data/lib/bettercap/network.rb +105 -105
- data/lib/bettercap/options.rb +99 -41
- data/lib/bettercap/packet_queue.rb +92 -0
- data/lib/bettercap/proxy/certstore.rb +49 -43
- data/lib/bettercap/proxy/module.rb +4 -2
- data/lib/bettercap/proxy/proxy.rb +7 -2
- data/lib/bettercap/proxy/request.rb +28 -16
- data/lib/bettercap/proxy/response.rb +23 -2
- data/lib/bettercap/proxy/stream_logger.rb +6 -0
- data/lib/bettercap/proxy/streamer.rb +13 -5
- data/lib/bettercap/proxy/thread_pool.rb +6 -14
- data/lib/bettercap/shell.rb +5 -3
- data/lib/bettercap/sniffer/parsers/base.rb +7 -1
- data/lib/bettercap/sniffer/parsers/custom.rb +6 -1
- data/lib/bettercap/sniffer/parsers/ftp.rb +8 -5
- data/lib/bettercap/sniffer/parsers/httpauth.rb +4 -1
- data/lib/bettercap/sniffer/parsers/https.rb +4 -1
- data/lib/bettercap/sniffer/parsers/irc.rb +8 -5
- data/lib/bettercap/sniffer/parsers/mail.rb +8 -5
- data/lib/bettercap/sniffer/parsers/ntlmss.rb +21 -18
- data/lib/bettercap/sniffer/parsers/post.rb +4 -1
- data/lib/bettercap/sniffer/parsers/url.rb +4 -1
- data/lib/bettercap/sniffer/sniffer.rb +7 -3
- data/lib/bettercap/spoofers/arp.rb +69 -94
- data/lib/bettercap/spoofers/base.rb +132 -0
- data/lib/bettercap/spoofers/icmp.rb +200 -0
- data/lib/bettercap/spoofers/none.rb +8 -2
- data/lib/bettercap/target.rb +117 -90
- data/lib/bettercap/update_checker.rb +6 -0
- data/lib/bettercap/version.rb +3 -1
- metadata +24 -8
- data/lib/bettercap/base/ifirewall.rb +0 -46
- data/lib/bettercap/base/ispoofer.rb +0 -32
@@ -11,9 +11,10 @@ This project is released under the GPL 3 license.
|
|
11
11
|
=end
|
12
12
|
require 'thread'
|
13
13
|
|
14
|
-
# Tnx to Puma ThreadPool!
|
15
14
|
module BetterCap
|
16
15
|
module Proxy
|
16
|
+
# Thread pool class used by the BetterCap::Proxy::Proxy.
|
17
|
+
# Tnx to Puma ThreadPool!
|
17
18
|
class ThreadPool
|
18
19
|
|
19
20
|
# Maintain a minimum of +min+ and maximum of +max+ threads
|
@@ -21,7 +22,6 @@ class ThreadPool
|
|
21
22
|
#
|
22
23
|
# The block passed is the work that will be performed in each
|
23
24
|
# thread.
|
24
|
-
#
|
25
25
|
def initialize(min, max, *extra, &block)
|
26
26
|
@not_empty = ConditionVariable.new
|
27
27
|
@not_full = ConditionVariable.new
|
@@ -46,12 +46,10 @@ class ThreadPool
|
|
46
46
|
@mutex.synchronize do
|
47
47
|
@min.times { spawn_thread }
|
48
48
|
end
|
49
|
-
|
50
|
-
@clean_thread_locals = false
|
51
49
|
end
|
52
50
|
|
53
|
-
|
54
|
-
|
51
|
+
# Number of spawned threads in the pool.
|
52
|
+
attr_reader :spawned
|
55
53
|
|
56
54
|
# How many objects have yet to be processed by the pool?
|
57
55
|
#
|
@@ -104,12 +102,6 @@ class ThreadPool
|
|
104
102
|
|
105
103
|
break unless continue
|
106
104
|
|
107
|
-
if @clean_thread_locals
|
108
|
-
Thread.current.keys.each do |key|
|
109
|
-
Thread.current[key] = nil unless key == :__recursive_key__
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
105
|
begin
|
114
106
|
block.call(work, *extra)
|
115
107
|
rescue Exception
|
@@ -184,7 +176,7 @@ class ThreadPool
|
|
184
176
|
|
185
177
|
# Tell all threads in the pool to exit and wait for them to finish.
|
186
178
|
#
|
187
|
-
def shutdown
|
179
|
+
def shutdown( join_threads = true )
|
188
180
|
threads = @mutex.synchronize do
|
189
181
|
@shutdown = true
|
190
182
|
@not_empty.broadcast
|
@@ -193,7 +185,7 @@ class ThreadPool
|
|
193
185
|
@workers.dup
|
194
186
|
end
|
195
187
|
|
196
|
-
threads.each(&:join)
|
188
|
+
threads.each(&:join) if join_threads
|
197
189
|
|
198
190
|
@spawned = 0
|
199
191
|
@workers = []
|
data/lib/bettercap/shell.rb
CHANGED
@@ -8,10 +8,11 @@ This project is released under the GPL 3 license.
|
|
8
8
|
require 'bettercap/error'
|
9
9
|
|
10
10
|
module BetterCap
|
11
|
+
# Class responsible of executing various shell commands.
|
11
12
|
module Shell
|
12
13
|
class << self
|
13
|
-
|
14
|
-
#
|
14
|
+
# Execute +command+ and return its output.
|
15
|
+
# Raise +BetterCap::Error+ if the return code is not 0.
|
15
16
|
def execute(command)
|
16
17
|
r = ''
|
17
18
|
10.times do
|
@@ -29,14 +30,15 @@ module Shell
|
|
29
30
|
r
|
30
31
|
end
|
31
32
|
|
33
|
+
# Get the +iface+ network interface configuration.
|
32
34
|
def ifconfig(iface = '')
|
33
35
|
self.execute( "LANG=en && ifconfig #{iface}" )
|
34
36
|
end
|
35
37
|
|
38
|
+
# Get the ARP table cached on this computer.
|
36
39
|
def arp
|
37
40
|
self.execute( 'LANG=en && arp -a -n' )
|
38
41
|
end
|
39
|
-
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
@@ -10,12 +10,17 @@ This project is released under the GPL 3 license.
|
|
10
10
|
|
11
11
|
=end
|
12
12
|
module BetterCap
|
13
|
-
|
13
|
+
module Parsers
|
14
|
+
# Base class for BetterCap::Parsers.
|
15
|
+
class Base
|
16
|
+
# Initialize this parser.
|
14
17
|
def initialize
|
15
18
|
@filters = []
|
16
19
|
@name = 'BASE'
|
17
20
|
end
|
18
21
|
|
22
|
+
# This method will be called from the BetterCap::Sniffer for each
|
23
|
+
# incoming packet ( +pkt ) and will apply the parser filter to it.
|
19
24
|
def on_packet( pkt )
|
20
25
|
s = pkt.to_s
|
21
26
|
@filters.each do |filter|
|
@@ -26,3 +31,4 @@ class BaseParser
|
|
26
31
|
end
|
27
32
|
end
|
28
33
|
end
|
34
|
+
end
|
@@ -12,10 +12,15 @@ This project is released under the GPL 3 license.
|
|
12
12
|
require 'bettercap/sniffer/parsers/base'
|
13
13
|
|
14
14
|
module BetterCap
|
15
|
-
|
15
|
+
module Parsers
|
16
|
+
# Parser used when the "--custom-parser EXPRESSION" command line
|
17
|
+
# argument is specified.
|
18
|
+
class Custom < Base
|
19
|
+
# Initialize the parser given the +filter+ Regexp object.
|
16
20
|
def initialize( filter )
|
17
21
|
@filters = [ filter ]
|
18
22
|
@name = 'DATA'
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
26
|
+
end
|
@@ -12,10 +12,13 @@ This project is released under the GPL 3 license.
|
|
12
12
|
require 'bettercap/sniffer/parsers/base'
|
13
13
|
|
14
14
|
module BetterCap
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
module Parsers
|
16
|
+
# FTP authentication parser.
|
17
|
+
class Ftp < Base
|
18
|
+
def initialize
|
19
|
+
@filters = [ /(USER|PASS)\s+.+/ ]
|
20
|
+
@name = 'FTP'
|
21
|
+
end
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
@@ -14,7 +14,9 @@ require 'colorize'
|
|
14
14
|
require 'base64'
|
15
15
|
|
16
16
|
module BetterCap
|
17
|
-
|
17
|
+
module Parsers
|
18
|
+
# HTTP basic and digest authentication parser.
|
19
|
+
class Httpauth < Base
|
18
20
|
def on_packet( pkt )
|
19
21
|
lines = pkt.to_s.split("\n")
|
20
22
|
hostname = nil
|
@@ -41,3 +43,4 @@ class HttpauthParser < BaseParser
|
|
41
43
|
end
|
42
44
|
end
|
43
45
|
end
|
46
|
+
end
|
@@ -14,7 +14,9 @@ require 'colorize'
|
|
14
14
|
require 'resolv'
|
15
15
|
|
16
16
|
module BetterCap
|
17
|
-
|
17
|
+
module Parsers
|
18
|
+
# HTTPS connections parser.
|
19
|
+
class Https < Base
|
18
20
|
@@prev = nil
|
19
21
|
|
20
22
|
def on_packet( pkt )
|
@@ -39,3 +41,4 @@ class HttpsParser < BaseParser
|
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
44
|
+
end
|
@@ -12,10 +12,13 @@ This project is released under the GPL 3 license.
|
|
12
12
|
require 'bettercap/sniffer/parsers/base'
|
13
13
|
|
14
14
|
module BetterCap
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
module Parsers
|
16
|
+
# IRC protocol parser.
|
17
|
+
class Irc < Base
|
18
|
+
def initialize
|
19
|
+
@filters = [ /NICK\s+.+/, /NS IDENTIFY\s+.+/, /nickserv :identify\s+.+/ ]
|
20
|
+
@name = 'IRC'
|
21
|
+
end
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
@@ -12,10 +12,13 @@ This project is released under the GPL 3 license.
|
|
12
12
|
require 'bettercap/sniffer/parsers/base'
|
13
13
|
|
14
14
|
module BetterCap
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
module Parsers
|
16
|
+
# POP/IMAP authentication parser.
|
17
|
+
class Mail < Base
|
18
|
+
def initialize
|
19
|
+
@filters = [ /(\d+ )?(auth|authenticate) ([a-z\-_0-9]+)/i ]
|
20
|
+
@name = 'MAIL'
|
21
|
+
end
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
@@ -13,26 +13,29 @@ require 'bettercap/sniffer/parsers/base'
|
|
13
13
|
require 'colorize'
|
14
14
|
|
15
15
|
module BetterCap
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
16
|
+
module Parsers
|
17
|
+
# NTLMSS traffic parser.
|
18
|
+
class Ntlmss < Base
|
19
|
+
# Convert binary +data+ into human readable hexadecimal representation.
|
20
|
+
def bin2hex( data )
|
21
|
+
hex = ''
|
22
|
+
data.each_byte do |byte|
|
23
|
+
if /[[:print:]]/ === byte.chr
|
24
|
+
hex += byte.chr
|
25
|
+
else
|
26
|
+
hex += "\\x" + byte.to_s(16)
|
27
|
+
end
|
28
28
|
end
|
29
|
+
hex
|
30
|
+
end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
32
|
+
def on_packet( pkt )
|
33
|
+
s = pkt.to_s
|
34
|
+
if s =~ /NTLMSSP\x00\x03\x00\x00\x00.+/
|
35
|
+
# TODO: Parse NTLMSSP packet.
|
36
|
+
StreamLogger.log_raw( pkt, 'NTLMSS', bin2hex( pkt.payload ) )
|
36
37
|
end
|
38
|
+
end
|
39
|
+
end
|
37
40
|
end
|
38
41
|
end
|
@@ -13,7 +13,9 @@ require 'bettercap/sniffer/parsers/base'
|
|
13
13
|
require 'colorize'
|
14
14
|
|
15
15
|
module BetterCap
|
16
|
-
|
16
|
+
module Parsers
|
17
|
+
# HTTP POST requests parser.
|
18
|
+
class Post < Base
|
17
19
|
def on_packet( pkt )
|
18
20
|
s = pkt.to_s
|
19
21
|
if s =~ /POST\s+[^\s]+\s+HTTP.+/
|
@@ -22,3 +24,4 @@ class PostParser < BaseParser
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
27
|
+
end
|
@@ -13,7 +13,9 @@ require 'bettercap/sniffer/parsers/base'
|
|
13
13
|
require 'colorize'
|
14
14
|
|
15
15
|
module BetterCap
|
16
|
-
|
16
|
+
module Parsers
|
17
|
+
# HTTP GET requests parser.
|
18
|
+
class Url < Base
|
17
19
|
def on_packet( pkt )
|
18
20
|
s = pkt.to_s
|
19
21
|
if s =~ /GET\s+([^\s]+)\s+HTTP.+Host:\s+([^\s]+).+/m
|
@@ -26,3 +28,4 @@ class UrlParser < BaseParser
|
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
31
|
+
end
|
@@ -10,11 +10,12 @@ This project is released under the GPL 3 license.
|
|
10
10
|
|
11
11
|
=end
|
12
12
|
require 'bettercap/logger'
|
13
|
-
require 'bettercap/factories/parser_factory'
|
14
13
|
require 'colorize'
|
15
14
|
require 'packetfu'
|
16
15
|
|
17
16
|
module BetterCap
|
17
|
+
# Class responsible of loading BetterCap::Parsers instances and performing
|
18
|
+
# network packet sniffing and dumping.
|
18
19
|
class Sniffer
|
19
20
|
include PacketFu
|
20
21
|
|
@@ -23,6 +24,9 @@ class Sniffer
|
|
23
24
|
@@pcap = nil
|
24
25
|
@@cap = nil
|
25
26
|
|
27
|
+
# Start a new thread that will sniff packets from the network and pass
|
28
|
+
# each one of them to the BetterCap::Parsers instances loaded inside the
|
29
|
+
# +ctx+ BetterCap::Context instance.
|
26
30
|
def self.start( ctx )
|
27
31
|
Thread.new do
|
28
32
|
Logger.info 'Starting sniffer ...'
|
@@ -94,9 +98,9 @@ class Sniffer
|
|
94
98
|
end
|
95
99
|
|
96
100
|
if @@ctx.options.custom_parser.nil?
|
97
|
-
@@parsers =
|
101
|
+
@@parsers = Factories::Parser.load_by_names @@ctx.options.parsers
|
98
102
|
else
|
99
|
-
@@parsers =
|
103
|
+
@@parsers = Factories::Parser.load_custom @@ctx.options.custom_parser
|
100
104
|
end
|
101
105
|
|
102
106
|
@@cap = Capture.new(
|
@@ -9,15 +9,18 @@ Blog : http://www.evilsocket.net/
|
|
9
9
|
This project is released under the GPL 3 license.
|
10
10
|
|
11
11
|
=end
|
12
|
+
require 'bettercap/spoofers/base'
|
12
13
|
require 'bettercap/error'
|
13
14
|
require 'bettercap/context'
|
14
|
-
require 'bettercap/base/ispoofer'
|
15
15
|
require 'bettercap/network'
|
16
16
|
require 'bettercap/logger'
|
17
17
|
require 'colorize'
|
18
18
|
|
19
19
|
module BetterCap
|
20
|
-
|
20
|
+
module Spoofers
|
21
|
+
# This class is responsible of performing ARP spoofing on the network.
|
22
|
+
class Arp < Base
|
23
|
+
# Initialize the BetterCap::Spoofers::Arp object.
|
21
24
|
def initialize
|
22
25
|
@ctx = Context.get
|
23
26
|
@gateway = nil
|
@@ -27,16 +30,12 @@ class ArpSpoofer < ISpoofer
|
|
27
30
|
@capture = nil
|
28
31
|
@running = false
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
hw = Network.get_hw_address( @ctx.ifconfig, @ctx.gateway )
|
33
|
-
raise BetterCap::Error, "Couldn't determine router MAC" if hw.nil?
|
34
|
-
|
35
|
-
@gateway = Target.new( @ctx.gateway, hw )
|
36
|
-
|
37
|
-
Logger.info " #{@gateway}"
|
33
|
+
update_gateway!
|
38
34
|
end
|
39
35
|
|
36
|
+
# Send a spoofed ARP reply to the target identified by the +daddr+ IP address
|
37
|
+
# and +dmac+ MAC address, spoofing the +saddr+ IP address and +smac+ MAC
|
38
|
+
# address as the source device.
|
40
39
|
def send_spoofed_packet( saddr, smac, daddr, dmac )
|
41
40
|
pkt = PacketFu::ARPPacket.new
|
42
41
|
pkt.eth_saddr = smac
|
@@ -47,9 +46,10 @@ class ArpSpoofer < ISpoofer
|
|
47
46
|
pkt.arp_daddr_ip = daddr
|
48
47
|
pkt.arp_opcode = 2
|
49
48
|
|
50
|
-
|
49
|
+
@ctx.packets.push(pkt)
|
51
50
|
end
|
52
51
|
|
52
|
+
# Start the ARP spoofing.
|
53
53
|
def start
|
54
54
|
Logger.info "Starting ARP spoofer ( #{@ctx.options.half_duplex ? 'Half' : 'Full'} Duplex ) ..."
|
55
55
|
|
@@ -58,89 +58,11 @@ class ArpSpoofer < ISpoofer
|
|
58
58
|
|
59
59
|
@ctx.firewall.enable_forwarding(true) unless @forwarding
|
60
60
|
|
61
|
-
@sniff_thread = Thread.new
|
62
|
-
|
63
|
-
begin
|
64
|
-
@capture = PacketFu::Capture.new(
|
65
|
-
iface: @ctx.options.iface,
|
66
|
-
filter: 'arp',
|
67
|
-
start: true
|
68
|
-
)
|
69
|
-
rescue Exception => e
|
70
|
-
Logger.error e.message
|
71
|
-
end
|
72
|
-
|
73
|
-
@capture.stream.each do |p|
|
74
|
-
begin
|
75
|
-
pkt = PacketFu::Packet.parse p
|
76
|
-
# we're only interested in 'who-has' packets
|
77
|
-
if pkt.arp_opcode == 1 and pkt.arp_dst_mac.to_s == '00:00:00:00:00:00'
|
78
|
-
is_from_us = ( pkt.arp_src_ip.to_s == @ctx.ifconfig[:ip_saddr] )
|
79
|
-
unless is_from_us
|
80
|
-
Logger.info "[ARP] #{pkt.arp_src_ip.to_s} is asking who #{pkt.arp_dst_ip.to_s} is."
|
81
|
-
|
82
|
-
send_spoofed_packet pkt.arp_dst_ip.to_s, @ctx.ifconfig[:eth_saddr], pkt.arp_src_ip.to_s, pkt.arp_src_mac.to_s
|
83
|
-
end
|
84
|
-
end
|
85
|
-
rescue Exception => e
|
86
|
-
Logger.error e.message
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
@spoof_thread = Thread.new do
|
92
|
-
prev_size = @ctx.targets.size
|
93
|
-
loop do
|
94
|
-
if not @running
|
95
|
-
Logger.debug 'Stopping spoofing thread ...'
|
96
|
-
Thread.exit
|
97
|
-
break
|
98
|
-
end
|
99
|
-
|
100
|
-
size = @ctx.targets.size
|
101
|
-
|
102
|
-
if size > prev_size
|
103
|
-
Logger.warn "Aquired #{size - prev_size} new targets."
|
104
|
-
elsif size < prev_size
|
105
|
-
Logger.warn "Lost #{prev_size - size} targets."
|
106
|
-
end
|
107
|
-
|
108
|
-
Logger.debug "Spoofing #{@ctx.targets.size} targets ..."
|
109
|
-
|
110
|
-
@ctx.targets.each do |target|
|
111
|
-
# targets could change, update mac addresses if needed
|
112
|
-
if target.mac.nil?
|
113
|
-
hw = Network.get_hw_address( @ctx.ifconfig, target.ip )
|
114
|
-
if hw.nil?
|
115
|
-
Logger.warn "Couldn't determine target #{ip} MAC!"
|
116
|
-
next
|
117
|
-
else
|
118
|
-
Logger.info " Target MAC : #{hw}"
|
119
|
-
target.mac = hw
|
120
|
-
end
|
121
|
-
# target was specified by MAC address
|
122
|
-
elsif target.ip_refresh
|
123
|
-
ip = Network.get_ip_address( @ctx, target.mac )
|
124
|
-
if ip.nil?
|
125
|
-
Logger.warn "Couldn't determine target #{target.mac} IP!"
|
126
|
-
next
|
127
|
-
else
|
128
|
-
Logger.info "Target #{target.mac} IP : #{ip}" if target.ip.nil? or target.ip != ip
|
129
|
-
target.ip = ip
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
send_spoofed_packet( @gateway.ip, @ctx.ifconfig[:eth_saddr], target.ip, target.mac )
|
134
|
-
send_spoofed_packet( target.ip, @ctx.ifconfig[:eth_saddr], @gateway.ip, @gateway.mac ) unless @ctx.options.half_duplex
|
135
|
-
end
|
136
|
-
|
137
|
-
prev_size = @ctx.targets.size
|
138
|
-
|
139
|
-
sleep(1)
|
140
|
-
end
|
141
|
-
end
|
61
|
+
@sniff_thread = Thread.new { arp_watcher }
|
62
|
+
@spoof_thread = Thread.new { arp_spoofer }
|
142
63
|
end
|
143
64
|
|
65
|
+
# Stop the ARP spoofing, reset firewall state and restore targets ARP table.
|
144
66
|
def stop
|
145
67
|
raise 'ARP spoofer is not running' unless @running
|
146
68
|
|
@@ -158,14 +80,67 @@ class ArpSpoofer < ISpoofer
|
|
158
80
|
Logger.info "Restoring ARP table of #{@ctx.targets.size} targets ..."
|
159
81
|
|
160
82
|
@ctx.targets.each do |target|
|
161
|
-
unless target.mac.nil?
|
83
|
+
unless target.ip.nil? or target.mac.nil?
|
162
84
|
begin
|
163
85
|
send_spoofed_packet( @gateway.ip, @gateway.mac, target.ip, target.mac )
|
164
86
|
send_spoofed_packet( target.ip, target.mac, @gateway.ip, @gateway.mac ) unless @ctx.options.half_duplex
|
165
87
|
rescue; end
|
166
88
|
end
|
167
89
|
end
|
168
|
-
sleep 1
|
169
90
|
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def update_targets!
|
95
|
+
@ctx.targets.each do |target|
|
96
|
+
# targets could change, update mac addresses if needed
|
97
|
+
if target.mac.nil?
|
98
|
+
hw = Network.get_hw_address( @ctx.ifconfig, target.ip )
|
99
|
+
if hw.nil?
|
100
|
+
Logger.warn "Couldn't determine target #{ip} MAC!"
|
101
|
+
next
|
102
|
+
else
|
103
|
+
Logger.info " Target MAC : #{hw}"
|
104
|
+
target.mac = hw
|
105
|
+
end
|
106
|
+
# target was specified by MAC address
|
107
|
+
elsif target.ip_refresh
|
108
|
+
ip = Network.get_ip_address( @ctx, target.mac )
|
109
|
+
if ip.nil?
|
110
|
+
Logger.warn "Couldn't determine target #{target.mac} IP!"
|
111
|
+
next
|
112
|
+
else
|
113
|
+
Logger.info "Target #{target.mac} IP : #{ip}" if target.ip.nil? or target.ip != ip
|
114
|
+
target.ip = ip
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def arp_spoofer
|
121
|
+
spoof_loop(1) { |target|
|
122
|
+
unless target.ip.nil? or target.mac.nil?
|
123
|
+
send_spoofed_packet( @gateway.ip, @ctx.ifconfig[:eth_saddr], target.ip, target.mac )
|
124
|
+
send_spoofed_packet( target.ip, @ctx.ifconfig[:eth_saddr], @gateway.ip, @gateway.mac ) unless @ctx.options.half_duplex
|
125
|
+
end
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def arp_watcher
|
130
|
+
Logger.info 'ARP watcher started ...'
|
131
|
+
|
132
|
+
sniff_packets('arp') { |pkt|
|
133
|
+
# we're only interested in 'who-has' packets
|
134
|
+
if pkt.arp_opcode == 1 and pkt.arp_dst_mac.to_s == '00:00:00:00:00:00'
|
135
|
+
is_from_us = ( pkt.arp_src_ip.to_s == @ctx.ifconfig[:ip_saddr] )
|
136
|
+
unless is_from_us
|
137
|
+
Logger.info "[ARP] #{pkt.arp_src_ip.to_s} is asking who #{pkt.arp_dst_ip.to_s} is."
|
138
|
+
|
139
|
+
send_spoofed_packet pkt.arp_dst_ip.to_s, @ctx.ifconfig[:eth_saddr], pkt.arp_src_ip.to_s, pkt.arp_src_mac.to_s
|
140
|
+
end
|
141
|
+
end
|
142
|
+
}
|
143
|
+
end
|
144
|
+
end
|
170
145
|
end
|
171
146
|
end
|