ruby_smb 3.3.13 → 3.3.15

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c74027d4436875845c9d219abd7cb3243d80acd61fbaeabb9c1256571354634
4
- data.tar.gz: 8dbe5857343dbb8e1b163c29a7d3ef8d8e30aa06dc7527195772a058f4022321
3
+ metadata.gz: c750cc33b1b323d9f28b7ad65702e26758d1341d419ae3271c0cb900b0e254de
4
+ data.tar.gz: 6d62d69876566ea5fc087104da49ca598ad2705cb9bb99723ac8b22d43cb63ab
5
5
  SHA512:
6
- metadata.gz: 5ed11e51a9babe4a7e478e4903dd4c201c8e714288ab49766e62ba3c01cf9b8358899276ecece683dbb586777739a016579e06a9dd9e6581e03a408a6a27cf5c
7
- data.tar.gz: a7bf609a4b94040075adda0c17728ef306d780d28db06f47fa2d1c9b6729821309c3c5395c5bb8d22ad76fe693f7f7b21a2de9f9239211af64417ef35da16e37
6
+ metadata.gz: a52b76ed65ba8112c3a8232d8568cfda030007d56e7b982623735b57b0515b6e0a13aab897ba56213a62c83e42132ce5f7d6c2946bee06f641029257c8681cd4
7
+ data.tar.gz: 87d493f9c4e6380d22f39debbce248e0b7f3c9eb9d8f39a93d5bb5db620fb2b47035ad3cafad6d1ba8bd1aa1d52d88ae3195daf43e5e840c7e11f38f2581ffcc
data/cortex.yaml CHANGED
@@ -10,6 +10,8 @@ info:
10
10
  x-cortex-type: service
11
11
  x-cortex-domain-parents:
12
12
  - tag: metasploit
13
+ x-cortex-groups:
14
+ - exposure:external-ship
13
15
  openapi: 3.0.1
14
16
  servers:
15
17
  - url: "/"
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'ruby_smb'
5
+
6
+ require 'optparse'
7
+ require 'pp'
8
+
9
+ options = {
10
+ major_version: 1,
11
+ minor_version: 0,
12
+ max_towers: 1,
13
+ }
14
+
15
+ parser = OptionParser.new do |opts|
16
+ opts.banner = "Usage: script.rb [options] TARGET PROTOCOL UUID"
17
+
18
+ opts.on("--major-version N", Integer, "Specify major version number (default: #{options[:major_version]})") do |v|
19
+ options[:major_version] = v
20
+ end
21
+
22
+ opts.on("--minor-version N", Integer, "Specify minor version number ((default: #{options[:minor_version]})") do |v|
23
+ options[:minor_version] = v
24
+ end
25
+
26
+ opts.on("--max-towers N", Integer, "Set the maximum number of towers (default: #{options[:max_towers]})") do |v|
27
+ options[:max_towers] = v
28
+ end
29
+
30
+ opts.on("-h", "--help", "Prints this help") do
31
+ puts opts
32
+ exit
33
+ end
34
+ end
35
+
36
+ # Parse and extract positional arguments
37
+ begin
38
+ parser.order!(ARGV)
39
+ if ARGV.size != 3
40
+ raise OptionParser::MissingArgument, "TARGET, PROTOCOL, and UUID are required"
41
+ end
42
+
43
+ options[:target], options[:protocol], options[:uuid] = ARGV
44
+ rescue OptionParser::ParseError => e
45
+ puts e.message
46
+ puts parser
47
+ exit 1
48
+ end
49
+
50
+ dcerpc_client = RubySMB::Dcerpc::Client.new(options[:target], RubySMB::Dcerpc::Epm)
51
+ dcerpc_client.connect
52
+ dcerpc_client.bind
53
+ dcerpc_client.ept_map(
54
+ uuid: options[:uuid],
55
+ maj_ver: options[:major_version],
56
+ min_ver: options[:minor_version],
57
+ protocol: options[:protocol].to_sym,
58
+ max_towers: options[:max_towers]
59
+ ).each do |tower|
60
+ puts "Tower: #{tower[:endpoint]}"
61
+ tower.each do |key, value|
62
+ next if key == :endpoint
63
+ puts " #{key}: #{value}"
64
+ end
65
+ end
@@ -11,7 +11,6 @@ module RubySMB
11
11
  require 'ruby_smb/peer_info'
12
12
 
13
13
  include Dcerpc
14
- include Epm
15
14
  include PeerInfo
16
15
 
17
16
  # The default maximum size of a RPC message that the Client accepts (in bytes)
@@ -146,27 +145,31 @@ module RubySMB
146
145
  # @return [TcpSocket] The connected TCP socket
147
146
  def connect(port: nil)
148
147
  return if @tcp_socket
148
+
149
149
  unless port
150
- @tcp_socket = TCPSocket.new(@host, ENDPOINT_MAPPER_PORT)
151
- bind(endpoint: Epm)
152
- begin
153
- host_port = get_host_port_from_ept_mapper(
154
- uuid: @endpoint::UUID,
155
- maj_ver: @endpoint::VER_MAJOR,
156
- min_ver: @endpoint::VER_MINOR
157
- )
158
- rescue RubySMB::Dcerpc::Error::DcerpcError => e
159
- e.message.prepend(
160
- "Cannot resolve the remote port number for endpoint #{@endpoint::UUID}. "\
161
- "Set @tcp_socket parameter to specify the service port number and bypass "\
162
- "EPM port resolution. Error: "
163
- )
164
- raise e
150
+ if @endpoint == Epm
151
+ port = ENDPOINT_MAPPER_PORT
152
+ else
153
+ epm_client = Client.new(@host, Epm, read_timeout: @read_timeout)
154
+ epm_client.connect
155
+ begin
156
+ epm_client.bind
157
+ towers = epm_client.ept_map_endpoint(@endpoint)
158
+ rescue RubySMB::Dcerpc::Error::DcerpcError => e
159
+ e.message.prepend(
160
+ "Cannot resolve the remote port number for endpoint #{@endpoint::UUID}. "\
161
+ "Set @tcp_socket parameter to specify the service port number and bypass "\
162
+ "EPM port resolution. Error: "
163
+ )
164
+ raise e
165
+ ensure
166
+ epm_client.close
167
+ end
168
+
169
+ port = towers.first[:port]
165
170
  end
