ruby_smb 0.0.21 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/examples/net_share_enum_all.rb +5 -2
- data/lib/ruby_smb.rb +1 -1
- data/lib/ruby_smb/client.rb +4 -35
- data/lib/ruby_smb/dcerpc.rb +7 -22
- data/lib/ruby_smb/dcerpc/bind.rb +30 -36
- data/lib/ruby_smb/dcerpc/bind_ack.rb +72 -0
- data/lib/ruby_smb/dcerpc/error.rb +15 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +31 -30
- data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +11 -0
- data/lib/ruby_smb/dcerpc/pdu_header.rb +29 -0
- data/lib/ruby_smb/dcerpc/ptypes.rb +26 -0
- data/lib/ruby_smb/dcerpc/request.rb +17 -30
- data/lib/ruby_smb/dcerpc/response.rb +15 -34
- data/lib/ruby_smb/dcerpc/srvsvc.rb +5 -7
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +8 -4
- data/lib/ruby_smb/dcerpc/uuid.rb +31 -13
- data/lib/ruby_smb/smb1/bit_field.rb +0 -1
- data/lib/ruby_smb/smb1/bit_field/trans_flags.rb +3 -2
- data/lib/ruby_smb/smb1/data_block.rb +5 -0
- data/lib/ruby_smb/smb1/dcerpc.rb +67 -0
- data/lib/ruby_smb/smb1/packet.rb +1 -0
- data/lib/ruby_smb/smb1/packet/trans.rb +7 -1
- data/lib/ruby_smb/smb1/packet/trans/data_block.rb +19 -7
- data/lib/ruby_smb/smb1/packet/trans/request.rb +36 -25
- data/lib/ruby_smb/smb1/packet/trans/response.rb +22 -21
- data/lib/ruby_smb/smb1/packet/trans/subcommands.rb +1 -0
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +61 -0
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +44 -0
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +1 -1
- data/lib/ruby_smb/smb1/pipe.rb +3 -0
- data/lib/ruby_smb/smb2/dcerpc.rb +68 -0
- data/lib/ruby_smb/smb2/pipe.rb +3 -0
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +53 -6
- data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +224 -0
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +255 -7
- data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +31 -0
- data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +84 -0
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +106 -13
- data/spec/lib/ruby_smb/dcerpc/response_spec.rb +89 -8
- data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +176 -0
- data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +97 -1
- data/spec/lib/ruby_smb/smb1/data_block_spec.rb +43 -3
- data/spec/lib/ruby_smb/smb1/packet/trans/data_block_spec.rb +137 -0
- data/spec/lib/ruby_smb/smb1/packet/trans/request_spec.rb +239 -13
- data/spec/lib/ruby_smb/smb1/packet/trans/response_spec.rb +122 -13
- data/spec/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request_spec.rb +254 -0
- data/spec/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response_spec.rb +122 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +199 -1
- data/spec/lib/ruby_smb/smb2/file_spec.rb +2 -1
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +196 -1
- metadata +25 -10
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/dcerpc/handle.rb +0 -60
- data/lib/ruby_smb/smb1/bit_field/trans2_flags.rb +0 -15
- data/spec/lib/ruby_smb/dcerpc/handle_spec.rb +0 -31
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +0 -13
- data/spec/lib/ruby_smb/smb1/bit_field/trans2_flags_spec.rb +0 -26
@@ -1,43 +1,30 @@
|
|
1
1
|
module RubySMB
|
2
2
|
module Dcerpc
|
3
|
-
#
|
3
|
+
# The Request PDU as defined in
|
4
|
+
# [The request PDU](http://pubs.opengroup.org/onlinepubs/9629399/chap12.htm#tagcjh_17_06_04_09)
|
4
5
|
class Request < BinData::Record
|
5
6
|
endian :little
|
6
7
|
|
7
|
-
|
8
|
-
uint8 :rpc_vers, initial_value: 5 # 00:01 RPC version
|
9
|
-
uint8 :rpc_vers_minor # 01:01 minor version
|
10
|
-
uint8 :ptype # 02:01 request PDU
|
11
|
-
struct :pfc_flags do
|
12
|
-
bit1 :object
|
13
|
-
bit1 :maybe
|
14
|
-
bit1 :did_not_execute
|
15
|
-
bit1 :multiplex
|
16
|
-
bit1 :reserved
|
17
|
-
bit1 :cancel
|
18
|
-
bit1 :last_frag, initial_value: 1
|
19
|
-
bit1 :first_frag, initial_value: 1
|
20
|
-
end
|
21
|
-
|
22
|
-
uint32 :packed_drep, initial_value: 0x00000010 # 04:04 NDR data rep format label
|
23
|
-
|
24
|
-
uint16 :frag_length, initial_value: -> { self.do_num_bytes } # 08:02 total length of fragment
|
25
|
-
uint16 :auth_length # 10:02 length of auth_value
|
26
|
-
uint32 :call_id # 12:04 call identifier
|
8
|
+
pdu_header :pdu_header, label: 'PDU header'
|
27
9
|
|
28
|
-
|
10
|
+
uint32 :alloc_hint, label: 'Allocation hint', initial_value: -> { stub.do_num_bytes }
|
11
|
+
uint16 :p_cont_id, label: 'Presentation context identification'
|
12
|
+
uint16 :opnum, label: 'Operation Number'
|
29
13
|
|
30
|
-
|
31
|
-
uint16 :p_cont_id # 20:02 pres context, i.e. data rep
|
32
|
-
uint16 :opnum # 22:02 operation #within the interface
|
14
|
+
uuid :object, label: 'Object UID', onlyif: -> { pdu_header.pfc_flags.object_uuid == 1 }
|
33
15
|
|
34
|
-
|
16
|
+
choice :stub, label: 'Stub', selection: -> { opnum } do
|
17
|
+
net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host }
|
18
|
+
end
|
35
19
|
|
36
|
-
string :
|
37
|
-
|
38
|
-
|
20
|
+
string :auth_verifier, label: 'Authentication verifier',
|
21
|
+
onlyif: -> { pdu_header.auth_length > 0 },
|
22
|
+
read_length: -> { pdu_header.auth_length }
|
39
23
|
|
40
|
-
|
24
|
+
def initialize_instance
|
25
|
+
super
|
26
|
+
pdu_header.ptype = RubySMB::Dcerpc::PTypes::REQUEST
|
27
|
+
end
|
41
28
|
end
|
42
29
|
end
|
43
30
|
end
|
@@ -1,46 +1,27 @@
|
|
1
1
|
module RubySMB
|
2
2
|
module Dcerpc
|
3
|
-
#
|
3
|
+
# The Response PDU as defined in
|
4
|
+
# [The response PDU](http://pubs.opengroup.org/onlinepubs/9629399/chap12.htm#tagcjh_17_06_04_10)
|
4
5
|
class Response < BinData::Record
|
5
6
|
endian :little
|
6
7
|
|
7
|
-
|
8
|
-
uint8 :rpc_vers # 00:01 RPC version
|
9
|
-
uint8 :rpc_vers_minor # 01:01 minor version
|
10
|
-
uint8 :ptype # 02:01 request PDU
|
11
|
-
struct :pfc_flags do
|
12
|
-
bit1 :object
|
13
|
-
bit1 :maybe
|
14
|
-
bit1 :did_not_execute
|
15
|
-
bit1 :multiplex
|
16
|
-
bit1 :reserved
|
17
|
-
bit1 :cancel
|
18
|
-
bit1 :last_frag, initial_value: 1
|
19
|
-
bit1 :first_frag, initial_value: 1
|
20
|
-
end
|
21
|
-
|
22
|
-
uint32 :packed_drep # 04:04 NDR data rep format label
|
23
|
-
|
24
|
-
uint16 :frag_length # 08:02 total length of fragment
|
25
|
-
uint16 :auth_length # 10:02 length of auth_value
|
26
|
-
uint32 :call_id # 12:04 call identifier
|
27
|
-
|
28
|
-
#needed on request, response, fault
|
8
|
+
pdu_header :pdu_header, label: 'PDU header'
|
29
9
|
|
30
|
-
uint32 :alloc_hint
|
31
|
-
uint16 :p_cont_id
|
32
|
-
|
10
|
+
uint32 :alloc_hint, label: 'Allocation hint', initial_value: -> { stub.do_num_bytes }
|
11
|
+
uint16 :p_cont_id, label: 'Presentation context identification'
|
12
|
+
uint8 :cancel_count, label: 'Cancel count'
|
13
|
+
uint8 :reserved
|
33
14
|
|
34
|
-
|
15
|
+
string :stub, label: 'Stub', read_length: -> { pdu_header.frag_length - stub.abs_offset - pdu_header.auth_length }
|
35
16
|
|
36
|
-
string :
|
17
|
+
string :auth_verifier, label: 'Authentication verifier',
|
18
|
+
onlyif: -> { pdu_header.auth_length > 0 },
|
19
|
+
read_length: -> { pdu_header.auth_length }
|
37
20
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
#auth_verifier_co_t auth_verifier # xx:yy
|
21
|
+
def initialize_instance
|
22
|
+
super
|
23
|
+
pdu_header.ptype = RubySMB::Dcerpc::PTypes::RESPONSE
|
24
|
+
end
|
44
25
|
end
|
45
26
|
end
|
46
27
|
end
|
@@ -2,14 +2,12 @@ module RubySMB
|
|
2
2
|
module Dcerpc
|
3
3
|
module Srvsvc
|
4
4
|
|
5
|
-
|
5
|
+
UUID = '4b324fc8-1670-01d3-1278-5a47bf6ee188'
|
6
|
+
VER_MAJOR = 3
|
7
|
+
VER_MINOR = 0
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
uuid :if_uuid, initial_value: '4b324fc8-1670-01d3-1278-5a47bf6ee188'
|
10
|
-
uint16 :if_ver, initial_value: 3
|
11
|
-
uint16 :if_ver_minor, initial_value: 0
|
12
|
-
end
|
9
|
+
# Operation numbers
|
10
|
+
NET_SHARE_ENUM_ALL = 0xF
|
13
11
|
|
14
12
|
require 'ruby_smb/dcerpc/srvsvc/net_share_enum_all'
|
15
13
|
end
|
@@ -5,17 +5,16 @@ module RubySMB
|
|
5
5
|
#https://msdn.microsoft.com/en-us/library/cc247293.aspx
|
6
6
|
|
7
7
|
class NetShareEnumAll < BinData::Record
|
8
|
-
Opnum = 0xF
|
9
|
-
|
10
8
|
endian :little
|
11
9
|
|
12
10
|
uint32 :referent_id, initial_value: 0x00000001
|
13
11
|
uint32 :max_count, initial_value: -> { server_unc.do_num_bytes / 2 }
|
14
12
|
uint32 :offset, initial_value: 0
|
15
13
|
uint32 :actual_count, initial_value: -> {max_count}
|
16
|
-
stringz16 :server_unc,
|
17
|
-
initial_value: -> {host.encode('utf-16le')}
|
14
|
+
stringz16 :server_unc, pad_front: false, read_length: -> { actual_count * 2 },
|
15
|
+
initial_value: -> {"\\\\#{host.encode('utf-8')}".encode('utf-16le')}
|
18
16
|
|
17
|
+
string :pad, length: lambda { pad_length }
|
19
18
|
uint32 :level, initial_value: 1
|
20
19
|
|
21
20
|
uint32 :ctr, initial_value: 1
|
@@ -28,6 +27,11 @@ module RubySMB
|
|
28
27
|
uint32 :resume_referent_id, initial_value: 0x00000001
|
29
28
|
uint32 :resume_handle, initial_value: 0
|
30
29
|
|
30
|
+
def pad_length
|
31
|
+
offset = (server_unc.abs_offset + server_unc.to_binary_s.length) % 4
|
32
|
+
(4 - offset) % 4
|
33
|
+
end
|
34
|
+
|
31
35
|
def self.parse_response(response)
|
32
36
|
|
33
37
|
shares = []
|
data/lib/ruby_smb/dcerpc/uuid.rb
CHANGED
@@ -1,28 +1,46 @@
|
|
1
1
|
module RubySMB
|
2
2
|
module Dcerpc
|
3
3
|
|
4
|
-
#
|
4
|
+
# [Universal Unique Identifier](http://pubs.opengroup.org/onlinepubs/9629399/apdxa.htm)
|
5
5
|
class Uuid < BinData::Primitive
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
endian :little
|
7
|
+
uint32 :time_low, label: 'Low field of the timestamp'
|
8
|
+
uint16 :time_mid, label: 'Middle field of the timestamp'
|
9
|
+
uint16 :time_hi_and_version, label: 'High field of the timestamp multiplexed with the version number'
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
uint8 :clock_seq_hi_and_reserved, label: 'High field of the clock sequence multiplexed with the variant'
|
12
|
+
uint8 :clock_seq_low, label: 'Low field of the clock sequence'
|
13
|
+
array :node, label: 'Spatially unique node identifier', :type => :uint8, initial_length: 6
|
12
14
|
|
13
15
|
def get
|
14
|
-
|
16
|
+
"#{to_string_le(time_low.to_binary_s)}"\
|
17
|
+
"-#{to_string_le(time_mid.to_binary_s)}"\
|
18
|
+
"-#{to_string_le(time_hi_and_version.to_binary_s)}"\
|
19
|
+
"-#{clock_seq_hi_and_reserved.to_hex}#{clock_seq_low.to_hex}"\
|
20
|
+
"-#{node.to_hex}"
|
15
21
|
end
|
16
22
|
|
17
23
|
def set(uuid_string)
|
18
24
|
components = uuid_string.split('-')
|
19
|
-
self.time_low
|
20
|
-
self.time_mid
|
21
|
-
self.time_hi_and_version
|
22
|
-
self.
|
23
|
-
self.
|
25
|
+
self.time_low.read(to_binary_le(components[0]))
|
26
|
+
self.time_mid.read(to_binary_le(components[1]))
|
27
|
+
self.time_hi_and_version.read(to_binary_le(components[2]))
|
28
|
+
self.clock_seq_hi_and_reserved.read(components[3][0,2].hex.chr)
|
29
|
+
self.clock_seq_low.read(components[3][2,2].hex.chr)
|
30
|
+
self.node.read(components[4].gsub(/../) {|e| e.hex.chr})
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def to_binary_le(str)
|
37
|
+
str.scan(/../).map {|char| char.hex.chr}.reverse.join
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_string_le(bin)
|
41
|
+
bin.each_byte.map {|byte| byte.to_s(16).rjust(2, '0')}.reverse.join
|
24
42
|
end
|
25
43
|
end
|
26
44
|
|
27
45
|
end
|
28
|
-
end
|
46
|
+
end
|
@@ -11,7 +11,6 @@ module RubySMB
|
|
11
11
|
require 'ruby_smb/smb1/bit_field/directory_access_mask'
|
12
12
|
require 'ruby_smb/smb1/bit_field/file_access_mask'
|
13
13
|
require 'ruby_smb/smb1/bit_field/trans_flags'
|
14
|
-
require 'ruby_smb/smb1/bit_field/trans2_flags'
|
15
14
|
require 'ruby_smb/smb1/bit_field/open2_flags'
|
16
15
|
require 'ruby_smb/smb1/bit_field/open2_access_mode'
|
17
16
|
require 'ruby_smb/smb1/bit_field/open2_open_mode'
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module RubySMB
|
2
2
|
module SMB1
|
3
3
|
module BitField
|
4
|
-
# The Flags bit-field for
|
5
|
-
# [2.2.4.33.1 Request](https://msdn.microsoft.com/en-us/library/ee441730.aspx)
|
4
|
+
# The Flags bit-field for Trans and Trans2 Request Packets as defined in
|
5
|
+
# [2.2.4.33.1 Request](https://msdn.microsoft.com/en-us/library/ee441730.aspx) and
|
6
|
+
# [2.2.4.46.1 Request](https://msdn.microsoft.com/en-us/library/ee442192.aspx)
|
6
7
|
class TransFlags < BinData::Record
|
7
8
|
endian :little
|
8
9
|
bit6 :reserved, label: 'Reserved Space', initial_value: 0
|
@@ -32,11 +32,16 @@ module RubySMB
|
|
32
32
|
def calculate_byte_count
|
33
33
|
total_count = 0
|
34
34
|
self.class.data_fields.each do |field_name|
|
35
|
+
next unless field_enabled?(field_name)
|
35
36
|
field_value = send(field_name)
|
36
37
|
total_count += field_value.do_num_bytes
|
37
38
|
end
|
38
39
|
total_count
|
39
40
|
end
|
41
|
+
|
42
|
+
def field_enabled?(field_name)
|
43
|
+
send("#{field_name}?".to_sym)
|
44
|
+
end
|
40
45
|
end
|
41
46
|
end
|
42
47
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module SMB1
|
3
|
+
module Dcerpc
|
4
|
+
|
5
|
+
def net_share_enum_all(host)
|
6
|
+
bind(endpoint: RubySMB::Dcerpc::Srvsvc)
|
7
|
+
|
8
|
+
response = request(RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: host)
|
9
|
+
|
10
|
+
shares = RubySMB::Dcerpc::Srvsvc::NetShareEnumAll.parse_response(response.stub.to_binary_s)
|
11
|
+
shares.map{|s|{name: s[0], type: s[1], comment: s[2]}}
|
12
|
+
end
|
13
|
+
|
14
|
+
def bind(options={})
|
15
|
+
bind_req = RubySMB::Dcerpc::Bind.new(options)
|
16
|
+
write(data: bind_req.to_binary_s)
|
17
|
+
@size = 1024
|
18
|
+
dcerpc_raw_response = read()
|
19
|
+
begin
|
20
|
+
dcerpc_response = RubySMB::Dcerpc::BindAck.read(dcerpc_raw_response)
|
21
|
+
rescue IOError
|
22
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the DCERPC response"
|
23
|
+
end
|
24
|
+
unless dcerpc_response.pdu_header.ptype == RubySMB::Dcerpc::PTypes::BIND_ACK
|
25
|
+
raise RubySMB::Dcerpc::Error::BindError, "Not a BindAck packet"
|
26
|
+
end
|
27
|
+
|
28
|
+
res_list = dcerpc_response.p_result_list
|
29
|
+
if res_list.n_results == 0 ||
|
30
|
+
res_list.p_results[0].result != RubySMB::Dcerpc::BindAck::ACCEPTANCE
|
31
|
+
raise RubySMB::Dcerpc::Error::BindError,
|
32
|
+
"Bind Failed (Result: #{res_list.p_results[0].result}, Reason: #{res_list.p_results[0].reason})"
|
33
|
+
end
|
34
|
+
dcerpc_response
|
35
|
+
end
|
36
|
+
|
37
|
+
def request(opnum, options={})
|
38
|
+
dcerpc_request = RubySMB::Dcerpc::Request.new({ :opnum => opnum }, options)
|
39
|
+
request = RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest.new(options)
|
40
|
+
@tree.set_header_fields(request)
|
41
|
+
request.set_fid(@fid)
|
42
|
+
request.data_block.trans_data.write_data = dcerpc_request.to_binary_s
|
43
|
+
|
44
|
+
trans_nmpipe_raw_response = @tree.client.send_recv(request)
|
45
|
+
trans_nmpipe_response = RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse.read(trans_nmpipe_raw_response)
|
46
|
+
unless trans_nmpipe_response.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_TRANSACTION
|
47
|
+
raise RubySMB::Error::InvalidPacket, 'Not a Trans packet'
|
48
|
+
end
|
49
|
+
unless trans_nmpipe_response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
50
|
+
raise RubySMB::Error::UnexpectedStatusCode, trans_nmpipe_response.status_code.name
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
dcerpc_response = RubySMB::Dcerpc::Response.read(trans_nmpipe_response.data_block.trans_data.read_data)
|
55
|
+
rescue IOError
|
56
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the DCERPC response"
|
57
|
+
end
|
58
|
+
unless dcerpc_response.pdu_header.ptype == RubySMB::Dcerpc::PTypes::RESPONSE
|
59
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Not a Response packet"
|
60
|
+
end
|
61
|
+
dcerpc_response
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/ruby_smb/smb1/packet.rb
CHANGED
@@ -4,10 +4,16 @@ module RubySMB
|
|
4
4
|
# Namespace for the Transaction sub-protocol documented in
|
5
5
|
# [2.2.4.33 SMB_COM_TRANSACTION (0x25)](https://msdn.microsoft.com/en-us/library/ee441489.aspx)
|
6
6
|
module Trans
|
7
|
-
|
7
|
+
MAX_PARAMETER_COUNT = 1024
|
8
|
+
MAX_DATA_COUNT = 1024
|
9
|
+
MAX_SETUP_COUNT = 255
|
10
|
+
|
8
11
|
require 'ruby_smb/smb1/packet/trans/data_block'
|
12
|
+
require 'ruby_smb/smb1/packet/trans/subcommands'
|
9
13
|
require 'ruby_smb/smb1/packet/trans/request'
|
10
14
|
require 'ruby_smb/smb1/packet/trans/response'
|
15
|
+
require 'ruby_smb/smb1/packet/trans/transact_nmpipe_request'
|
16
|
+
require 'ruby_smb/smb1/packet/trans/transact_nmpipe_response'
|
11
17
|
require 'ruby_smb/smb1/packet/trans/peek_nmpipe_request'
|
12
18
|
require 'ruby_smb/smb1/packet/trans/peek_nmpipe_response'
|
13
19
|
end
|
@@ -2,6 +2,7 @@ module RubySMB
|
|
2
2
|
module SMB1
|
3
3
|
module Packet
|
4
4
|
module Trans
|
5
|
+
|
5
6
|
# Extends the {RubySMB::SMB1::DataBlock} to include padding methods
|
6
7
|
# that all Trans DataBlocks will need to handle proper byte alignment.
|
7
8
|
class DataBlock < RubySMB::SMB1::DataBlock
|
@@ -18,14 +19,14 @@ module RubySMB
|
|
18
19
|
private
|
19
20
|
|
20
21
|
# Determines the correct length for the padding in front of
|
21
|
-
# trans_parameters. It should always force a 4-byte alignment.
|
22
|
+
# #trans_parameters. It should always force a 4-byte alignment.
|
22
23
|
def pad1_length
|
23
24
|
if enable_padding
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
if self.respond_to?(:name)
|
26
|
+
offset = (name.abs_offset + name.to_binary_s.length) % 4
|
27
|
+
else
|
28
|
+
offset = (byte_count.abs_offset + 2) % 4
|
29
|
+
end
|
29
30
|
(4 - offset) % 4
|
30
31
|
else
|
31
32
|
0
|
@@ -33,7 +34,7 @@ module RubySMB
|
|
33
34
|
end
|
34
35
|
|
35
36
|
# Determines the correct length for the padding in front of
|
36
|
-
# trans_data. It should always force a 4-byte alignment.
|
37
|
+
# #trans_data. It should always force a 4-byte alignment.
|
37
38
|
def pad2_length
|
38
39
|
if enable_padding
|
39
40
|
offset = (trans_parameters.abs_offset + trans_parameters.length) % 4
|
@@ -42,6 +43,17 @@ module RubySMB
|
|
42
43
|
0
|
43
44
|
end
|
44
45
|
end
|
46
|
+
|
47
|
+
# Determines the correct length for the padding in front of
|
48
|
+
# #name. It should always force a 2-byte alignment.
|
49
|
+
def pad_name_length
|
50
|
+
if enable_padding
|
51
|
+
offset = (byte_count.abs_offset + 2) % 2
|
52
|
+
(2 - offset) % 2
|
53
|
+
else
|
54
|
+
0
|
55
|
+
end
|
56
|
+
end
|
45
57
|
end
|
46
58
|
end
|
47
59
|
end
|
@@ -2,37 +2,46 @@ module RubySMB
|
|
2
2
|
module SMB1
|
3
3
|
module Packet
|
4
4
|
module Trans
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
# This class represents a generic SMB1 Trans Request Packet as defined in
|
7
|
+
# [2.2.4.33.1 Request](https://msdn.microsoft.com/en-us/library/ee441730.aspx)
|
7
8
|
class Request < RubySMB::GenericPacket
|
8
9
|
# A SMB1 Parameter Block
|
9
10
|
class ParameterBlock < RubySMB::SMB1::ParameterBlock
|
10
|
-
uint16
|
11
|
-
uint16
|
12
|
-
uint16
|
13
|
-
uint16
|
14
|
-
uint8
|
15
|
-
uint8
|
16
|
-
trans_flags
|
17
|
-
uint32
|
18
|
-
uint16
|
19
|
-
uint16
|
20
|
-
uint16
|
21
|
-
uint16
|
22
|
-
uint16
|
23
|
-
uint8
|
24
|
-
uint8
|
25
|
-
|
26
|
-
array :setup, type: :uint16, initial_length: 0
|
11
|
+
uint16 :total_parameter_count, label: 'Total Parameter Count(bytes)', initial_value: -> { parameter_count }
|
12
|
+
uint16 :total_data_count, label: 'Total Data Count(bytes)', initial_value: -> { data_count }
|
13
|
+
uint16 :max_parameter_count, label: 'Max Parameter Count(bytes)', initial_value: Trans::MAX_PARAMETER_COUNT
|
14
|
+
uint16 :max_data_count, label: 'Max Data Count(bytes)', initial_value: Trans::MAX_DATA_COUNT
|
15
|
+
uint8 :max_setup_count, label: 'Max Setup Count', initial_value: Trans::MAX_SETUP_COUNT
|
16
|
+
uint8 :reserved, label: 'Reserved Space', value: 0x00
|
17
|
+
trans_flags :flags
|
18
|
+
uint32 :timeout, label: 'Timeout', initial_value: 0x00000000
|
19
|
+
uint16 :reserved2, label: 'Reserved Space', value: 0x0000
|
20
|
+
uint16 :parameter_count, label: 'Parameter Count(bytes)', initial_value: -> { parent.data_block.trans_parameters.length }
|
21
|
+
uint16 :parameter_offset, label: 'Parameter Offset', initial_value: -> { parent.data_block.trans_parameters.abs_offset }
|
22
|
+
uint16 :data_count, label: 'Data Count(bytes)', initial_value: -> { parent.data_block.trans_data.length }
|
23
|
+
uint16 :data_offset, label: 'Data Offset', initial_value: -> { parent.data_block.trans_data.abs_offset }
|
24
|
+
uint8 :setup_count, label: 'Setup Count', initial_value: -> { setup.length }
|
25
|
+
uint8 :reserved3, label: 'Reserved Space', value: 0x00
|
26
|
+
array :setup, type: :uint16, initial_length: :setup_count
|
27
27
|
end
|
28
28
|
|
29
29
|
# The {RubySMB::SMB1::DataBlock} specific to this packet type.
|
30
30
|
class DataBlock < RubySMB::SMB1::Packet::Trans::DataBlock
|
31
|
-
|
32
|
-
|
33
|
-
string :
|
34
|
-
|
35
|
-
|
31
|
+
# If unicode is set, the name field must be aligned to start on a 2-byte
|
32
|
+
# boundary from the start of the SMB header:
|
33
|
+
string :pad_name, length: -> { pad_name_length },
|
34
|
+
onlyif: -> { parent.smb_header.flags2.unicode.to_i == 1 }
|
35
|
+
choice :name, :selection => lambda { parent.smb_header.flags2.unicode.to_i },
|
36
|
+
:copy_on_change => true do
|
37
|
+
stringz 0, label: 'Name', initial_value: "\\PIPE\\"
|
38
|
+
stringz16 1, label: 'Name', initial_value: "\\PIPE\\".encode('utf-16le')
|
39
|
+
|
40
|
+
end
|
41
|
+
string :pad1, length: lambda { pad1_length }
|
42
|
+
string :trans_parameters, label: 'Trans Parameters', read_length: -> { parent.parameter_block.parameter_count }
|
43
|
+
string :pad2, length: lambda { pad2_length }
|
44
|
+
string :trans_data, label: 'Trans Data', read_length: -> { parent.parameter_block.data_count }
|
36
45
|
end
|
37
46
|
|
38
47
|
smb_header :smb_header
|
@@ -43,8 +52,10 @@ module RubySMB
|
|
43
52
|
super
|
44
53
|
smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION
|
45
54
|
end
|
55
|
+
|
46
56
|
end
|
47
57
|
end
|
48
58
|
end
|
49
59
|
end
|
50
|
-
end
|
60
|
+
end
|
61
|
+
|