bettercap 1.1.1 → 1.1.2

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