bettercap 1.1.1 → 1.1.2

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.
@@ -12,9 +12,11 @@ This project is released under the GPL 3 license.
12
12
  require 'bettercap/logger'
13
13
  require 'bettercap/shell'
14
14
  require 'bettercap/target'
15
+ require 'bettercap/discovery/base'
15
16
 
16
17
  # Parse the ARP table searching for new hosts.
17
- class ArpAgent
18
+ class ArpAgent < BaseAgent
19
+
18
20
  def self.parse( ctx )
19
21
  arp = Shell.arp
20
22
  targets = []
@@ -24,7 +26,7 @@ class ArpAgent
24
26
  arp.split("\n").each do |line|
25
27
  m = /[^\s]+\s+\(([0-9\.]+)\)\s+at\s+([a-f0-9:]+).+#{ctx.ifconfig[:iface]}.*/i.match(line)
26
28
  if !m.nil?
27
- if m[1] != ctx.gateway and m[1] != ctx.iface[:ip_saddr] and m[2] != 'ff:ff:ff:ff:ff:ff'
29
+ if m[1] != ctx.gateway and m[1] != ctx.ifconfig[:ip_saddr] and m[2] != 'ff:ff:ff:ff:ff:ff'
28
30
  target = Target.new( m[1], m[2] )
29
31
  targets << target
30
32
  Logger.debug "FOUND #{target}"
@@ -34,4 +36,18 @@ class ArpAgent
34
36
 
35
37
  targets
36
38
  end
39
+
40
+ private
41
+
42
+ def send_probe( ip )
43
+ pkt = PacketFu::ARPPacket.new
44
+
45
+ pkt.eth_saddr = pkt.arp_saddr_mac = @ifconfig[:eth_saddr]
46
+ pkt.eth_daddr = 'ff:ff:ff:ff:ff:ff'
47
+ pkt.arp_daddr_mac = '00:00:00:00:00:00'
48
+ pkt.arp_saddr_ip = @ifconfig[:ip_saddr]
49
+ pkt.arp_daddr_ip = ip
50
+
51
+ pkt.to_w( @ifconfig[:iface] )
52
+ end
37
53
  end
@@ -0,0 +1,64 @@
1
+ =begin
2
+
3
+ BETTERCAP
4
+
5
+ Author : Simone 'evilsocket' Margaritelli
6
+ Email : evilsocket@gmail.com
7
+ Blog : http://www.evilsocket.net/
8
+
9
+ This project is released under the GPL 3 license.
10
+
11
+ =end
12
+ require 'bettercap/logger'
13
+
14
+ # Base class for discovery agents.
15
+ class BaseAgent
16
+ def initialize( ifconfig, gw_ip, local_ip )
17
+ @local_ip = local_ip
18
+ @ifconfig = ifconfig
19
+ @queue = Queue.new
20
+
21
+ net = ip = @ifconfig[:ip4_obj]
22
+
23
+ # loop each ip in our subnet and push it to the queue
24
+ while net.include?ip
25
+ # rescanning the gateway could cause an issue when the
26
+ # gateway itself has multiple interfaces ( LAN, WAN ... )
27
+ if ip != gw_ip and ip != local_ip
28
+ @queue.push ip
29
+ end
30
+
31
+ ip = ip.succ
32
+ end
33
+
34
+ # spawn the workers! ( tnx to https://blog.engineyard.com/2014/ruby-thread-pool )
35
+ @workers = (0...4).map do
36
+ Thread.new do
37
+ begin
38
+ while ip = @queue.pop(true)
39
+ Logger.debug "#{self.class.name} : Probing #{ip} ..."
40
+
41
+ send_probe ip.to_s
42
+ end
43
+ rescue Exception => e
44
+ Logger.debug "#{self.class.name} : #{ip} -> #{e.message}"
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def wait
51
+ begin
52
+ @workers.map(&:join)
53
+ rescue Exception => e
54
+ Logger.debug "#{self.class.name}.wait: #{e.message}"
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def send_probe( ip )
61
+ Logger.warn "#{self.class.name} not implemented!"
62
+ end
63
+ end
64
+
@@ -16,15 +16,15 @@ require 'bettercap/factories/firewall_factory'
16
16
  # Send a broadcast ping trying to filling the ARP table.
17
17
  class IcmpAgent
18
18
  def initialize( timeout = 5 )
19
- @thread = Thread.new do
19
+ @thread = Thread.new {
20
20
  FirewallFactory.get_firewall.enable_icmp_bcast(true)
21
21
 
22
22
  if RUBY_PLATFORM =~ /darwin/
23
23
  ping = Shell.execute("ping -i #{timeout} -c 2 255.255.255.255")
24
- elsif RUBY_PLATFORM =~ /linux/
24
+ elsif RUBY_PLATFORM =~ /linux/
25
25
  ping = Shell.execute("ping -i #{timeout} -c 2 -b 255.255.255.255")
26
26
  end
27
- end
27
+ }
28
28
  end
