packetgen-plugin-smb 0.2.0 → 0.3.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-plugin-smb.rb +7 -5
- data/lib/packetgen/plugin/gssapi.rb +125 -0
- data/lib/packetgen/plugin/smb.rb +26 -32
- data/lib/packetgen/plugin/smb/blocks.rb +2 -2
- data/lib/packetgen/plugin/smb/browser.rb +3 -3
- data/lib/packetgen/plugin/smb/browser/domain_announcement.rb +3 -3
- data/lib/packetgen/plugin/smb/browser/host_announcement.rb +4 -4
- data/lib/packetgen/plugin/smb/browser/local_master_announcement.rb +3 -3
- data/lib/packetgen/plugin/smb/close.rb +9 -59
- data/lib/packetgen/plugin/smb/close/request.rb +45 -0
- data/lib/packetgen/plugin/smb/close/response.rb +36 -0
- data/lib/packetgen/plugin/smb/filetime.rb +10 -9
- data/lib/packetgen/plugin/smb/nt_create_and_x.rb +9 -264
- data/lib/packetgen/plugin/smb/ntcreateandx/request.rb +159 -0
- data/lib/packetgen/plugin/smb/ntcreateandx/response.rb +128 -0
- data/lib/packetgen/plugin/smb/string.rb +4 -4
- data/lib/packetgen/plugin/smb/trans.rb +9 -190
- data/lib/packetgen/plugin/smb/trans/request.rb +121 -0
- data/lib/packetgen/plugin/smb/trans/response.rb +94 -0
- data/lib/packetgen/plugin/smb2.rb +181 -0
- data/lib/packetgen/plugin/smb2/base.rb +31 -0
- data/lib/packetgen/plugin/smb2/error.rb +50 -0
- data/lib/packetgen/plugin/smb2/guid.rb +68 -0
- data/lib/packetgen/plugin/smb2/negotiate.rb +22 -0
- data/lib/packetgen/plugin/smb2/negotiate/context.rb +131 -0
- data/lib/packetgen/plugin/smb2/negotiate/request.rb +166 -0
- data/lib/packetgen/plugin/smb2/negotiate/response.rb +190 -0
- data/lib/packetgen/plugin/smb2/session_setup.rb +21 -0
- data/lib/packetgen/plugin/smb2/session_setup/request.rb +98 -0
- data/lib/packetgen/plugin/smb2/session_setup/response.rb +69 -0
- data/lib/packetgen/plugin/smb_version.rb +1 -1
- data/packetgen-plugin-smb.gemspec +2 -1
- metadata +42 -4
@@ -0,0 +1,45 @@
|
|
1
|
+
# This file is part of packetgen-plugin-smb.
|
2
|
+
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
+
# Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
module Close
|
11
|
+
# Close Request.
|
12
|
+
# @author Sylvain Daubert
|
13
|
+
# @since 0.3.0
|
14
|
+
class Request < PacketGen::Header::Base
|
15
|
+
# @!attribute word_count
|
16
|
+
# The size, in 2-byte words, of the SMB command parameters. It should
|
17
|
+
# be +3+.
|
18
|
+
# @return [Integer]
|
19
|
+
define_field :word_count, PacketGen::Types::Int8, default: 3
|
20
|
+
# @!attribute fid
|
21
|
+
# 16-bit FID of the object to close
|
22
|
+
# @return [Integer]
|
23
|
+
define_field :fid, PacketGen::Types::Int16le, default: 3
|
24
|
+
# @!attribute last_modified
|
25
|
+
# 32-bit time value encoded as the number of seconds since January
|
26
|
+
# 1, 1970 00:00:00.0. The client can request that the last modification
|
27
|
+
# time for the file be updated to this time value. A value of +0x00000000+
|
28
|
+
# or +0xFFFFFFFF+ results in the server not updating the last modification
|
29
|
+
# time.
|
30
|
+
# @return [Integer]
|
31
|
+
define_field :last_modified, PacketGen::Types::Int32le
|
32
|
+
# @!attribute byte_count
|
33
|
+
# Should be 0.
|
34
|
+
# @return [Integer]
|
35
|
+
define_field :byte_count, PacketGen::Types::Int16le, default: 0
|
36
|
+
|
37
|
+
# Give protocol name for this class
|
38
|
+
# @return [String]
|
39
|
+
def protocol_name
|
40
|
+
'SMB::Close::Request'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# This file is part of packetgen-plugin-smb.
|
2
|
+
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
+
# Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
module Close
|
11
|
+
# Close Response.
|
12
|
+
#
|
13
|
+
# This is a void container. {#word_count} and {#byte_count} should be 0.
|
14
|
+
# @author Sylvain Daubert
|
15
|
+
# @since 0.3.0
|
16
|
+
class Response < PacketGen::Header::Base
|
17
|
+
# @!attribute word_count
|
18
|
+
# The size, in 2-byte words, of the SMB command parameters. It should
|
19
|
+
# be +0+.
|
20
|
+
# @return [Integer]
|
21
|
+
define_field :word_count, PacketGen::Types::Int8, default: 3
|
22
|
+
define_field :last_modified, PacketGen::Types::Int32le
|
23
|
+
# @!attribute byte_count
|
24
|
+
# Should be 0.
|
25
|
+
# @return [Integer]
|
26
|
+
define_field :byte_count, PacketGen::Types::Int16le, default: 0
|
27
|
+
|
28
|
+
# Give protocol name for this class
|
29
|
+
# @return [String]
|
30
|
+
def protocol_name
|
31
|
+
'SMB::Close::Response'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
# This file is part of
|
1
|
+
# This file is part of packetgen-plugin-smb.
|
2
2
|
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
4
|
# This program is published under MIT license.
|
5
5
|
|
6
6
|
# frozen_string_literal: true
|
@@ -14,6 +14,9 @@ module PacketGen::Plugin
|
|
14
14
|
# This value also indicate no time.
|
15
15
|
NO_TIME = Time.utc(1601).freeze
|
16
16
|
|
17
|
+
# Numbers of 100ns in one second
|
18
|
+
ONE_SEC = 10_000_000
|
19
|
+
|
17
20
|
# @param [Hash] options
|
18
21
|
# @option options [Integer] :filetime
|
19
22
|
# @option options [Time] :time
|
@@ -25,7 +28,7 @@ module PacketGen::Plugin
|
|
25
28
|
|
26
29
|
@int = PacketGen::Types::SInt64le.new(options[:filetime])
|
27
30
|
if options[:time]
|
28
|
-
@time = options[:time]
|
31
|
+
@time = options[:time].getgm
|
29
32
|
@int.value = time2filetime
|
30
33
|
else
|
31
34
|
@time = filetime2time
|
@@ -46,7 +49,7 @@ module PacketGen::Plugin
|
|
46
49
|
if no_time?
|
47
50
|
'no time'
|
48
51
|
else
|
49
|
-
@time.
|
52
|
+
@time.strftime("%Y-%m-%d %H:%M:%S.%9N %Z")
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
@@ -81,21 +84,19 @@ module PacketGen::Plugin
|
|
81
84
|
|
82
85
|
def filetime2time
|
83
86
|
filetime = @int.to_i
|
84
|
-
secs = filetime / 10_000
|
85
|
-
nsecs = (filetime % 10_000) * 100
|
86
87
|
if filetime.zero?
|
87
88
|
NO_TIME
|
88
89
|
elsif filetime.positive?
|
89
|
-
Time.at(NO_TIME) + Rational("#{
|
90
|
+
Time.at(NO_TIME) + Rational("#{filetime}/#{ONE_SEC}")
|
90
91
|
else
|
91
|
-
Time.at(Time.now.utc) + Rational("#{
|
92
|
+
Time.at(Time.now.utc) + Rational("#{filetime}/#{ONE_SEC}")
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
95
96
|
def time2filetime
|
96
97
|
# Time#to_f then #to_r is more precise than Time#to_r
|
97
98
|
# (ie Time#to_r sometimes does a rounding error).
|
98
|
-
(@time.to_i - NO_TIME.to_i) *
|
99
|
+
(@time.to_i - NO_TIME.to_i) * ONE_SEC + ((@time.to_f.to_r * ONE_SEC) % ONE_SEC).to_i
|
99
100
|
end
|
100
101
|
end
|
101
102
|
end
|
@@ -1,273 +1,18 @@
|
|
1
|
-
# This file is part of
|
1
|
+
# This file is part of packetgen-plugin-smb.
|
2
2
|
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
4
|
# This program is published under MIT license.
|
5
5
|
|
6
6
|
# frozen_string_literal: true
|
7
7
|
|
8
8
|
module PacketGen::Plugin
|
9
9
|
class SMB
|
10
|
-
#
|
11
|
-
|
12
|
-
# A NtCreateAndXRequest contains:
|
13
|
-
# * a {#word_count} field (+Int8+), size, in 2-byte words of SMB
|
14
|
-
# parameters:
|
15
|
-
# * {#and_xcommand} (+Int8+), next command in packet,
|
16
|
-
# * {#rsv1} (+Int8+),
|
17
|
-
# * {#and_xoffset} (+Int16le+), offset of the next command from the
|
18
|
-
# start of SMB header,
|
19
|
-
# * {#rsv2} (+Int8+),
|
20
|
-
# * {#filename_len} (+Int16le+), size of {#filename} in SMB data,
|
21
|
-
# * {#flags} (+Int32le+),
|
22
|
-
# * {#root_dir_fid} (+Int32le+),
|
23
|
-
# * {#access_mask} (+Int32le+),
|
24
|
-
# * {#alloc_size} (+Int64le+),
|
25
|
-
# * {#attributes} (+Int32le+),
|
26
|
-
# * {#share_access} (+Int32le+),
|
27
|
-
# * {#disposition} (+Int32le+),
|
28
|
-
# * {#options} (+Int32le+),
|
29
|
-
# * {#impersonation} (+Int32le+),
|
30
|
-
# * {#sec_flags} (+Int38+),
|
31
|
-
# * #{byte_count} (+Int16le+), size in bytes of SMB data:
|
32
|
-
# * {#pad1} (+Int8),
|
33
|
-
# * {#filename} ({SMB::String}),
|
34
|
-
# * {#extra_bytes} (+String+).
|
35
|
-
#
|
36
|
-
# == Known limitations
|
37
|
-
# 1. Only the first command is properly handled. Chained commands are not.
|
38
|
-
# 2. {#filename} is mandatory handled as Windows Unicode string.
|
39
|
-
# @author Sylvain Daubert
|
40
|
-
class NtCreateAndXRequest < PacketGen::Header::Base
|
41
|
-
# Commands that may follow this one in a SMB packet
|
42
|
-
COMMANDS = {
|
43
|
-
'read' => 0x0a,
|
44
|
-
'read_andx' => 0x2e,
|
45
|
-
'ioctl' => 0x27,
|
46
|
-
'no further commands' => 0xff
|
47
|
-
}.freeze
|
48
|
-
|
49
|
-
# @!attribute word_count
|
50
|
-
# The size, in 2-byte words, of the SMB parameters.
|
51
|
-
# @return [Integer]
|
52
|
-
define_field :word_count, PacketGen::Types::Int8, default: 24
|
53
|
-
# @!attribute and_xcommand
|
54
|
-
# 8-bit command code for the next SMB command in the
|
55
|
-
# packet.
|
56
|
-
# @return [Integer]
|
57
|
-
define_field :and_xcommand, PacketGen::Types::Int8Enum, enum: COMMANDS
|
58
|
-
# @!attribute rsv1
|
59
|
-
# 8-bit reserved field.
|
60
|
-
# @return [Integer]
|
61
|
-
define_field :rsv1, PacketGen::Types::Int8, default: 0
|
62
|
-
# @!attribute and_xoffset
|
63
|
-
# 16-bit offset from the start of SMB header to the start of
|
64
|
-
# the {#word_count} field in the next SMB command in this
|
65
|
-
# packet.
|
66
|
-
# @return [Integer]
|
67
|
-
define_field :and_xoffset, PacketGen::Types::Int16le, default: 0
|
68
|
-
# @!attribute rsv2
|
69
|
-
# 8-bit reserved field.
|
70
|
-
# @return [Integer]
|
71
|
-
define_field :rsv2, PacketGen::Types::Int8, default: 0
|
72
|
-
# @!attribute filename_len
|
73
|
-
# 16-bit length of the {#filename} field.
|
74
|
-
# @return [Integer]
|
75
|
-
define_field :filename_len, PacketGen::Types::Int16le
|
76
|
-
alias filename_length filename_len
|
77
|
-
alias filename_length= filename_len=
|
78
|
-
# @!attribute flags
|
79
|
-
# 32-bit flags word
|
80
|
-
# @return [Integer]
|
81
|
-
define_field :flags, PacketGen::Types::Int32le
|
82
|
-
# @!attribute root_dir_fid
|
83
|
-
# 32-bit file ID of an opened root directory.
|
84
|
-
# @return [Integer]
|
85
|
-
define_field :root_dir_fid, PacketGen::Types::Int32le
|
86
|
-
# @!attribute access_mask
|
87
|
-
# 32-bit flags that indicate access rights.
|
88
|
-
# @return [Integer]
|
89
|
-
define_field :access_mask, PacketGen::Types::Int32le
|
90
|
-
# @!attribute alloc_size
|
91
|
-
# 64-bit initial allocation size.
|
92
|
-
# @return [Integer]
|
93
|
-
define_field :alloc_size, PacketGen::Types::Int64le
|
94
|
-
# @!attribute attributes
|
95
|
-
# 32-bit extended file attributes.
|
96
|
-
# @return [Integer]
|
97
|
-
define_field :attributes, PacketGen::Types::Int32le
|
98
|
-
# @!attribute share_access
|
99
|
-
# 32-bit field that specifies how the file should be shared.
|
100
|
-
# @return [Integer]
|
101
|
-
define_field :share_access, PacketGen::Types::Int32le
|
102
|
-
# @!attribute disposition
|
103
|
-
# 32-bit value that represents the action to take if the file
|
104
|
-
# already exists or if the file is a new file and does not already
|
105
|
-
# exist.
|
106
|
-
# @return [Integer]
|
107
|
-
define_field :disposition, PacketGen::Types::Int32le
|
108
|
-
# @!attribute options
|
109
|
-
# 32-bit field containing flag options to use if creating the file
|
110
|
-
# or the directory.
|
111
|
-
# @return [Integer]
|
112
|
-
define_field :options, PacketGen::Types::Int32le
|
113
|
-
# @!attribute impersonation
|
114
|
-
# 32-bit field specifying the impersonation level requested by
|
115
|
-
# the application.
|
116
|
-
# @return [Integer]
|
117
|
-
define_field :impersonation, PacketGen::Types::Int32le
|
118
|
-
# @!attribute sec_flags
|
119
|
-
# 8-bit security flags.
|
120
|
-
define_field :sec_flags, PacketGen::Types::Int8
|
121
|
-
# @!attribute byte_count
|
122
|
-
# The size, in bytes, of the SMB data.
|
123
|
-
# @return [Integer]
|
124
|
-
define_field :byte_count, PacketGen::Types::Int16le
|
125
|
-
# @!attribute pad1
|
126
|
-
# Padding before {#filename} to align it on 16-bit boundary. Only present
|
127
|
-
# if {SMB#flags2_unicode?} is +true+.
|
128
|
-
# @return [Integer]
|
129
|
-
define_field :pad1, PacketGen::Types::Int8, optional: ->(h) { h.packet && h.packet.smb.flags2_unicode? }
|
130
|
-
# @!attribute filename
|
131
|
-
# A string that represents the fully qualified name of the file
|
132
|
-
# relative to the supplied TID
|
133
|
-
# @return [String]
|
134
|
-
define_field :filename, SMB::String, builder: ->(h, t) { t.new(unicode: !h.packet || h.packet.smb.flags2_unicode?) }
|
135
|
-
# @!attribute extra_bytes
|
136
|
-
# @return [Integer]
|
137
|
-
define_field :extra_bytes, PacketGen::Types::String,
|
138
|
-
builder: ->(h, t) { t.new(length_from: -> { h.byte_count - (h.present?(:pad1) ? 1 : 0) - h[:filename].sz }) }
|
139
|
-
|
140
|
-
# Give protocol name for this class
|
141
|
-
# @return [String]
|
142
|
-
def protocol_name
|
143
|
-
'SMB::NtCreateAndXRequest'
|
144
|
-
end
|
145
|
-
|
146
|
-
# Compute {#filename_len} and {#byte_count}
|
147
|
-
# @return [void]
|
148
|
-
def calc_length
|
149
|
-
self.filename_len = self[:filename].sz
|
150
|
-
pad1sz = self.present?(:pad1) ? 1 : 0
|
151
|
-
bcount = pad1sz + filename_len + self[:extra_bytes].sz
|
152
|
-
self.byte_count = bcount
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
# SMB Command NtCreateAndX response
|
157
|
-
# @author Sylvain Daubert
|
158
|
-
class NtCreateAndXResponse < PacketGen::Header::Base
|
159
|
-
# OpLock levels
|
160
|
-
OP_LOCK_LEVELS = {
|
161
|
-
'none' => 0,
|
162
|
-
'exclusive' => 1,
|
163
|
-
'batch' => 2,
|
164
|
-
'level II' => 3,
|
165
|
-
}.freeze
|
166
|
-
|
167
|
-
# @!attribute word_count
|
168
|
-
# The size, in 2-byte words, of the SMB parameters.
|
169
|
-
# @return [Integer]
|
170
|
-
define_field :word_count, PacketGen::Types::Int8, default: 34
|
171
|
-
# @!attribute and_xcommand
|
172
|
-
# 8-bit command code for the next SMB command in the
|
173
|
-
# packet.
|
174
|
-
# @return [Integer]
|
175
|
-
define_field :and_xcommand, PacketGen::Types::Int8Enum, enum: NtCreateAndXRequest::COMMANDS
|
176
|
-
# @!attribute rsv1
|
177
|
-
# 8-bit reserved field.
|
178
|
-
# @return [Integer]
|
179
|
-
define_field :rsv1, PacketGen::Types::Int8, default: 0
|
180
|
-
# @!attribute and_xoffset
|
181
|
-
# 16-bit offset from the start of SMB header to the start of
|
182
|
-
# the {#word_count} field in the next SMB command in this
|
183
|
-
# packet.
|
184
|
-
# @return [Integer]
|
185
|
-
define_field :and_xoffset, PacketGen::Types::Int16le, default: 0
|
186
|
-
# @!attribute oplock_level
|
187
|
-
# 8-bit OpLock level.
|
188
|
-
# @return [Integer]
|
189
|
-
define_field :oplock_level, PacketGen::Types::Int8Enum, enum: OP_LOCK_LEVELS
|
190
|
-
# @!attribute fid
|
191
|
-
# 16-bit FID.
|
192
|
-
# @return [Integer]
|
193
|
-
define_field :fid, PacketGen::Types::Int16le
|
194
|
-
# @!attribute disposition
|
195
|
-
# 32-bit value that represents the action to take if the file
|
196
|
-
# already exists or if the file is a new file and does not already
|
197
|
-
# exist.
|
198
|
-
# @return [Integer]
|
199
|
-
define_field :disposition, PacketGen::Types::Int32le
|
200
|
-
# @!attribute create_time
|
201
|
-
# 64-bit integer representing the time that the file was created.
|
202
|
-
# @return [Integer]
|
203
|
-
define_field :create_time, SMB::Filetime
|
204
|
-
# @!attribute access_time
|
205
|
-
# 64-bit integer representing the time that the file was last accessed.
|
206
|
-
# @return [Integer]
|
207
|
-
define_field :access_time, SMB::Filetime
|
208
|
-
# @!attribute write_time
|
209
|
-
# 64-bit integer representing the time that the file was last writen.
|
210
|
-
# @return [Integer]
|
211
|
-
define_field :write_time, SMB::Filetime
|
212
|
-
# @!attribute change_time
|
213
|
-
# 64-bit integer representing the time that the file was last changed.
|
214
|
-
# @return [Integer]
|
215
|
-
define_field :change_time, SMB::Filetime
|
216
|
-
# @!attribute attributes
|
217
|
-
# 32-bit extended file attributes.
|
218
|
-
# @return [Integer]
|
219
|
-
define_field :attributes, PacketGen::Types::Int32le
|
220
|
-
# @!attribute alloc_size
|
221
|
-
# 64-bit integer representing the number of bytes allocated to the file.
|
222
|
-
# @return [Integer]
|
223
|
-
define_field :alloc_size, PacketGen::Types::Int64le
|
224
|
-
# @!attribute end_of_file
|
225
|
-
# 64-bit integer representing the end of file offset.
|
226
|
-
# @return [Integer]
|
227
|
-
define_field :end_of_file, PacketGen::Types::Int64le
|
228
|
-
# @!attribute res_type
|
229
|
-
# 16-bit file type.
|
230
|
-
# @return [Integer]
|
231
|
-
define_field :res_type, PacketGen::Types::Int16le
|
232
|
-
# @!attribute pipe_status
|
233
|
-
# 16-bit field that shows the status of the named pipe (if opened resource
|
234
|
-
# is a named pipe).
|
235
|
-
# @return [Integer]
|
236
|
-
define_field :pipe_status, PacketGen::Types::Int16le
|
237
|
-
# @!attribute directory
|
238
|
-
# 8-bit field indicating is the FID represents a directory.
|
239
|
-
# @return [Integer]
|
240
|
-
define_field :directory, PacketGen::Types::Int8
|
241
|
-
# @!attribute byte_count
|
242
|
-
# The size, in bytes, of the SMB data. Should be zero.
|
243
|
-
# @return [Integer]
|
244
|
-
define_field :byte_count, PacketGen::Types::Int16le, default: 0
|
245
|
-
|
246
|
-
# Give protocol name for this class
|
247
|
-
# @return [String]
|
248
|
-
def protocol_name
|
249
|
-
'SMB::NtCreateAndXResponse'
|
250
|
-
end
|
251
|
-
|
252
|
-
# Say if FID is a directory
|
253
|
-
# @return [Boolean]
|
254
|
-
def directory?
|
255
|
-
self.directory > 0
|
256
|
-
end
|
257
|
-
|
258
|
-
# @!method human_create_time
|
259
|
-
# @return [String]
|
260
|
-
# @!method human_access_time
|
261
|
-
# @return [String]
|
262
|
-
# @!method human_write_time
|
263
|
-
# @return [String]
|
264
|
-
# @!method human_change_time
|
265
|
-
# @return [String]
|
266
|
-
%i[create access write change].each do |type|
|
267
|
-
class_eval "def human_#{type}_time; self[:#{type}_time].to_human; end"
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
self.bind_command 'nt_create_and_x'
|
10
|
+
# Namespace for NT_CREATE_ANDX related classes
|
11
|
+
module NtCreateAndX; end
|
272
12
|
end
|
273
13
|
end
|
14
|
+
|
15
|
+
require_relative 'ntcreateandx/request'
|
16
|
+
require_relative 'ntcreateandx/response'
|
17
|
+
|
18
|
+
PacketGen::Plugin::SMB.bind_command 'nt_create_and_x'
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# This file is part of packetgen-plugin-smb.
|
2
|
+
# See https://github.com/sdaubert/packetgen-plugin-smb for more informations
|
3
|
+
# Copyright (C) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
|
+
# This program is published under MIT license.
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
# Namespace for NT_CREATE_ANDX related classes
|
11
|
+
module NtCreateAndX
|
12
|
+
# SMB Command NtCreateAndX request.
|
13
|
+
#
|
14
|
+
# A NtCreateAndXRequest contains:
|
15
|
+
# * a {#word_count} field (+Int8+), size, in 2-byte words of SMB
|
16
|
+
# parameters:
|
17
|
+
# * {#and_xcommand} (+Int8+), next command in packet,
|
18
|
+
# * {#rsv1} (+Int8+),
|
19
|
+
# * {#and_xoffset} (+Int16le+), offset of the next command from the
|
20
|
+
# start of SMB header,
|
21
|
+
# * {#rsv2} (+Int8+),
|
22
|
+
# * {#filename_len} (+Int16le+), size of {#filename} in SMB data,
|
23
|
+
# * {#flags} (+Int32le+),
|
24
|
+
# * {#root_dir_fid} (+Int32le+),
|
25
|
+
# * {#access_mask} (+Int32le+),
|
26
|
+
# * {#alloc_size} (+Int64le+),
|
27
|
+
# * {#attributes} (+Int32le+),
|
28
|
+
# * {#share_access} (+Int32le+),
|
29
|
+
# * {#disposition} (+Int32le+),
|
30
|
+
# * {#options} (+Int32le+),
|
31
|
+
# * {#impersonation} (+Int32le+),
|
32
|
+
# * {#sec_flags} (+Int38+),
|
33
|
+
# * #{byte_count} (+Int16le+), size in bytes of SMB data:
|
34
|
+
# * {#pad1} (+Int8),
|
35
|
+
# * {#filename} ({SMB::String}),
|
36
|
+
# * {#extra_bytes} (+String+).
|
37
|
+
#
|
38
|
+
# == Known limitations
|
39
|
+
# 1. Only the first command is properly handled. Chained commands are not.
|
40
|
+
# 2. {#filename} is mandatory handled as Windows Unicode string.
|
41
|
+
# @author Sylvain Daubert
|
42
|
+
class Request < PacketGen::Header::Base
|
43
|
+
# Commands that may follow this one in a SMB packet
|
44
|
+
COMMANDS = {
|
45
|
+
'read' => 0x0a,
|
46
|
+
'read_andx' => 0x2e,
|
47
|
+
'ioctl' => 0x27,
|
48
|
+
'no further commands' => 0xff
|
49
|
+
}.freeze
|
50
|
+
|
51
|
+
# @!attribute word_count
|
52
|
+
# The size, in 2-byte words, of the SMB parameters.
|
53
|
+
# @return [Integer]
|
54
|
+
define_field :word_count, PacketGen::Types::Int8, default: 24
|
55
|
+
# @!attribute and_xcommand
|
56
|
+
# 8-bit command code for the next SMB command in the
|
57
|
+
# packet.
|
58
|
+
# @return [Integer]
|
59
|
+
define_field :and_xcommand, PacketGen::Types::Int8Enum, enum: COMMANDS
|
60
|
+
# @!attribute rsv1
|
61
|
+
# 8-bit reserved field.
|
62
|
+
# @return [Integer]
|
63
|
+
define_field :rsv1, PacketGen::Types::Int8, default: 0
|
64
|
+
# @!attribute and_xoffset
|
65
|
+
# 16-bit offset from the start of SMB header to the start of
|
66
|
+
# the {#word_count} field in the next SMB command in this
|
67
|
+
# packet.
|
68
|
+
# @return [Integer]
|
69
|
+
define_field :and_xoffset, PacketGen::Types::Int16le, default: 0
|
70
|
+
# @!attribute rsv2
|
71
|
+
# 8-bit reserved field.
|
72
|
+
# @return [Integer]
|
73
|
+
define_field :rsv2, PacketGen::Types::Int8, default: 0
|
74
|
+
# @!attribute filename_len
|
75
|
+
# 16-bit length of the {#filename} field.
|
76
|
+
# @return [Integer]
|
77
|
+
define_field :filename_len, PacketGen::Types::Int16le
|
78
|
+
alias filename_length filename_len
|
79
|
+
alias filename_length= filename_len=
|
80
|
+
# @!attribute flags
|
81
|
+
# 32-bit flags word
|
82
|
+
# @return [Integer]
|
83
|
+
define_field :flags, PacketGen::Types::Int32le
|
84
|
+
# @!attribute root_dir_fid
|
85
|
+
# 32-bit file ID of an opened root directory.
|
86
|
+
# @return [Integer]
|
87
|
+
define_field :root_dir_fid, PacketGen::Types::Int32le
|
88
|
+
# @!attribute access_mask
|
89
|
+
# 32-bit flags that indicate access rights.
|
90
|
+
# @return [Integer]
|
91
|
+
define_field :access_mask, PacketGen::Types::Int32le
|
92
|
+
# @!attribute alloc_size
|
93
|
+
# 64-bit initial allocation size.
|
94
|
+
# @return [Integer]
|
95
|
+
define_field :alloc_size, PacketGen::Types::Int64le
|
96
|
+
# @!attribute attributes
|
97
|
+
# 32-bit extended file attributes.
|
98
|
+
# @return [Integer]
|
99
|
+
define_field :attributes, PacketGen::Types::Int32le
|
100
|
+
# @!attribute share_access
|
101
|
+
# 32-bit field that specifies how the file should be shared.
|
102
|
+
# @return [Integer]
|
103
|
+
define_field :share_access, PacketGen::Types::Int32le
|
104
|
+
# @!attribute disposition
|
105
|
+
# 32-bit value that represents the action to take if the file
|
106
|
+
# already exists or if the file is a new file and does not already
|
107
|
+
# exist.
|
108
|
+
# @return [Integer]
|
109
|
+
define_field :disposition, PacketGen::Types::Int32le
|
110
|
+
# @!attribute options
|
111
|
+
# 32-bit field containing flag options to use if creating the file
|
112
|
+
# or the directory.
|
113
|
+
# @return [Integer]
|
114
|
+
define_field :options, PacketGen::Types::Int32le
|
115
|
+
# @!attribute impersonation
|
116
|
+
# 32-bit field specifying the impersonation level requested by
|
117
|
+
# the application.
|
118
|
+
# @return [Integer]
|
119
|
+
define_field :impersonation, PacketGen::Types::Int32le
|
120
|
+
# @!attribute sec_flags
|
121
|
+
# 8-bit security flags.
|
122
|
+
define_field :sec_flags, PacketGen::Types::Int8
|
123
|
+
# @!attribute byte_count
|
124
|
+
# The size, in bytes, of the SMB data.
|
125
|
+
# @return [Integer]
|
126
|
+
define_field :byte_count, PacketGen::Types::Int16le
|
127
|
+
# @!attribute pad1
|
128
|
+
# Padding before {#filename} to align it on 16-bit boundary. Only present
|
129
|
+
# if {SMB#flags2_unicode?} is +true+.
|
130
|
+
# @return [Integer]
|
131
|
+
define_field :pad1, PacketGen::Types::Int8, optional: ->(h) { h.packet && h.packet.smb.flags2_unicode? }
|
132
|
+
# @!attribute filename
|
133
|
+
# A string that represents the fully qualified name of the file
|
134
|
+
# relative to the supplied TID
|
135
|
+
# @return [String]
|
136
|
+
define_field :filename, SMB::String, builder: ->(h, t) { t.new(unicode: !h.packet || h.packet.smb.flags2_unicode?) }
|
137
|
+
# @!attribute extra_bytes
|
138
|
+
# @return [Integer]
|
139
|
+
define_field :extra_bytes, PacketGen::Types::String,
|
140
|
+
builder: ->(h, t) { t.new(length_from: -> { h.byte_count - (h.present?(:pad1) ? 1 : 0) - h[:filename].sz }) }
|
141
|
+
|
142
|
+
# Give protocol name for this class
|
143
|
+
# @return [String]
|
144
|
+
def protocol_name
|
145
|
+
'SMB::NtCreateAndX::Request'
|
146
|
+
end
|
147
|
+
|
148
|
+
# Compute {#filename_len} and {#byte_count}
|
149
|
+
# @return [void]
|
150
|
+
def calc_length
|
151
|
+
self.filename_len = self[:filename].sz
|
152
|
+
pad1sz = self.present?(:pad1) ? 1 : 0
|
153
|
+
bcount = pad1sz + filename_len + self[:extra_bytes].sz
|
154
|
+
self.byte_count = bcount
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|