bettercap 1.2.0 → 1.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a830b906b0c9ea8c95b66699910e60e79c1eb728
4
- data.tar.gz: 607fb72b1fd6dc77b4481ff2c3d8cb2dddefc8d3
3
+ metadata.gz: 14c3df538db89404723e56bde2c2a8a92446d8f9
4
+ data.tar.gz: 7b48c98712b2c2b879f6e7bfc67529627ba1668d
5
5
  SHA512:
6
- metadata.gz: 37ffe1a82e6da08ea9e1136892a9ec1b720b8fd5841eb74370e6e462151aa004e8ad0a3391d0db449dae5b5b86f2c5f7fe7d752c42566500039b1b7f478e677d
7
- data.tar.gz: 1a2c0b6e2035a144bf677adaefba785abf614b375d9bb9d0d5284232ec1bac9cff467272eca2c3fa01e8acdbaf0c66ec726f47f6ba60e380bce61be615d2779e
6
+ metadata.gz: c35e2b12effaa67a2236427922d0f7af6d200f177304e3d2f09adb3b38db1b7c7cc6b0c7f9f6ee7f70a3d8155a99f8dedcc0351f099871819357277338e54148
7
+ data.tar.gz: 1477fda71236367e364c3e392f2b44b1edbef1d19f3a792231d0a32bc613500a9b6dea86881d699a92b1afcfe5a58a61c604963df3ad16eecc99abb2a60d3d09
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  http://www.bettercap.org/
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/bettercap.svg)](http://badge.fury.io/rb/bettercap) [![Code Climate](https://codeclimate.com/github/evilsocket/bettercap/badges/gpa.svg)](https://codeclimate.com/github/evilsocket/bettercap)
5
+ [![Gem Version](https://badge.fury.io/rb/bettercap.svg)](http://badge.fury.io/rb/bettercap) [![Code Climate](https://codeclimate.com/github/evilsocket/bettercap/badges/gpa.svg)](https://codeclimate.com/github/evilsocket/bettercap) [![Join the chat at https://gitter.im/evilsocket/bettercap-proxy-modules](https://badges.gitter.im/evilsocket/bettercap-proxy-modules.svg)](https://gitter.im/evilsocket/bettercap-proxy-modules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
6
  ---
7
7
 
8
8
  **bettercap** is a complete, modular, portable and easily extensible **MITM** tool and framework with every kind of diagnostic
data/bin/bettercap CHANGED
@@ -18,6 +18,9 @@ begin
18
18
  puts BetterCap::BANNER.green.bold
19
19
  puts "\n\n\n"
20
20
 
21
+ # We need this in order to report unhandled exceptions.
22
+ original_argv = ARGV.clone
23
+
21
24
  # Create global context, parse command line arguments and perform basic
22
25
  # error checking.
23
26
  ctx = BetterCap::Options.parse!
@@ -78,9 +81,17 @@ rescue BetterCap::Error => e
78
81
  BetterCap::Logger.error e.message
79
82
 
80
83
  rescue Exception => e
81
- BetterCap::Logger.error "EXCEPTION '#{e.class}' :"
82
- BetterCap::Logger.error e.message
83
- BetterCap::Logger.error e.backtrace.join("\n")
84
+ puts "\n\n"
85
+ BetterCap::Logger.error "Oooops, seems like something weird occurred, please copy paste the following output " \
86
+ "and open a new issue on https://github.com/evilsocket/bettercap/issues :\n"
87
+
88
+ BetterCap::Logger.error "Platform : #{RUBY_PLATFORM}"
89
+ BetterCap::Logger.error "Ruby Version : #{RUBY_VERSION}"
90
+ BetterCap::Logger.error "BetterCap Version : #{BetterCap::VERSION}"
91
+ BetterCap::Logger.error "Command Line : #{original_argv.join(" ")}"
92
+ BetterCap::Logger.error "Exception : #{e.class}"
93
+ BetterCap::Logger.error "Message : #{e.message}"
94
+ BetterCap::Logger.error "Backtrace :\n\n #{e.backtrace.join("\n ")}\n"
84
95
 
85
96
  ensure
86
97
  # Make sure all the messages on the logger queue are printed.
data/lib/bettercap.rb CHANGED
@@ -26,7 +26,9 @@ Config = RbConfig
26
26
 
27
27
  require 'bettercap/update_checker'
28
28
  require 'bettercap/error'
29
+ require 'bettercap/loader'
29
30
  require 'bettercap/options'
31
+ require 'bettercap/arp_reader'
30
32
  require 'bettercap/packet_queue'
31
33
  require 'bettercap/discovery/thread'
32
34
  require 'bettercap/discovery/agents/base'
@@ -0,0 +1,78 @@
1
+ =begin
2
+ BETTERCAP
3
+ Author : Simone 'evilsocket' Margaritelli
4
+ Email : evilsocket@gmail.com
5
+ Blog : http://www.evilsocket.net/
6
+ This project is released under the GPL 3 license.
7
+ =end
8
+ require 'bettercap/error'
9
+
10
+ module BetterCap
11
+ # This class is responsible for reading the computer ARP table.
12
+ class ArpReader
13
+ # Parse the current ARP cache and return a list of BetterCap::Target
14
+ # objects which are found inside it, using the +ctx+ BetterCap::Context
15
+ # instance.
16
+ def self.parse( ctx )
17
+ targets = []
18
+ self.parse_cache do |ip,mac|
19
+ if ip != ctx.gateway and ip != ctx.ifconfig[:ip_saddr]
20
+ if ctx.options.ignore_ip?(ip)
21
+ Logger.debug "Ignoring #{ip} ..."
22
+ else
23
+ # reuse Target object if it's already a known address
24
+ known = ctx.find_target ip, mac
25
+ if known.nil?
26
+ targets << Target.new( ip, mac )
27
+ else
28
+ targets << known
29
+ end
30
+ end
31
+ end
32
+ end
33
+ targets
34
+ end
35
+
36
+ # Parse the ARP cache searching for the given IP +address+ and return its
37
+ # MAC if found, otherwise nil.
38
+ def self.find_address( address )
39
+ self.parse_cache do |ip,mac|
40
+ if ip == address
41
+ return mac
42
+ end
43
+ end
44
+ nil
45
+ end
46
+
47
+ # Parse the ARP cache searching for the given MAC +address+ and return its
48
+ # IP if found, otherwise nil.
49
+ def self.find_mac( address )
50
+ self.parse_cache do |ip,mac|
51
+ if mac == address
52
+ return ip
53
+ end
54
+ end
55
+ nil
56
+ end
57
+
58
+ private
59
+
60
+ def self.parse_cache
61
+ iface = Context.get.ifconfig[:iface]
62
+ Shell.arp.split("\n").each do |line|
63
+ m = self.parse_cache_line(iface,line)
64
+ unless m.nil?
65
+ ip = m[1]
66
+ hw = Target.normalized_mac( m[2] )
67
+ if hw != 'FF:FF:FF:FF:FF:FF'
68
+ yield( ip, hw )
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def self.parse_cache_line( iface, line )
75
+ /[^\s]+\s+\(([0-9\.]+)\)\s+at\s+([a-f0-9:]+).+#{iface}.*/i.match(line)
76
+ end
77
+ end
78
+ end
@@ -127,10 +127,8 @@ class Context
127
127
  # is needed in order to run proxy modules.
128
128
  def create_proxies
129
129
  if @options.has_proxy_module?
130
- require @options.proxy_module
131
-
132
130
  Proxy::Module.register_modules
133
-
131
+
134
132
  raise BetterCap::Error, "#{@options.proxy_module} is not a valid bettercap proxy module." if Proxy::Module.modules.empty?
135
133
  end
136
134
 
@@ -14,73 +14,10 @@ This project is released under the GPL 3 license.
14
14
  module BetterCap
15
15
  module Discovery
16
16
  module Agents
17
- # Class responsible to parse ARP cache and send ARP probes to each
18
- # possible IP on the network.
17
+ # Class responsible of sending ARP probes to each possible IP on the network.
19
18
  class Arp < Discovery::Agents::Base
20
- # Parse the current ARP cache and return a list of BetterCap::Target
21
- # objects which are found inside it, using the +ctx+ BetterCap::Context
22
- # instance.
23
- def self.parse( ctx )
24
- targets = []
25
- self.parse_cache do |ip,mac|
26
- if ip != ctx.gateway and ip != ctx.ifconfig[:ip_saddr]
27
- if ctx.options.ignore_ip?(ip)
28
- Logger.debug "Ignoring #{ip} ..."
29
- else
30
- # reuse Target object if it's already a known address
31
- known = ctx.find_target ip, mac
32
- if known.nil?
33
- targets << Target.new( ip, mac )
34
- else
35
- targets << known
36
- end
37
- end
38
- end
39
- end
40
- targets
41
- end
42
-
43
- # Parse the ARP cache searching for the given IP +address+ and return its
44
- # MAC if found, otherwise nil.
45
- def self.find_address( address )
46
- self.parse_cache do |ip,mac|
47
- if ip == address
48
- return mac
49
- end
50
- end
51
- nil
52
- end
53
-
54
- # Parse the ARP cache searching for the given MAC +address+ and return its
55
- # IP if found, otherwise nil.
56
- def self.find_mac( address )
57
- self.parse_cache do |ip,mac|
58
- if mac == address
59
- return ip
60
- end
61
- end
62
- nil
63
- end
64
-
65
19
  private
66
20
 
67
- def self.parse_cache
68
- Shell.arp.split("\n").each do |line|
69
- m = self.parse_cache_line(line)
70
- unless m.nil?
71
- ip = m[1]
72
- hw = Target.normalized_mac( m[2] )
73
- if hw != 'FF:FF:FF:FF:FF:FF'
74
- yield( ip, hw )
75
- end
76
- end
77
- end
78
- end
79
-
80
- def self.parse_cache_line( line )
81
- /[^\s]+\s+\(([0-9\.]+)\)\s+at\s+([a-f0-9:]+).+#{Context.get.ifconfig[:iface]}.*/i.match(line)
82
- end
83
-
84
21
  def get_probe( ip )
85
22
  pkt = PacketFu::ARPPacket.new
86
23
 
@@ -55,7 +55,7 @@ class Parser
55
55
 
56
56
  require_relative "#{@@path}#{file}"
57
57
 
58
- loaded << Kernel.const_get("BetterCap::Parsers::#{cname.capitalize}").new
58
+ loaded << BetterCap::Loader.load("BetterCap::Parsers::#{cname.capitalize}").new
59
59
  end
60
60
  end
61
61
  loaded
@@ -37,7 +37,7 @@ class Spoofer
37
37
 
38
38
  require_relative "../spoofers/#{name}"
39
39
 
40
- Kernel.const_get("BetterCap::Spoofers::#{name.capitalize}").new
40
+ BetterCap::Loader.load("BetterCap::Spoofers::#{name.capitalize}").new
41
41
  end
42
42
 
43
43
  private
@@ -0,0 +1,23 @@
1
+ =begin
2
+ BETTERCAP
3
+ Author : Simone 'evilsocket' Margaritelli
4
+ Email : evilsocket@gmail.com
5
+ Blog : http://www.evilsocket.net/
6
+ This project is released under the GPL 3 license.
7
+ =end
8
+ require 'bettercap/error'
9
+
10
+ module BetterCap
11
+ # This class is responsible for dynamically loading modules.
12
+ class Loader
13
+ # Dynamically load a class given its +name+.
14
+ # @see https://github.com/evilsocket/bettercap/issues/88
15
+ def self.load(name)
16
+ root = Kernel
17
+ name.split('::').each do |part|
18
+ root = root.const_get(part)
19
+ end
20
+ root
21
+ end
22
+ end
23
+ end
@@ -70,16 +70,16 @@ class << self
70
70
  Logger.debug 'Using current ARP cache.'
71
71
  end
72
72
 
73
- Discovery::Agents::Arp.parse ctx
73
+ ArpReader.parse ctx
74
74
  end
75
75
 
76
76
  # Return the IP address associated with the +mac+ hardware address using the
77
77
  # given BetterCap::Context ( +ctx+ ).
78
78
  def get_ip_address( ctx, mac )
79
- ip = Discovery::Agents::Arp.find_mac( mac )
79
+ ip = ArpReader.find_mac( mac )
80
80
  if ip.nil?
81
81
  start_agents( ctx )
82
- ip = Discovery::Agents::Arp.find_mac( mac )
82
+ ip = ArpReader.find_mac( mac )
83
83
  end
84
84
  ip
85
85
  end
@@ -88,7 +88,7 @@ class << self
88
88
  # the +iface+ network interface.
89
89
  # The resolution will be performed for the specified number of +attempts+.
90
90
  def get_hw_address( iface, ip_address, attempts = 2 )
91
- hw_address = Discovery::Agents::Arp.find_address( ip_address )
91
+ hw_address = ArpReader.find_address( ip_address )
92
92
 
93
93
  if hw_address.nil?
94
94
  attempts.times do
@@ -135,7 +135,7 @@ class << self
135
135
 
136
136
  def start_agents( ctx )
137
137
  [ 'Icmp', 'Udp', 'Arp' ].each do |name|
138
- Kernel.const_get("BetterCap::Discovery::Agents::#{name}").new( ctx )
138
+ BetterCap::Loader.load("BetterCap::Discovery::Agents::#{name}").new(ctx)
139
139
  end
140
140
  ctx.packets.wait_empty( ctx.timeout )
141
141
  end
@@ -80,6 +80,9 @@ class Options
80
80
  attr_accessor :check_updates
81
81
  # If true, targets NBNS hostname resolution won't be performed.
82
82
  attr_accessor :no_target_nbns
83
+ # If true, bettercap won't forward packets for any target, causing
84
+ # connections to be killed.
85
+ attr_accessor :kill
83
86
 
84
87
  # Create a BetterCap::Options class instance using the specified network interface.
85
88
  def initialize( iface )
@@ -93,6 +96,7 @@ class Options
93
96
  @debug = false
94
97
  @arpcache = false
95
98
  @no_target_nbns = false
99
+ @kill = false
96
100
 
97
101
  @ignore = nil
98
102
 
@@ -131,8 +135,11 @@ class Options
131
135
  ctx = Context.get
132
136
 
133
137
  OptionParser.new do |opts|
134
- opts.banner = "Usage: #{$0} [options]"
135
138
  opts.version = BetterCap::VERSION
139
+ opts.banner = "Usage: bettercap [options]"
140
+ opts.separator ""
141
+ opts.separator "Specific options:"
142
+ opts.separator ""
136
143
 
137
144
  opts.on( '-G', '--gateway ADDRESS', 'Manually specify the gateway address, if not specified the current gateway will be retrieved and used. ' ) do |v|
138
145
  ctx.options.gateway = v
@@ -246,6 +253,10 @@ class Options
246
253
  opts.on( '--proxy-module MODULE', 'Ruby proxy module to load.' ) do |v|
247
254
  ctx.options.proxy = true
248
255
  ctx.options.proxy_module = File.expand_path v
256
+
257
+ require ctx.options.proxy_module
258
+
259
+ Proxy::Module.register_options(opts)
249
260
  end
250
261
 
251
262
  opts.on( '--custom-proxy ADDRESS', 'Use a custom HTTP upstream proxy instead of the builtin one.' ) do |v|
@@ -278,6 +289,10 @@ class Options
278
289
  ctx.options.httpd_path = v
279
290
  end
280
291
 
292
+ opts.on( '--kill', 'Instead of forwarding packets, this switch will make targets connections to be killed.' ) do
293
+ ctx.options.kill = true
294
+ end
295
+
281
296
  opts.on( '--check-updates', 'Will check if any update is available and then exit.' ) do
282
297
  ctx.options.check_updates = true
283
298
  end
@@ -17,53 +17,9 @@ class PacketQueue
17
17
  @nworkers = nworkers
18
18
  @running = true
19
19
  @injector = PacketFu::Inject.new(:iface => iface)
20
+ @udp = UDPSocket.new
20
21
  @queue = Queue.new
21
- @workers = (0...nworkers).map {
22
- ::Thread.new {
23
- Logger.debug "PacketQueue worker started."
24
-
25
- while @running
26
- begin
27
- packet = @queue.pop
28
- # nil packet pushed to signal stopping
29
- if packet.nil?
30
- Logger.debug "Got nil packet, PacketQueue stopping ..."
31
- break
32
-
33
- # [ ip, port, data ] pushed by Discovery::Agents::Udp
34
- elsif packet.is_a?(Array)
35
- ip, port, data = packet
36
- Logger.debug "Sending UDP data packet to #{ip}:#{port} ..."
37
-
38
- # TODO: Maybe just create one globally?
39
- sd = UDPSocket.new
40
- sd.send( data, 0, ip, port )
41
- sd = nil
42
-
43
- # PacketFu packet
44
- else
45
- Logger.debug "Sending #{packet.class.name} packet ..."
46
-
47
- # Use a global PacketFu::Inject object.
48
- @injector.array = [packet.headers[0].to_s]
49
- @injector.inject
50
- end
51
- rescue Exception => e
52
- Logger.debug "#{self.class.name} ( #{packet.class.name} ) : #{e.message}"
53
-
54
- # If we've got an error message such as:
55
- # (cannot open BPF device) /dev/bpf0: Too many open files
56
- # We want to retry to probe this ip in a while.
57
- if e.message.include? 'Too many open files'
58
- Logger.debug "Repushing #{self.class.name} to the packet queue ..."
59
- push(packet)
60
- end
61
- end
62
- end
63
-
64
- Logger.debug "PacketQueue worker stopped."
65
- }
66
- }
22
+ @workers = (0...nworkers).map { ::Thread.new { worker } }
67
23
  end
68
24
 
69
25
  # Push a packet to the queue.
@@ -88,5 +44,53 @@ class PacketQueue
88
44
  @nworkers.times { push(nil) }
89
45
  @workers.map(&:join)
90
46
  end
47
+
48
+ private
49
+
50
+ def dispatch_udp_packet(packet)
51
+ ip, port, data = packet
52
+ Logger.debug "Sending UDP data packet to #{ip}:#{port} ..."
53
+ @udp.send( data, 0, ip, port )
54
+ end
55
+
56
+ def dispatch_raw_packet(packet)
57
+ Logger.debug "Sending #{packet.class.name} packet ..."
58
+ @injector.array = [packet.headers[0].to_s]
59
+ @injector.inject
60
+ end
61
+
62
+ def worker
63
+ Logger.debug "PacketQueue worker started."
64
+
65
+ while @running
66
+ begin
67
+ packet = @queue.pop
68
+ case packet
69
+ # nil packet pushed to signal stopping
70
+ when nil
71
+ Logger.debug "Got nil packet, PacketQueue stopping ..."
72
+ break
73
+ # [ ip, port, data ] pushed by Discovery::Agents::Udp
74
+ when Array
75
+ dispatch_udp_packet(packet)
76
+ # PacketFu raw packet
77
+ when Object
78
+ dispatch_raw_packet(packet)
79
+ end
80
+ rescue Exception => e
81
+ Logger.debug "#{self.class.name} ( #{packet.class.name} ) : #{e.message}"
82
+
83
+ # If we've got an error message such as:
84
+ # (cannot open BPF device) /dev/bpf0: Too many open files
85
+ # We want to retry to probe this ip in a while.
86
+ if e.message.include? 'Too many open files'
87
+ Logger.debug "Repushing #{self.class.name} to the packet queue ..."
88
+ push(packet)
89
+ end
90
+ end
91
+ end
92
+
93
+ Logger.debug "PacketQueue worker stopped."
94
+ end
91
95
  end
92
96
  end
@@ -26,13 +26,30 @@ class Module
26
26
  true
27
27
  end
28
28
 
29
+ # Register custom options for each available module.
30
+ def self.register_options(opts)
31
+ self.each_module do |const|
32
+ if const.respond_to?(:on_options)
33
+ const.on_options(opts)
34
+ end
35
+ end
36
+ end
37
+
29
38
  # Register available proxy modules into the system.
30
39
  def self.register_modules
40
+ self.each_module do |const|
41
+ Logger.debug "Registering module #{const}"
42
+ @@modules << const.new
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def self.each_module
31
49
  Object.constants.each do |klass|
32
50
  const = Kernel.const_get(klass)
33
51
  if const.respond_to?(:superclass) and const.superclass == self
34
- Logger.debug "Registering module #{const}"
35
- @@modules << const.new
52
+ yield const
36
53
  end
37
54
  end
38
55
  end
@@ -29,7 +29,7 @@ class Sniffer
29
29
  # +ctx+ BetterCap::Context instance.
30
30
  def self.start( ctx )
31
31
  Thread.new do
32
- Logger.info 'Starting sniffer ...'
32
+ Logger.debug 'Starting sniffer ...'
33
33
 
34
34
  setup( ctx )
35
35
 
@@ -51,12 +51,17 @@ class Arp < Base
51
51
 
52
52
  # Start the ARP spoofing.
53
53
  def start
54
- Logger.info "Starting ARP spoofer ( #{@ctx.options.half_duplex ? 'Half' : 'Full'} Duplex ) ..."
54
+ Logger.debug "Starting ARP spoofer ( #{@ctx.options.half_duplex ? 'Half' : 'Full'} Duplex ) ..."
55
55
 
56
56
  stop() if @running
57
57
  @running = true
58
58
 
59
- @ctx.firewall.enable_forwarding(true) unless @forwarding
59
+ if @ctx.options.kill
60
+ Logger.warn "Disabling packet forwarding."
61
+ @ctx.firewall.enable_forwarding(false) if @forwarding
62
+ else
63
+ @ctx.firewall.enable_forwarding(true) unless @forwarding
64
+ end
60
65
 
61
66
  @sniff_thread = Thread.new { arp_watcher }
62
67
  @spoof_thread = Thread.new { arp_spoofer }
@@ -66,8 +71,7 @@ class Arp < Base
66
71
  def stop
67
72
  raise 'ARP spoofer is not running' unless @running
68
73
 
69
- Logger.info 'Stopping ARP spoofer ...'
70
-
74
+ Logger.debug 'Stopping ARP spoofer ...'
71
75
  Logger.debug "Resetting packet forwarding to #{@forwarding} ..."
72
76
  @ctx.firewall.enable_forwarding( @forwarding )
73
77
 
@@ -77,7 +81,7 @@ class Arp < Base
77
81
  rescue
78
82
  end
79
83
 
80
- Logger.info "Restoring ARP table of #{@ctx.targets.size} targets ..."
84
+ Logger.debug "Restoring ARP table of #{@ctx.targets.size} targets ..."
81
85
 
82
86
  @ctx.targets.each do |target|
83
87
  unless target.ip.nil? or target.mac.nil?
@@ -91,32 +95,6 @@ class Arp < Base
91
95
 
92
96
  private
93
97
 
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
98
  def arp_spoofer
121
99
  spoof_loop(1) { |target|
122
100
  unless target.ip.nil? or target.mac.nil?
@@ -127,7 +105,7 @@ class Arp < Base
127
105
  end
128
106
 
129
107
  def arp_watcher
130
- Logger.info 'ARP watcher started ...'
108
+ Logger.debug 'ARP watcher started ...'
131
109
 
132
110
  sniff_packets('arp') { |pkt|
133
111
  # we're only interested in 'who-has' packets
@@ -88,14 +88,11 @@ private
88
88
  end
89
89
 
90
90
  def update_gateway!
91
- Logger.info "Getting gateway #{@ctx.gateway} MAC address ..."
92
-
93
91
  hw = Network.get_hw_address( @ctx.ifconfig, @ctx.gateway )
94
92
  raise BetterCap::Error, "Couldn't determine router MAC" if hw.nil?
95
-
96
93
  @gateway = Target.new( @ctx.gateway, hw )
97
94
 
98
- Logger.info " #{@gateway}"
95
+ Logger.info "[#{'GATEWAY'.green}] #{@gateway.to_s(false)}"
99
96
  end
100
97
 
101
98
  def update_targets!
@@ -104,21 +101,22 @@ private
104
101
  if target.mac.nil?
105
102
  hw = Network.get_hw_address( @ctx.ifconfig, target.ip )
106
103
  if hw.nil?
107
- Logger.warn "Couldn't determine target #{ip} MAC!"
104
+ Logger.warn "Couldn't determine target #{ip} MAC address!"
108
105
  next
109
106
  else
110
- Logger.info " Target MAC : #{hw}"
111
107
  target.mac = hw
108
+ Logger.info "[#{'TARGET'.green}] #{target.to_s(false)}"
112
109
  end
113
110
  # target was specified by MAC address
114
111
  elsif target.ip_refresh
115
112
  ip = Network.get_ip_address( @ctx, target.mac )
116
113
  if ip.nil?
117
- Logger.warn "Couldn't determine target #{target.mac} IP!"
114
+ Logger.warn "Couldn't determine target #{target.mac} IP address!"
118
115
  next
119
116
  else
120
- Logger.info "Target #{target.mac} IP : #{ip}" if target.ip.nil? or target.ip != ip
117
+ doprint = ( target.ip.nil? or target.ip != ip )
121
118
  target.ip = ip
119
+ Logger.info("[#{'TARGET'.green}] #{target.to_s(false)}") if doprint
122
120
  end
123
121
  end
124
122
  end
@@ -112,12 +112,18 @@ class Icmp < Base
112
112
 
113
113
  # Start the ICMP redirect spoofing.
114
114
  def start
115
- Logger.info "Starting ICMP redirect spoofer ..."
115
+ Logger.debug "Starting ICMP redirect spoofer ..."
116
116
 
117
117
  stop() if @running
118
118
  @running = true
119
119
 
120
- @ctx.firewall.enable_forwarding(true) unless @forwarding
120
+ if @ctx.options.kill
121
+ Logger.warn "Disabling packet forwarding."
122
+ @ctx.firewall.enable_forwarding(false) if @forwarding
123
+ else
124
+ @ctx.firewall.enable_forwarding(true) unless @forwarding
125
+ end
126
+
121
127
  @ctx.firewall.enable_send_redirects(false)
122
128
 
123
129
  @spoof_thread = Thread.new { icmp_spoofer }
@@ -128,8 +134,7 @@ class Icmp < Base
128
134
  def stop
129
135
  raise 'ICMP redirect spoofer is not running' unless @running
130
136
 
131
- Logger.info 'Stopping ICMP redirect spoofer ...'
132
-
137
+ Logger.debug 'Stopping ICMP redirect spoofer ...'
133
138
  Logger.debug "Resetting packet forwarding to #{@forwarding} ..."
134
139
  @ctx.firewall.enable_forwarding( @forwarding )
135
140
 
@@ -156,7 +161,7 @@ class Icmp < Base
156
161
  end
157
162
 
158
163
  def dns_watcher
159
- Logger.info 'DNS watcher started ...'
164
+ Logger.debug 'DNS watcher started ...'
160
165
 
161
166
  sniff_packets('udp and port 53') { |pkt|
162
167
  next unless is_interesting_packet?(pkt)
@@ -72,8 +72,12 @@ class Target
72
72
  end
73
73
 
74
74
  # Return a verbose string representation of this object.
75
- def to_s
76
- s = sprintf( '%-15s : %-17s', if @ip.nil? then '???' else @ip end, @mac )
75
+ def to_s(padding=true)
76
+ if padding
77
+ s = sprintf( '%-15s : %-17s', if @ip.nil? then '???' else @ip end, @mac )
78
+ else
79
+ s = sprintf( '%s : %s', if @ip.nil? then '???' else @ip end, @mac )
80
+ end
77
81
  s += " / #{@hostname}" unless @hostname.nil?
78
82
  s += if @vendor.nil? then " ( ??? )" else " ( #{@vendor} )" end
79
83
  s
@@ -11,7 +11,7 @@ This project is released under the GPL 3 license.
11
11
  =end
12
12
  module BetterCap
13
13
  # Current version of bettercap.
14
- VERSION = '1.2.0'
14
+ VERSION = '1.2.1'
15
15
  # Program banner.
16
16
  BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
17
17
  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.2.0
4
+ version: 1.2.1
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-01-11 00:00:00.000000000 Z
11
+ date: 2016-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -91,6 +91,7 @@ files:
91
91
  - LICENSE.md
92
92
  - README.md
93
93
  - TODO.md
94
+ - lib/bettercap/arp_reader.rb
94
95
  - lib/bettercap/banner
95
96
  - lib/bettercap/context.rb
96
97
  - lib/bettercap/discovery/agents/arp.rb
@@ -108,6 +109,7 @@ files:
108
109
  - lib/bettercap/firewalls/redirection.rb
109
110
  - lib/bettercap/httpd/server.rb
110
111
  - lib/bettercap/hw-prefixes
112
+ - lib/bettercap/loader.rb
111
113
  - lib/bettercap/logger.rb
112
114
  - lib/bettercap/monkey/packetfu/utils.rb
113
115
  - lib/bettercap/network.rb