29
29
 
30
30
  def wait
@@ -9,57 +9,13 @@ Blog : http://www.evilsocket.net/
9
9
  This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
- require 'bettercap/logger'
12
+ require 'bettercap/discovery/base'
13
13
 
14
14
  # Send SYN probes trying to filling the ARP table.
15
- class SynAgent
16
- def initialize( ifconfig, gw_ip, local_ip )
17
- @local_ip = local_ip
18
- @ifconfig = ifconfig
19
- @queue = Queue.new
20
-
21
- net = ip = @ifconfig[:ip4_obj]
22
-
23
- # loop each ip in our subnet and push it to the queue
24
- while net.include?ip
25
- # rescanning the gateway could cause an issue when the
26
- # gateway itself has multiple interfaces ( LAN, WAN ... )
27
- if ip != gw_ip and ip != local_ip
28
- @queue.push ip
29
- end
30
-
31
- ip = ip.succ
32
- end
33
-
34
- # spawn the workers! ( tnx to https://blog.engineyard.com/2014/ruby-thread-pool )
35
- @workers = (0...4).map do
36
- Thread.new do
37
- begin
38
- while ip = @queue.pop(true)
39
- Logger.debug "SYN Probing #{ip} ..."
40
-
41
- pkt = get_packet ip.to_s
42
-
43
- pkt.to_w( @ifconfig[:iface] )
44
- end
45
- rescue Exception => e
46
- Logger.debug "#{ip} -> #{e.message}"
47
- end
48
- end
49
- end
50
- end
51
-
52
- def wait
53
- begin
54
- @workers.map(&:join)
55
- rescue Exception => e
56
- Logger.debug "SynAgent.wait: #{e.message}"
57
- end
58
- end
59
-
15
+ class SynAgent < BaseAgent
60
16
  private
61
17
 
62
- def get_packet( destination )
18
+ def send_probe( ip )
63
19
  pkt = PacketFu::TCPPacket.new
64
20
  pkt.ip_v = 4
65
21
  pkt.ip_hl = 5
@@ -69,7 +25,7 @@ class SynAgent
69
25
  pkt.ip_ttl = 115
70
26
  pkt.ip_proto = 6 # TCP
71
27
  pkt.ip_saddr = @local_ip
72
- pkt.ip_daddr = destination
28
+ pkt.ip_daddr = ip
73
29
  pkt.payload = "\xC\x0\xF\xF\xE\xE"
74
30
  pkt.tcp_flags.ack = 0
75
31
  pkt.tcp_flags.fin = 0
@@ -82,7 +38,8 @@ class SynAgent
82
38
  pkt.tcp_hlen = 5
83
39
  pkt.tcp_dst = rand(1024..65535)
84
40
  pkt.recalc
85
- pkt
41
+
42
+ pkt.to_w( @ifconfig[:iface] )
86
43
  end
87
44
  end
88
45
 
@@ -9,66 +9,31 @@ Blog : http://www.evilsocket.net/
9
9
  This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
- require 'bettercap/logger'
12
+ require 'bettercap/discovery/base'
13
13
 
14
14
  # Send UDP probes trying to filling the ARP table.
