bettercap 1.1.4 → 1.1.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0302105b4b7c6f181542e22fff7662fa6b4b922b
4
- data.tar.gz: b46e666f283922dbe0bdb09fd6f2883dee7d89b2
3
+ metadata.gz: 724a91086ccfab829ec09e9ad381a9025dfd8380
4
+ data.tar.gz: 59292cebacc9ed01bb85d2ce3ac5a63151fd58fc
5
5
  SHA512:
6
- metadata.gz: ef42d62d1d051931e7b2ea84d56e09498e630628a1293bd3be5fc7a23d5457b57a2470896431171638bd59981ec0736a85847b359f592ca991ba378301831a34
7
- data.tar.gz: ca6291a117033ab2139a616a7e8734fbf0bc5b05b57e25299b222bfceed8bcbc9785b148a988c4c059cfd4079d79b7f24d1cdfd76a439ce3c3b35f42d0c4a6d8
6
+ metadata.gz: 7eb4990aeac1e69a85b87ea3dcd6e09f29701efc6932668919e5ecf1ba2de0a3d2c8da97b33350a7246947eef0adf5247fbc0f44c56b1520816c95a225198720
7
+ data.tar.gz: b0f32c69b41f4308b1bcbe7c9119c2b307579fbe9aaa7f2abc5d29b8c8376ada977e0ca6a8a41caff9a531da8e7b83cb97d4dcb71cf4ba23f6175d23a8a35f1c
data/.gitignore CHANGED
@@ -2,4 +2,9 @@
2
2
  *.swo
3
3
  *.gem
4
4
  *.sh
5
- .idea
5
+ .idea
6
+ cert.crt
7
+ cert.key
8
+ cert.pem
9
+ test_https_proxy.rb
10
+ mkchangelog.rb
@@ -23,6 +23,10 @@ begin
23
23
  OptionParser.new do |opts|
24
24
  opts.banner = "Usage: #{$0} [options]"
25
25
  opts.version = BetterCap::VERSION
26
+
27
+ opts.on( '-G', '--gateway ADDRESS', 'Manually specify the gateway address, if not specified the current gateway will be retrieved and used. ' ) do |v|
28
+ ctx.options[:gateway] = v
29
+ end
26
30
 
27
31
  opts.on( '-I', '--interface IFACE', 'Network interface name - default: ' + ctx.options[:iface].to_s ) do |v|
28
32
  ctx.options[:iface] = v
@@ -53,6 +57,11 @@ begin
53
57
  ctx.options[:sniffer] = true
54
58
  end
55
59
 
60
+ opts.on( '--sniffer-source FILE', 'Load packets from the specified PCAP file instead of the interface ( will enable sniffer ).' ) do |v|
61
+ ctx.options[:sniffer] = true
62
+ ctx.options[:sniffer_src] = File.expand_path v
63
+ end
64
+
56
65
  opts.on( '--sniffer-pcap FILE', 'Save all packets to the specified PCAP file ( will enable sniffer ).' ) do |v|
57
66
  ctx.options[:sniffer] = true
58
67
  ctx.options[:sniffer_pcap] = File.expand_path v
@@ -131,23 +140,7 @@ begin
131
140
 
132
141
  opts.on('-h', '--help', 'Display the available options.') do
133
142
  puts opts
134
- puts "\nExamples:\n".bold
135
- puts " - Sniffer / Credentials Harvester\n".bold
136
- puts " Default sniffer mode, all parsers enabled:\n\n"
137
- puts " sudo bettercap -X\n".bold
138
- puts " Enable sniffer and load only specified parsers:\n\n"
139
- puts " sudo bettercap -X -P \"FTP,HTTPAUTH,MAIL,NTLMSS\"\n".bold
140
- puts " Enable sniffer + all parsers and parse local traffic as well:\n\n"
141
- puts " sudo bettercap -X -L\n".bold
142
- puts " - Transparent Proxy\n".bold
143
- puts " Enable proxy on default ( 8080 ) port with no modules ( quite useless ):\n\n"
144
- puts " sudo bettercap --proxy\n".bold
145
- puts " Enable proxy and use a custom port:\n\n"
146
- puts " sudo bettercap --proxy --proxy-port=8081\n".bold
147
- puts " Enable proxy and load the module example_proxy_module.rb:\n\n"
148
- puts " sudo bettercap --proxy --proxy-module=example_proxy_module.rb\n".bold
149
- puts " Disable spoofer and enable proxy ( stand alone proxy mode ):\n\n"
150
- puts " sudo bettercap -S NONE --proxy".bold
143
+ puts "\nFor examples & instructions please visit " + "http://bettercap.org/features/".bold
151
144
  exit
