bettercap 1.3.5 → 1.3.6
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/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
|