15
- class UdpAgent
16
- def initialize( ifconfig, gw_ip, local_ip )
17
- @ifconfig = ifconfig
18
- @port = 137
19
- @message =
20
- "\x82\x28\x00\x00\x00" +
21
- "\x01\x00\x00\x00\x00" +
22
- "\x00\x00\x20\x43\x4B" +
23
- "\x41\x41\x41\x41\x41" +
24
- "\x41\x41\x41\x41\x41" +
25
- "\x41\x41\x41\x41\x41" +
26
- "\x41\x41\x41\x41\x41" +
27
- "\x41\x41\x41\x41\x41" +
28
- "\x41\x41\x41\x41\x41" +
29
- "\x00\x00\x21\x00\x01"
30
-
31
- @queue = Queue.new
32
-
33
- net = ip = @ifconfig[:ip4_obj]
34
-
35
- # loop each ip in our subnet and push it to the queue
36
- while net.include?ip
37
- # rescanning the gateway could cause an issue when the
38
- # gateway itself has multiple interfaces ( LAN, WAN ... )
39
- if ip != gw_ip and ip != local_ip
40
- @queue.push ip
41
- end
42
-
43
- ip = ip.succ
44
- end
45
-
46
- # spawn the workers! ( tnx to https://blog.engineyard.com/2014/ruby-thread-pool )
47
- @workers = (0...4).map do
48
- Thread.new do
49
- begin
50
- while ip = @queue.pop(true)
51
- Logger.debug "Probing #{ip} ..."
52
-
53
- # send netbios udp packet, just to fill ARP table
54
- sd = UDPSocket.new
55
- sd.send( @message, 0, ip.to_s, @port )
56
- sd = nil
57
- # TODO: Parse response for hostname?
58
- end
59
- rescue Exception => e
60
- Logger.debug "#{ip} -> #{e.message}"
61
- end
62
- end
63
- end
64
- end
65
-
66
- def wait
67
- begin
68
- @workers.map(&:join)
69
- rescue Exception => e
70
- Logger.debug "UdpAgent.wait: #{e.message}"
71
- end
15
+ class UdpAgent < BaseAgent
16
+ private
17
+
18
+ def send_probe( ip )
19
+ port = 137
20
+ message =
21
+ "\x82\x28\x00\x00\x00" +
22
+ "\x01\x00\x00\x00\x00" +
23
+ "\x00\x00\x20\x43\x4B" +
24
+ "\x41\x41\x41\x41\x41" +
25
+ "\x41\x41\x41\x41\x41" +
26
+ "\x41\x41\x41\x41\x41" +
27
+ "\x41\x41\x41\x41\x41" +
28
+ "\x41\x41\x41\x41\x41" +
29
+ "\x41\x41\x41\x41\x41" +
30
+ "\x00\x00\x21\x00\x01"
31
+
32
+ # send netbios udp packet, just to fill ARP table
33
+ sd = UDPSocket.new
34
+ sd.send( message, 0, ip.to_s, port )
35
+ sd = nil
36
+ # TODO: Parse response for hostname?
72
37
  end
73
38
  end
74
39
 
@@ -16,7 +16,7 @@ require 'bettercap/firewalls/linux'
16
16
  class FirewallFactory
17
17
  @@instance = nil
18
18
 
19
- def FirewallFactory.get_firewall
19
+ def self.get_firewall
20
20
  return @@instance unless @@instance.nil?
21
21
 
22
22
  if RUBY_PLATFORM =~ /darwin/
@@ -16,38 +16,40 @@ require 'bettercap/logger'
16
16
  class ParserFactory
17
17
  @@path = File.dirname(__FILE__) + '/../sniffer/parsers/'
18
18
 
19
- def ParserFactory.available
20
- avail = []
21
- Dir.foreach( @@path ) do |file|
22
- if file =~ /.rb/ and file != 'base.rb'
23
- avail << file.gsub('.rb','').upcase
19
+ class << self
20
+ def available
21
+ avail = []
22
+ Dir.foreach( @@path ) do |file|
23
+ if file =~ /.rb/ and file != 'base.rb'
24
+ avail << file.gsub('.rb','').upcase
25
+ end
24
26
  end
27
+ avail
25
28
  end
26
- avail
27
- end
28
29
 
29
- def ParserFactory.from_cmdline(v)
30
- avail = ParserFactory.available
31
- list = v.split(',').collect(&:strip).collect(&:upcase).reject{ |c| c.empty? }
32
- list.each do |parser|
33
- raise BetterCap::Error, "Invalid parser name '#{parser}'." unless avail.include?(parser) or parser == '*'
30
+ def from_cmdline(v)
31
+ avail = available
32
+ list = v.split(',').collect(&:strip).collect(&:upcase).reject{ |c| c.empty? }
33
+ list.each do |parser|
34
+ raise BetterCap::Error, "Invalid parser name '#{parser}'." unless avail.include?(parser) or parser == '*'
35
+ end
36
+ list
34
37
  end
35
- list
36
- end
37
38
 
38
- def ParserFactory.load_by_names(parsers)
39
- loaded = []
40
- Dir.foreach( @@path ) do |file|
41
- cname = file.gsub('.rb','').upcase
42
- if file =~ /.rb/ and file != 'base.rb' and ( parsers.include?(cname) or parsers == ['*'] )
43
- Logger.debug "Loading parser #{cname} ..."
44
-
45
- require_relative "#{@@path}#{file}"
46
-
47
- loaded << Kernel.const_get("#{cname.capitalize}Parser").new
39
+ def ParserFactory.load_by_names(parsers)
40
+ loaded = []
41
+ Dir.foreach( @@path ) do |file|
42
+ cname = file.gsub('.rb','').upcase
43
+ if file =~ /.rb/ and file != 'base.rb' and ( parsers.include?(cname) or parsers == ['*'] )
44
+ Logger.debug "Loading parser #{cname} ..."
45
+
46
+ require_relative "#{@@path}#{file}"
47
+
48
+ loaded << Kernel.const_get("#{cname.capitalize}Parser").new
49
+ end
48
50
  end