166
- port = host_port[:port]
167
- @tcp_socket.close
168
- @tcp_socket = nil
169
171
  end
172
+
170
173
  @tcp_socket = TCPSocket.new(@host, port)
171
174
  end
172
175
 
@@ -27,39 +27,39 @@ module RubySMB
27
27
 
28
28
  uint16 :lhs_bytecount, byte_align: 1, initial_value: -> {prot_identifier.num_bytes}
29
29
  # Protocol Identifiers:
30
- # 0x00: "OSI Object Identifier [OID]"
31
- # 0x02: "DNA Session Control Phase 4"
32
- # 0x03: "DNA Session Control V3 Phase 5"
33
- # 0x04: "DNA NSP Transport"
34
- # 0x05: "OSI TP4 [T-Selector]"
35
- # 0x06: "OSI CLNS [NSAP]"
36
- # 0x07: "DOD TCP port"
37
- # 0x08: "DOD UDP port"
38
- # 0x09: "DOD IP v4 big-endian"
39
- # 0x0a: "RPC Connectionless v4"
40
- # 0x0b: "RPC Connection-oriented v5"
41
- # 0x0c: "MS Named Pipes"
42
- # 0x0d: "UUID"
43
- # 0x0e: "ncadg_ipx"
44
- # 0x0f: "NetBIOS Named Pipes"
45
- # 0x10: "MS Named Pipe Name" or "Local InterProcess Communication (LRPC)")
46
- # 0x11: "MS NetBIOS"
47
- # 0x12: "MS NetBEUI"
48
- # 0x13: "Netware SPX"
49
- # 0x14: "Netware IPX"
50
- # 0x15: "NMP_TOWER_ID"
51
- # 0x16: "Appletalk Stream [endpoint]"
52
- # 0x17: "Appletalk Datagram [endpoint]"
53
- # 0x18: "Appletalk [NBP-style Name]"
54
- # 0x19: "NetBIOS [CL on all protocols]"
55
- # 0x1a: "VINES SPP"
56
- # 0x1b: "VINES IPC"
57
- # 0x1c: "StreetTalk [name]"
58
- # 0x1d: "MSMQ"
59
- # 0x1f: "MS IIS (http)"
60
- # 0x20: "Unix Domain socket [pathname]"
61
- # 0x21: "null"
62
- # 0x22: "NetBIOS name"
30
+ # 0x00: "OSI Object Identifier [OID]"
31
+ # 0x02: "DNA Session Control Phase 4"
32
+ # 0x03: "DNA Session Control V3 Phase 5"
33
+ # 0x04: "DNA NSP Transport"
34
+ # 0x05: "OSI TP4 [T-Selector]"
35
+ # 0x06: "OSI CLNS [NSAP]"
36
+ # 0x07: "DOD TCP port"
37
+ # 0x08: "DOD UDP port"
38
+ # 0x09: "DOD IP v4 big-endian"
39
+ # 0x0a: "RPC Connectionless v4"
40
+ # 0x0b: "RPC Connection-oriented v5"
41
+ # 0x0c: "MS Named Pipes"
42
+ # 0x0d: "UUID"
43
+ # 0x0e: "ncadg_ipx"
44
+ # 0x0f: "NetBIOS Named Pipes"
45
+ # 0x10: "MS Named Pipe Name" or "Local InterProcess Communication (LRPC)")
46
+ # 0x11: "MS NetBIOS"
47
+ # 0x12: "MS NetBEUI"
48
+ # 0x13: "Netware SPX"
49
+ # 0x14: "Netware IPX"
50
+ # 0x15: "NMP_TOWER_ID"
51
+ # 0x16: "Appletalk Stream [endpoint]"
52
+ # 0x17: "Appletalk Datagram [endpoint]"
53
+ # 0x18: "Appletalk [NBP-style Name]"
54
+ # 0x19: "NetBIOS [CL on all protocols]"
55
+ # 0x1a: "VINES SPP"
56
+ # 0x1b: "VINES IPC"
57
+ # 0x1c: "StreetTalk [name]"
58
+ # 0x1d: "MSMQ"
59
+ # 0x1f: "MS IIS (http)"
60
+ # 0x20: "Unix Domain socket [pathname]"
61
+ # 0x21: "null"
62
+ # 0x22: "NetBIOS name"
63
63
  uint8 :prot_identifier, byte_align: 1, initial_value: 0x0b
64
64
  uint16 :rhs_bytecount, byte_align: 1, initial_value: 2
65
65
  uint16 :minor_version, byte_align: 1
@@ -77,7 +77,7 @@ module RubySMB
77
77
  # default: Host name
78
78
  uint8 :identifier, byte_align: 1
79
79
  uint16 :rhs_bytecount, byte_align: 1, initial_value: -> { name.length }
80
- ndr_fixed_byte_array :name, initial_length: :rhs_bytecount
80
+ uint8_array :name, initial_length: :rhs_bytecount, byte_align: 1
81
81
  end
82
82
 
83
83
  class EpmFloorPipeOrPort < Ndr::NdrStruct
@@ -100,9 +100,9 @@ module RubySMB
100
100
  uint8 :identifier, byte_align: 1, initial_value: 0x07
101
101
  uint16 :rhs_bytecount, byte_align: 1, initial_value: -> { pipe_or_port.num_bytes }
102
102
  choice :pipe_or_port, selection: :identifier, byte_align: 1 do
103
- ndr_fixed_byte_array 0x10, initial_length: :rhs_bytecount
104
- ndr_fixed_byte_array 0x0c, initial_length: :rhs_bytecount
105
- ndr_fixed_byte_array 0x0f, initial_length: :rhs_bytecount
103
+ uint8_array 0x10, initial_length: :rhs_bytecount, byte_align: 1
104
+ uint8_array 0x0c, initial_length: :rhs_bytecount, byte_align: 1
105
+ uint8_array 0x0f, initial_length: :rhs_bytecount, byte_align: 1
106
106
  uint16be 0x07
