bettercap 1.1.8 → 1.1.9
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 +4 -4
- data/TODO.md +2 -0
- data/bin/bettercap +17 -186
- data/lib/bettercap.rb +2 -0
- data/lib/bettercap/base/ifirewall.rb +2 -2
- data/lib/bettercap/context.rb +46 -126
- data/lib/bettercap/discovery.rb +57 -0
- data/lib/bettercap/firewalls/linux.rb +4 -4
- data/lib/bettercap/firewalls/osx.rb +3 -3
- data/lib/bettercap/logger.rb +23 -17
- data/lib/bettercap/network.rb +0 -5
- data/lib/bettercap/options.rb +182 -1
- data/lib/bettercap/proxy/stream_logger.rb +1 -1
- data/lib/bettercap/shell.rb +14 -5
- data/lib/bettercap/sniffer/parsers/base.rb +1 -1
- data/lib/bettercap/sniffer/parsers/httpauth.rb +2 -2
- data/lib/bettercap/sniffer/parsers/https.rb +1 -1
- data/lib/bettercap/sniffer/parsers/ntlmss.rb +1 -1
- data/lib/bettercap/sniffer/parsers/post.rb +1 -1
- data/lib/bettercap/sniffer/parsers/url.rb +1 -1
- data/lib/bettercap/sniffer/sniffer.rb +18 -15
- data/lib/bettercap/spoofers/arp.rb +14 -13
- data/lib/bettercap/target.rb +18 -7
- data/lib/bettercap/update_checker.rb +53 -0
- data/lib/bettercap/version.rb +1 -1
- data/test/logger_test.rb +1 -1
- metadata +7 -9
- data/.gitignore +0 -12
- data/Gemfile +0 -2
- data/Gemfile.lock +0 -25
- data/bettercap.gemspec +0 -28
@@ -28,7 +28,7 @@ class HttpsParser < BaseParser
|
|
28
28
|
end
|
29
29
|
|
30
30
|
if @@prev.nil? or @@prev != hostname
|
31
|
-
Logger.
|
31
|
+
Logger.raw "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
|
32
32
|
'[HTTPS] '.green +
|
33
33
|
"https://#{hostname}/".yellow
|
34
34
|
|
@@ -30,7 +30,7 @@ class NtlmssParser < BaseParser
|
|
30
30
|
s = pkt.to_s
|
31
31
|
if s =~ /NTLMSSP\x00\x03\x00\x00\x00.+/
|
32
32
|
# TODO: Parse NTLMSSP packet.
|
33
|
-
Logger.
|
33
|
+
Logger.raw "[#{addr2s(pkt.ip_saddr)} > #{addr2s(pkt.ip_daddr)} #{pkt.proto.last}] " +
|
34
34
|
'[NTLMSS] '.green +
|
35
35
|
bin2hex( pkt.payload ).yellow
|
36
36
|
end
|
@@ -16,7 +16,7 @@ class PostParser < BaseParser
|
|
16
16
|
def on_packet( pkt )
|
17
17
|
s = pkt.to_s
|
18
18
|
if s =~ /POST\s+[^\s]+\s+HTTP.+/
|
19
|
-
Logger.
|
19
|
+
Logger.raw "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
|
20
20
|
"[POST]\n".green +
|
21
21
|
pkt.payload.strip.yellow
|
22
22
|
end
|
@@ -19,7 +19,7 @@ class UrlParser < BaseParser
|
|
19
19
|
host = $2
|
20
20
|
url = $1
|
21
21
|
if not url =~ /.+\.(png|jpg|jpeg|bmp|gif|img|ttf|woff|css|js).*/i
|
22
|
-
Logger.
|
22
|
+
Logger.raw "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
|
23
23
|
'[GET] '.green +
|
24
24
|
"http://#{host}#{url}".yellow
|
25
25
|
end
|
@@ -23,21 +23,24 @@ class Sniffer
|
|
23
23
|
@@cap = nil
|
24
24
|
|
25
25
|
def self.start( ctx )
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
26
|
+
Thread.new do
|
27
|
+
Logger.info 'Starting sniffer ...'
|
28
|
+
|
29
|
+
setup( ctx )
|
30
|
+
|
31
|
+
self.stream.each do |p|
|
32
|
+
break unless @@ctx.running
|
33
|
+
begin
|
34
|
+
parsed = Packet.parse p
|
35
|
+
rescue Exception => e
|
36
|
+
parsed = nil
|
37
|
+
Logger.debug e.message
|
38
|
+
end
|
39
|
+
|
40
|
+
if not parsed.nil? and parsed.is_ip? and !skip_packet?(parsed)
|
41
|
+
append_packet p
|
42
|
+
parse_packet parsed
|
43
|
+
end
|
41
44
|
end
|
42
45
|
end
|
43
46
|
end
|
@@ -19,22 +19,21 @@ require 'colorize'
|
|
19
19
|
class ArpSpoofer < ISpoofer
|
20
20
|
def initialize
|
21
21
|
@ctx = Context.get
|
22
|
-
@
|
22
|
+
@gateway = nil
|
23
23
|
@forwarding = @ctx.firewall.forwarding_enabled?
|
24
24
|
@spoof_thread = nil
|
25
25
|
@sniff_thread = nil
|
26
26
|
@capture = nil
|
27
27
|
@running = false
|
28
28
|
|
29
|
-
Logger.debug 'ARP SPOOFER SELECTED'
|
30
|
-
|
31
29
|
Logger.info "Getting gateway #{@ctx.gateway} MAC address ..."
|
32
|
-
@gw_hw = Network.get_hw_address( @ctx.ifconfig, @ctx.gateway )
|
33
|
-
if @gw_hw.nil?
|
34
|
-
raise BetterCap::Error, "Couldn't determine router MAC"
|
35
|
-
end
|
36
30
|
|
37
|
-
|
31
|
+
hw = Network.get_hw_address( @ctx.ifconfig, @ctx.gateway )
|
32
|
+
raise BetterCap::Error, "Couldn't determine router MAC" if hw.nil?
|
33
|
+
|
34
|
+
@gateway = Target.new( @ctx.gateway, hw )
|
35
|
+
|
36
|
+
Logger.info " #{@gateway}"
|
38
37
|
end
|
39
38
|
|
40
39
|
def send_spoofed_packet( saddr, smac, daddr, dmac )
|
@@ -122,8 +121,8 @@ class ArpSpoofer < ISpoofer
|
|
122
121
|
end
|
123
122
|
end
|
124
123
|
|
125
|
-
send_spoofed_packet( @
|
126
|
-
send_spoofed_packet( target.ip, @ctx.ifconfig[:eth_saddr], @
|
124
|
+
send_spoofed_packet( @gateway.ip, @ctx.ifconfig[:eth_saddr], target.ip, target.mac )
|
125
|
+
send_spoofed_packet( target.ip, @ctx.ifconfig[:eth_saddr], @gateway.ip, @gateway.mac ) unless @ctx.options.half_duplex
|
127
126
|
end
|
128
127
|
|
129
128
|
prev_size = @ctx.targets.size
|
@@ -150,9 +149,11 @@ class ArpSpoofer < ISpoofer
|
|
150
149
|
Logger.info "Restoring ARP table of #{@ctx.targets.size} targets ..."
|
151
150
|
|
152
151
|
@ctx.targets.each do |target|
|
153
|
-
|
154
|
-
|
155
|
-
|
152
|
+
unless target.mac.nil?
|
153
|
+
begin
|
154
|
+
send_spoofed_packet( @gateway.ip, @gateway.mac, target.ip, target.mac )
|
155
|
+
send_spoofed_packet( target.ip, target.mac, @gateway.ip, @gateway.mac ) unless @ctx.options.half_duplex
|
156
|
+
rescue; end
|
156
157
|
end
|
157
158
|
end
|
158
159
|
sleep 1
|
data/lib/bettercap/target.rb
CHANGED
@@ -24,22 +24,25 @@ class Target
|
|
24
24
|
|
25
25
|
def initialize( ip, mac=nil )
|
26
26
|
@ip = ip
|
27
|
-
@mac = mac
|
28
|
-
@vendor = Target.lookup_vendor(mac)
|
27
|
+
@mac = normalized_mac mac unless mac.nil?
|
28
|
+
@vendor = Target.lookup_vendor(@mac) unless mac.nil?
|
29
29
|
@hostname = nil
|
30
30
|
@resolver = Thread.new { resolve! }
|
31
31
|
end
|
32
32
|
|
33
|
+
def sortable_ip
|
34
|
+
@ip.split('.').inject(0) {|total,value| (total << 8 ) + value.to_i}
|
35
|
+
end
|
36
|
+
|
33
37
|
def mac=(value)
|
34
|
-
@mac = value
|
38
|
+
@mac = normalized_mac value
|
35
39
|
@vendor = Target.lookup_vendor(@mac) if not @mac.nil?
|
36
40
|
end
|
37
41
|
|
38
42
|
def to_s
|
39
|
-
s = @ip
|
40
|
-
s += "
|
41
|
-
s += "
|
42
|
-
s += " ( #{@vendor} )" unless @vendor.nil?
|
43
|
+
s = sprintf( '%-15s : %-17s', @ip, @mac )
|
44
|
+
s += " / #{@hostname}" unless @hostname.nil?
|
45
|
+
s += if @vendor.nil? then " ( ??? )" else " ( #{@vendor} )" end
|
43
46
|
s
|
44
47
|
end
|
45
48
|
|
@@ -51,8 +54,16 @@ class Target
|
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
57
|
+
def equals?(ip, mac)
|
58
|
+
( @ip == ip && ( mac.nil? || @mac == normalized_mac(mac) ) )
|
59
|
+
end
|
60
|
+
|
54
61
|
private
|
55
62
|
|
63
|
+
def normalized_mac(v)
|
64
|
+
v.split(':').map { |e| if e.size == 2 then e.upcase else "0#{e.upcase}" end }.join(':')
|
65
|
+
end
|
66
|
+
|
56
67
|
def resolve!
|
57
68
|
resp, sock = nil, nil
|
58
69
|
begin
|
@@ -0,0 +1,53 @@
|
|
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/version'
|
13
|
+
require 'bettercap/error'
|
14
|
+
require 'bettercap/logger'
|
15
|
+
require 'net/http'
|
16
|
+
require 'json'
|
17
|
+
|
18
|
+
class UpdateChecker
|
19
|
+
def self.check
|
20
|
+
ver = self.get_latest_version
|
21
|
+
if self.vton( BetterCap::VERSION ) < self.vton( ver )
|
22
|
+
Logger.warn "New version '#{ver}' available!"
|
23
|
+
else
|
24
|
+
Logger.info 'You are running the latest version.'
|
25
|
+
end
|
26
|
+
rescue Exception => e
|
27
|
+
Logger.error("Error '#{e.class}' while checking for updates: #{e.message}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.vton v
|
31
|
+
vi = 0.0
|
32
|
+
v.split('.').reverse.each_with_index do |e,i|
|
33
|
+
vi += ( e.to_i * 10**i ) - ( if e =~ /[\d+]b/ then 0.5 else 0 end )
|
34
|
+
end
|
35
|
+
vi
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.get_latest_version
|
39
|
+
Logger.info 'Checking for updates ...'
|
40
|
+
|
41
|
+
api = URI('https://rubygems.org/api/v1/versions/bettercap/latest.json')
|
42
|
+
response = Net::HTTP.get_response(api)
|
43
|
+
|
44
|
+
case response
|
45
|
+
when Net::HTTPSuccess
|
46
|
+
json = JSON.parse(response.body)
|
47
|
+
else
|
48
|
+
raise response.message
|
49
|
+
end
|
50
|
+
|
51
|
+
return json['version']
|
52
|
+
end
|
53
|
+
end
|
data/lib/bettercap/version.rb
CHANGED
data/test/logger_test.rb
CHANGED
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
|
+
version: 1.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simone Margaritelli
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -87,17 +87,11 @@ executables:
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- .gitignore
|
91
90
|
- CONTRIBUTING.md
|
92
|
-
- Gemfile
|
93
|
-
- Gemfile.lock
|
94
91
|
- LICENSE.md
|
95
92
|
- README.md
|
96
|
-
- Rakefile
|
97
93
|
- TODO.md
|
98
|
-
-
|
99
|
-
- bin/bettercap
|
100
|
-
- lib/bettercap.rb
|
94
|
+
- Rakefile
|
101
95
|
- lib/bettercap/banner
|
102
96
|
- lib/bettercap/base/ifirewall.rb
|
103
97
|
- lib/bettercap/base/ispoofer.rb
|
@@ -106,6 +100,7 @@ files:
|
|
106
100
|
- lib/bettercap/discovery/base.rb
|
107
101
|
- lib/bettercap/discovery/icmp.rb
|
108
102
|
- lib/bettercap/discovery/udp.rb
|
103
|
+
- lib/bettercap/discovery.rb
|
109
104
|
- lib/bettercap/error.rb
|
110
105
|
- lib/bettercap/factories/firewall_factory.rb
|
111
106
|
- lib/bettercap/factories/parser_factory.rb
|
@@ -141,7 +136,10 @@ files:
|
|
141
136
|
- lib/bettercap/spoofers/arp.rb
|
142
137
|
- lib/bettercap/spoofers/none.rb
|
143
138
|
- lib/bettercap/target.rb
|
139
|
+
- lib/bettercap/update_checker.rb
|
144
140
|
- lib/bettercap/version.rb
|
141
|
+
- lib/bettercap.rb
|
142
|
+
- bin/bettercap
|
145
143
|
- test/factories/firewall_factory_test.rb
|
146
144
|
- test/factories/parser_factory_test.rb
|
147
145
|
- test/factories/spoofer_factory_test.rb
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
bettercap (1.1.3)
|
5
|
-
colorize (~> 0.7.5)
|
6
|
-
packetfu (~> 1.1.10)
|
7
|
-
pcaprub (~> 0.12.0)
|
8
|
-
|
9
|
-
GEM
|
10
|
-
remote: https://rubygems.org/
|
11
|
-
specs:
|
12
|
-
colorize (0.7.7)
|
13
|
-
minitest (5.7.0)
|
14
|
-
packetfu (1.1.10)
|
15
|
-
pcaprub (0.12.0)
|
16
|
-
|
17
|
-
PLATFORMS
|
18
|
-
ruby
|
19
|
-
|
20
|
-
DEPENDENCIES
|
21
|
-
bettercap!
|
22
|
-
minitest
|
23
|
-
|
24
|
-
BUNDLED WITH
|
25
|
-
1.10.3
|
data/bettercap.gemspec
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require './lib/bettercap/version'
|
2
|
-
|
3
|
-
Gem::Specification.new do |gem|
|
4
|
-
gem.name = %q{bettercap}
|
5
|
-
gem.version = BetterCap::VERSION
|
6
|
-
gem.license = 'GPL3'
|
7
|
-
gem.description = %q{A complete, modular, portable and easily extensible MITM framework.}
|
8
|
-
gem.summary = %q{A complete, modular, portable and easily extensible MITM framework.}
|
9
|
-
gem.required_ruby_version = '>= 1.9'
|
10
|
-
|
11
|
-
|
12
|
-
gem.authors = ['Simone Margaritelli']
|
13
|
-
gem.email = %q{evilsocket@gmail.com}
|
14
|
-
gem.homepage = %q{http://github.com/evilsocket/bettercap}
|
15
|
-
|
16
|
-
gem.add_dependency( 'colorize', '~> 0.7.5' )
|
17
|
-
gem.add_dependency( 'packetfu', '~> 1.1.10' )
|
18
|
-
gem.add_dependency( 'pcaprub', '~> 0.12.0' )
|
19
|
-
gem.add_dependency( 'network_interface', '~> 0.0.1' )
|
20
|
-
|
21
|
-
gem.add_development_dependency( 'minitest' )
|
22
|
-
|
23
|
-
gem.files = `git ls-files`.split("\n")
|
24
|
-
gem.require_paths = ["lib"]
|
25
|
-
|
26
|
-
gem.executables = %w(bettercap)
|
27
|
-
gem.rdoc_options = ["--charset=UTF-8"]
|
28
|
-
end
|