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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -10
  3. data/lib/bettercap.rb +28 -3
  4. data/lib/bettercap/context.rb +2 -2
  5. data/lib/bettercap/discovery/agents/icmp.rb +1 -1
  6. data/lib/bettercap/firewalls/base.rb +25 -0
  7. data/lib/bettercap/monkey/packetfu/utils.rb +70 -10
  8. data/lib/bettercap/network/network.rb +11 -3
  9. data/lib/bettercap/network/packet_queue.rb +1 -1
  10. data/lib/bettercap/network/protos/base.rb +97 -0
  11. data/lib/bettercap/network/protos/dhcp.rb +350 -0
  12. data/lib/bettercap/options.rb +4 -4
  13. data/lib/bettercap/proxy/stream_logger.rb +7 -3
  14. data/lib/bettercap/shell.rb +23 -1
  15. data/lib/bettercap/sniffer/parsers/base.rb +52 -0
  16. data/lib/bettercap/sniffer/parsers/cookie.rb +45 -0
  17. data/lib/bettercap/sniffer/parsers/custom.rb +0 -1
  18. data/lib/bettercap/sniffer/parsers/dhcp.rb +48 -0
  19. data/lib/bettercap/sniffer/parsers/dict.rb +0 -1
  20. data/lib/bettercap/sniffer/parsers/ftp.rb +0 -1
  21. data/lib/bettercap/sniffer/parsers/httpauth.rb +0 -2
  22. data/lib/bettercap/sniffer/parsers/https.rb +0 -2
  23. data/lib/bettercap/sniffer/parsers/irc.rb +0 -1
  24. data/lib/bettercap/sniffer/parsers/mail.rb +0 -1
  25. data/lib/bettercap/sniffer/parsers/mpd.rb +0 -1
  26. data/lib/bettercap/sniffer/parsers/nntp.rb +0 -1
  27. data/lib/bettercap/sniffer/parsers/ntlmss.rb +0 -2
  28. data/lib/bettercap/sniffer/parsers/post.rb +5 -3
  29. data/lib/bettercap/sniffer/parsers/redis.rb +0 -1
  30. data/lib/bettercap/sniffer/parsers/rlogin.rb +0 -1
  31. data/lib/bettercap/sniffer/parsers/snpp.rb +0 -1
  32. data/lib/bettercap/sniffer/parsers/url.rb +0 -2
  33. data/lib/bettercap/sniffer/parsers/whatsapp.rb +33 -0
  34. data/lib/bettercap/sniffer/sniffer.rb +6 -6
  35. data/lib/bettercap/spoofers/base.rb +23 -0
  36. data/lib/bettercap/version.rb +1 -1
  37. metadata +7 -5
  38. data/lib/bettercap/factories/firewall.rb +0 -43
  39. data/lib/bettercap/factories/parser.rb +0 -74
  40. data/lib/bettercap/factories/spoofer.rb +0 -53
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a20bd3d46b26a06c270e2d034fda7c00ea60a41
4
- data.tar.gz: 1bbf692b6a880d19988566d86c88c1c64f27bb7b
3
+ metadata.gz: a07e86570365f443ee439d850b72ce33ea9f9496
4
+ data.tar.gz: f29023f45a2b8f77100096529539fee383b2d0ca
5
5
  SHA512:
6
- metadata.gz: bafc05fd0e7580d479c6a12956cd4b5d74569ae572d39222864b89b71041ef230b17092a9a127c7e5392787512a67873ea8ccf812800ad368fed8088bf19d0cc
7
- data.tar.gz: 0d0397e693c90ad2ab4bafc23afc908b390b3c2e9975a6dc90ecd62c21ca756b0cebfff0cf6820ff5f516adc8782a8c27d5b4040ccd4f67dad817f8c304e630d
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/factories/firewall'
43
- require 'bettercap/factories/spoofer'
44
- require 'bettercap/factories/parser'
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'
@@ -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 = Factories::Firewall.get
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
- Factories::Firewall.get.enable_icmp_bcast(true)
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
- ifconfig_data = BetterCap::Shell.ifconfig(iface)
30
- if ifconfig_data =~ /#{iface}/i
31
- ifconfig_data = ifconfig_data.split(/[\s]*\n[\s]*/)
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
- raise ArgumentError, "Cannot ifconfig #{iface}"
34
- end
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
- case RUBY_PLATFORM
37
- when /linux/i
38
- ret = linux_ifconfig iface, ifconfig_data
39
- when /darwin/i
40
- ret = darwin_ifconfig iface, ifconfig_data
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.ifconfig.split("\n").each do |line|
57
- if line =~ /inet [adr:]*([\d\.]+)/
58
- ips << $1
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