152
145
  end
153
146
  end.parse!
@@ -168,10 +161,18 @@ begin
168
161
 
169
162
  Logger.logfile = ctx.options[:logfile]
170
163
 
164
+
165
+ if !ctx.options[:gateway].nil?
166
+ raise BetterCap::Error, "Invalid gateway" if !Network.is_ip?(ctx.options[:gateway])
167
+ ctx.gateway = ctx.options[:gateway]
168
+ Logger.info("Targetting manual gateway #{ctx.gateway}")
169
+ end
170
+
171
171
  ctx.update_network
172
172
 
173
173
  if ctx.options[:target].nil?
174
- Logger.info "Targeting the whole subnet #{ctx.network.to_range} ..."
174
+ Logger.info( "Targeting the whole subnet #{ctx.network.to_range} ..." ) unless \
175
+ ctx.options[:spoofer] == 'NONE' or ctx.options[:spoofer] == 'none'
175
176
 
176
177
  ctx.start_discovery_thread
177
178
  else
@@ -192,7 +193,6 @@ begin
192
193
  ctx.spoofer=Array.new
193
194
  spoofer_modules_names=ctx.options[:spoofer].split(",")
194
195
  spoofer_modules_names.each do |module_name|
195
- Logger.info "Loading module : #{module_name}"
196
196
  ctx.spoofer << SpooferFactory.get_by_name( module_name )
197
197
  ctx.spoofer.last.start
198
198
  end
@@ -12,6 +12,10 @@
12
12
 
13
13
  =end
14
14
 
15
+ # they hate us 'cause they ain't us
16
+ Encoding.default_external = Encoding::UTF_8
17
+ Encoding.default_internal = Encoding::UTF_8
18
+
15
19
  require 'optparse'
16
20
  require 'colorize'
17
21
  require 'packetfu'