107
107
  uint16be 0x08
108
108
  uint16be 0x13
@@ -110,7 +110,7 @@ module RubySMB
110
110
  uint16be 0x1a
111
111
  uint16be 0x1b
112
112
  uint16be 0x1f
113
- ndr_fixed_byte_array :default, initial_length: :rhs_bytecount
113
+ uint8_array :default, initial_length: :rhs_bytecount, byte_align: 1
114
114
  end
115
115
  end
116
116
 
@@ -143,17 +143,17 @@ module RubySMB
143
143
  uint8 :identifier, byte_align: 1, initial_value: 0x09
144
144
  uint16 :rhs_bytecount, byte_align: 1, initial_value: -> { host_or_addr.num_bytes }
145
145
  choice :host_or_addr, selection: :identifier, byte_align: 1 do
146
- ndr_fixed_byte_array 0x11, initial_length: :rhs_bytecount
147
- ndr_fixed_byte_array 0x12, initial_length: :rhs_bytecount
148
- ndr_fixed_byte_array 0x22, initial_length: :rhs_bytecount
146
+ uint8_array 0x11, initial_length: :rhs_bytecount, byte_align: 1
147
+ uint8_array 0x12, initial_length: :rhs_bytecount, byte_align: 1
148
+ uint8_array 0x22, initial_length: :rhs_bytecount, byte_align: 1
149
149
  epm_ipv4_address 0x09
150
150
  epm_ipx_spx_address 0x13
151
151
  epm_ipx_spx_address 0x14
152
- choice 0x00, selection: -> {rhs_bytecount.num_bytes} do
153
- ndr_fixed_byte_array 16, initial_length: 16
154
- ndr_fixed_byte_array :default, initial_length: :rhs_bytecount
152
+ choice 0x00, selection: -> { rhs_bytecount.num_bytes } do
153
+ uint8_array 16, initial_length: 16, byte_align: 1
154
+ uint8_array :default, initial_length: :rhs_bytecount, byte_align: 1
155
155
  end
156
- ndr_fixed_byte_array :default, initial_length: :rhs_bytecount
156
+ uint8_array :default, initial_length: :rhs_bytecount, byte_align: 1
157
157
  end
158
158
  end
159
159
 
@@ -9,37 +9,91 @@ module RubySMB
9
9
  # Operation numbers
10
10
  EPT_MAP = 0x0003
11
11
 
12
+ # MS-RPCE specific error codes
13
+ STATUS_NO_ELEMENTS = 0x16C9A0D6
14
+
12
15
  require 'ruby_smb/dcerpc/epm/epm_twrt'
13
16
  require 'ruby_smb/dcerpc/epm/epm_ept_map_request'
14
17
  require 'ruby_smb/dcerpc/epm/epm_ept_map_response'
15
18
 
16
- # Retrieve the service port number given a DCERPC interface UUID
17
- # See:
18
- # [2.2.1.2.5 ept_map Method](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/ab744583-430e-4055-8901-3c6bc007e791)
19
- # [https://pubs.opengroup.org/onlinepubs/9629399/apdxo.htm](https://pubs.opengroup.org/onlinepubs/9629399/apdxo.htm)
19
+ # Map a service to a connection end point.
20
20
  #
21
- # @param uuid [String] The interface UUID
22
- # @param maj_ver [Integer] The interface Major version
23
- # @param min_ver [Integer] The interface Minor version
24
- # @param max_towers [Integer] The maximum number of elements to be returned
25
- # @return [Hash] A hash with the host and port
26
- # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a
27
- # EpmEptMap packet
28
- # @raise [RubySMB::Dcerpc::Error::EpmError] if the response error status
29
- # is not STATUS_SUCCESS
30
- def get_host_port_from_ept_mapper(uuid:, maj_ver:, min_ver:, max_towers: 1)
31
- decoded_tower = EpmDecodedTowerOctetString.new(
32
- interface_identifier: {
33
- interface: uuid,
34
- major_version: maj_ver,
35
- minor_version: min_ver
36
- },
37
- data_representation: {
38
- interface: Ndr::UUID,
39
- major_version: Ndr::VER_MAJOR,
40
- minor_version: Ndr::VER_MINOR
41
- }
42
- )
21
+ # @param uuid [String] The object UUID of the interface.
22
+ # @param maj_ver [Integer] The major version number of the interface.
23
+ # @param min_ver [Integer] The minor version number of the interface.
24
+ # @param max_towers [Integer] The maximum number of results to obtain.
25
+ # @param protocol [Symbol] The protocol of endpoint to obtain.
26
+ #
27
+ # @return [Array<Hash<Symbol,>>] The mapped endpoints. The hash keys will
28
+ # depend on the protocol that was selected but an endpoint key will
29
+ # always be present.
30
+ # @raise [NotImplementedError] Raised if the *protocol* argument is not
31
+ # supported.
32
+ def ept_map(uuid:, maj_ver:, min_ver: 0, max_towers: 1, protocol: :ncacn_ip_tcp)
33
+ interface_identifier = {
34
+ interface: uuid,
35
+ major_version: maj_ver,
36
+ minor_version: min_ver
37
+ }
38
+ data_representation = {
39
+ interface: Ndr::UUID,
40
+ major_version: Ndr::VER_MAJOR,
41
+ minor_version: Ndr::VER_MINOR
42
+ }
43
+
44
+ case protocol
45
+ when :ncacn_ip_tcp
46
+ decoded_tower = EpmDecodedTowerOctetString.new(
47
+ interface_identifier: interface_identifier,
48
+ data_representation: data_representation,
49
+ pipe_or_port: {
50
+ identifier: 7, # 0x07: DOD TCP port
51
+ pipe_or_port: 0
52
+ },
53
+ host_or_addr: {
54
+ identifier: 9, # 0x09: DOD IP v4 address (big-endian)
55
+ host_or_addr: 0
56
+ }
57
+ )
58
+
59
+ process_tower = lambda do |tower|
60
+ port = tower.pipe_or_port.pipe_or_port.value
61
+ address = IPAddr.new(tower.host_or_addr.host_or_addr.value, Socket::AF_INET)
62
+ {
63
+ port: port,
64
+ address: address,
65
+ # https://learn.microsoft.com/en-us/windows/win32/midl/ncacn-ip-tcp
66
+ endpoint: "ncacn_ip_tcp:#{address}[#{port}]"
67
+ }
68
+ end
69
+ when :ncacn_np
70
+ decoded_tower = EpmDecodedTowerOctetString.new(
71
+ interface_identifier: interface_identifier,
72
+ data_representation: data_representation,
73
+ pipe_or_port: {
74
+ identifier: 0x0f, # 0x0f: NetBIOS pipe name
75
+ pipe_or_port: [0]
76
+ },
77
+ host_or_addr: {
78
+ identifier: 0x11, # 0x11: MS NetBIOS host name
79
+ host_or_addr: [0]
80
+ }
81
+ )
82
+
83
+ process_tower = lambda do |tower|
84
+ pipe = tower.pipe_or_port.pipe_or_port[...-1].pack('C*')
85
+ host = tower.host_or_addr.host_or_addr[...-1].pack('C*')
86
+ {
87
+ pipe: pipe,
88
+ host: host,
89
+ # https://learn.microsoft.com/en-us/windows/win32/midl/ncacn-nb-nb
90
+ endpoint: "ncacn_np:#{host}[#{pipe}]"
91
+ }
92
+ end
93
+ else
94
+ raise NotImplementedError, "Unsupported protocol: #{protocol}"
95
+ end
96
+
43
97
  tower = EpmTwrt.new(decoded_tower)
