bettercap 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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