packetgen-plugin-smb 0.2.0 → 0.3.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-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
|