bettercap 1.1.0

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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +225 -0
  3. data/README.md +96 -0
  4. data/bettercap.gemspec +28 -0
  5. data/bin/bettercap +184 -0
  6. data/example_proxy_module.rb +21 -0
  7. data/lib/bettercap/base/ifirewall.rb +28 -0
  8. data/lib/bettercap/base/ispoofer.rb +24 -0
  9. data/lib/bettercap/context.rb +124 -0
  10. data/lib/bettercap/discovery/arp.rb +37 -0
  11. data/lib/bettercap/discovery/icmp.rb +37 -0
  12. data/lib/bettercap/discovery/syn.rb +88 -0
  13. data/lib/bettercap/discovery/udp.rb +74 -0
  14. data/lib/bettercap/error.rb +16 -0
  15. data/lib/bettercap/factories/firewall_factory.rb +32 -0
  16. data/lib/bettercap/factories/parser_factory.rb +53 -0
  17. data/lib/bettercap/factories/spoofer_factory.rb +36 -0
  18. data/lib/bettercap/firewalls/linux.rb +55 -0
  19. data/lib/bettercap/firewalls/osx.rb +70 -0
  20. data/lib/bettercap/hw-prefixes +19651 -0
  21. data/lib/bettercap/logger.rb +53 -0
  22. data/lib/bettercap/monkey/packetfu/utils.rb +96 -0
  23. data/lib/bettercap/network.rb +131 -0
  24. data/lib/bettercap/proxy/module.rb +39 -0
  25. data/lib/bettercap/proxy/proxy.rb +262 -0
  26. data/lib/bettercap/proxy/request.rb +77 -0
  27. data/lib/bettercap/proxy/response.rb +76 -0
  28. data/lib/bettercap/shell.rb +31 -0
  29. data/lib/bettercap/sniffer/parsers/base.rb +31 -0
  30. data/lib/bettercap/sniffer/parsers/ftp.rb +19 -0
  31. data/lib/bettercap/sniffer/parsers/httpauth.rb +45 -0
  32. data/lib/bettercap/sniffer/parsers/https.rb +36 -0
  33. data/lib/bettercap/sniffer/parsers/irc.rb +19 -0
  34. data/lib/bettercap/sniffer/parsers/mail.rb +19 -0
  35. data/lib/bettercap/sniffer/parsers/ntlmss.rb +38 -0
  36. data/lib/bettercap/sniffer/parsers/post.rb +24 -0
  37. data/lib/bettercap/sniffer/parsers/url.rb +28 -0
  38. data/lib/bettercap/sniffer/sniffer.rb +39 -0
  39. data/lib/bettercap/spoofers/arp.rb +130 -0
  40. data/lib/bettercap/spoofers/none.rb +23 -0
  41. data/lib/bettercap/target.rb +52 -0
  42. data/lib/bettercap/version.rb +14 -0
  43. metadata +129 -0
