packetgen 2.1.4 → 2.2.0
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/lib/packetgen/config.rb +1 -0
- data/lib/packetgen/header.rb +3 -0
- data/lib/packetgen/header/bootp.rb +151 -0
- data/lib/packetgen/header/dhcp.rb +65 -0
- data/lib/packetgen/header/dhcp/option.rb +154 -0
- data/lib/packetgen/header/dhcp/options.rb +42 -0
- data/lib/packetgen/header/dns.rb +4 -4
- data/lib/packetgen/header/dns/name.rb +2 -2
- data/lib/packetgen/header/dns/rr.rb +1 -1
- data/lib/packetgen/header/eap/md5.rb +1 -1
- data/lib/packetgen/header/esp.rb +1 -1
- data/lib/packetgen/header/eth.rb +1 -1
- data/lib/packetgen/header/http.rb +8 -0
- data/lib/packetgen/header/http/headers.rb +76 -0
- data/lib/packetgen/header/http/request.rb +88 -0
- data/lib/packetgen/header/http/response.rb +116 -0
- data/lib/packetgen/header/ike/notify.rb +1 -1
- data/lib/packetgen/header/ike/sa.rb +2 -2
- data/lib/packetgen/header/ike/ts.rb +1 -1
- data/lib/packetgen/header/ip.rb +32 -2
- data/lib/packetgen/header/ipv6.rb +1 -1
- data/lib/packetgen/packet.rb +4 -2
- data/lib/packetgen/types.rb +1 -0
- data/lib/packetgen/types/cstring.rb +67 -0
- data/lib/packetgen/types/fields.rb +7 -5
- data/lib/packetgen/types/int.rb +1 -0
- data/lib/packetgen/types/int_string.rb +10 -3
- data/lib/packetgen/types/string.rb +12 -4
- data/lib/packetgen/types/tlv.rb +44 -12
- data/lib/packetgen/utils.rb +51 -1
- data/lib/packetgen/utils/arp_spoofer.rb +2 -2
- data/lib/packetgen/version.rb +1 -1
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 543fd7ef2efee43e0bf0d61c8a6520d178c869a2
|
4
|
+
data.tar.gz: bcdd42ce36fc83c202abe8c2fd6f820a13a1b588
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04c3d376f587f745972f534655f83e5fa12c30e039a58854411f89c57d769c235f9fa8faf1f6bfb37bf2deba639f45ea96a1eea8706dda77ea3c01a753aac502
|
7
|
+
data.tar.gz: ed8d4002df84be1f0e1ddbcf19dd29bbf8290ed05606648421af3e7914b6288f9aacd8ec252bec6edd1357e5c42923f84400088c0fd2bc744c06e88c179d16b0
|
data/lib/packetgen/config.rb
CHANGED
data/lib/packetgen/header.rb
CHANGED
@@ -0,0 +1,151 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
|
9
|
+
# Bootstrap Protocol, {https://tools.ietf.org/html/rfc951
|
10
|
+
# RFC 951}
|
11
|
+
#
|
12
|
+
# A BOOTP header consists of:
|
13
|
+
# * an operation code field ({#op} of type {Types::Int8Enum}),
|
14
|
+
# * a hardware address type ({#htype} of type {Types::Int8}),
|
15
|
+
# * a hardware address length ({#hlen} of type {Types::Int8}),
|
16
|
+
# * a {#hops} field ({Types::Int8}),
|
17
|
+
# * a transaction ID ({#xid} of type {Types::Int32}),
|
18
|
+
# * a {#secs} field (){Types::Int16}),
|
19
|
+
# * a {#flags} field (){Types::Int16}):
|
20
|
+
# * a 1-bit broadcast flag ({#b}),
|
21
|
+
# * a 15-bit Must Be Zero field ({#mbz}),
|
22
|
+
# * a {#ciaddr} field ({IP::Addr}),
|
23
|
+
# * a {#yiaddr} field ({IP::Addr}),
|
24
|
+
# * a {#siaddr} field ({IP::Addr}),
|
25
|
+
# * a {#giaddr} field ({IP::Addr}),
|
26
|
+
# * a {#chaddr} field (16-byte {Types::String}),
|
27
|
+
# * a {#sname} field (64-byte {Types::CString}),
|
28
|
+
# * a {#file} field (128-byte {Types::CString}),
|
29
|
+
# * and a body ({Types::String}).
|
30
|
+
#
|
31
|
+
# == Create a BOOTP header
|
32
|
+
# # standalone
|
33
|
+
# bootp = PacketGen::Header::BOOTP.new
|
34
|
+
# # in a packet
|
35
|
+
# pkt = PacketGen.gen('IP').add('BOOTP')
|
36
|
+
# # access to BOOTP header
|
37
|
+
# pkt.bootp # => PacketGen::Header::BOOTP
|
38
|
+
# @author Sylvain Daubert
|
39
|
+
# @since 2.2.0
|
40
|
+
class BOOTP < Base
|
41
|
+
|
42
|
+
UDP_SERVER_PORT = 67
|
43
|
+
UDP_CLIENT_PORT = 68
|
44
|
+
|
45
|
+
# DHCP opcodes
|
46
|
+
OPCODES = {
|
47
|
+
'BOOTREQUEST' => 1,
|
48
|
+
'BOOTREPLY' => 2
|
49
|
+
}
|
50
|
+
|
51
|
+
# @!attribute op
|
52
|
+
# 8-bit opcode
|
53
|
+
# @return [Integer]
|
54
|
+
define_field :op, Types::Int8Enum, enum: OPCODES
|
55
|
+
|
56
|
+
# @!attribute htype
|
57
|
+
# 8-bit hardware address type
|
58
|
+
# @return [Integer]
|
59
|
+
define_field :htype, Types::Int8, default: 1
|
60
|
+
|
61
|
+
# @!attribute hlen
|
62
|
+
# 8-bit hardware address length
|
63
|
+
# @return [Integer]
|
64
|
+
define_field :hlen, Types::Int8, default: 6
|
65
|
+
|
66
|
+
# @!attribute hops
|
67
|
+
# @return [Integer]
|
68
|
+
define_field :hops, Types::Int8
|
69
|
+
|
70
|
+
# @!attribute xid
|
71
|
+
# 32-bit Transaction ID
|
72
|
+
# @return [Integer]
|
73
|
+
define_field :xid, Types::Int32
|
74
|
+
|
75
|
+
# @!attribute secs
|
76
|
+
# 16-bit integer: number of seconds elapsed since client began address
|
77
|
+
# acquisition or renewal process
|
78
|
+
# @return [Integer]
|
79
|
+
define_field :secs, Types::Int16
|
80
|
+
|
81
|
+
# @!attribute flags
|
82
|
+
# 16-bit flag field
|
83
|
+
# @return [Integer]
|
84
|
+
define_field :flags, Types::Int16
|
85
|
+
|
86
|
+
# @!attribute ciaddr
|
87
|
+
# client IP address
|
88
|
+
# @return [String]
|
89
|
+
define_field :ciaddr, IP::Addr
|
90
|
+
|
91
|
+
# @!attribute yiaddr
|
92
|
+
# 'your' (client) IP address
|
93
|
+
# @return [String]
|
94
|
+
define_field :yiaddr, IP::Addr
|
95
|
+
|
96
|
+
# @!attribute siaddr
|
97
|
+
# IP address of next server to use in bootstrap
|
98
|
+
# @return [String]
|
99
|
+
define_field :siaddr, IP::Addr
|
100
|
+
|
101
|
+
# @!attribute giaddr
|
102
|
+
# Relay agent IP address, used in booting via a relay agent
|
103
|
+
# @return [String]
|
104
|
+
define_field :giaddr, IP::Addr
|
105
|
+
|
106
|
+
# @!attribute chaddr
|
107
|
+
# client hardware address
|
108
|
+
# @return [String]
|
109
|
+
define_field :chaddr, Types::String, static_length: 16
|
110
|
+
|
111
|
+
# @!attribute sname
|
112
|
+
# optional server hostname, null-terminated string
|
113
|
+
# @return [String]
|
114
|
+
define_field :sname, Types::CString, static_length: 64
|
115
|
+
|
116
|
+
# @!attribute file
|
117
|
+
# Boot file name, null terminated string
|
118
|
+
# @return [String]
|
119
|
+
define_field :file, Types::CString, static_length: 128
|
120
|
+
|
121
|
+
# @!attribute body
|
122
|
+
# @return [String]
|
123
|
+
define_field :body, Types::String
|
124
|
+
|
125
|
+
# @!attribute b
|
126
|
+
# Broadcast flag, from {#flags}
|
127
|
+
# @return [Boolean]
|
128
|
+
# @!attribute mbz
|
129
|
+
# 15-bit Must Be Zero bits, from {#flags}
|
130
|
+
# @return [Boolean]
|
131
|
+
define_bit_fields_on :flags, :b, :mbz, 15
|
132
|
+
|
133
|
+
def inspect
|
134
|
+
str = Inspect.dashed_line(self.class, 2)
|
135
|
+
fields.each do |attr|
|
136
|
+
next if attr == :body
|
137
|
+
next unless is_present?(attr)
|
138
|
+
if attr == :chaddr and self.hlen == 6
|
139
|
+
str << Inspect.inspect_attribute(attr, Eth::MacAddr.new.read(self[:chaddr][0, 6]), 2)
|
140
|
+
else
|
141
|
+
str << Inspect.inspect_attribute(attr, self[attr], 2)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
str
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
UDP.bind_header BOOTP, sport: 67, dport: 68
|
149
|
+
UDP.bind_header BOOTP, sport: 68, dport: 67
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
|
9
|
+
# Dynamic Host Configuration Protocol, {https://tools.ietf.org/html/rfc2131
|
10
|
+
# RFC 2131}
|
11
|
+
#
|
12
|
+
# A DHCP header is quite simple. It is composed of:
|
13
|
+
# * a {#magic} field ({Types::Int32}) to retrieve it in a BOOTP header,
|
14
|
+
# * a, {#options} field ({Options} type, which is a collection of DHCP
|
15
|
+
# options).
|
16
|
+
#
|
17
|
+
# In PacketGen, a DHCP header is always a secondary header after {BOOTP} one.
|
18
|
+
#
|
19
|
+
# == Create a DHCP header
|
20
|
+
# # standalone
|
21
|
+
# dhcp = PacketGen::Header::DHCP.new
|
22
|
+
# # in a packet
|
23
|
+
# pkt = PacketGen.gen('IP').add('BOOTP').add('DHCP')
|
24
|
+
# # access to DHCP header
|
25
|
+
# pkt.dhcp # => PacketGen::Header::DHCP
|
26
|
+
#
|
27
|
+
# == Add options
|
28
|
+
# Options may be added these ways:
|
29
|
+
# dhcp = PacketGen::Header::DHCP.new
|
30
|
+
# # Add a lease_time option
|
31
|
+
# dhcp.options << { type: 'lease_time', value: 3600 }
|
32
|
+
# # Add a domain option. Here, use integer type
|
33
|
+
# dhcp.options << { type: 15, value: 'example.net'}
|
34
|
+
# # Add an end option
|
35
|
+
# dhcp.options << { type: 'end' }
|
36
|
+
# # And finish with padding
|
37
|
+
# dhcp.options << { type: 'pad' }
|
38
|
+
# @author Sylvain Daubert
|
39
|
+
# @since 2.2.0
|
40
|
+
class DHCP < Base; end
|
41
|
+
|
42
|
+
require_relative 'dhcp/option'
|
43
|
+
require_relative 'dhcp/options'
|
44
|
+
|
45
|
+
class DHCP < Base
|
46
|
+
# DHCP magic value in BOOTP options
|
47
|
+
DHCP_MAGIC = 0x63825363
|
48
|
+
|
49
|
+
# @!attribute magic
|
50
|
+
# @return [Integer]
|
51
|
+
define_field :magic, Types::Int32, default: 0x63825563
|
52
|
+
# @!attribute options
|
53
|
+
# @return [DHCP::Options]
|
54
|
+
define_field :options, DHCP::Options
|
55
|
+
|
56
|
+
# differentiate from BOOTP by checking presence of DHCP magic
|
57
|
+
# @return [Boolean]
|
58
|
+
def parse?
|
59
|
+
self.magic == DHCP_MAGIC
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
BOOTP.bind_header DHCP
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
class DHCP
|
9
|
+
|
10
|
+
# define DHCP Options.
|
11
|
+
# keys are option type, value are arrays containing option names
|
12
|
+
# as strings, and a hash passed to {Option#initialize}.
|
13
|
+
DHCPOptions = {
|
14
|
+
1 => ['subnet_mask', length: 4, v: IP::Addr],
|
15
|
+
2 => ['time_zone'],
|
16
|
+
3 => ['router', length: 4, v: IP::Addr],
|
17
|
+
4 => ['time_server', length: 4, v: IP::Addr],
|
18
|
+
5 => ['IEN_name_server', length: 4, v: IP::Addr],
|
19
|
+
6 => ['name_server', length: 4, v: IP::Addr],
|
20
|
+
7 => ['log_server', length: 4, v: IP::Addr],
|
21
|
+
8 => ['cookie_server', length: 4, v: IP::Addr],
|
22
|
+
9 => ['lpr_server', length: 4, v: IP::Addr],
|
23
|
+
12 => ['hostname'],
|
24
|
+
14 => ['dump_path'],
|
25
|
+
15 => ['domain'],
|
26
|
+
17 => ['root_disk_path'],
|
27
|
+
23 => ['default_ttl'],
|
28
|
+
24 => ['pmtu_timeout'],
|
29
|
+
28 => ['broadcast_address', length: 4, v: IP::Addr],
|
30
|
+
40 => ['NIS_domain'],
|
31
|
+
41 => ['NIS_server', length: 4, v: IP::Addr],
|
32
|
+
42 => ['NTP_server', length: 4, v: IP::Addr],
|
33
|
+
43 => ['vendor_specific'],
|
34
|
+
44 => ['NetBIOS_server', length: 4, v: IP::Addr],
|
35
|
+
45 => ['NetBIOS_dist_server', length: 4, v: IP::Addr],
|
36
|
+
50 => ['requested_addr', length: 4, v: IP::Addr],
|
37
|
+
51 => ['lease_time', length: 4, v: Types::Int32, value: 43200],
|
38
|
+
53 => ['message-type', length: 1, v: Types::Int8],
|
39
|
+
54 => ['server_id', length: 4, v: IP::Addr],
|
40
|
+
55 => ['param_req_list'],
|
41
|
+
56 => ['error_message'],
|
42
|
+
57 => ['max_dhcp_size', length: 2, v: Types::Int16, value: 1500],
|
43
|
+
58 => ['renewal_time', length: 4, v: Types::Int32, value: 21600],
|
44
|
+
59 => ['rebinding_time', length: 4, v: Types::Int32, value: 37800],
|
45
|
+
60 => ['vendor_class_id'],
|
46
|
+
61 => ['client_id'],
|
47
|
+
64 => ['NISplus_domain'],
|
48
|
+
65 => ['NISplus_server', length: 4, v: IP::Addr],
|
49
|
+
69 => ['SMTP_server', length: 4, v: IP::Addr],
|
50
|
+
70 => ['POP3_server', length: 4, v: IP::Addr],
|
51
|
+
71 => ['NNTP_server', length: 4, v: IP::Addr],
|
52
|
+
72 => ['WWW_server', length: 4, v: IP::Addr],
|
53
|
+
73 => ['finger_server', length: 4, v: IP::Addr],
|
54
|
+
74 => ['IRC_server', length: 4, v: IP::Addr]
|
55
|
+
}
|
56
|
+
|
57
|
+
# Class to indicate DHCP options end
|
58
|
+
class End < Types::Int8
|
59
|
+
def initialize(value=255)
|
60
|
+
super
|
61
|
+
end
|
62
|
+
def to_human; self.class.to_s.sub(/.*::/, '').downcase; end
|
63
|
+
alias human_type to_human
|
64
|
+
end
|
65
|
+
|
66
|
+
# Class to indicate padding after DHCP options
|
67
|
+
class Pad < End
|
68
|
+
def initialize(value=0)
|
69
|
+
super
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# DHCP option
|
74
|
+
#
|
75
|
+
# A DHCP option is a {Types::TLV TLV}, so it has:
|
76
|
+
# * a {#type} ({Types::Int8}),
|
77
|
+
# * a {#length} ({Types::Int8}),
|
78
|
+
# * and a {#value}. Defalt type is {Types::String} but some options
|
79
|
+
# may use more suitable type (by example, a {IP::Addr} for +router+
|
80
|
+
# option).
|
81
|
+
# @author Sylvain Daubert
|
82
|
+
class Option < Types::TLV
|
83
|
+
|
84
|
+
# Option types
|
85
|
+
TYPES = Hash[DHCPOptions.to_a.map { |type, ary| [type, ary[0]] }]
|
86
|
+
|
87
|
+
# @param [Hash] options
|
88
|
+
# @option options [Integer] :type
|
89
|
+
# @option options [Integer] :length
|
90
|
+
# @option options [String] :value
|
91
|
+
def initialize(options={})
|
92
|
+
super
|
93
|
+
if DHCPOptions.has_key?(self.type)
|
94
|
+
h = DHCPOptions[self.type].last
|
95
|
+
if h.is_a? Hash
|
96
|
+
h.each do |k, v|
|
97
|
+
self.length = v if k == :length
|
98
|
+
if k == :v
|
99
|
+
self[:value] = v.new
|
100
|
+
self.value = options[:value] if options[:value]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# @private
|
108
|
+
alias private_read read
|
109
|
+
|
110
|
+
# Populate object from a binary string
|
111
|
+
# @param [String] str
|
112
|
+
# @return [Option,End,Pad] may return another object than itself
|
113
|
+
def read(str)
|
114
|
+
read_type = str[0].unpack('C').first
|
115
|
+
if read_type == 0
|
116
|
+
Pad.new.read(str)
|
117
|
+
elsif read_type == 255
|
118
|
+
End.new.read(str)
|
119
|
+
elsif DHCPOptions.has_key?(read_type)
|
120
|
+
Option.new(DHCPOptions[read_type][1] || {}).private_read(str)
|
121
|
+
else
|
122
|
+
super
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def has_human_types?
|
127
|
+
true
|
128
|
+
end
|
129
|
+
|
130
|
+
def human_type
|
131
|
+
if DHCPOptions.has_key?(type)
|
132
|
+
DHCPOptions[type].first.dup
|
133
|
+
else
|
134
|
+
type.to_s
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def to_human
|
139
|
+
s = human_type
|
140
|
+
if length > 0
|
141
|
+
if value.respond_to? :to_human
|
142
|
+
s << ":#{value.to_human}"
|
143
|
+
elsif self[:value].is_a? Types::Int
|
144
|
+
s << ":#{self.value.to_i}"
|
145
|
+
else
|
146
|
+
s << ":#{value.inspect}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
s
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# This file is part of PacketGen
|
2
|
+
# See https://github.com/sdaubert/packetgen for more informations
|
3
|
+
# Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
module PacketGen
|
7
|
+
module Header
|
8
|
+
class DHCP
|
9
|
+
|
10
|
+
# Container class for DHCP Options
|
11
|
+
#
|
12
|
+
# == Add DHCP options to an +Options+ instance
|
13
|
+
# options = PacketGen::Header::DHCP::Options.new
|
14
|
+
# # Add a lease_time option
|
15
|
+
# options << { type: 'lease_time', value: 3600 }
|
16
|
+
# # Add a domain option. Here, use integer type
|
17
|
+
# options << { type: 15, value: 'example.net'}
|
18
|
+
# # Add an end option
|
19
|
+
# options << { type: 'end' }
|
20
|
+
# # And finish with padding
|
21
|
+
# options << { type: 'pad' }
|
22
|
+
# @author Sylvain Daubert
|
23
|
+
class Options < Types::Array
|
24
|
+
set_of Option
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def record_from_hash(hsh)
|
29
|
+
case hsh[:type]
|
30
|
+
when 'pad', 0
|
31
|
+
Pad.new
|
32
|
+
when 'end', 255
|
33
|
+
End.new
|
34
|
+
else
|
35
|
+
obj_klass = self.class.class_eval { @klass }
|
36
|
+
obj_klass.new(hsh)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/packetgen/header/dns.rb
CHANGED
@@ -144,16 +144,16 @@ module PacketGen
|
|
144
144
|
define_field :arcount, Types::Int16
|
145
145
|
# @!attribute qd
|
146
146
|
# @return [QDSection]
|
147
|
-
define_field :qd, QDSection, builder: ->(
|
147
|
+
define_field :qd, QDSection, builder: ->(h,t) { t.new(h, h[:qdcount]) }
|
148
148
|
# @!attribute an
|
149
149
|
# @return [RRSection]
|
150
|
-
define_field :an, RRSection, builder: ->(
|
150
|
+
define_field :an, RRSection, builder: ->(h,t) { t.new(h, h[:ancount]) }
|
151
151
|
# @!attribute ns
|
152
152
|
# @return [RRSection]
|
153
|
-
define_field :ns, RRSection, builder: ->(
|
153
|
+
define_field :ns, RRSection, builder: ->(h,t) { t.new(h, h[:nscount]) }
|
154
154
|
# @!attribute ar
|
155
155
|
# @return [RRSection]
|
156
|
-
define_field :ar, RRSection, builder: ->(
|
156
|
+
define_field :ar, RRSection, builder: ->(h,t) { t.new(h, h[:arcount]) }
|
157
157
|
|
158
158
|
# @!attribute qr
|
159
159
|
# @return [Boolean] query (+false+) or response (+true+)
|