44
98
  ept_map_request = EpmEptMapRequest.new(
45
99
  obj: Uuid.new,
@@ -53,21 +107,31 @@ module RubySMB
53
107
  rescue IOError
54
108
  raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading EptMapResponse'
55
109
  end
56
- unless ept_map_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
110
+
111
+ if ept_map_response.error_status == STATUS_NO_ELEMENTS
112
+ raise RubySMB::Dcerpc::Error::EpmError,
113
+ "Error returned with ept_map: "\
114
+ "(0x16c9a0d6) STATUS_NO_ELEMENTS: There are no elements that satisfy the specified search criteria."
115
+ elsif ept_map_response.error_status != WindowsError::NTStatus::STATUS_SUCCESS
57
116
  raise RubySMB::Dcerpc::Error::EpmError,
58
117
  "Error returned with ept_map: "\
59
118
  "#{WindowsError::NTStatus.find_by_retval(ept_map_response.error_status.value).join(',')}"
60
119
  end
61
- tower_binary = ept_map_response.towers[0].tower_octet_string.to_binary_s
62
- begin
63
- decoded_tower = EpmDecodedTowerOctetString.read(tower_binary)
64
- rescue IOError
65
- raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading EpmDecodedTowerOctetString'
120
+
121
+ ept_map_response.towers.map do |tower|
122
+ tower_binary = tower.tower_octet_string.to_binary_s
123
+ begin
124
+ decoded_tower = EpmDecodedTowerOctetString.read(tower_binary)
125
+ rescue IOError
126
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading EpmDecodedTowerOctetString'
127
+ end
128
+
129
+ process_tower.(decoded_tower)
66
130
  end
67
- {
68
- port: decoded_tower.pipe_or_port.pipe_or_port.to_i,
69
- host: decoded_tower.host_or_addr.host_or_addr.to_i
70
- }
131
+ end
132
+
133
+ def ept_map_endpoint(endpoint, **kwargs)
134
+ ept_map(uuid: endpoint::UUID, maj_ver: endpoint::VER_MAJOR, min_ver: endpoint::VER_MINOR, **kwargs)
71
135
  end
72
136
  end
73
137
  end
@@ -70,6 +70,16 @@ module RubySMB
70
70
  super(msg)
71
71
  end
72
72
  end
73
+
74
+ class GkdiError < DcerpcError
75
+ include RubySMB::Error::UnexpectedStatusCode::Mixin
76
+
77
+ def initialize(msg, status_code: nil)
78
+ self.status_code = status_code unless status_code.nil?
79
+
80
+ super(msg)
81
+ end
82
+ end
73
83
  end
74
84
  end
75
85
  end
@@ -0,0 +1,17 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Gkdi
4
+
5
+ # [2.2.3.1 FFC DH Key](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gkdi/f8770f01-036d-4bf6-a4cf-1bd0e3913404)
6
+ class GkdiFfcDhKey < BinData::Record
7
+ endian :little
8
+
9
+ uint8_array :magic, initial_length: 4, initial_value: [ 0x44, 0x48, 0x50, 0x42 ]
10
+ uint32 :key_length
11
+ uint8_array :field_order, initial_length: :key_length
12
+ uint8_array :generator, initial_length: :key_length
13
+ uint8_array :public_key, initial_length: :key_length
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Gkdi
4
+
5
+ # [2.2.2 FFC DH Parameters](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gkdi/e15ae269-ee21-446a-a480-de3ea243db5f)
6
+ class GkdiFfcDhParameters < BinData::Record
7
+ endian :little
8
+
9
+ uint32 :parameters_length, initial_value: -> { (key_length * 2) + offset_of(generator) }
10
+ uint8_array :magic, initial_length: 4, initial_value: [ 0x44, 0x48, 0x50, 0x4d ]
11
+ uint32 :key_length
12
+ uint8_array :field_order, initial_length: :key_length
13
+ uint8_array :generator, initial_length: :key_length
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Gkdi
4
+
5
+ # [3.1.4.1 GetKey (Opnum 0)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gkdi/4cac87a3-521e-4918-a272-240f8fabed39)
6
+ class GkdiGetKeyRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_uint32 :cb_target_sd
12
+ ndr_conf_array :pb_target_sd, type: :ndr_uint8
13
+ uuid_ptr :p_root_key_id
14
+ ndr_int32 :l0_key_id
15
+ ndr_int32 :l1_key_id
16
+ ndr_int32 :l2_key_id
17
+
18
+ def initialize_instance
19
+ super
20
+ @opnum = GKDI_GET_KEY
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Gkdi
4
+
5
+ # [3.1.4.1 GetKey (Opnum 0)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gkdi/4cac87a3-521e-4918-a272-240f8fabed39)
6
+ class GkdiGetKeyResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_uint32 :pcb_out
12
+ ndr_byte_conf_array_ptr :pbb_out
13
+ ndr_uint32 :error_status
14
+
15
+ def initialize_instance
16
+ super
17
+ @opnum = GKDI_GET_KEY
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Gkdi
4
+
5
+ # [2.2.4 Group Key Envelope](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gkdi/192c061c-e740-4aa0-ab1d-6954fb3e58f7)
6
+ class GkdiGroupKeyEnvelope < BinData::Record
7
+ endian :little
8
+
9
+ uint32 :version
10
+ uint8_array :magic, initial_length: 4, initial_value: [ 0x4b, 0x44, 0x53, 0x5b ]
11
+ uint32 :dw_flags
12
+ uint32 :l0_index
13
+ uint32 :l1_index
14
+ uint32 :l2_index
15
+ uuid :root_key_identifier
16
+ uint32 :cb_kdf_algorithm
17
+ uint32 :cb_kdf_parameters, initial_value: -> { kdf_parameters.length }
18
+ uint32 :cb_secret_agreement_algorithm
19
+ uint32 :cb_secret_agreement_parameters
20
+ uint32 :private_key_length
21
+ uint32 :public_key_length
22
+ uint32 :cb_l1_key
23
+ uint32 :cb_l2_key
24
+ uint32 :cb_domain_name
25
+ uint32 :cb_forest_name
26
+ stringz16 :kdf_algorithm
27
+ struct :kdf_parameters, only_if: -> { cb_kdf_parameters > 0 } do
28
+ uint8_array :block0, initial_length: 8, initial_value: [ 0, 0, 0, 0, 1, 0, 0, 0 ]
29
+ uint32 :length_of_hash_name, initial_value: -> { hash_algorithm_name.length }
30
+ uint8_array :block1, initial_length: 4, initial_value: [ 0, 0, 0, 0 ]
31
+ stringz16 :hash_algorithm_name
32
+ end
33
+ stringz16 :secret_agreement_algorithm
34
+ uint8_array :secret_agreement_parameters, initial_length: :cb_secret_agreement_parameters
35
+ stringz16 :domain_name
36
+ stringz16 :forest_name
37
+ uint8_array :l1_key, initial_length: 64, only_if: -> { cb_l1_key != 0 }
38
+ uint8_array :l2_key, initial_length: :l2_key_length, only_if: -> { cb_l2_key != 0 }
39
+
40
+ private
41
+
42
+ def l2_key_length
43
+ return 0 if cb_l2_key == 0
44
+ return 64 if (dw_flags & (1 << 31)) == 0
45
+
46
+ public_key_length
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,54 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Gkdi
4
+
5
+ # [2.1 Transport](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gkdi/2ca63ad2-2464-4a41-ba84-2e0270e95e86)
6
+ UUID = 'b9785960-524f-11df-8b6d-83dcded72085'
7
+ VER_MAJOR = 1
8
+ VER_MINOR = 0
9
+
10
+ # Operation numbers
11
+ GKDI_GET_KEY = 0x0000
12
+
13
+ require 'ruby_smb/dcerpc/gkdi/gkdi_get_key_request'
14
+ require 'ruby_smb/dcerpc/gkdi/gkdi_get_key_response'
15
+ require 'ruby_smb/dcerpc/gkdi/gkdi_ffc_dh_key'
16
+ require 'ruby_smb/dcerpc/gkdi/gkdi_ffc_dh_parameters'
17
+ require 'ruby_smb/dcerpc/gkdi/gkdi_group_key_envelope'
18
+
19
+ def gkdi_get_key(target_sd, root_key_id, l0_key_id, l1_key_id, l2_key_id)
20
+ target_sd = target_sd.to_binary_s if target_sd.respond_to?(:to_binary_s)
21
+
22
+ gkdi_get_key_request = GkdiGetKeyRequest.new(
23
+ cb_target_sd: target_sd.length,
24
+ pb_target_sd: target_sd.unpack('C*'),
25
+ p_root_key_id: root_key_id,
26
+ l0_key_id: l0_key_id,
27
+ l1_key_id: l1_key_id,
28
+ l2_key_id: l2_key_id
29
+ )
30
+
31
+ response = dcerpc_request(
32
+ gkdi_get_key_request,
33
+ auth_level: @auth_level,
34
+ auth_type: @auth_type
35
+ )
36
+ begin
37
+ gkdi_get_key_response = GkdiGetKeyResponse.read(response)
38
+ rescue IOError
39
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading CertServerRequestResponse'
40
+ end
41
+ unless gkdi_get_key_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS
42
+ status_code = WindowsError::Win32.find_by_retval(gkdi_get_key_response.error_status.value).first
43
+ raise RubySMB::Dcerpc::Error::GkdiError.new(
44
+ "Error returned with gkdi_get_key: #{status_code}",
45
+ status_code: status_code
46
+ )
47
+ end
48
+
49
+ GkdiGroupKeyEnvelope.read(gkdi_get_key_response.pbb_out.snapshot.pack('C*'))
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -124,6 +124,9 @@ module RubySMB
124
124
  lsar_close_handle_request Lsarpc::LSAR_CLOSE_HANDLE
125
125
  lsar_lookup_sids_request Lsarpc::LSAR_LOOKUP_SIDS
126
126
  end
127
+ choice 'Gkdi', selection: -> { opnum } do
128
+ gkdi_get_key_request Gkdi::GKDI_GET_KEY
129
+ end
127
130
  string :default
128
131
  end
129
132
 
@@ -522,16 +522,25 @@ module RubySMB
522
522
  # [2.2.10.1 USER_PROPERTIES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/8263e7ab-aba9-43d2-8a36-3a9cb2dd3dad)
523
523
  class UserProperties < BinData::Record
524
524
  endian :little
525
+ hide :bytes_remaining
525
526
 
526
527
  uint32 :reserved1
527
- uint32 :struct_length, initial_value: -> { num_bytes - 12 }
528
+ # Length, in bytes, of the entire structure, starting from the :reserved4 field (offset 12):
529
+ uint32 :struct_length, value: -> { num_bytes - 12}
528
530
  uint16 :reserved2
529
531
  uint16 :reserved3
530
532
  string :reserved4, length: 96
531
533
  uint16 :property_signature, initial_value: 0x50
532
- uint16 :property_count, initial_value: -> { user_properties.size }, onlyif: -> { struct_length > 111 }
533
- array :user_properties, type: :user_property, initial_length: :property_count, onlyif: :property_count?
534
+ count_bytes_remaining :bytes_remaining
535
+ # When there are zero `user_property` elements in the `:user_properties` field, this field MUST be omitted;
536
+ # the resultant `UserProperties` structure has a constant size of 0x6F bytes.
537
+ uint16 :property_count, value: -> { user_properties.size }, onlyif: :display_user_properties?
538
+ array :user_properties, type: :user_property, read_until: -> { array.size == property_count }, onlyif: :display_user_properties?
534
539
  uint8 :reserved5
540
+
541
+ def display_user_properties?
542
+ (bytes_remaining > 1 && reading?) || user_properties.size > 0
543
+ end
535
544
  end
536
545
 
537
546
  # [2.2.10.7 KERB_KEY_DATA_NEW](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/447520a5-e1cc-48cc-8fdc-b90db57f7eac)
@@ -28,6 +28,7 @@ module RubySMB
28
28
  DCE_C_AUTHZ_DCE = 2
29
29
 
30
30
  require 'windows_error/win32'
31
+ require 'ruby_smb/dcerpc/client'
31
32
  require 'ruby_smb/dcerpc/error'
32
33
  require 'ruby_smb/dcerpc/fault'
33
34
  require 'ruby_smb/dcerpc/uuid'
@@ -50,6 +51,7 @@ module RubySMB
50
51
  require 'ruby_smb/dcerpc/icpr'
51
52
  require 'ruby_smb/dcerpc/efsrpc'
52
53
  require 'ruby_smb/dcerpc/lsarpc'
54
+ require 'ruby_smb/dcerpc/gkdi'
53
55
  require 'ruby_smb/dcerpc/request'
54
56
  require 'ruby_smb/dcerpc/response'
55
57
  require 'ruby_smb/dcerpc/rpc_auth3'
@@ -189,6 +191,8 @@ module RubySMB
189
191
  # @raise [ArgumentError] if `:auth_type` is unknown
190
192
  # @raise [NotImplementedError] if `:auth_type` is not implemented (yet)
191
193
  def bind(options={})
194
+ options = options.merge(endpoint: @endpoint) if !options[:endpoint] && defined?(:@endpoint) && @endpoint
195
+
192
196
  @call_id ||= 1
193
197
  bind_req = Bind.new(options)
194
198
  bind_req.pdu_header.call_id = @call_id
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '3.3.13'.freeze
2
+ VERSION = '3.3.15'.freeze
3
3
  end
@@ -1,8 +1,9 @@
1
1
  require 'ruby_smb/dcerpc/client'
2
+ require 'ipaddr'
2
3
 
3
4
  RSpec.describe RubySMB::Dcerpc::Client do
4
- it 'includes the RubySMB::Dcerpc::Epm class' do
5
- expect(described_class < RubySMB::Dcerpc::Epm).to be true
5
+ it 'includes the RubySMB::PeerInfo class' do
6
+ expect(described_class < RubySMB::PeerInfo).to be true
6
7
  end
7
8
 
8
9
  let(:host) { '1.2.3.4' }
@@ -75,42 +76,38 @@ RSpec.describe RubySMB::Dcerpc::Client do
75
76
  end
76
77
 
77
78
  context 'without TCP port' do
78
- let(:host_port) { {host: '0.9.8.7', port: 999} }
79
+ let(:host_port) { {host: '192.0.2.1', port: 999} }
80
+ let(:epm_client) { double('EPM DCERPC Client') }
79
81
  let(:epm_tcp_socket) { double('EPM TcpSocket') }
80
82
  before :example do
81
- allow(TCPSocket).to receive(:new).with(host, 135).and_return(epm_tcp_socket)
82
- allow(client).to receive(:bind)
83
- allow(client).to receive(:get_host_port_from_ept_mapper).and_return(host_port)
84
- allow(epm_tcp_socket).to receive(:close)
85
- end
86
-
87
- it 'connects to port 135' do
88
- client.connect
89
- expect(TCPSocket).to have_received(:new).with(host, 135)
83
+ allow(described_class).to receive(:new).with(host, endpoint).and_call_original
84
+ allow(described_class).to receive(:new).with(host, RubySMB::Dcerpc::Epm, {:read_timeout => 30}).and_return(epm_client)
85
+ allow(epm_client).to receive(:connect)
86
+ allow(epm_client).to receive(:bind)
87
+ allow(epm_client).to receive(:ept_map_endpoint).with(endpoint).and_return(
88
+ [{address: IPAddr.new(host_port[:host], Socket::AF_INET), port: host_port[:port]}]
89
+ )
90
+ allow(epm_client).to receive(:close)
90
91
  end
91
92
 
92
- it 'binds to the Endpoint Mapper endpoint' do
93
+ it 'creates a new client bound to the Endpoint Mapper endpoint' do
93
94
  client.connect
94
- expect(client).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Epm)
95
+ expect(described_class).to have_received(:new).with(host, RubySMB::Dcerpc::Epm, {:read_timeout => 30})
95
96
  end
