bettercap 1.3.5 → 1.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -10
- data/lib/bettercap.rb +28 -3
- data/lib/bettercap/context.rb +2 -2
- data/lib/bettercap/discovery/agents/icmp.rb +1 -1
- data/lib/bettercap/firewalls/base.rb +25 -0
- data/lib/bettercap/monkey/packetfu/utils.rb +70 -10
- data/lib/bettercap/network/network.rb +11 -3
- data/lib/bettercap/network/packet_queue.rb +1 -1
- data/lib/bettercap/network/protos/base.rb +97 -0
- data/lib/bettercap/network/protos/dhcp.rb +350 -0
- data/lib/bettercap/options.rb +4 -4
- data/lib/bettercap/proxy/stream_logger.rb +7 -3
- data/lib/bettercap/shell.rb +23 -1
- data/lib/bettercap/sniffer/parsers/base.rb +52 -0
- data/lib/bettercap/sniffer/parsers/cookie.rb +45 -0
- data/lib/bettercap/sniffer/parsers/custom.rb +0 -1
- data/lib/bettercap/sniffer/parsers/dhcp.rb +48 -0
- data/lib/bettercap/sniffer/parsers/dict.rb +0 -1
- data/lib/bettercap/sniffer/parsers/ftp.rb +0 -1
- data/lib/bettercap/sniffer/parsers/httpauth.rb +0 -2
- data/lib/bettercap/sniffer/parsers/https.rb +0 -2
- data/lib/bettercap/sniffer/parsers/irc.rb +0 -1
- data/lib/bettercap/sniffer/parsers/mail.rb +0 -1
- data/lib/bettercap/sniffer/parsers/mpd.rb +0 -1
- data/lib/bettercap/sniffer/parsers/nntp.rb +0 -1
- data/lib/bettercap/sniffer/parsers/ntlmss.rb +0 -2
- data/lib/bettercap/sniffer/parsers/post.rb +5 -3
- data/lib/bettercap/sniffer/parsers/redis.rb +0 -1
- data/lib/bettercap/sniffer/parsers/rlogin.rb +0 -1
- data/lib/bettercap/sniffer/parsers/snpp.rb +0 -1
- data/lib/bettercap/sniffer/parsers/url.rb +0 -2
- data/lib/bettercap/sniffer/parsers/whatsapp.rb +33 -0
- data/lib/bettercap/sniffer/sniffer.rb +6 -6
- data/lib/bettercap/spoofers/base.rb +23 -0
- data/lib/bettercap/version.rb +1 -1
- metadata +7 -5
- data/lib/bettercap/factories/firewall.rb +0 -43
- data/lib/bettercap/factories/parser.rb +0 -74
- data/lib/bettercap/factories/spoofer.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a07e86570365f443ee439d850b72ce33ea9f9496
|
4
|
+
data.tar.gz: f29023f45a2b8f77100096529539fee383b2d0ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28f7271d87b8cb7727ef4f2ddff8ff0ceef18d692271dd6dafc0a6aced5d84aeb595161692bbc05b9a0dd96df681b6ee352cba24edac29ba31a32ee0ca53adb3
|
7
|
+
data.tar.gz: 1db150ee30cd6baf75f3b19bc51ca4d860888c95e9686ed0a2e496b4db976e1177553de38f756a8d376269b22e8dd182eb6dc5f13f92dc849917e394ecd751ac
|
data/README.md
CHANGED
@@ -66,6 +66,15 @@ Before submitting issues, please read the relevant [section](http://www.betterca
|
|
66
66
|
Installation
|
67
67
|
============
|
68
68
|
|
69
|
+
**Dependencies**
|
70
|
+
|
71
|
+
All dependencies will be automatically installed through the GEM system but in some case you might need to install some system
|
72
|
+
dependency in order to make everything work:
|
73
|
+
|
74
|
+
sudo apt-get install build-essential ruby-dev libpcap-dev
|
75
|
+
|
76
|
+
This should solve issues such as [this one](https://github.com/evilsocket/bettercap/issues/22) or [this one](https://github.com/evilsocket/bettercap/issues/100).
|
77
|
+
|
69
78
|
**Stable Release ( GEM )**
|
70
79
|
|
71
80
|
gem install bettercap
|
@@ -77,16 +86,6 @@ Installation
|
|
77
86
|
gem build bettercap.gemspec
|
78
87
|
sudo gem install bettercap*.gem
|
79
88
|
|
80
|
-
Dependencies
|
81
|
-
============
|
82
|
-
|
83
|
-
All dependencies will be automatically installed through the GEM system, in some case you might need to install some system
|
84
|
-
dependency in order to make everything work:
|
85
|
-
|
86
|
-
sudo apt-get install build-essential ruby-dev libpcap-dev
|
87
|
-
|
88
|
-
This should solve issues such as [this one](https://github.com/evilsocket/bettercap/issues/22) or [this one](https://github.com/evilsocket/bettercap/issues/100).
|
89
|
-
|
90
89
|
Documentation and Examples
|
91
90
|
============
|
92
91
|
|
data/lib/bettercap.rb
CHANGED
@@ -20,6 +20,7 @@ Encoding.default_internal = Encoding::UTF_8
|
|
20
20
|
require 'optparse'
|
21
21
|
require 'colorize'
|
22
22
|
require 'packetfu'
|
23
|
+
require 'pcaprub'
|
23
24
|
require 'ipaddr'
|
24
25
|
require 'uri'
|
25
26
|
|
@@ -39,16 +40,40 @@ require 'bettercap/discovery/agents/icmp'
|
|
39
40
|
require 'bettercap/discovery/agents/udp'
|
40
41
|
require 'bettercap/context'
|
41
42
|
require 'bettercap/monkey/packetfu/utils'
|
42
|
-
require 'bettercap/
|
43
|
-
require 'bettercap/
|
44
|
-
require 'bettercap/
|
43
|
+
require 'bettercap/spoofers/base'
|
44
|
+
require 'bettercap/spoofers/arp'
|
45
|
+
require 'bettercap/spoofers/icmp'
|
46
|
+
require 'bettercap/spoofers/none'
|
45
47
|
require 'bettercap/logger'
|
46
48
|
require 'bettercap/shell'
|
47
49
|
require 'bettercap/network/network'
|
48
50
|
require 'bettercap/version'
|
49
51
|
require 'bettercap/network/target'
|
52
|
+
require 'bettercap/network/protos/base'
|
53
|
+
require 'bettercap/network/protos/dhcp'
|
50
54
|
require 'bettercap/sniffer/sniffer'
|
55
|
+
require "bettercap/sniffer/parsers/base"
|
56
|
+
require "bettercap/sniffer/parsers/custom"
|
57
|
+
require "bettercap/sniffer/parsers/dict"
|
58
|
+
require "bettercap/sniffer/parsers/cookie"
|
59
|
+
require "bettercap/sniffer/parsers/ftp"
|
60
|
+
require "bettercap/sniffer/parsers/httpauth"
|
61
|
+
require "bettercap/sniffer/parsers/https"
|
62
|
+
require "bettercap/sniffer/parsers/irc"
|
63
|
+
require "bettercap/sniffer/parsers/mail"
|
64
|
+
require "bettercap/sniffer/parsers/mpd"
|
65
|
+
require "bettercap/sniffer/parsers/nntp"
|
66
|
+
require "bettercap/sniffer/parsers/ntlmss"
|
67
|
+
require "bettercap/sniffer/parsers/post"
|
68
|
+
require "bettercap/sniffer/parsers/dhcp"
|
69
|
+
require "bettercap/sniffer/parsers/redis"
|
70
|
+
require "bettercap/sniffer/parsers/rlogin"
|
71
|
+
require "bettercap/sniffer/parsers/snpp"
|
72
|
+
require "bettercap/sniffer/parsers/url"
|
73
|
+
require "bettercap/sniffer/parsers/whatsapp"
|
51
74
|
require 'bettercap/firewalls/redirection'
|
75
|
+
require 'bettercap/firewalls/osx'
|
76
|
+
require 'bettercap/firewalls/linux'
|
52
77
|
require 'bettercap/proxy/stream_logger'
|
53
78
|
require 'bettercap/proxy/request'
|
54
79
|
require 'bettercap/proxy/response'
|
data/lib/bettercap/context.rb
CHANGED
@@ -57,7 +57,7 @@ class Context
|
|
57
57
|
# Initialize the global context object.
|
58
58
|
def initialize
|
59
59
|
begin
|
60
|
-
iface = Pcap.lookupdev
|
60
|
+
iface = PCAPRUB::Pcap.lookupdev
|
61
61
|
rescue Exception => e
|
62
62
|
iface = nil
|
63
63
|
Logger.debug e.message
|
@@ -78,7 +78,7 @@ class Context
|
|
78
78
|
@proxies = []
|
79
79
|
@redirections = []
|
80
80
|
@discovery = Discovery::Thread.new self
|
81
|
-
@firewall =
|
81
|
+
@firewall = Firewalls::Base.get
|
82
82
|
@packets = nil
|
83
83
|
end
|
84
84
|
|
@@ -20,7 +20,7 @@ class Icmp
|
|
20
20
|
# Create a thread which will perform a ping-sweep on the network in order
|
21
21
|
# to populate the ARP cache with active targets.
|
22
22
|
def initialize( ctx )
|
23
|
-
|
23
|
+
Firewalls::Base.get.enable_icmp_bcast(true)
|
24
24
|
|
25
25
|
# TODO: Use the real broadcast address for this network.
|
26
26
|
3.times do
|
@@ -14,6 +14,31 @@ module BetterCap
|
|
14
14
|
module Firewalls
|
15
15
|
# Base class for BetterCap::Firewalls objects.
|
16
16
|
class Base
|
17
|
+
# Instance of the loaded firewall.
|
18
|
+
@@instance = nil
|
19
|
+
|
20
|
+
class << self
|
21
|
+
# Save and return an instance of the appropriate BetterCap::Firewalls object.
|
22
|
+
def get
|
23
|
+
return @@instance unless @@instance.nil?
|
24
|
+
|
25
|
+
if RUBY_PLATFORM =~ /darwin/
|
26
|
+
@@instance = Firewalls::OSX.new
|
27
|
+
elsif RUBY_PLATFORM =~ /linux/
|
28
|
+
@@instance = Firewalls::Linux.new
|
29
|
+
else
|
30
|
+
raise BetterCap::Error, 'Unsupported operating system'
|
31
|
+
end
|
32
|
+
|
33
|
+
@@instance
|
34
|
+
end
|
35
|
+
|
36
|
+
# Clear the instance of the BetterCap::Firewalls object.
|
37
|
+
def clear
|
38
|
+
@@instance = nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
17
42
|
# Initialize the firewall object.
|
18
43
|
# Raise NotImplementedError
|
19
44
|
def initialize
|
@@ -19,6 +19,17 @@ This project is released under the GPL 3 license.
|
|
19
19
|
require 'bettercap/logger'
|
20
20
|
|
21
21
|
module PacketFu
|
22
|
+
class Packet
|
23
|
+
def eth2s(which = :src)
|
24
|
+
case which
|
25
|
+
when :src
|
26
|
+
self.eth_src.bytes.map(&(Proc.new {|x| sprintf('%02X',x) })).join(':')
|
27
|
+
when :dst
|
28
|
+
self.eth_dst.bytes.map(&(Proc.new {|x| sprintf('%02X',x) })).join(':')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
22
33
|
class Utils
|
23
34
|
def self.ifconfig(iface='eth0')
|
24
35
|
ret = {}
|
@@ -26,18 +37,27 @@ module PacketFu
|
|
26
37
|
|
27
38
|
BetterCap::Logger.debug "ifconfig #{iface}"
|
28
39
|
|
29
|
-
|
30
|
-
|
31
|
-
|
40
|
+
if BetterCap::Shell.available?('ip')
|
41
|
+
BetterCap::Logger.debug "Using iproute2"
|
42
|
+
|
43
|
+
data = BetterCap::Shell.ip(iface)
|
44
|
+
ret = linux_ip iface, data
|
32
45
|
else
|
33
|
-
|
34
|
-
|
46
|
+
BetterCap::Logger.debug "Using ifconfig"
|
47
|
+
|
48
|
+
data = BetterCap::Shell.ifconfig(iface)
|
49
|
+
if data =~ /#{iface}/i
|
50
|
+
data = data.split(/[\s]*\n[\s]*/)
|
51
|
+
else
|
52
|
+
raise ArgumentError, "Cannot ifconfig #{iface}"
|
53
|
+
end
|
35
54
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
55
|
+
case RUBY_PLATFORM
|
56
|
+
when /linux/i
|
57
|
+
ret = linux_ifconfig iface, data
|
58
|
+
when /darwin/i
|
59
|
+
ret = darwin_ifconfig iface, data
|
60
|
+
end
|
41
61
|
end
|
42
62
|
|
43
63
|
ret
|
@@ -45,6 +65,46 @@ module PacketFu
|
|
45
65
|
|
46
66
|
private
|
47
67
|
|
68
|
+
def self.linux_ip(iface='eth0',data)
|
69
|
+
BetterCap::Logger.debug "Linux ip #{iface}:\n#{data}"
|
70
|
+
|
71
|
+
ret = {
|
72
|
+
:iface => iface,
|
73
|
+
:eth_saddr => nil,
|
74
|
+
:eth_src => nil,
|
75
|
+
:ip_saddr => nil,
|
76
|
+
:ip_src => nil,
|
77
|
+
:ip4_obj => nil
|
78
|
+
}
|
79
|
+
|
80
|
+
lines = data.split("\n").map(&:strip)
|
81
|
+
|
82
|
+
# search for interface
|
83
|
+
lines.each_with_index do |line,i|
|
84
|
+
if line =~ /\d+:\s+#{iface}:.+/i
|
85
|
+
# start parsing this block
|
86
|
+
lines[i..lines.size].each do |line|
|
87
|
+
case line
|
88
|
+
when /^.+([0-9a-f:]{17})\s+.+[0-9a-f:]{17}$/i
|
89
|
+
ret[:eth_saddr] = $1.downcase
|
90
|
+
ret[:eth_src] = EthHeader.mac2str(ret[:eth_saddr])
|
91
|
+
when /^inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/(\d+)\s.+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s.+$/i
|
92
|
+
addr = $1
|
93
|
+
bits = $2
|
94
|
+
|
95
|
+
ret[:ip_saddr] = addr
|
96
|
+
ret[:ip_src] = [IPAddr.new(addr).to_i].pack('N')
|
97
|
+
ret[:ip4_obj] = IPAddr.new(addr)
|
98
|
+
ret[:ip4_obj] = ret[:ip4_obj].mask(bits) if bits
|
99
|
+
end
|
100
|
+
end
|
101
|
+
break
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
ret
|
106
|
+
end
|
107
|
+
|
48
108
|
def self.linux_ifconfig(iface='eth0',ifconfig_data)
|
49
109
|
BetterCap::Logger.debug "Linux ifconfig #{iface}:\n#{ifconfig_data}"
|
50
110
|
|
@@ -53,9 +53,17 @@ class << self
|
|
53
53
|
def get_local_ips
|
54
54
|
ips = []
|
55
55
|
|
56
|
-
Shell.
|
57
|
-
|
58
|
-
|
56
|
+
if Shell.available?('ip')
|
57
|
+
Shell.ip.split("\n").each do |line|
|
58
|
+
if line.strip =~ /^inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/(\d+).+$/i
|
59
|
+
ips << $1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
Shell.ifconfig.split("\n").each do |line|
|
64
|
+
if line =~ /inet [adr:]*([\d\.]+)/
|
65
|
+
ips << $1
|
66
|
+
end
|
59
67
|
end
|
60
68
|
end
|
61
69
|
|
@@ -25,7 +25,7 @@ class PacketQueue
|
|
25
25
|
@nworkers = nworkers
|
26
26
|
@throttle = packet_throttle;
|
27
27
|
@running = true
|
28
|
-
@stream = Pcap.open_live( iface, 0xffff, false , 1 )
|
28
|
+
@stream = PCAPRUB::Pcap.open_live( iface, 0xffff, false , 1 )
|
29
29
|
@mutex = Mutex.new
|
30
30
|
@udp = UDPSocket.new
|
31
31
|
@queue = Queue.new
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
|
4
|
+
BETTERCAP
|
5
|
+
|
6
|
+
Author : Simone 'evilsocket' Margaritelli
|
7
|
+
Email : evilsocket@gmail.com
|
8
|
+
Blog : http://www.evilsocket.net/
|
9
|
+
|
10
|
+
This project is released under the GPL 3 license.
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
module BetterCap
|
15
|
+
module Network
|
16
|
+
module Protos
|
17
|
+
|
18
|
+
class Base
|
19
|
+
TYPES = [
|
20
|
+
:uint8,
|
21
|
+
:uint16,
|
22
|
+
:uint32,
|
23
|
+
:uint32rev,
|
24
|
+
:ip,
|
25
|
+
:mac,
|
26
|
+
:bytes
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
@@fields = {}
|
30
|
+
|
31
|
+
def self.method_missing(method_name, *arguments, &block)
|
32
|
+
type = method_name.to_sym
|
33
|
+
name = arguments[0]
|
34
|
+
if TYPES.include?(type)
|
35
|
+
@@fields[name] = { :type => type, :opts => arguments.length > 1 ? arguments[1] : {} }
|
36
|
+
class_eval "attr_accessor :#{name}"
|
37
|
+
else
|
38
|
+
raise NoMethodError, method_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.parse( data )
|
43
|
+
pkt = self.new
|
44
|
+
|
45
|
+
begin
|
46
|
+
offset = 0
|
47
|
+
limit = data.length
|
48
|
+
value = nil
|
49
|
+
|
50
|
+
@@fields.each do |name, info|
|
51
|
+
value = nil
|
52
|
+
|
53
|
+
case info[:type]
|
54
|
+
when :uint8
|
55
|
+
value = data[offset].ord
|
56
|
+
offset += 1
|
57
|
+
when :uint16
|
58
|
+
value = data[offset..offset + 1].unpack('S')[0]
|
59
|
+
offset += 2
|
60
|
+
when :uint32
|
61
|
+
value = data[offset..offset + 3].unpack('L')[0]
|
62
|
+
offset += 4
|
63
|
+
when :uint32rev
|
64
|
+
value = data[offset..offset + 3].reverse.unpack('L')[0]
|
65
|
+
offset += 4
|
66
|
+
when :ip
|
67
|
+
tmp = data[offset..offset + 3].reverse.unpack('L')[0]
|
68
|
+
value = IPAddr.new(tmp, Socket::AF_INET)
|
69
|
+
offset += 4
|
70
|
+
when :mac
|
71
|
+
tmp = data[offset..offset + 7]
|
72
|
+
value = tmp.bytes.map(&(Proc.new {|x| sprintf('%02X',x) })).join(':')
|
73
|
+
offset += size( info, 16 )
|
74
|
+
when :bytes
|
75
|
+
size = size( info, data.length )
|
76
|
+
value = data[offset..offset + size - 1].bytes
|
77
|
+
offset += size
|
78
|
+
end
|
79
|
+
|
80
|
+
pkt.send("#{name}=", value)
|
81
|
+
end
|
82
|
+
|
83
|
+
rescue Exception => e
|
84
|
+
pkt = nil
|
85
|
+
end
|
86
|
+
|
87
|
+
pkt
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.size( info, default )
|
91
|
+
info[:opts].has_key?(:size) ? info[:opts][:size] : default
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,350 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
|
4
|
+
BETTERCAP
|
5
|
+
|
6
|
+
Author : Simone 'evilsocket' Margaritelli
|
7
|
+
Email : evilsocket@gmail.com
|
8
|
+
Blog : http://www.evilsocket.net/
|
9
|
+
|
10
|
+
This project is released under the GPL 3 license.
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
module BetterCap
|
15
|
+
module Network
|
16
|
+
module Protos
|
17
|
+
module DHCP
|
18
|
+
|
19
|
+
OP_MESSAGETYPES = {
|
20
|
+
# DHCP Message type responses (all len = 1)
|
21
|
+
1 => 'DISCOVER',
|
22
|
+
2 => 'OFFER',
|
23
|
+
3 => 'REQUEST',
|
24
|
+
4 => 'DECLINE',
|
25
|
+
5 => 'ACK',
|
26
|
+
6 => 'NAK',
|
27
|
+
7 => 'RELEASE'
|
28
|
+
}
|
29
|
+
|
30
|
+
OP_CONSTANTS = {
|
31
|
+
# DHCP Options
|
32
|
+
:DHCPPad => 0,
|
33
|
+
:DHCPSubnetMask => 1,
|
34
|
+
:DHCPTimeOffset => 2,
|
35
|
+
:DHCPRouter => 3,
|
36
|
+
:DHCPTimeServer => 4,
|
37
|
+
:DHCPNameServer => 5,
|
38
|
+
:DHCPDNS => 6,
|
39
|
+
:DHCPLogServer => 7,
|
40
|
+
:DHCPQuoteServer => 8,
|
41
|
+
:DHCPLPRServer => 9,
|
42
|
+
:DHCPImpressServer => 10,
|
43
|
+
:DHCPRLServer => 11,
|
44
|
+
:DHCPHostName => 12,
|
45
|
+
:DHCPBootFileSize => 13,
|
46
|
+
:DHCPMeritDumpFile => 14,
|
47
|
+
:DHCPDomainName => 15,
|
48
|
+
:DHCPSwapServer => 16,
|
49
|
+
:DHCPRootPath => 17,
|
50
|
+
:DHCPExtensionsPath => 18,
|
51
|
+
:DHCPIPForwarding => 19,
|
52
|
+
:DHCPNonLocalRouting => 20,
|
53
|
+
:DHCPPolicyFilter => 21,
|
54
|
+
:DHCPMaximumDRSize => 22, # Datagram reassembly size
|
55
|
+
:DHCPDefaultIPTTL => 23,
|
56
|
+
:DHCPPathMTUAgingTimeout => 24,
|
57
|
+
:DHCPPathMTUPlateauTable => 25,
|
58
|
+
:DHCPInterfaceMTU => 26,
|
59
|
+
:DHCPAllSubnetsLocal => 27,
|
60
|
+
:DHCPBroadcastAddress => 28,
|
61
|
+
:DHCPPerformMask => 29, # Perform mask discovery
|
62
|
+
:DHCPMaskSupplier => 30, # Zelda flashbacks
|
63
|
+
:DHCPPerformRouter => 31, # Perform router discovery
|
64
|
+
:DHCPRouterSolicitation => 32, # Router Solicitation Address
|
65
|
+
:DHCPStaticRoutingEnable => 33,
|
66
|
+
:DHCPTrailerEncap => 34, # Trailer Encapsulation
|
67
|
+
:DHCPArpCacheTimeout => 35,
|
68
|
+
:DHCPEthernetEncap => 36, # ethernet encapsulation
|
69
|
+
:DHCPDefaultTCPTTL => 37,
|
70
|
+
:DHCPTCPKeepAliveInt => 38, # TCP Keepalive interval
|
71
|
+
:DHCPTCPKeepAliveGB => 39, # TCP Keepalive garbage
|
72
|
+
:DHCPNISDomain => 40,
|
73
|
+
:DHCPNISServer => 41,
|
74
|
+
:DHCPNTPServers => 42,
|
75
|
+
:DHCPVendorSpecificInfo => 43,
|
76
|
+
:DHCPNetBIOSNameServer => 44,
|
77
|
+
:DHCPNetBIOSDDS => 45,
|
78
|
+
:DHCPNetBIOSNodeType => 46,
|
79
|
+
:DHCPNetBIOSScope => 47,
|
80
|
+
:DHCPXWindowSystemFont => 48, # XWindow Font server
|
81
|
+
:DHCPXWindowSystemDM => 49, # Xwindow System Display Server
|
82
|
+
:DHCPRequestedIPAddress => 50,
|
83
|
+
:DHCPIPAddressLeaseTime => 51,
|
84
|
+
:DHCPOptionOverload => 52,
|
85
|
+
:DHCPMessageType => 53,
|
86
|
+
:DHCPServerIdentifier => 54,
|
87
|
+
:DHCPParameters => 55,
|
88
|
+
:DHCPMessage => 56,
|
89
|
+
:DHCPMaxDHCPMessageSize => 57,
|
90
|
+
:DHCPRenewTimeValue => 58,
|
91
|
+
:DHCPRebindingTimeValue => 59,
|
92
|
+
:DHCPClassIdentifier => 60,
|
93
|
+
:DHCPClientIdentifier => 61,
|
94
|
+
:DHCPNetWareIPDomainName => 62,
|
95
|
+
:DHCPNetWareIPInformation => 63,
|
96
|
+
:DHCPNISClientDomain => 64,
|
97
|
+
:DHCPNISServers => 65,
|
98
|
+
:DHCPTFTPServerName => 66,
|
99
|
+
:DHCPBootFileName => 67,
|
100
|
+
:DHCPMobileIPHomeAgent => 68,
|
101
|
+
:DHCPSMTPServer => 69,
|
102
|
+
:DHCPPOPServer => 70,
|
103
|
+
:DHCPNNTPServer => 71,
|
104
|
+
:DHCPDefaultWWWServer => 72,
|
105
|
+
:DHCPDefaultFingerServer => 73,
|
106
|
+
:DHCPDefaultIRCServer => 74,
|
107
|
+
:DHCPStreetTalkServer => 75,
|
108
|
+
:DHCPStreetTalkDAS => 76,
|
109
|
+
:DHCPUserClassInformation => 77,
|
110
|
+
:DHCPSLPDirectoryAgent => 78,
|
111
|
+
:DHCPSLPServiceScope => 79,
|
112
|
+
:DHCPRapidCommit => 80,
|
113
|
+
:DHCPFQDN => 81,
|
114
|
+
:DHCPRelayAgentInformation => 82,
|
115
|
+
:DHCPInternetStorageNameService => 83,
|
116
|
+
# ??
|
117
|
+
:DHCPNDSServers => 85,
|
118
|
+
:DHCPNDSTreeName => 86,
|
119
|
+
:DHCPNDSContext => 87,
|
120
|
+
:DHCPBCMCSContDomainNameList => 88,
|
121
|
+
:DHCPBCMCSContIPV4AddressList => 89,
|
122
|
+
:DHCPAuthentication => 90,
|
123
|
+
:DHCPClientLastTransactTime => 91,
|
124
|
+
:DHCPAssociatedIP => 92,
|
125
|
+
:DHCPClientSystemArchType => 93,
|
126
|
+
:DHCPClientNetworkInterfaceIdent => 94,
|
127
|
+
:DHCPLDAP => 95,
|
128
|
+
# ??
|
129
|
+
:DHCPClientMachineIdent => 97,
|
130
|
+
:DHCPOGUA => 98,
|
131
|
+
# ??
|
132
|
+
:DHCPAutonomousSystemNumber => 109,
|
133
|
+
# ??
|
134
|
+
:DHCPNetInfoParentServerAddress => 112,
|
135
|
+
:DHCPNetInfoParentServerTag => 113,
|
136
|
+
:DHCPURL => 114,
|
137
|
+
:DHCPAutoConfigure => 116,
|
138
|
+
:DHCPNameServiceSearch => 117,
|
139
|
+
:DHCPSubnetSelection => 118,
|
140
|
+
:DHCPDNSDomainSearchList => 119,
|
141
|
+
:DHCPSIPServers => 120,
|
142
|
+
:DHCPClasslessStaticRoute => 121,
|
143
|
+
:DHCPCableLabsClientConfig => 122,
|
144
|
+
:DHCPGeoConf => 123,
|
145
|
+
# ??
|
146
|
+
:DHCPProxyAutoDiscovery => 252
|
147
|
+
}
|
148
|
+
|
149
|
+
OP_CONSTANTS_REV = {
|
150
|
+
0 => :Pad,
|
151
|
+
1 => :SubnetMask,
|
152
|
+
2 => :TimeOffset,
|
153
|
+
3 => :Router,
|
154
|
+
4 => :TimeServer,
|
155
|
+
5 => :NameServer,
|
156
|
+
6 => :DNS,
|
157
|
+
7 => :LogServer,
|
158
|
+
8 => :QuoteServer,
|
159
|
+
9 => :LPRServer,
|
160
|
+
10 => :ImpressServer,
|
161
|
+
11 => :RLServer,
|
162
|
+
12 => :HostName,
|
163
|
+
13 => :BootFileSize,
|
164
|
+
14 => :MeritDumpFile,
|
165
|
+
15 => :DomainName,
|
166
|
+
16 => :SwapServer,
|
167
|
+
17 => :RootPath,
|
168
|
+
18 => :ExtensionsPath,
|
169
|
+
19 => :IPForwarding,
|
170
|
+
20 => :NonLocalRouting,
|
171
|
+
21 => :PolicyFilter,
|
172
|
+
22 => :MaximumDRSize,
|
173
|
+
23 => :DefaultIPTTL,
|
174
|
+
24 => :PathMTUAgingTimeout,
|
175
|
+
25 => :PathMTUPlateauTable,
|
176
|
+
26 => :InterfaceMTU,
|
177
|
+
27 => :AllSubnetsLocal,
|
178
|
+
28 => :BroadcastAddress,
|
179
|
+
29 => :PerformMask,
|
180
|
+
30 => :MaskSupplier,
|
181
|
+
31 => :PerformRouter,
|
182
|
+
32 => :RouterSolicitation,
|
183
|
+
33 => :StaticRoutingEnable,
|
184
|
+
34 => :TrailerEncap,
|
185
|
+
35 => :ArpCacheTimeout,
|
186
|
+
36 => :EthernetEncap,
|
187
|
+
37 => :DefaultTCPTTL,
|
188
|
+
38 => :TCPKeepAliveInt,
|
189
|
+
39 => :TCPKeepAliveGB,
|
190
|
+
40 => :NISDomain,
|
191
|
+
41 => :NISServer,
|
192
|
+
42 => :NTPServers,
|
193
|
+
43 => :VendorSpecificInfo,
|
194
|
+
44 => :NetBIOSNameServer,
|
195
|
+
45 => :NetBIOSDDS,
|
196
|
+
46 => :NetBIOSNodeType,
|
197
|
+
47 => :NetBIOSScope,
|
198
|
+
48 => :XWindowSystemFont,
|
199
|
+
49 => :XWindowSystemDM,
|
200
|
+
50 => :RequestedIPAddress,
|
201
|
+
51 => :IPAddressLeaseTime,
|
202
|
+
52 => :OptionOverload,
|
203
|
+
53 => :MessageType,
|
204
|
+
54 => :ServerIdentifier,
|
205
|
+
55 => :Parameters,
|
206
|
+
56 => :Message,
|
207
|
+
57 => :MaxDHCPMessageSize,
|
208
|
+
58 => :RenewTimeValue,
|
209
|
+
59 => :RebindingTimeValue,
|
210
|
+
60 => :ClassIdentifier,
|
211
|
+
61 => :ClientIdentifier,
|
212
|
+
62 => :NetWareIPDomainName,
|
213
|
+
63 => :NetWareIPInformation,
|
214
|
+
64 => :NISClientDomain,
|
215
|
+
65 => :NISServers,
|
216
|
+
66 => :TFTPServerName,
|
217
|
+
67 => :BootFileName,
|
218
|
+
68 => :MobileIPHomeAgent,
|
219
|
+
69 => :SMTPServer,
|
220
|
+
70 => :POPServer,
|
221
|
+
71 => :NNTPServer,
|
222
|
+
72 => :DefaultWWWServer,
|
223
|
+
73 => :DefaultFingerServer,
|
224
|
+
74 => :DefaultIRCServer,
|
225
|
+
75 => :StreetTalkServer,
|
226
|
+
76 => :StreetTalkDAS,
|
227
|
+
77 => :UserClassInformation,
|
228
|
+
78 => :SLPDirectoryAgent,
|
229
|
+
79 => :SLPServiceScope,
|
230
|
+
80 => :RapidCommit,
|
231
|
+
81 => :FQDN,
|
232
|
+
82 => :RelayAgentInformation,
|
233
|
+
83 => :InternetStorageNameService,
|
234
|
+
# ??
|
235
|
+
85 => :NDSServers,
|
236
|
+
86 => :NDSTreeName,
|
237
|
+
87 => :NDSContext,
|
238
|
+
88 => :BCMCSContDomainNameList,
|
239
|
+
89 => :BCMCSContIPV4AddressList,
|
240
|
+
90 => :Authentication,
|
241
|
+
91 => :ClientLastTransactTime,
|
242
|
+
92 => :AssociatedIP,
|
243
|
+
93 => :ClientSystemArchType,
|
244
|
+
94 => :ClientNetworkInterfaceIdent,
|
245
|
+
95 => :LDAP,
|
246
|
+
# ??
|
247
|
+
97 => :ClientMachineIdent,
|
248
|
+
98 => :OGUA,
|
249
|
+
# ??
|
250
|
+
109 => :AutonomousSystemNumber,
|
251
|
+
# ??
|
252
|
+
112 => :NetInfoParentServerAddress,
|
253
|
+
113 => :NetInfoParentServerTag,
|
254
|
+
114 => :URL,
|
255
|
+
116 => :AutoConfigure,
|
256
|
+
117 => :NameServiceSearch,
|
257
|
+
118 => :SubnetSelection,
|
258
|
+
119 => :DNSDomainSearchList,
|
259
|
+
120 => :SIPServers,
|
260
|
+
121 => :ClasslessStaticRoute,
|
261
|
+
122 => :CableLabsClientConfig,
|
262
|
+
123 => :GeoConf,
|
263
|
+
252 => :ProxyAutoDiscovery
|
264
|
+
}
|
265
|
+
|
266
|
+
AUTH_PROTOCOLS = {
|
267
|
+
0 => "configuration token",
|
268
|
+
1 => "delayed authentication"
|
269
|
+
}
|
270
|
+
|
271
|
+
class Packet < Network::Protos::Base
|
272
|
+
uint8 :op
|
273
|
+
uint8 :htype
|
274
|
+
uint8 :hlen
|
275
|
+
uint8 :hops
|
276
|
+
uint32rev :xid
|
277
|
+
uint16 :secs
|
278
|
+
uint16 :flags
|
279
|
+
ip :ciaddr
|
280
|
+
ip :yiaddr
|
281
|
+
ip :siaddr
|
282
|
+
ip :giaddr
|
283
|
+
mac :chaddr, :size => 16
|
284
|
+
bytes :sname, :size => 64
|
285
|
+
bytes :file, :size => 128
|
286
|
+
uint32 :isdhcp
|
287
|
+
bytes :dhcpoptions
|
288
|
+
|
289
|
+
def type
|
290
|
+
self.each_option( :MessageType ) do |opt,data|
|
291
|
+
return OP_MESSAGETYPES[ data[0] ]
|
292
|
+
end
|
293
|
+
OP_MESSAGETYPES[ @op ]
|
294
|
+
end
|
295
|
+
|
296
|
+
def client_identifier
|
297
|
+
self.each_option( :ClientIdentifier ) do |opt,data|
|
298
|
+
return data.pack('c*')
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def authentication
|
303
|
+
# Thank you Wireshark BOOTP dissector!
|
304
|
+
self.each_option( :Authentication ) do |opt,data|
|
305
|
+
auth = {}
|
306
|
+
|
307
|
+
auth['Protocol'] = AUTH_PROTOCOLS[ data[0] ]
|
308
|
+
|
309
|
+
if data[0] == 1
|
310
|
+
auth['Delay Algorithm'] = 'HMAC_MD5'
|
311
|
+
end
|
312
|
+
|
313
|
+
auth['Replay Detection Method'] = 'Monotonically-increasing counter'
|
314
|
+
auth['RDM Replay Detection Value'] = "0x" + data[3..10].map { |b| sprintf( "%02x", b ) }.join
|
315
|
+
auth['Secret ID'] = "0x" + data[11..14].map { |b| sprintf( "%02x", b ) }.join
|
316
|
+
auth['HMAC MD5 Hash'] = data[15..data.size].map { |b| sprintf( "%02X", b ) }.join
|
317
|
+
|
318
|
+
return auth
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def each_option sym = nil
|
323
|
+
offset = 0
|
324
|
+
limit = self.dhcpoptions.size
|
325
|
+
|
326
|
+
while offset < limit
|
327
|
+
opt = self.dhcpoptions[offset]
|
328
|
+
break if opt == 0xFF
|
329
|
+
offset += 1
|
330
|
+
len = self.dhcpoptions[offset]
|
331
|
+
break if len.nil?
|
332
|
+
offset += 1
|
333
|
+
data = self.dhcpoptions[offset..offset+len-1]
|
334
|
+
offset += len
|
335
|
+
|
336
|
+
if sym.nil? or OP_CONSTANTS_REV[opt] == sym
|
337
|
+
yield( OP_CONSTANTS_REV[opt], data )
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
def transaction_id
|
343
|
+
sprintf( "0x%X", @xid )
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|