bettercap 1.1.8 → 1.1.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|