96
97
 
97
98
  it 'gets host and port information from the Endpoint Mapper' do
98
99
  client.connect
99
- expect(client).to have_received(:get_host_port_from_ept_mapper).with(
100
- uuid: endpoint::UUID,
101
- maj_ver: endpoint::VER_MAJOR,
102
- min_ver: endpoint::VER_MINOR
103
- )
100
+ expect(epm_client).to have_received(:ept_map_endpoint).with(endpoint)
104
101
  end
105
102
 
106
- it 'closes the EPM socket' do
103
+ it 'closes the EPM client socket' do
107
104
  client.connect
108
- expect(epm_tcp_socket).to have_received(:close)
105
+ expect(epm_client).to have_received(:close)
109
106
  end
110
107
 
111
108
  it 'connects to the endpoint and returns the socket' do
112
109
  expect(client.connect).to eq(tcp_socket)
113
- expect(TCPSocket).to have_received(:new).with(host, 999)
110
+ expect(TCPSocket).to have_received(:new).with(host, host_port[:port])
114
111
  end
115
112
  end
116
113
  end
@@ -330,7 +327,7 @@ RSpec.describe RubySMB::Dcerpc::Client do
330
327
 
331
328
  it 'sends an auth3 request' do
332
329
  client.bind(**kwargs)
