packetgen-plugin-smb 0.1.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 +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +12 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +29 -0
- data/Rakefile +13 -0
- data/lib/packetgen-plugin-smb.rb +3 -0
- data/lib/packetgen/plugin/smb.rb +185 -0
- data/lib/packetgen/plugin/smb/blocks.rb +48 -0
- data/lib/packetgen/plugin/smb/close.rb +57 -0
- data/lib/packetgen/plugin/smb/filetime.rb +114 -0
- data/lib/packetgen/plugin/smb/nt_create_and_x.rb +273 -0
- data/lib/packetgen/plugin/smb/string.rb +52 -0
- data/lib/packetgen/plugin/smb/trans.rb +200 -0
- data/lib/packetgen/plugin/smb_version.rb +5 -0
- data/packetgen-plugin-smb.gemspec +29 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0420b25c4cbb969cd7178373395736f61b5de2ac31710168305f1cb42281cef7
|
4
|
+
data.tar.gz: 7a6fc87b651548518e7b3fb9baa4b48619c4666ce9b33705a4990245999ed613
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 36efbeb7817f790c660ff0d6ff71c6284ec7ec1235d99f4473ad34993942c0fe2e7c992a448d6e50640b5d009fc84abe4f0e25ed048cb4f202e320c11e936656
|
7
|
+
data.tar.gz: dd3f345d46ec5b59b31f72d34c3aa7bce2878211acafb796cf40b7c7e2c24eaff54056ce3c7a1b6bd85a35ff4861f257e7aadfb3dfd0a52e04de4c45d055bb44
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Sylvain Daubert
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
[](https://travis-ci.com/sdaubert/packetgen-plugin-smb)
|
2
|
+
|
3
|
+
# Packetgen::Plugin::SMB
|
4
|
+
|
5
|
+
This is a plugin for [PacketGen gem](https://github.com/sdaubert/packetgen). It adds some support for SMB protocol suite.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'packetgen-plugin-smb'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install packetgen-plugin-smb
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sdaubert/packetgen-plugin-smb.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require 'yard'
|
5
|
+
|
6
|
+
task default: :spec
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new
|
9
|
+
|
10
|
+
YARD::Rake::YardocTask.new do |t|
|
11
|
+
t.options = ['--no-private']
|
12
|
+
t.files = ['lib/**/*.rb', '-', 'LICENSE']
|
13
|
+
end
|
@@ -0,0 +1,185 @@
|
|
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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
# Server Message Block (SMB) header.
|
10
|
+
# @author Sylvain Daubert
|
11
|
+
# @since 0.1.0
|
12
|
+
class SMB < PacketGen::Header::Base
|
13
|
+
# Known commands
|
14
|
+
COMMANDS = {
|
15
|
+
'delete_dir' => 0x01,
|
16
|
+
'close' => 0x04,
|
17
|
+
'delete' => 0x06,
|
18
|
+
'query_info2' => 0x23,
|
19
|
+
'trans' => 0x25,
|
20
|
+
'echo' => 0x2b,
|
21
|
+
'open_and_x' => 0x2d,
|
22
|
+
'read_and_x' => 0x2e,
|
23
|
+
'write_and_x' => 0x2f,
|
24
|
+
'trans2' => 0x32,
|
25
|
+
'tree_disconnect' => 0x71,
|
26
|
+
'negotiate' => 0x72,
|
27
|
+
'session_setup_and_x' => 0x73,
|
28
|
+
'tree_connect_and_x' => 0x75,
|
29
|
+
'nt_trans' => 0xa0,
|
30
|
+
'nt_create_and_x' => 0xa2
|
31
|
+
}.freeze
|
32
|
+
# SMB marker, on start of header
|
33
|
+
MARKER = PacketGen.force_binary("\xffSMB")
|
34
|
+
|
35
|
+
# @!attribute protocol
|
36
|
+
# This field must contain {MARKER SMB marker}
|
37
|
+
# @return [String]
|
38
|
+
define_field :protocol, PacketGen::Types::String, static_length: 4, default: MARKER
|
39
|
+
# @!attribute command
|
40
|
+
# 8-bit SMB command
|
41
|
+
# @return [Integer]
|
42
|
+
define_field :command, PacketGen::Types::Int8Enum, enum: COMMANDS
|
43
|
+
# @!attribute status
|
44
|
+
# 32-bit status field. Used to communicate errors from server to client.
|
45
|
+
# @return [Integer]
|
46
|
+
define_field :status, PacketGen::Types::Int32le
|
47
|
+
# @!attribute flags
|
48
|
+
# 8-bit flags field
|
49
|
+
# @return [Integer]
|
50
|
+
define_field :flags, PacketGen::Types::Int8
|
51
|
+
# @!attribute flags2
|
52
|
+
# 16-bit flags field
|
53
|
+
# @return [Integer]
|
54
|
+
define_field :flags2, PacketGen::Types::Int16le
|
55
|
+
# @!attribute pid_high
|
56
|
+
# 16 high order bits of a process identifier (PID)
|
57
|
+
# @return [Integer]
|
58
|
+
define_field :pid_high, PacketGen::Types::Int16le
|
59
|
+
# @!attribute sec_features
|
60
|
+
# 64-bit field. May be:
|
61
|
+
# * a 64-bit cryptographic message signature if signature was negotiated,
|
62
|
+
# * a SecurityFeatures structure, only over connectionless transport,
|
63
|
+
# composed of:
|
64
|
+
# * a 16-bit sequence number,
|
65
|
+
# * a 16-bit connection identifier (CID),
|
66
|
+
# * a 32-bit key to validate message,
|
67
|
+
# * a reserved field in all others cases.
|
68
|
+
# @return [Integer]
|
69
|
+
define_field :sec_features, PacketGen::Types::Int64le
|
70
|
+
# @!attribute reserved
|
71
|
+
# 16-bit reserved field
|
72
|
+
# @return [Integer]
|
73
|
+
define_field :reserved, PacketGen::Types::Int16le
|
74
|
+
# @!attribute tid
|
75
|
+
# 16-bit tree identifier (TID)
|
76
|
+
define_field :tid, PacketGen::Types::Int16le
|
77
|
+
# @!attribute pid
|
78
|
+
# 16 low order bits of a process identifier (PID)
|
79
|
+
# @return [Integer]
|
80
|
+
define_field :pid, PacketGen::Types::Int16le
|
81
|
+
# @!attribute uid
|
82
|
+
# 16-bit user identifier (UID)
|
83
|
+
define_field :uid, PacketGen::Types::Int16le
|
84
|
+
# @!attribute mid
|
85
|
+
# 16-bit multiplex identifier (MID)
|
86
|
+
define_field :mid, PacketGen::Types::Int16le
|
87
|
+
# @!attribute body
|
88
|
+
# @return [String]
|
89
|
+
define_field :body, PacketGen::Types::String
|
90
|
+
# @!attribute flags_reply
|
91
|
+
# When set, the message is a reply from server to client.
|
92
|
+
# @return [Boolean]
|
93
|
+
# @!attribute flags_opbatch
|
94
|
+
# Obsolescent.
|
95
|
+
# @return [Boolean]
|
96
|
+
# @!attribute flags_oplock
|
97
|
+
# Obsolescent.
|
98
|
+
# @return [Boolean]
|
99
|
+
# @!attribute flags_canon_paths
|
100
|
+
# Obsolescent.
|
101
|
+
# @return [Boolean]
|
102
|
+
# @!attribute flags_case_insensitive
|
103
|
+
# Obsolete.
|
104
|
+
# @return [Boolean]
|
105
|
+
# @!attribute flags_reserved
|
106
|
+
# @return [Boolean]
|
107
|
+
# @!attribute flags_rbuf_avail
|
108
|
+
# Obsolete.
|
109
|
+
# @return [Boolean]
|
110
|
+
# @!attribute flags_locknread
|
111
|
+
# When set in SMB_COM_NEGOTIATE response, the server supports
|
112
|
+
# SMB_COM_LOCK_AND_READ and SNB_COM_WRITE_AND_UNLOCK commands.
|
113
|
+
# @return [Boolean]
|
114
|
+
define_bit_fields_on :flags, :flags_reply, :flags_opbatch, :flags_oplock,
|
115
|
+
:flags_canon_paths, :flags_case_insensitive,
|
116
|
+
:flags_reserved, :flags_buf_avail, :flags_locknread
|
117
|
+
# @!attribute flags2_unicode
|
118
|
+
# If set, each field that contains a string in this message is encoded
|
119
|
+
# as UTF-16.
|
120
|
+
# @return [Boolean]
|
121
|
+
# @!attribute flags2_ntstatus
|
122
|
+
# If set in a client request, server must return errors as NTSTATUS, else
|
123
|
+
# as SMBSTATUS.
|
124
|
+
# @return [Boolean]
|
125
|
+
# @!attribute flags2_paging_io
|
126
|
+
# Client may read a file if it does not have read permission but have
|
127
|
+
# execute one.
|
128
|
+
# @return [Boolean]
|
129
|
+
# @!attribute flags2_dfs
|
130
|
+
# If set, any pathnames should be resolved in the Distributed File System
|
131
|
+
# (DFS).
|
132
|
+
# @return [Boolean]
|
133
|
+
# @!attribute flags2_extended_security
|
134
|
+
# @return [Boolean]
|
135
|
+
# @!attribute flags2_reparse_path
|
136
|
+
# @return [Boolean]
|
137
|
+
# @!attribute flags2_reserved
|
138
|
+
# 3-bit reserved field
|
139
|
+
# @return [Integer]
|
140
|
+
# @!attribute flags2_is_long_name
|
141
|
+
# @return [Boolean]
|
142
|
+
# @!attribute flags2_rsv
|
143
|
+
# @return [Boolean]
|
144
|
+
# @!attribute flags2_security_signature_required
|
145
|
+
# @return [Boolean]
|
146
|
+
# @!attribute flags2_compressed
|
147
|
+
# @return [Boolean]
|
148
|
+
# @!attribute flags2_signature
|
149
|
+
# @return [Boolean]
|
150
|
+
# @!attribute flags2_eas
|
151
|
+
# @return [Boolean]
|
152
|
+
# @!attribute flags2_long_names
|
153
|
+
# If unset, file names must adhere to the 8.3 naming convention.
|
154
|
+
# @return [Boolean]
|
155
|
+
define_bit_fields_on :flags2, :flags2_unicode, :flags2_ntstatus,
|
156
|
+
:flags2_paging_io, :flags2_dfs, :flags2_extended_security,
|
157
|
+
:flags2_reparse_path, :flags2_reserved, 3,
|
158
|
+
:flags2_is_long_name, :flags2_rsv,
|
159
|
+
:flags2_security_signature_required, :flags2_compresses,
|
160
|
+
:flags2_signature, :flags2_eas, :flags2_long_names
|
161
|
+
|
162
|
+
# Helper to bind a SMB command to {SMB} header.
|
163
|
+
# @param [String] command name
|
164
|
+
# @return [void]
|
165
|
+
def self.bind_command(command)
|
166
|
+
contantized = command.capitalize.gsub(/_(\w)/) { $1.upcase }
|
167
|
+
krequest = self.const_get("#{contantized}Request")
|
168
|
+
kresponse = self.const_get("#{contantized}Response")
|
169
|
+
PacketGen::Header.add_class krequest
|
170
|
+
self.bind krequest, command: SMB::COMMANDS[command], flags: ->(v) { v.nil? ? 0 : (v & 0x80).zero? }
|
171
|
+
PacketGen::Header.add_class kresponse
|
172
|
+
self.bind kresponse, command: SMB::COMMANDS[command], flags: ->(v) { v.nil? ? 0 : (v & 0x80 == 0x80) }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
PacketGen::Header.add_class SMB
|
176
|
+
PacketGen::Header::NetBIOS::Session.bind SMB, body: ->(val) { val.nil? ? SMB::MARKER : val[0..3] == SMB::MARKER }
|
177
|
+
PacketGen::Header::NetBIOS::Datagram.bind SMB, body: ->(val) { val.nil? ? SMB::MARKER : val[0..3] == SMB::MARKER }
|
178
|
+
end
|
179
|
+
|
180
|
+
require_relative 'smb/string'
|
181
|
+
require_relative 'smb/filetime'
|
182
|
+
require_relative 'smb/close'
|
183
|
+
require_relative 'smb/trans'
|
184
|
+
require_relative 'smb/nt_create_and_x'
|
185
|
+
require_relative 'smb/blocks'
|
@@ -0,0 +1,48 @@
|
|
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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
# Common blocks used for unsupported SMB messages.
|
11
|
+
#
|
12
|
+
# {Blocks} handles parameter block and data block. Parameter block is
|
13
|
+
# composed of:
|
14
|
+
# * a 8-bit {#word_count} field,
|
15
|
+
# * a {#words} field, an array of +PacketGen::Types::Int16le+.
|
16
|
+
# Data block is composed of:
|
17
|
+
# * a little endian 16-bit {#byte_count} field,
|
18
|
+
# * a {#bytes} field, an array of +PacketGen::Types::Int8+.
|
19
|
+
# @author Sylvain Daubert
|
20
|
+
# @since 0.1.0
|
21
|
+
class Blocks < PacketGen::Header::Base
|
22
|
+
# @!attribute word_count
|
23
|
+
# The size, in 2-byte words, of the {#words} field.
|
24
|
+
# @return [Integer]
|
25
|
+
define_field :word_count, PacketGen::Types::Int8
|
26
|
+
# @!attribute words
|
27
|
+
# The message-specific parameters structure.
|
28
|
+
# @return [PacketGen::Types::ArrayOfInt16le]
|
29
|
+
define_field :words, PacketGen::Types::ArrayOfInt16le, builder: ->(h, t) { t.new(counter: h[:word_count]) }
|
30
|
+
# @!attribute byte_count
|
31
|
+
# The size, in bytes, of the {#bytes} field.
|
32
|
+
# @return [Integer]
|
33
|
+
define_field :byte_count, PacketGen::Types::Int16le
|
34
|
+
# @!attribute bytes
|
35
|
+
# The message-specific data structure.
|
36
|
+
# @return [PacketGen::Types::ArrayOfInt8]
|
37
|
+
define_field :bytes, PacketGen::Types::ArrayOfInt8, builder: ->(h, t) { t.new(counter: h[:byte_count]) }
|
38
|
+
|
39
|
+
# Give protocol name for this class
|
40
|
+
# @return [String]
|
41
|
+
def protocol_name
|
42
|
+
'SMB::Blocks'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
PacketGen::Header.add_class SMB::Blocks
|
47
|
+
SMB.bind SMB::Blocks
|
48
|
+
end
|
@@ -0,0 +1,57 @@
|
|
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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
# Close Request.
|
11
|
+
# @author Sylvain Daubert
|
12
|
+
# @since 0.1.0
|
13
|
+
class CloseRequest < PacketGen::Header::Base
|
14
|
+
# @!attribute word_count
|
15
|
+
# The size, in 2-byte words, of the SMB command parameters. It should
|
16
|
+
# be +3+.
|
17
|
+
# @return [Integer]
|
18
|
+
define_field :word_count, PacketGen::Types::Int8, default: 3
|
19
|
+
# @!attribute fid
|
20
|
+
# 16-bit FID of the object to close
|
21
|
+
# @return [Integer]
|
22
|
+
define_field :fid, PacketGen::Types::Int16le, default: 3
|
23
|
+
# @!attribute last_modified
|
24
|
+
# 32-bit time value encoded as the number of seconds since January
|
25
|
+
# 1, 1970 00:00:00.0. The client can request that the last modification
|
26
|
+
# time for the file be updated to this time value. A value of +0x00000000+
|
27
|
+
# or +0xFFFFFFFF+ results in the server not updating the last modification
|
28
|
+
# time.
|
29
|
+
# @return [Integer]
|
30
|
+
define_field :last_modified, PacketGen::Types::Int32le
|
31
|
+
# @!attribute byte_count
|
32
|
+
# Should be 0.
|
33
|
+
# @return [Integer]
|
34
|
+
define_field :byte_count, PacketGen::Types::Int16le, default: 0
|
35
|
+
end
|
36
|
+
|
37
|
+
# Close Response.
|
38
|
+
#
|
39
|
+
# This is a void container. {#word_count} and {#byte_count} should be 0.
|
40
|
+
# @author Sylvain Daubert
|
41
|
+
# @since 0.1.0
|
42
|
+
class CloseResponse < PacketGen::Header::Base
|
43
|
+
# @!attribute word_count
|
44
|
+
# The size, in 2-byte words, of the SMB command parameters. It should
|
45
|
+
# be +0+.
|
46
|
+
# @return [Integer]
|
47
|
+
define_field :word_count, PacketGen::Types::Int8, default: 3
|
48
|
+
define_field :last_modified, PacketGen::Types::Int32le
|
49
|
+
# @!attribute byte_count
|
50
|
+
# Should be 0.
|
51
|
+
# @return [Integer]
|
52
|
+
define_field :byte_count, PacketGen::Types::Int16le, default: 0
|
53
|
+
end
|
54
|
+
|
55
|
+
self.bind_command 'close'
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,114 @@
|
|
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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
# 64-bit signed integer, little endian representation
|
11
|
+
# @author Sylvain Daubert
|
12
|
+
# @private
|
13
|
+
# @since 0.1.0
|
14
|
+
class SInt64le < PacketGen::Types::Int64le
|
15
|
+
def initialize(value=nil)
|
16
|
+
super
|
17
|
+
@packstr[:little] = 'q<'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# SMB FILETIME.
|
22
|
+
# @author Sylvain Daubert
|
23
|
+
# @since 0.1.0
|
24
|
+
class Filetime
|
25
|
+
# Base time for SMB FILETIME.
|
26
|
+
# This value also indicate no time.
|
27
|
+
NO_TIME = Time.utc(1601).freeze
|
28
|
+
|
29
|
+
# @param [Hash] options
|
30
|
+
# @option options [Integer] :filetime
|
31
|
+
# @option options [Time] :time
|
32
|
+
# @raise [ArgumentError] if +:time+ and +:filetime+ are both given.
|
33
|
+
def initialize(options={})
|
34
|
+
if (options.keys & %i[time filetime]).size == 2
|
35
|
+
raise ArgumentError, ':time and :filetime options are both given'
|
36
|
+
end
|
37
|
+
|
38
|
+
@int = SInt64le.new(options[:filetime])
|
39
|
+
if options[:time]
|
40
|
+
@time = options[:time]
|
41
|
+
@int.value = time2filetime
|
42
|
+
else
|
43
|
+
@time = filetime2time
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param [::String] str
|
48
|
+
# @return [String] self
|
49
|
+
def read(str)
|
50
|
+
@int.read(str[0, 8])
|
51
|
+
@time = filetime2time
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
# Human readable filetime
|
56
|
+
# @return [String]
|
57
|
+
def to_human
|
58
|
+
if no_time?
|
59
|
+
'no time'
|
60
|
+
else
|
61
|
+
@time.to_s
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get filetime integer value
|
66
|
+
# @return [Integer]
|
67
|
+
def to_i
|
68
|
+
@int.to_i
|
69
|
+
end
|
70
|
+
|
71
|
+
# Check if there is no time specified
|
72
|
+
# @return [Boolean]
|
73
|
+
def no_time?
|
74
|
+
to_i.zero?
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [Integer]
|
78
|
+
def sz
|
79
|
+
@int.sz
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [String]
|
83
|
+
def to_s
|
84
|
+
@int.to_s
|
85
|
+
end
|
86
|
+
|
87
|
+
# @return [Time]
|
88
|
+
def to_time
|
89
|
+
@time
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def filetime2time
|
95
|
+
filetime = @int.to_i
|
96
|
+
secs = filetime / 10_000
|
97
|
+
nsecs = (filetime % 10_000) * 100
|
98
|
+
if filetime.zero?
|
99
|
+
NO_TIME
|
100
|
+
elsif filetime.positive?
|
101
|
+
Time.at(NO_TIME) + Rational("#{secs}.%09d" % nsecs)
|
102
|
+
else
|
103
|
+
Time.at(Time.now.utc) + Rational("#{secs}.%09d" % nsecs)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def time2filetime
|
108
|
+
# Time#to_f then #to_r is more precise than Time#to_r
|
109
|
+
# (ie Time#to_r sometimes does a rounding error).
|
110
|
+
(@time.to_i - NO_TIME.to_i) * 10_000 + ((@time.to_f.to_r * 10_000) % 10_000).to_i
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,273 @@
|
|
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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
# SMB Command NtCreateAndX request.
|
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
|
+
# @since 0.1.0
|
41
|
+
class NtCreateAndXRequest < PacketGen::Header::Base
|
42
|
+
# Commands that may follow this one in a SMB packet
|
43
|
+
COMMANDS = {
|
44
|
+
'read' => 0x0a,
|
45
|
+
'read_andx' => 0x2e,
|
46
|
+
'ioctl' => 0x27,
|
47
|
+
'no further commands' => 0xff
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
# @!attribute word_count
|
51
|
+
# The size, in 2-byte words, of the SMB parameters.
|
52
|
+
# @return [Integer]
|
53
|
+
define_field :word_count, PacketGen::Types::Int8, default: 24
|
54
|
+
# @!attribute and_xcommand
|
55
|
+
# 8-bit command code for the next SMB command in the
|
56
|
+
# packet.
|
57
|
+
# @return [Integer]
|
58
|
+
define_field :and_xcommand, PacketGen::Types::Int8Enum, enum: COMMANDS
|
59
|
+
# @!attribute rsv1
|
60
|
+
# 8-bit reserved field.
|
61
|
+
# @return [Integer]
|
62
|
+
define_field :rsv1, PacketGen::Types::Int8, default: 0
|
63
|
+
# @!attribute and_xoffset
|
64
|
+
# 16-bit offset from the start of SMB header to the start of
|
65
|
+
# the {#word_count} field in the next SMB command in this
|
66
|
+
# packet.
|
67
|
+
# @return [Integer]
|
68
|
+
define_field :and_xoffset, PacketGen::Types::Int16le, default: 0
|
69
|
+
# @!attribute rsv2
|
70
|
+
# 8-bit reserved field.
|
71
|
+
# @return [Integer]
|
72
|
+
define_field :rsv2, PacketGen::Types::Int8, default: 0
|
73
|
+
# @!attribute filename_len
|
74
|
+
# 16-bit length of the {#filename} field.
|
75
|
+
# @return [Integer]
|
76
|
+
define_field :filename_len, PacketGen::Types::Int16le
|
77
|
+
alias filename_length filename_len
|
78
|
+
alias filename_length= filename_len=
|
79
|
+
# @!attribute flags
|
80
|
+
# 32-bit flags word
|
81
|
+
# @return [Integer]
|
82
|
+
define_field :flags, PacketGen::Types::Int32le
|
83
|
+
# @!attribute root_dir_fid
|
84
|
+
# 32-bit file ID of an opened root directory.
|
85
|
+
# @return [Integer]
|
86
|
+
define_field :root_dir_fid, PacketGen::Types::Int32le
|
87
|
+
# @!attribute access_mask
|
88
|
+
# 32-bit flags that indicate access rights.
|
89
|
+
# @return [Integer]
|
90
|
+
define_field :access_mask, PacketGen::Types::Int32le
|
91
|
+
# @!attribute alloc_size
|
92
|
+
# 64-bit initial allocation size.
|
93
|
+
# @return [Integer]
|
94
|
+
define_field :alloc_size, PacketGen::Types::Int64le
|
95
|
+
# @!attribute attributes
|
96
|
+
# 32-bit extended file attributes.
|
97
|
+
# @return [Integer]
|
98
|
+
define_field :attributes, PacketGen::Types::Int32le
|
99
|
+
# @!attribute share_access
|
100
|
+
# 32-bit field that specifies how the file should be shared.
|
101
|
+
# @return [Integer]
|
102
|
+
define_field :share_access, PacketGen::Types::Int32le
|
103
|
+
# @!attribute disposition
|
104
|
+
# 32-bit value that represents the action to take if the file
|
105
|
+
# already exists or if the file is a new file and does not already
|
106
|
+
# exist.
|
107
|
+
# @return [Integer]
|
108
|
+
define_field :disposition, PacketGen::Types::Int32le
|
109
|
+
# @!attribute options
|
110
|
+
# 32-bit field containing flag options to use if creating the file
|
111
|
+
# or the directory.
|
112
|
+
# @return [Integer]
|
113
|
+
define_field :options, PacketGen::Types::Int32le
|
114
|
+
# @!attribute impersonation
|
115
|
+
# 32-bit field specifying the impersonation level requested by
|
116
|
+
# the application.
|
117
|
+
# @return [Integer]
|
118
|
+
define_field :impersonation, PacketGen::Types::Int32le
|
119
|
+
# @!attribute sec_flags
|
120
|
+
# 8-bit security flags.
|
121
|
+
define_field :sec_flags, PacketGen::Types::Int8
|
122
|
+
# @!attribute byte_count
|
123
|
+
# The size, in bytes, of the SMB data.
|
124
|
+
# @return [Integer]
|
125
|
+
define_field :byte_count, PacketGen::Types::Int16le
|
126
|
+
# @!attribute pad1
|
127
|
+
# Padding before {#filename} to align it on 16-bit boundary
|
128
|
+
# @return [Integer]
|
129
|
+
define_field :pad1, PacketGen::Types::Int8
|
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
|
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 - 1 - 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
|
+
bcount = 1 + filename_len + self[:extra_bytes].sz
|
151
|
+
self.byte_count = bcount
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# SMB Command NtCreateAndX response
|
156
|
+
# @author Sylvain Daubert
|
157
|
+
# @since 0.1.0
|
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'
|
272
|
+
end
|
273
|
+
end
|
@@ -0,0 +1,52 @@
|
|
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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
# SMB strings (UTF-16 little-endian).
|
11
|
+
# @author Sylvain Daubert
|
12
|
+
# @since 0.1.0
|
13
|
+
class String < PacketGen::Types::CString
|
14
|
+
# @param [Boolean, Proc] is string UTF-16 encoded?
|
15
|
+
# @param [Hash] options
|
16
|
+
# @option options [Integer] :static_length set a static length for this string
|
17
|
+
def initialize(options={})
|
18
|
+
super
|
19
|
+
self.encode!('UTF-16LE')
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [::String] str
|
23
|
+
# @return [String] self
|
24
|
+
def read(str)
|
25
|
+
return self if str.nil?
|
26
|
+
|
27
|
+
str2 = case str.encoding
|
28
|
+
when Encoding::BINARY
|
29
|
+
binidx = nil
|
30
|
+
0.step(to: str.size, by: 2) do |i|
|
31
|
+
binidx = i if str[i, 2] == "\x00\x00"
|
32
|
+
end
|
33
|
+
s = if binidx.nil?
|
34
|
+
str
|
35
|
+
else
|
36
|
+
str[0, binidx]
|
37
|
+
end
|
38
|
+
s.force_encoding('UTF-16LE')
|
39
|
+
when Encoding::UTF_16LE
|
40
|
+
str
|
41
|
+
else
|
42
|
+
str.encode('UTF-16LE')
|
43
|
+
end
|
44
|
+
str2 = str2[0, @static_length / 2] if @static_length.is_a? Integer
|
45
|
+
idx = str2.index(+"\x00".encode('UTF-16LE'))
|
46
|
+
str2 = str2[0, idx] unless idx.nil?
|
47
|
+
self.replace str2
|
48
|
+
self
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,200 @@
|
|
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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class SMB
|
10
|
+
# Transaction Request.
|
11
|
+
#
|
12
|
+
# See also {Blocks}, as {TransRequest} is a specialization of {Blocks#words}
|
13
|
+
# and {Blocks#bytes}.
|
14
|
+
# @author Sylvain Daubert
|
15
|
+
# @since 0.1.0
|
16
|
+
class TransRequest < PacketGen::Header::Base
|
17
|
+
# @!attribute word_count
|
18
|
+
# The size, in 2-byte words, of the SMB command parameters. It should
|
19
|
+
# be +14 + setup_count+.
|
20
|
+
# @return [Integer]
|
21
|
+
define_field :word_count, PacketGen::Types::Int8, default: 14
|
22
|
+
# @!attribute total_param_count
|
23
|
+
# The total number of transaction parameter bytes.
|
24
|
+
# @return [Integer]
|
25
|
+
define_field :total_param_count, PacketGen::Types::Int16le
|
26
|
+
# @!attribute total_data_count
|
27
|
+
# The total number of transaction data bytes.
|
28
|
+
# @return [Integer]
|
29
|
+
define_field :total_data_count, PacketGen::Types::Int16le
|
30
|
+
# @!attribute max_param_count
|
31
|
+
# The maximum number of parameter bytes that the client will accept
|
32
|
+
# in transaction response.
|
33
|
+
# @return [Integer]
|
34
|
+
define_field :max_param_count, PacketGen::Types::Int16le
|
35
|
+
# @!attribute max_data_count
|
36
|
+
# The maximum number of data bytes that the client will accept
|
37
|
+
# in transaction response.
|
38
|
+
# @return [Integer]
|
39
|
+
define_field :max_data_count, PacketGen::Types::Int16le
|
40
|
+
# @!attribute max_setup_count
|
41
|
+
# The maximum number of setup bytes that the client will accept
|
42
|
+
# in transaction response.
|
43
|
+
# @return [Integer]
|
44
|
+
define_field :max_setup_count, PacketGen::Types::Int8
|
45
|
+
# @!attribute rsv1
|
46
|
+
# 8-bit reserved field
|
47
|
+
# @return [Integer]
|
48
|
+
define_field :rsv1, PacketGen::Types::Int8, default: 0
|
49
|
+
# @!attribute flags
|
50
|
+
# 16-bit flags
|
51
|
+
# @return [Integer]
|
52
|
+
define_field :flags, PacketGen::Types::Int16le
|
53
|
+
# @!attribute timeout
|
54
|
+
# 32-bit timeout
|
55
|
+
# @return [Integer]
|
56
|
+
define_field :timeout, PacketGen::Types::Int32le
|
57
|
+
# @!attribute rsv2
|
58
|
+
# 16-bit reserved field
|
59
|
+
# @return [Integer]
|
60
|
+
define_field :rsv2, PacketGen::Types::Int16le, default: 0
|
61
|
+
# @!attribute param_count
|
62
|
+
# 16-bit number of transaction parameter bytes that the clients attempts to
|
63
|
+
# send to the server in this request.
|
64
|
+
# @return [Integer]
|
65
|
+
define_field :param_count, PacketGen::Types::Int16le
|
66
|
+
# @!attribute param_offset
|
67
|
+
# 16-bit offset (in bytes) from the start of the SMB header to the start of the
|
68
|
+
# transaction parameters.
|
69
|
+
# @return [Integer]
|
70
|
+
define_field :param_offset, PacketGen::Types::Int16le
|
71
|
+
# @!attribute data_count
|
72
|
+
# 16-bit number of transaction data bytes that the clients sends to
|
73
|
+
# the server in this request.
|
74
|
+
# @return [Integer]
|
75
|
+
define_field :data_count, PacketGen::Types::Int16le
|
76
|
+
# @!attribute data_offset
|
77
|
+
# 16-bit offset (in bytes) from the start of the SMB header to the start
|
78
|
+
# of the data field.
|
79
|
+
# @return [Integer]
|
80
|
+
define_field :data_offset, PacketGen::Types::Int16le
|
81
|
+
# @!attribute setup_count
|
82
|
+
# 8-bit number of setup words (ie 16-bit words) contained in {#setup} field.
|
83
|
+
define_field :setup_count, PacketGen::Types::Int8
|
84
|
+
# @!attribute rsv3
|
85
|
+
# 8-bit reserved field
|
86
|
+
# @return [Integer]
|
87
|
+
define_field :rsv3, PacketGen::Types::Int8
|
88
|
+
# @!attribute setup
|
89
|
+
# Array of 2-byte words.
|
90
|
+
# @return [Array]
|
91
|
+
define_field :setup, PacketGen::Types::ArrayOfInt16le, builder: ->(h, t) { t.new(counter: h[:setup_count]) }
|
92
|
+
# @!attribute byte_count
|
93
|
+
# @return [Integer]
|
94
|
+
define_field :byte_count, PacketGen::Types::Int16le
|
95
|
+
# @!attribute padname
|
96
|
+
# 8-bit optional padding to align {#name} on a 2-byte boundary.
|
97
|
+
# @return [Integer]
|
98
|
+
define_field :padname, PacketGen::Types::Int8
|
99
|
+
# @!attribute name
|
100
|
+
# Pathname of the mailslot or named pipe.
|
101
|
+
# @return [String]
|
102
|
+
define_field :name, SMB::String
|
103
|
+
# @!attribute pad1
|
104
|
+
# Padding to align {#body} on 4-byte boundary.
|
105
|
+
# @return [String]
|
106
|
+
define_field :pad1, PacketGen::Types::String, default: "\0" * 4,
|
107
|
+
builder: ->(h, t) { t.new(length_from: -> { h.data_offset - SMB.new.sz - (h.offset_of(:name) + h[:name].sz) }) }
|
108
|
+
define_field :body, PacketGen::Types::String
|
109
|
+
|
110
|
+
# Give protocol name for this class
|
111
|
+
# @return [String]
|
112
|
+
def protocol_name
|
113
|
+
'SMB::TransRequest'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Transaction Response.
|
118
|
+
#
|
119
|
+
# See also {Blocks}, as {TransResponse} is a specialization of {Blocks#words}
|
120
|
+
# and {Blocks#bytes}.
|
121
|
+
# @author Sylvain Daubert
|
122
|
+
# @since 0.1.0
|
123
|
+
class TransResponse < PacketGen::Header::Base
|
124
|
+
# @!attribute word_count
|
125
|
+
# The size, in 2-byte words, of the SMB command parameters. It should
|
126
|
+
# be +14 + setup_count+.
|
127
|
+
# @return [Integer]
|
128
|
+
define_field :word_count, PacketGen::Types::Int8, default: 10
|
129
|
+
# @!attribute total_param_count
|
130
|
+
# The total number of transaction parameter bytes.
|
131
|
+
# @return [Integer]
|
132
|
+
define_field :total_param_count, PacketGen::Types::Int16le
|
133
|
+
# @!attribute total_data_count
|
134
|
+
# The total number of transaction data bytes.
|
135
|
+
# @return [Integer]
|
136
|
+
define_field :total_data_count, PacketGen::Types::Int16le
|
137
|
+
# @!attribute rsv1
|
138
|
+
# 16-bit reserved field
|
139
|
+
# @return [Integer]
|
140
|
+
define_field :rsv1, PacketGen::Types::Int16le, default: 0
|
141
|
+
# @!attribute param_count
|
142
|
+
# 16-bit number of transaction parameter bytes sent in this response.
|
143
|
+
# @return [Integer]
|
144
|
+
define_field :param_count, PacketGen::Types::Int16le
|
145
|
+
# @!attribute param_offset
|
146
|
+
# 16-bit offset (in bytes) from the start of the SMB header to the start of the
|
147
|
+
# transaction parameters.
|
148
|
+
# @return [Integer]
|
149
|
+
define_field :param_offset, PacketGen::Types::Int16le
|
150
|
+
# @!attribute param_displacement
|
151
|
+
# 16-bit offset (in bytes) relative to all of the transaction
|
152
|
+
# parameter bytes in this transaction response at which this block of
|
153
|
+
# parameter bytes SHOULD be placed.
|
154
|
+
# @return [Integer]
|
155
|
+
define_field :param_displacement, PacketGen::Types::Int16le
|
156
|
+
# @!attribute data_count
|
157
|
+
# 16-bit number of transaction data bytes sent in this response.
|
158
|
+
# @return [Integer]
|
159
|
+
define_field :data_count, PacketGen::Types::Int16le
|
160
|
+
# @!attribute data_offset
|
161
|
+
# 16-bit offset (in bytes) from the start of the SMB header to the start
|
162
|
+
# of the data field.
|
163
|
+
# @return [Integer]
|
164
|
+
define_field :data_offset, PacketGen::Types::Int16le
|
165
|
+
# @!attribute data_displacement
|
166
|
+
# 16-bit offset (in bytes) relative to all of the transaction data bytes in
|
167
|
+
# this transaction response at which this block of data bytes SHOULD be placed.
|
168
|
+
# @return [Integer]
|
169
|
+
define_field :data_displacement, PacketGen::Types::Int16le
|
170
|
+
# @!attribute setup_count
|
171
|
+
# 8-bit number of setup words (ie 16-bit words) contained in {#setup} field.
|
172
|
+
define_field :setup_count, PacketGen::Types::Int8
|
173
|
+
# @!attribute rsv3
|
174
|
+
# 8-bit reserved field
|
175
|
+
# @return [Integer]
|
176
|
+
define_field :rsv2, PacketGen::Types::Int8
|
177
|
+
# @!attribute setup
|
178
|
+
# Array of 2-byte words.
|
179
|
+
# @return [ArrayPacketGen::]
|
180
|
+
define_field :setup, PacketGen::Types::ArrayOfInt16le, builder: ->(h, t) { t.new(counter: h[:setup_count]) }
|
181
|
+
# @!attribute byte_count
|
182
|
+
# @return [Integer]
|
183
|
+
define_field :byte_count, PacketGen::Types::Int16le
|
184
|
+
# @!attribute pad1
|
185
|
+
# Padding before {#body} to align it on 32-bit boundary
|
186
|
+
# @return [Integer]
|
187
|
+
define_field :pad1, PacketGen::Types::String, default: "\0" * 4,
|
188
|
+
builder: ->(h, t) { t.new(length_from: -> { h.data_offset - SMB.new.sz - (h.offset_of(:byte_count) + h[:byte_count].sz) }) }
|
189
|
+
define_field :body, PacketGen::Types::String
|
190
|
+
|
191
|
+
# Give protocol name for this class
|
192
|
+
# @return [String]
|
193
|
+
def protocol_name
|
194
|
+
'SMB::TransResponse'
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
self.bind_command 'trans'
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'packetgen/plugin/smb_version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'packetgen-plugin-smb'
|
7
|
+
spec.version = PacketGen::Plugin::SMB_VERSION
|
8
|
+
spec.authors = ['Sylvain Daubert']
|
9
|
+
spec.email = ['sylvain.daubert@laposte.net']
|
10
|
+
|
11
|
+
spec.summary = %q{SMB plugin for packetgen.}
|
12
|
+
#spec.description = %q{TODO: Write a longer description or delete this line.}
|
13
|
+
spec.homepage = 'https://github.com/sdaubert/packetgen-plugin-smb'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_dependency 'packetgen', '~>2.8', '>= 2.8.1'
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.7'
|
25
|
+
spec.add_development_dependency 'simplecov', '~> 0.16'
|
26
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
27
|
+
|
28
|
+
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: packetgen-plugin-smb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sylvain Daubert
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: packetgen
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.8'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.8.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.8'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.8.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.16'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.16'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rspec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.7'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.7'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: simplecov
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.16'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0.16'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: yard
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0.9'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.9'
|
103
|
+
description:
|
104
|
+
email:
|
105
|
+
- sylvain.daubert@laposte.net
|
106
|
+
executables: []
|
107
|
+
extensions: []
|
108
|
+
extra_rdoc_files: []
|
109
|
+
files:
|
110
|
+
- ".gitignore"
|
111
|
+
- ".travis.yml"
|
112
|
+
- Gemfile
|
113
|
+
- LICENSE
|
114
|
+
- README.md
|
115
|
+
- Rakefile
|
116
|
+
- lib/packetgen-plugin-smb.rb
|
117
|
+
- lib/packetgen/plugin/smb.rb
|
118
|
+
- lib/packetgen/plugin/smb/blocks.rb
|
119
|
+
- lib/packetgen/plugin/smb/close.rb
|
120
|
+
- lib/packetgen/plugin/smb/filetime.rb
|
121
|
+
- lib/packetgen/plugin/smb/nt_create_and_x.rb
|
122
|
+
- lib/packetgen/plugin/smb/string.rb
|
123
|
+
- lib/packetgen/plugin/smb/trans.rb
|
124
|
+
- lib/packetgen/plugin/smb_version.rb
|
125
|
+
- packetgen-plugin-smb.gemspec
|
126
|
+
homepage: https://github.com/sdaubert/packetgen-plugin-smb
|
127
|
+
licenses: []
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 2.7.6
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
148
|
+
summary: SMB plugin for packetgen.
|
149
|
+
test_files: []
|