packetgen 2.1.4 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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+)
|