333
- expect(client).to have_received(:auth_provider_complete_handshake).with(bindack_response, auth_type: kwargs[:auth_type], auth_level: kwargs[:auth_level])
330
+ expect(client).to have_received(:auth_provider_complete_handshake).with(bindack_response, auth_type: kwargs[:auth_type], auth_level: kwargs[:auth_level], endpoint: endpoint)
334
331
  end
335
332
  end
336
333
  end
@@ -0,0 +1,76 @@
1
+ RSpec.describe RubySMB::Dcerpc::Samr::UserProperties do
2
+ describe '#read' do
3
+ context 'when reading a structure with no user properties' do
4
+ let(:binary) { [ 0, 0x63, 0, 0, 0x50, 0].pack('L<L<S<S<x96<SC') }
5
+ let(:subject) { described_class.read(binary) }
6
+
7
+ it 'does not include the property_count' do
8
+ expect(subject.property_count?).to be_falsey
9
+ expect(subject.snapshot).to_not include(:property_count)
10
+ end
11
+
12
+ it 'does not include the user_properties' do
13
+ expect(subject.user_properties?).to be_falsey
14
+ expect(subject.snapshot).to_not include(:user_properties)
15
+ end
16
+
17
+ it 'serializes to the value that was read' do
18
+ expect(subject.to_binary_s).to eq(binary)
19
+ end
20
+ end
21
+
22
+ context 'when reading a structure with two user properties' do
23
+ let(:user_property1) { RubySMB::Dcerpc::Samr::UserProperty.new(property_name: 'key1', property_value: 'value1') }
24
+ let(:user_property2) { RubySMB::Dcerpc::Samr::UserProperty.new(property_name: 'key2', property_value: 'value2') }
25
+ let(:user_properties) { user_property1.to_binary_s + user_property2.to_binary_s }
26
+ let(:binary) { [ 0, 0x63 + 2 + user_properties.length, 0, 0, 0x50, 2].pack('L<L<S<S<x96<S<S') + user_properties + "\x00".b }
27
+ let(:subject) { described_class.read(binary) }
28
+
29
+ it 'includes the property_count' do
30
+ expect(subject.property_count?).to be_truthy
31
+ expect(subject.property_count).to eq(2)
32
+ expect(subject.snapshot).to include(:property_count)
33
+ end
34
+
35
+ it 'includes the user_properties' do
36
+ expect(subject.user_properties?).to be_truthy
37
+ expect(subject.user_properties).to eq([user_property1, user_property2])
38
+ expect(subject.snapshot).to include(:user_properties)
39
+ end
40
+
41
+ it 'serializes to the value that was read' do
42
+ expect(subject.to_binary_s).to eq(binary)
43
+ end
44
+
45
+ context 'when #user_properties is cleared' do
46
+ before(:each) { subject.user_properties.clear }
47
+
48
+ it 'does not include the property_count' do
49
+ expect(subject.property_count?).to be_falsey
50
+ expect(subject.snapshot).to_not include(:property_count)
51
+ end
52
+
53
+ it 'does not include the user_properties' do
54
+ expect(subject.user_properties?).to be_falsey
55
+ expect(subject.snapshot).to_not include(:user_properties)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#initialize' do
62
+ let(:subject) { described_class.new }
63
+
64
+ it 'initializes #struct_length to 0x63' do
65
+ expect(subject.struct_length).to eq(0x63)
66
+ end
67
+
68
+ it 'initializes #property_signature to 0x50' do
69
+ expect(subject.property_signature).to eq(0x50)
70
+ end
71
+
72
+ it 'does not include user_properties' do
73
+ expect(subject.user_properties).to be_empty
74
+ end
75
+ end
76
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_smb
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.13
4
+ version: 3.3.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -10,36 +10,10 @@ authors:
10
10
  - Dev Mohanty