51
+ loaded
49
52
  end
50
- loaded
51
53
  end
52
54
  end
53
55
 
@@ -12,25 +12,31 @@ This project is released under the GPL 3 license.
12
12
  require 'bettercap/error'
13
13
 
14
14
  class SpooferFactory
15
- def SpooferFactory.available
16
- avail = []
17
- Dir.foreach( File.dirname(__FILE__) + '/../spoofers/') do |file|
18
- if file =~ /.rb/
19
- avail << file.gsub('.rb','').upcase
15
+ class << self
16
+ def available
17
+ avail = []
18
+ Dir.foreach( File.dirname(__FILE__) + '/../spoofers/') do |file|
19
+ if file =~ /.rb/
20
+ avail << file.gsub('.rb','').upcase
21
+ end
20
22
  end
23
+ avail
21
24
  end
22
- avail
23
- end
24
25
 
25
- def SpooferFactory.get_by_name(name)
26
- avail = SpooferFactory.available
26
+ def get_by_name(name)
27
+ raise BetterCap::Error, "Invalid spoofer name '#{name}'!" unless available? name
28
+
29
+ name.downcase!
27
30
 
28
- raise BetterCap::Error, "Invalid spoofer name '#{name}'!" unless avail.include? name
31
+ require_relative "../spoofers/#{name}"
29
32
 
30
- name.downcase!
33
+ Kernel.const_get("#{name.capitalize}Spoofer").new
34
+ end
31
35
 
32
- require_relative "../spoofers/#{name}"
36
+ private
33
37
 
34
- Kernel.const_get("#{name.capitalize}Spoofer").new
38
+ def available?(name)
39
+ available.include?(name)
40
+ end
35
41
  end
36
42
  end
@@ -14,23 +14,15 @@ require 'bettercap/shell'
14
14
 
15
15
  class LinuxFirewall < IFirewall
16
16
  def enable_forwarding(enabled)
17
- if enabled then
18
- Shell.execute('echo 1 > /proc/sys/net/ipv4/ip_forward')
19
- else
20
- Shell.execute('echo 0 > /proc/sys/net/ipv4/ip_forward')
21
- end
17
+ Shell.execute("echo #{enabled ? 1 : 0} > /proc/sys/net/ipv4/ip_forward")
22
18
  end
23
19
 
24
20
  def forwarding_enabled?
25
21
  Shell.execute('cat /proc/sys/net/ipv4/ip_forward').strip == '1'
26
22
  end
27
-
23
+
28
24
  def enable_icmp_bcast(enabled)
29
- if enabled then
30
- Shell.execute('echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts')
31
- else
32
- Shell.execute('echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts')
33
- end
25
+ Shell.execute("echo #{enabled ? 0 : 1} > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts")
34
26
  end
35
27
 
36
28
  def add_port_redirection( iface, proto, from, addr, to )
@@ -14,34 +14,21 @@ require 'bettercap/shell'
14
14
 
15
15
  class OSXFirewall < IFirewall
16
16
  def enable_forwarding(enabled)
17
- if enabled then
18
- Shell.execute('sysctl -w net.inet.ip.forwarding=1')
19
- else
20
- Shell.execute('sysctl -w net.inet.ip.forwarding=0')
21
- end
17
+ Shell.execute("sysctl -w net.inet.ip.forwarding=#{enabled ? 1 : 0}")
22
18
  end
23
19
 
24
20
  def enable_icmp_bcast(enabled)
25
- if enabled then
26
- Shell.execute('sysctl -w net.inet.icmp.bmcastecho=1')
27
- else
28
- Shell.execute('sysctl -w net.inet.icmp.bmcastecho=0')
29
- end
21
+ Shell.execute("sysctl -w net.inet.icmp.bmcastecho=#{enabled ? 1 : 0}")
30
22
  end
31
23
 
32
- def forwarding_enabled?()
24
+ def forwarding_enabled?
33
25
  Shell.execute('sysctl net.inet.ip.forwarding').strip.split(' ')[1] == '1'
34
26
  end
35
27
 
36
28
  def enable(enabled)
37
29
  begin
38
- if enabled
39
- Shell.execute('pfctl -e >/dev/null 2>&1')
40
- else
41
- Shell.execute('pfctl -d >/dev/null 2>&1')
42
- end
43
- rescue
44
- end
30
+ Shell.execute("pfctl -#{enabled ? ?e : ?d} >/dev/null 2>&1")
31
+ rescue; end
45
32
  end
46
33
 
47
34
  def add_port_redirection( iface, proto, from, addr, to )