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.
@@ -28,7 +28,7 @@ class HttpsParser < BaseParser
28
28
  end
29
29
 
30
30
  if @@prev.nil? or @@prev != hostname
31
- Logger.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
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.write "[#{addr2s(pkt.ip_saddr)} > #{addr2s(pkt.ip_daddr)} #{pkt.proto.last}] " +
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.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
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.write "[#{addr2s(pkt.ip_saddr)}:#{pkt.tcp_src} > #{addr2s(pkt.ip_daddr)}:#{pkt.tcp_dst} #{pkt.proto.last}] " +
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
- Logger.info 'Starting sniffer ...'
27
-
28
- setup( ctx )
29
-
30
- self.stream.each do |p|
31
- begin
32
- parsed = Packet.parse p
33
- rescue Exception => e
34
- parsed = nil
35
- Logger.debug e.message
36
- end
37
-
38
- if not parsed.nil? and parsed.is_ip? and !skip_packet?(parsed)
39
- append_packet p
40
- parse_packet parsed
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
- @gw_hw = nil
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
- Logger.info " Gateway : #{@ctx.gateway} ( #{@gw_hw} )"
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( @ctx.gateway, @ctx.ifconfig[:eth_saddr], target.ip, target.mac )
126
- send_spoofed_packet( target.ip, @ctx.ifconfig[:eth_saddr], @ctx.gateway, @gw_hw ) unless @ctx.options.half_duplex
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
- if !target.mac.nil?
154
- send_spoofed_packet( @ctx.gateway, @gw_hw, target.ip, target.mac )
155
- send_spoofed_packet( target.ip, target.mac, @ctx.gateway, @gw_hw ) unless @ctx.options.half_duplex
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
@@ -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) if not mac.nil?
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 += " ( #{@hostname} )" unless @hostname.nil?
41
- s += " : #{@mac}"
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
@@ -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.8'
13
+ VERSION = '1.1.9'
14
14
  BANNER = File.read( File.dirname(__FILE__) + '/banner' ).gsub( '#VERSION#', "v#{VERSION}")
15
15
  end
data/test/logger_test.rb CHANGED
@@ -5,7 +5,7 @@ require 'logger'
5
5
  class LoggerTest < MiniTest::Test
6
6
  def test_writing_with_a_logfile
7
7
  silence do |output|
8
- Logger.write 'Test log message'
8
+ Logger.raw 'Test log message'
9
9
  assert_equal output.read, "Test log message\n"
10
10
  end
11
11
  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.8
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: 2015-12-14 00:00:00.000000000 Z
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
- - bettercap.gemspec
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
@@ -1,12 +0,0 @@
1
- *.swp
2
- *.swo
3
- *.gem
4
- *.sh
5
- .idea
6
- cert.crt
7
- cert.key
8
- cert.pem
9
- test_https_proxy.rb
10
- test_chunked.rb
11
- mkchangelog.rb
12
- .tags*
data/Gemfile DELETED
@@ -1,2 +0,0 @@
1
- source "https://rubygems.org"
2
- gemspec
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