@@ -0,0 +1,77 @@
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 Proxy
14
+
15
+ class Request
16
+ attr_reader :lines, :verb, :url, :host, :port, :content_length
17
+
18
+ def initialize
19
+ @lines = []
20
+ @verb = nil
21
+ @url = nil
22
+ @host = nil
23
+ @port = 80
24
+ @content_length = 0
25
+ end
26
+
27
+ def <<(line)
28
+ line = line.chomp
29
+
30
+ # is this the first line '<VERB> <URI> HTTP/<VERSION>' ?
31
+ if @url.nil? and line =~ /^(\w+)\s+(\S+)\s+HTTP\/[\d\.]+\s*$/
32
+ @verb = $1
33
+ @url = $2
34
+
35
+ # fix url
36
+ if @url.include? '://'
37
+ uri = URI::parse @url
38
+ @url = "#{uri.path}" + ( uri.query ? "?#{uri.query}" : "" )
39
+ end
40
+
41
+ line = "#{@verb} #{url} HTTP/1.0"
42
+
43
+ # get the host header value
44
+ elsif line =~ /^Host: (.*)$/
45
+ @host = $1
46
+ if host =~ /([^:]*):([0-9]*)$/
47
+ @host = $1
48
+ @port = $2.to_i
49
+ end
50
+
51
+ # parse content length, this will speed up data streaming
52
+ elsif line =~ /^Content-Length:\s+(\d+)\s*$/i
53
+ @content_length = $1.to_i
54
+
55
+ # we don't want to have hundreds of threads running
56
+ elsif line =~ /Connection: keep-alive/i
57
+ line = 'Connection: close'
58
+
59
+ # disable gzip, chunked, etc encodings
60
+ elsif line =~ /^Accept-Encoding:.*/i
61
+ line = 'Accept-Encoding: identity'
62
+
63
+ end
64
+
65
+ @lines << line
66
+ end
67
+
68
+ def is_post?
69
+ return @verb == 'POST'
70
+ end
71
+
72
+ def to_s
73
+ return @lines.join("\n") + "\n"
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,76 @@
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 Proxy
14
+
15
+ class Response
16
+ attr_reader :content_type, :content_length, :headers, :code, :headers_done
17
+ attr_accessor :body
18
+
19
+ def initialize
20
+ @content_type = nil
21
+ @content_length = nil
22
+ @body = ''
23
+ @code = nil
24
+ @headers = []
25
+ @headers_done = false
26
+ end
27
+
28
+ def <<(line)
29
+ # we already parsed the heders, collect response body
30
+ if @headers_done
31
+ @body += line
32
+ else
33
+ # parse the response status
34
+ if @code.nil? and line =~ /^HTTP\/[\d\.]+\s+(.+)/
35
+ @code = $1.chomp
36
+
37
+ # parse the content type
38
+ elsif line =~ /^Content-Type: ([^;]+).*/i
39
+ @content_type = $1.chomp
40
+
41
+ # parse content length
42
+ elsif line =~ /^Content-Length:\s+(\d+)\s*$/i
43
+ @content_length = $1.to_i
44
+
45
+ # last line, we're done with the headers
46
+ elsif line.chomp == ""
47
+ @headers_done = true
48
+
49
+ end
50
+
51
+ @headers << line.chomp
52
+ end
53
+ end
54
+
55
+ def is_textual?
56
+ @content_type and ( @content_type =~ /^text\/.+/ or @content_type =~ /^application\/.+/ )
57
+ end
58
+
59
+ def to_s
60
+ if is_textual?
61
+ @headers.map! do |header|
62
+ # update content length in case the body was
63
+ # modified
64
+ if header =~ /Content-Length:\s*(\d+)/i
65
+ "Content-Length: #{@body.size}"
66
+ else
67
+ header
68
+ end
69
+ end
70
+ end
71
+
72
+ @headers.join("\n") + "\n" + @body
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,31 @@
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 Shell
11
+ class << self
12
+
13
+ #return the output of command
14
+ def execute(command)
15
+ r=%x(#{command})
16
+ if $? != 0
17
+ raise BetterCap::Error, "Error, executing #{command}"
18
+ end
19
+ return r
20
+ end
21
+
22
+ def ifconfig(iface = '')
23
+ self.execute( "LANG=en && ifconfig #{iface}" )
24
+ end
25
+
26
+ def arp
27
+ self.execute( 'LANG=en && arp -a' )
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,31 @@
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
+ require 'colorize'
14
+
15
+ class BaseParser
16
+ def initialize
17
+ @filters = []
18
+ @name = 'BASE'
19
+ end
20
+
21
+ def on_packet( pkt )
22
+ s = pkt.to_s
23
+ @filters.each do |filter|
24
+ if s =~ filter
25
+ Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
26
+ "[#{@name}] ".green +
27
+ pkt.payload.strip.yellow
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
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/sniffer/parsers/base'
13
+
14
+ class FtpParser < BaseParser
15
+ def initialize
16
+ @filters = [ /(USER|PASS)\s+.+/ ]
17
+ @name = 'FTP'
18
+ end
19
+ 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
+ require 'bettercap/sniffer/parsers/base'
13
+ require 'colorize'
14
+ require 'base64'
15
+
16
+ class HttpauthParser < BaseParser
17
+ def on_packet( pkt )
18
+ lines = pkt.to_s.split("\n")
19
+ hostname = nil
20
+ path = nil
21
+
22
+ lines.each do |line|
23
+ if line =~ /[A-Z]+\s+(\/[^\s]+)\s+HTTP\/\d\.\d/
24
+ path = $1
25
+
26
+ elsif line =~ /Host:\s*([^\s]+)/i
27
+ hostname = $1
28
+
29
+ elsif line =~ /Authorization:\s*Basic\s+([^\s]+)/i
30
+ encoded = $1
31
+ decoded = Base64.decode64(encoded)
32
+ user, pass = decoded.split(':')
33
+
34
+ Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
35
+ '[HTTP BASIC AUTH]'.green + " http://#{hostname}#{path} - username=#{user} password=#{pass}".yellow
36
+
37
+ elsif line =~ /Authorization:\s*Digest\s+(.+)/i
38
+ Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
39
+ '[HTTP DIGEST AUTH]'.green + " http://#{hostname}#{path}\n#{$1}".yellow
40
+
41
+ end
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,36 @@
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/sniffer/parsers/base'
13
+ require 'colorize'
14
+ require 'resolv'
15
+
16
+ class HttpsParser < BaseParser
17
+ def on_packet( pkt )
18
+ begin
19
+ if pkt.tcp_dst == 443
20
+ # the DNS resolution could take a while and block other parsers.
21
+ Thread.new do
22
+ begin
23
+ hostname = Resolv.getname pkt.ip_daddr
24
+ rescue
25
+ hostname = pkt.ip_daddr.to_s
26
+ end
27
+
28
+ Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
29
+ '[HTTPS] '.green +
30
+ "https://#{hostname}/".yellow
31
+ end
32
+ end
33
+ rescue
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
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/sniffer/parsers/base'
13
+
14
+ class IrcParser < BaseParser
15
+ def initialize
16
+ @filters = [ /NICK\s+.+/, /NS IDENTIFY\s+.+/, /nickserv :identify\s+.+/ ]
17
+ @name = 'IRC'
18
+ end
19
+ end
@@ -0,0 +1,19 @@
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/sniffer/parsers/base'
13
+
14
+ class MailParser < BaseParser
15
+ def initialize
16
+ @filters = [ /(\d+ )?(auth|authenticate) (login|plain)/i, /(\d+ )?login/i ]
17
+ @name = 'MAIL'
18
+ end
19
+ end
@@ -0,0 +1,38 @@
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/sniffer/parsers/base'
13
+ require 'colorize'
14
+
15
+ class NtlmssParser < BaseParser
16
+ def bin2hex( data )
17
+ hex = ''
18
+ data.each_byte do |byte|
19
+ if /[[:print:]]/ === byte.chr
20
+ hex += byte.chr
21
+ else
22
+ hex += "\\x" + byte.to_s(16)
23
+ end
24
+ end
25
+
26
+ hex
27
+ end
28
+
29
+ def on_packet( pkt )
30
+ s = pkt.to_s
31
+ if s =~ /NTLMSSP\x00\x03\x00\x00\x00.+/
32
+ # TODO: Parse NTLMSSP packet.
33
+ Logger.write "[#{pkt.ip_saddr} > #{pkt.ip_daddr} #{pkt.proto.last}] " +
34
+ '[NTLMSS] '.green +
35
+ bin2hex( pkt.payload ).yellow
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,24 @@
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/sniffer/parsers/base'
13
+ require 'colorize'
14
+
15
+ class PostParser < BaseParser
16
+ def on_packet( pkt )
17
+ s = pkt.to_s
18
+ if s =~ /POST\s+[^\s]+\s+HTTP.+/
19
+ Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
20
+ "[POST]\n".green +
21
+ pkt.payload.strip.yellow
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
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/sniffer/parsers/base'
13
+ require 'colorize'
14
+
15
+ class UrlParser < BaseParser
16
+ def on_packet( pkt )
17
+ s = pkt.to_s
18
+ if s =~ /GET\s+([^\s]+)\s+HTTP.+Host:\s+([^\s]+).+/m
19
+ host = $2
20
+ url = $1
21
+ if not url =~ /.+\.(png|jpg|jpeg|bmp|gif|img|ttf|woff|css|js).*/i
22
+ Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
23
+ '[GET] '.green +
24
+ "http://#{host}#{url}".yellow
25
+ end
26
+ end
27
+ end
28
+ end