bettercap 1.3.5 → 1.3.6

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