@@ -3,4 +3,5 @@
3
3
  | '_ \ / _ \ __| __/ _ \ '__/ __/ _` | '_ \
4
4
  | |_) | __/ |_| || __/ | | (_| (_| | |_) |
5
5
  |_.__/ \___|\__|\__\___|_| \___\__,_| .__/
6
- |_| #VERSION#
6
+ |_| #VERSION#
7
+ http://bettercap.org/
@@ -36,6 +36,7 @@ class Context
36
36
  end
37
37
 
38
38
  @options = {
39
+ gateway: nil,
39
40
  iface: iface,
40
41
  spoofer: 'ARP',
41
42
  half_duplex: false,
@@ -47,6 +48,7 @@ class Context
47
48
  sniffer: false,
48
49
  sniffer_pcap: nil,
49
50
  sniffer_filter: nil,
51
+ sniffer_src: nil,
50
52
  parsers: ['*'],
51
53
  local: false,
52
54
 
@@ -113,7 +115,7 @@ class Context
113
115
  @firewall = FirewallFactory.get_firewall
114
116
  @ifconfig = PacketFu::Utils.ifconfig @options[:iface]
115
117
  @network = @ifconfig[:ip4_obj]
116
- @gateway = Network.get_gateway
118
+ @gateway = Network.get_gateway if @gateway.nil?
117
119
 
118
120
  raise BetterCap::Error, "Could not determine IPv4 address of '#{@options[:iface]}' interface." unless !@network.nil?
119
121
 
@@ -124,7 +126,7 @@ class Context
124
126
  def start_discovery_thread
125
127
  @discovery_running = true
126
128
  @discovery_thread = Thread.new {
127
- Logger.info 'Network discovery thread started.'
129
+ Logger.info( 'Network discovery thread started.' ) unless @options[:arpcache]
128
130
 
129
131
  while @discovery_running
130
132
  empty_list = false
@@ -158,11 +160,10 @@ class Context
158
160
  @discovery_running = false
159
161
 
160
162
  if @discovery_thread != nil
161
- Logger.info 'Stopping network discovery thread ...'
163
+ Logger.info( 'Stopping network discovery thread ...' ) unless @options[:arpcache]
162
164
 
163
- # I doubt this will ever raise an exception
164
165
  begin
165
- @discovery_thread.join
166
+ @discovery_thread.exit
166
167
  rescue
167
168
  end
168
169
  end
@@ -22,7 +22,7 @@ class IcmpAgent
22
22
  if RUBY_PLATFORM =~ /darwin/
23
23
  ping = Shell.execute("ping -i #{timeout} -c 2 255.255.255.255")
24
24
  elsif RUBY_PLATFORM =~ /linux/
25
- ping = Shell.execute("ping -i #{timeout} -c 2 -b 255.255.255.255")
25
+ ping = Shell.execute("ping -i #{timeout} -c 2 -b 255.255.255.255 2> /dev/null")
26
26
  end
27
27
  }
28
28
  end
@@ -26,10 +26,6 @@ class LinuxFirewall < IFirewall
26
26
  end
27
27
 
28
28
  def add_port_redirection( iface, proto, from, addr, to )
29
- # clear nat
30
- shell.execute('iptables -t nat -F')
31
- # clear
32
- shell.execute('iptables -F')
33
29
  # post route
34
30
  shell.execute('iptables -t nat -I POSTROUTING -s 0/0 -j MASQUERADE')
35
31
  # accept all
@@ -18,7 +18,6 @@ require 'bettercap/target'
18
18
  require 'bettercap/factories/firewall_factory'
19
19
  require 'bettercap/discovery/icmp'
20
20
  require 'bettercap/discovery/udp'
21
- require 'bettercap/discovery/syn'
22
21
  require 'bettercap/discovery/arp'
23
22
 
24
23
  class Network
@@ -70,10 +69,8 @@ class Network
70
69
  if ctx.options[:arpcache] == false
71
70
  icmp = IcmpAgent.new timeout
72
71
  udp = UdpAgent.new ctx.ifconfig, ctx.gateway, ctx.ifconfig[:ip_saddr]
73
- syn = SynAgent.new ctx.ifconfig, ctx.gateway, ctx.ifconfig[:ip_saddr]
74
72
  arp = ArpAgent.new ctx.ifconfig, ctx.gateway, ctx.ifconfig[:ip_saddr]
75
73
 
76
- syn.wait
77
74
  icmp.wait
78
75
  arp.wait
79
76
  udp.wait
@@ -85,8 +82,6 @@ class Network
85
82
  end
86
83
 
87
84
  =begin
88
- FIXME:
89
-
90
85
  Apparently on Mac OSX the gem pcaprub ( or libpcap itself ) has
91
86
  a bug, so we can't use 'PacketFu::Utils::arp' since the funtion
92
87
  it's using:
@@ -121,13 +121,14 @@ class Proxy
121
121
  total_size = opts[:request].content_length unless opts[:request].content_length.nil?
122
122
  end
123
123
 
124
- buff = ""
124
+ buff = ''
125
125
  read = 0
126
126
 
127
+
127
128
  if total_size
128
- chunk_size = 1024
129
- else
130
129
  chunk_size = [ 1024, total_size ].min
130
+ else
131
+ chunk_size = 1024
131
132
  end
132
133
 
133
134
  if chunk_size > 0
@@ -154,11 +155,17 @@ class Proxy
154
155
 
155
156
  def html_streaming( request, response, from, to )
156
157
  buff = ''
157
- loop do
158
- from.read 1024, buff
159
158
 
160
- break unless buff.size > 0
159
+ if response.content_length.nil?
160
+ loop do
161
+ from.read 1024, buff
162
+
163
+ break unless buff.size > 0
161
164
 
165
+ response << buff
166
+ end
167
+ else
168
+ from.read response.content_length, buff
162
169
  response << buff
163
170
  end
164
171
 
@@ -13,11 +13,12 @@ This project is released under the GPL 3 license.
13
13
  module Proxy
14
14
 
15
15
  class Response
16
- attr_reader :content_type, :content_length, :headers, :code, :headers_done
16
+ attr_reader :content_type, :charset, :content_length, :headers, :code, :headers_done
17
17
  attr_accessor :body
18
18
 
19
19
  def initialize
20
20
  @content_type = nil
21
+ @charset = 'UTF-8'
21
22
  @content_length = nil
22
23
  @body = ''
23
24
  @code = nil
@@ -43,22 +44,25 @@ class Response
43
44
  def <<(line)
44
45
  # we already parsed the heders, collect response body
45
46
  if @headers_done
46
- @body += line
47
+ @body += line.force_encoding( @charset )
47
48
  else
48
49
  # parse the response status
49
50
  if @code.nil? and line =~ /^HTTP\/[\d\.]+\s+(.+)/
50
51
  @code = $1.chomp
51
52
 
52
- # parse the content type
53
- elsif line =~ /^Content-Type: ([^;]+).*/i
53
+ # parse the content type
54
+ elsif line =~ /^Content-Type:\s*([^;]+).*/i
54
55
  @content_type = $1.chomp
56
+ if line =~ /^.+;\s*charset=(.+)/i
57
+ @charset = $1.chomp
58
+ end
55
59
 
56
- # parse content length
60
+ # parse content length
57
61
  elsif line =~ /^Content-Length:\s+(\d+)\s*$/i
58
62
  @content_length = $1.to_i
59
63
 
60
- # last line, we're done with the headers
61
- elsif line.chomp == ""
64
+ # last line, we're done with the headers
65
+ elsif line.chomp.empty?
62
66
  @headers_done = true
63
67
 
64
68
  end
@@ -14,23 +14,29 @@ require 'colorize'
14
14
  require 'resolv'
15
15
 
16
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
17
+ @@prev = nil
18
+
19
+ def on_packet( pkt )
20
+ begin
21
+ if pkt.tcp_dst == 443
22
+ # the DNS resolution could take a while and block other parsers.
23
+ Thread.new do
24
+ begin
25
+ hostname = Resolv.getname pkt.ip_daddr
26
+ rescue
27
+ hostname = pkt.ip_daddr.to_s
28
+ end
29
+
30
+ if @@prev.nil? or @@prev != hostname
31
+ Logger.write "[#{pkt.ip_saddr}:#{pkt.tcp_src} > #{pkt.ip_daddr}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
32
+ '[HTTPS] '.green +
33
+ "https://#{hostname}/".yellow
34
+
35
+ @@prev = hostname
32
36
  end
33
- rescue
34
37
  end
38
+ end
39
+ rescue
35
40
  end
41
+ end
36
42
  end
@@ -27,7 +27,7 @@ class Sniffer
27
27
 
28
28
  setup( ctx )
29
29
 
30
- @@cap.stream.each do |p|
30
+ self.stream.each do |p|
31
31
  begin
32
32
  parsed = Packet.parse p
33
33
  rescue Exception => e
@@ -44,6 +44,16 @@ class Sniffer
44
44
 
45
45
  private
46
46
 
47
+ def self.stream
48
+ if @@ctx.options[:sniffer_src].nil?
49
+ @@cap.stream
50
+ else
51
+ Logger.info "Reading packets from #{@@ctx.options[:sniffer_src]} ..."
52
+
53
+ PcapFile.file_to_array @@ctx.options[:sniffer_src]
54
+ end
55
+ end
56
+
47
57
  def self.skip_packet?( pkt )
48
58
  !@@ctx.options[:local] and
49
59
  ( pkt.ip_saddr == @@ctx.ifconfig[:ip_saddr] or
@@ -147,7 +147,10 @@ class ArpSpoofer < ISpoofer
147
147
  @ctx.firewall.enable_forwarding( @forwarding )
148
148
 
149
149
  @running = false
150
- @spoof_thread.join
150
+ begin
151
+ @spoof_thread.exit
152
+ rescue
153
+ end
151
154
 
152
155
  Logger.info "Restoring ARP table of #{@ctx.targets.size} targets ..."
153
156
 
@@ -10,6 +10,6 @@ This project is released under the GPL 3 license.
10
10
 
11
11
  =end
12
12
  module BetterCap
13
- VERSION = '1.1.4'
13
+ VERSION = '1.1.5'
14
14
  BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
15
15
  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.1.4
4
+ version: 1.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simone Margaritelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-08 00:00:00.000000000 Z
11
+ date: 2015-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -91,7 +91,6 @@ files:
91
91
  - lib/bettercap/discovery/arp.rb
92
92
  - lib/bettercap/discovery/base.rb
93
93
  - lib/bettercap/discovery/icmp.rb
94
- - lib/bettercap/discovery/syn.rb
95
94
  - lib/bettercap/discovery/udp.rb
96
95
  - lib/bettercap/error.rb
97
96
  - lib/bettercap/factories/firewall_factory.rb
@@ -142,7 +141,6 @@ files:
142
141
  - test/sniffer/parsers/url_parser_test.rb
143
142
  - test/target_test.rb
144
143
  - test/test_helper.rb
145
- - test_https_proxy.rb
146
144
  homepage: http://github.com/evilsocket/bettercap
147
145
  licenses:
148
146
  - GPL3
@@ -1,45 +0,0 @@
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/discovery/base'
13
-
14
- # Send SYN probes trying to filling the ARP table.
15
- class SynAgent < BaseAgent
16
- private
17
-
18
- def send_probe( ip )
19
- pkt = PacketFu::TCPPacket.new
20
- pkt.ip_v = 4
21
- pkt.ip_hl = 5
22
- pkt.ip_tos = 0
23
- pkt.ip_len = 20
24
- pkt.ip_frag = 0
25
- pkt.ip_ttl = 115
26
- pkt.ip_proto = 6 # TCP
27
- pkt.ip_saddr = @local_ip
28
- pkt.ip_daddr = ip
29
- pkt.payload = "\xC\x0\xF\xF\xE\xE"
30
- pkt.tcp_flags.ack = 0
31
- pkt.tcp_flags.fin = 0
32
- pkt.tcp_flags.psh = 0
33
- pkt.tcp_flags.rst = 0
34
- pkt.tcp_flags.syn = 1
35
- pkt.tcp_flags.urg = 0
36
- pkt.tcp_ecn = 0
37
- pkt.tcp_win = 8192
38
- pkt.tcp_hlen = 5
39
- pkt.tcp_dst = rand(1024..65535)
40
- pkt.recalc
41
-
42
- pkt.to_w( @ifconfig[:iface] )
43
- end
44
- end
45
-
@@ -1,29 +0,0 @@
1
- require 'openssl'
2
- require 'socket'
3
-
4
- sock = TCPSocket.new( '172.20.10.2', 8083 )
5
-
6
- ctx = OpenSSL::SSL::SSLContext.new
7
-
8
- # we need this? :P ctx.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER)
9
-
10
- socket = OpenSSL::SSL::SSLSocket.new(sock, ctx).tap do |socket|
11
- socket.sync_close = true
12
- socket.connect
13
-
14
- socket.write "GET / HTTP/1.1\n" +
15
- "Host: www.facebook.com\n" +
16
- "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\n" +
17
- "Accept-encoding: gzip, deflate, sdch\n" +
18
- "Accept-language: it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4,la;q=0.2\n" +
19
- "Cache-control: max-age=0\n" +
20
- "User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36\n" +
21
- "\n\n"
22
-
23
- while line = socket.gets # Read lines from socket
24
- puts line # and print them
25
- end
26
-
27
- socket.close
28
- end
29
-