ruby_smb 0.0.21 → 0.0.22
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|