packetgen-plugin-smb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.com/sdaubert/packetgen-plugin-smb.svg?branch=master)](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: []
|