11
11
  - Christophe De La Fuente
12
12
  - Spencer McIntyre
13
- autorequire:
13
+ autorequire:
14
14
  bindir: bin
15
- cert_chain:
16
- - |
17
- -----BEGIN CERTIFICATE-----
18
- MIIERDCCAqygAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBttc2Zk
19
- ZXYvREM9bWV0YXNwbG9pdC9EQz1jb20wHhcNMjMxMDMwMTYwNDI1WhcNMjUxMDI5
20
- MTYwNDI1WjAmMSQwIgYDVQQDDBttc2ZkZXYvREM9bWV0YXNwbG9pdC9EQz1jb20w
21
- ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDZN/EKv+yVjwiKWvjAVhjF
22
- aWNYI0E9bJ5d1qKd29omRYX9a+OOKBCu5+394fyF5RjwU4mYGr2iopX9ixRJrWXH
23
- ojs70tEvV1CmvP9rhz7JKzQQoJOkinrz4d+StIylxVxVdgm7DeiB3ruTwvl7qKUv
24
- piWzhrBFiVU6XIEAwq6wNEmnv2D+Omyf4h0Tf99hc6G0QmBnU3XydqvnZ+AzUbBV
25
- 24RH3+NQoigLbvK4M5aOeYhk19di58hznebOw6twHzNczshrBeMFQp985ScNgsvF
26
- rL+7HNNwpcpngERwZfzDNn7iYN5X3cyvTcykShtsuPMa5zXsYo42LZrsTF87DW38
27
- D8sxL6Dgdqu25Mltdw9m+iD4rHSfb1KJYEoNO+WwBJLO2Y4d6G1CR66tVeWsZspb
28
- zneOVC+sDuil7hOm+6a7Y2yrrRyT6IfL/07DywjPAIRUp5+Jn8ZrkWRNo2AOwWBG
29
- k5gz7SfJPHuyVnPlxoMA0MTFCUnnnbyHu882TGoJGgMCAwEAAaN9MHswCQYDVR0T
30
- BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFIQfNa4E889ZE334cwU7eNu2hScH
31
- MCAGA1UdEQQZMBeBFW1zZmRldkBtZXRhc3Bsb2l0LmNvbTAgBgNVHRIEGTAXgRVt
32
- c2ZkZXZAbWV0YXNwbG9pdC5jb20wDQYJKoZIhvcNAQELBQADggGBAMfzvKcV27p7
33
- pctmpW2JmIXLMrjNLyGJAxELH/t9pJueXdga7uj2fJkYQDbwGw5x4MGyFqhqJLH4
34
- l/qsUF3PyAXDTSWLVaqXQVWO+IIHxecG0XjPXTNudzMU0hzqbqiBKvsW7/a3V5BP
35
- SWlFzrFkoXWlPouFpoakyYMJjpW4SGdPzRv7pM4OhXtkXpHiRvx5985FrHgHlI89
36
- NSIuIUbp8zqk4hP1i9MV0Lc/vTf2gOmo+RHnjqG1NiYfMCYyY/Mcd4W36kGOl468
37
- I8VDTwgCufkAzFu7BJ5yCOueqtDcuq+d3YhAyU7NI4+Ja8EwazOnB+07sWhKpg7z
38
- yuQ1mWYPmZfVQpoSVv1CvXsoqJYXVPBBLOacKKSj8ArVG6pPn9Bej7IOQdblaFjl
39
- DgscAao7wB3xW2BWEp1KnaDWkf1x9ttgoBEYyuYwU7uatB67kBQG1PKvLt79wHvz
40
- Dxs+KOjGbBRfMnPgVGYkORKVrZIwlaboHbDKxcVW5xv+oZc7KYXWGg==
41
- -----END CERTIFICATE-----
42
- date: 2024-12-06 00:00:00.000000000 Z
15
+ cert_chain: []
16
+ date: 2025-04-30 00:00:00.000000000 Z
43
17
  dependencies:
44
18
  - !ruby/object:Gem::Dependency
45
19
  name: redcarpet
@@ -209,6 +183,7 @@ files:
209
183
  - examples/enum_domain_users.rb
210
184
  - examples/enum_registry_key.rb
211
185
  - examples/enum_registry_values.rb
186
+ - examples/epm_client.rb
212
187
  - examples/file_server.rb
213
188
  - examples/get_computer_info.rb
214
189
  - examples/list_directory.rb
@@ -279,6 +254,12 @@ files:
279
254
  - lib/ruby_smb/dcerpc/epm/epm_twrt.rb
280
255
  - lib/ruby_smb/dcerpc/error.rb
281
256
  - lib/ruby_smb/dcerpc/fault.rb
257
+ - lib/ruby_smb/dcerpc/gkdi.rb
258
+ - lib/ruby_smb/dcerpc/gkdi/gkdi_ffc_dh_key.rb
259
+ - lib/ruby_smb/dcerpc/gkdi/gkdi_ffc_dh_parameters.rb
260
+ - lib/ruby_smb/dcerpc/gkdi/gkdi_get_key_request.rb
261
+ - lib/ruby_smb/dcerpc/gkdi/gkdi_get_key_response.rb
262
+ - lib/ruby_smb/dcerpc/gkdi/gkdi_group_key_envelope.rb
282
263
  - lib/ruby_smb/dcerpc/icpr.rb
283
264
  - lib/ruby_smb/dcerpc/icpr/cert_server_request_request.rb
284
265
  - lib/ruby_smb/dcerpc/icpr/cert_server_request_response.rb
@@ -746,6 +727,7 @@ files:
746
727
  - spec/lib/ruby_smb/dcerpc/samr/samr_set_information_user2_response_spec.rb
747
728
  - spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request_spec.rb
748
729
  - spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response_spec.rb
730
+ - spec/lib/ruby_smb/dcerpc/samr/user_properties_spec.rb
749
731
  - spec/lib/ruby_smb/dcerpc/samr_spec.rb
750
732
  - spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb
751
733
  - spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb
@@ -995,7 +977,7 @@ homepage: https://github.com/rapid7/ruby_smb
995
977
  licenses:
996
978
  - BSD-3-clause
997
979
  metadata: {}
998
- post_install_message:
980
+ post_install_message:
999
981
  rdoc_options: []
1000
982
  require_paths:
1001
983
  - lib
@@ -1010,8 +992,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1010
992
  - !ruby/object:Gem::Version
1011
993
  version: '0'
1012
994
  requirements: []
1013
- rubygems_version: 3.5.22
1014
- signing_key:
995
+ rubygems_version: 3.4.19
996
+ signing_key:
1015
997
  specification_version: 4
1016
998
  summary: A pure Ruby implementation of the SMB Protocol Family
1017
999
  test_files:
@@ -1096,6 +1078,7 @@ test_files:
1096
1078
  - spec/lib/ruby_smb/dcerpc/samr/samr_set_information_user2_response_spec.rb
1097
1079
  - spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request_spec.rb
1098
1080
  - spec/lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response_spec.rb
1081
+ - spec/lib/ruby_smb/dcerpc/samr/user_properties_spec.rb
1099
1082
  - spec/lib/ruby_smb/dcerpc/samr_spec.rb
1100
1083
  - spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb
1101
1084
  - spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb
checksums.yaml.gz.sig DELETED
Binary file
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
Binary file