ruby_smb 2.0.1 → 2.0.6

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.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -1
  4. data/examples/anonymous_auth.rb +3 -3
  5. data/examples/append_file.rb +10 -8
  6. data/examples/authenticate.rb +9 -5
  7. data/examples/delete_file.rb +8 -6
  8. data/examples/enum_registry_key.rb +5 -4
  9. data/examples/enum_registry_values.rb +5 -4
  10. data/examples/list_directory.rb +8 -6
  11. data/examples/negotiate_with_netbios_service.rb +9 -5
  12. data/examples/net_share_enum_all.rb +6 -4
  13. data/examples/pipes.rb +11 -12
  14. data/examples/query_service_status.rb +64 -0
  15. data/examples/read_file.rb +8 -6
  16. data/examples/read_registry_key_value.rb +6 -5
  17. data/examples/rename_file.rb +9 -7
  18. data/examples/tree_connect.rb +7 -5
  19. data/examples/write_file.rb +9 -7
  20. data/lib/ruby_smb/client.rb +81 -48
  21. data/lib/ruby_smb/client/authentication.rb +5 -10
  22. data/lib/ruby_smb/client/echo.rb +2 -4
  23. data/lib/ruby_smb/client/negotiation.rb +21 -14
  24. data/lib/ruby_smb/client/tree_connect.rb +2 -4
  25. data/lib/ruby_smb/client/utils.rb +16 -10
  26. data/lib/ruby_smb/client/winreg.rb +1 -1
  27. data/lib/ruby_smb/dcerpc.rb +4 -0
  28. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  29. data/lib/ruby_smb/dcerpc/ndr.rb +306 -44
  30. data/lib/ruby_smb/dcerpc/netlogon.rb +101 -0
  31. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +28 -0
  32. data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +26 -0
  33. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +27 -0
  34. data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +23 -0
  35. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +25 -0
  36. data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +24 -0
  37. data/lib/ruby_smb/dcerpc/request.rb +19 -0
  38. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
  39. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
  40. data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
  41. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
  42. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
  43. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
  44. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
  45. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
  46. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
  47. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
  48. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
  49. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
  50. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
  51. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
  52. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
  53. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
  54. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
  55. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
  56. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
  57. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
  58. data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
  59. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
  60. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
  61. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
  62. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
  63. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
  64. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
  65. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
  66. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
  67. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
  68. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
  69. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
  70. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  71. data/lib/ruby_smb/dispatcher/socket.rb +1 -1
  72. data/lib/ruby_smb/error.rb +21 -5
  73. data/lib/ruby_smb/field/stringz16.rb +17 -1
  74. data/lib/ruby_smb/generic_packet.rb +11 -1
  75. data/lib/ruby_smb/nbss/session_header.rb +4 -4
  76. data/lib/ruby_smb/smb1/file.rb +10 -25
  77. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
  78. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
  79. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
  80. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
  81. data/lib/ruby_smb/smb1/pipe.rb +8 -6
  82. data/lib/ruby_smb/smb1/tree.rb +13 -9
  83. data/lib/ruby_smb/smb2/file.rb +33 -33
  84. data/lib/ruby_smb/smb2/pipe.rb +9 -6
  85. data/lib/ruby_smb/smb2/tree.rb +21 -11
  86. data/lib/ruby_smb/version.rb +1 -1
  87. data/spec/lib/ruby_smb/client_spec.rb +195 -101
  88. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
  89. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +69 -0
  90. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response_spec.rb +53 -0
  91. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +69 -0
  92. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response_spec.rb +37 -0
  93. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +45 -0
  94. data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +37 -0
  95. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
  96. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
  97. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
  98. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
  99. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
  100. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
  101. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
  102. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
  103. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
  104. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
  105. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
  106. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
  107. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
  108. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
  109. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
  110. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
  111. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
  112. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
  113. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
  114. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
  115. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
  116. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
  117. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
  118. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
  119. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
  120. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
  121. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
  122. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
  123. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
  124. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
  125. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
  126. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +227 -41
  127. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
  128. data/spec/lib/ruby_smb/error_spec.rb +34 -5
  129. data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
  130. data/spec/lib/ruby_smb/generic_packet_spec.rb +7 -0
  131. data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
  132. data/spec/lib/ruby_smb/smb1/file_spec.rb +2 -4
  133. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
  134. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
  135. data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
  136. data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
  137. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +30 -5
  138. data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
  139. data/spec/lib/ruby_smb/smb2/file_spec.rb +61 -9
  140. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +9 -5
  141. data/spec/lib/ruby_smb/smb2/tree_spec.rb +58 -1
  142. metadata +91 -2
  143. metadata.gz.sig +0 -0
@@ -0,0 +1,28 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Netlogon
6
+
7
+ # [3.5.4.4.2 NetrServerAuthenticate3 (Opnum 26)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/3a9ed16f-8014-45ae-80af-c0ecb06e2db9)
8
+ class NetrServerAuthenticate3Request < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ logonsrv_handle :primary_name
14
+ ndr_string :account_name
15
+ netlogon_secure_channel_type :secure_channel_type
16
+ ndr_string :computer_name
17
+ netlogon_credential :client_credential
18
+ uint32 :flags
19
+
20
+ def initialize_instance
21
+ super
22
+ @opnum = NETR_SERVER_AUTHENTICATE3
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Netlogon
6
+
7
+ # [3.5.4.4.2 NetrServerAuthenticate3 (Opnum 26)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/3a9ed16f-8014-45ae-80af-c0ecb06e2db9)
8
+ class NetrServerAuthenticate3Response < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ netlogon_credential :server_credential
14
+ uint32 :negotiate_flags
15
+ uint32 :account_rid
16
+ uint32 :error_status
17
+
18
+ def initialize_instance
19
+ super
20
+ @opnum = NETR_SERVER_AUTHENTICATE3
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Netlogon
6
+
7
+ # [3.5.4.4.5 NetrServerPasswordSet2 (Opnum 30)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/14b020a8-0bcf-4af5-ab72-cc92bc6b1d81)
8
+ class NetrServerPasswordSet2Request < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ logonsrv_handle :primary_name
14
+ ndr_string :account_name
15
+ netlogon_secure_channel_type :secure_channel_type
16
+ ndr_string :computer_name
17
+ netlogon_authenticator :authenticator
18
+ ndr_fixed_byte_array :clear_new_password, length: 516 # this is an encrypted NL_TRUST_PASSWORD
19
+
20
+ def initialize_instance
21
+ super
22
+ @opnum = Netlogon::NETR_SERVER_PASSWORD_SET2
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Netlogon
6
+
7
+ # [3.5.4.4.5 NetrServerPasswordSet2 (Opnum 30)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/14b020a8-0bcf-4af5-ab72-cc92bc6b1d81)
8
+ class NetrServerPasswordSet2Response < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ netlogon_authenticator :return_authenticator
14
+ uint32 :error_status
15
+
16
+ def initialize_instance
17
+ super
18
+ @opnum = Netlogon::NETR_SERVER_PASSWORD_SET2
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Netlogon
6
+
7
+ # [3.5.4.4.1 NetrServerReqChallenge (Opnum 4)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/5ad9db9f-7441-4ce5-8c7b-7b771e243d32)
8
+ class NetrServerReqChallengeRequest < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ logonsrv_handle :primary_name
14
+ ndr_string :computer_name
15
+ netlogon_credential :client_challenge
16
+
17
+ def initialize_instance
18
+ super
19
+ @opnum = NETR_SERVER_REQ_CHALLENGE
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Netlogon
6
+
7
+ # [3.5.4.4.1 NetrServerReqChallenge (Opnum 4)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/5ad9db9f-7441-4ce5-8c7b-7b771e243d32)
8
+ class NetrServerReqChallengeResponse < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ netlogon_credential :server_challenge
14
+ uint32 :error_status
15
+
16
+ def initialize_instance
17
+ super
18
+ @opnum = NETR_SERVER_REQ_CHALLENGE
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -27,12 +27,31 @@ module RubySMB
27
27
  open_key_request RubySMB::Dcerpc::Winreg::REG_OPEN_KEY
28
28
  query_info_key_request RubySMB::Dcerpc::Winreg::REG_QUERY_INFO_KEY
29
29
  query_value_request RubySMB::Dcerpc::Winreg::REG_QUERY_VALUE
30
+ create_key_request RubySMB::Dcerpc::Winreg::REG_CREATE_KEY
31
+ save_key_request RubySMB::Dcerpc::Winreg::REG_SAVE_KEY
30
32
  string :default
31
33
  end
34
+ choice 'Netlogon', selection: -> { opnum } do
35
+ netr_server_authenticate3_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_AUTHENTICATE3
36
+ netr_server_password_set2_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_PASSWORD_SET2
37
+ netr_server_req_challenge_request RubySMB::Dcerpc::Netlogon::NETR_SERVER_REQ_CHALLENGE
38
+ string :default
39
+ end
32
40
  choice 'Srvsvc', selection: -> { opnum } do
33
41
  net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host rescue '' }
34
42
  string :default
35
43
  end
44
+ choice 'Svcctl', selection: -> { opnum } do
45
+ open_sc_manager_w_request RubySMB::Dcerpc::Svcctl::OPEN_SC_MANAGER_W
46
+ open_service_w_request RubySMB::Dcerpc::Svcctl::OPEN_SERVICE_W
47
+ query_service_status_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_STATUS
48
+ query_service_config_w_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_CONFIG_W
49
+ change_service_config_w_request RubySMB::Dcerpc::Svcctl::CHANGE_SERVICE_CONFIG_W
50
+ start_service_w_request RubySMB::Dcerpc::Svcctl::START_SERVICE_W
51
+ control_service_request RubySMB::Dcerpc::Svcctl::CONTROL_SERVICE
52
+ close_service_handle_request RubySMB::Dcerpc::Svcctl::CLOSE_SERVICE_HANDLE
53
+ string :default
54
+ end
36
55
  string :default
37
56
  end
38
57
 
@@ -0,0 +1,34 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+
4
+ # This class represents a RPC_SECURITY_DESCRIPTOR structure as defined in
5
+ # [2.2.8 RPC_SECURITY_DESCRIPTOR](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/9729e781-8eb9-441b-82ca-e898f98d29c2)
6
+ class RpcSecurityDescriptor < BinData::Record
7
+ endian :little
8
+
9
+ ndr_lp_byte_array :lp_security_descriptor
10
+ uint32 :cb_in_security_descriptor
11
+ uint32 :cb_out_security_descriptor
12
+ end
13
+
14
+ # This class represents a RPC_SECURITY_ATTRIBUTES structure as defined in
15
+ # [2.2.7 RPC_SECURITY_ATTRIBUTES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc37b8cf-8c94-4804-ad53-0aaf5eaf0ecb)
16
+ class RpcSecurityAttributes < BinData::Record
17
+ endian :little
18
+
19
+ uint32 :n_length
20
+ rpc_security_descriptor :rpc_security_descriptor
21
+ uint8 :b_inheritHandle
22
+ end
23
+
24
+ # This class represents a pointer to a RPC_SECURITY_ATTRIBUTES structure as defined in
25
+ # [2.2.7 RPC_SECURITY_ATTRIBUTES](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc37b8cf-8c94-4804-ad53-0aaf5eaf0ecb)
26
+ class PrpcSecurityAttributes < Ndr::NdrPointer
27
+ endian :little
28
+
29
+ rpc_security_attributes :referent, onlyif: -> { self.referent_id != 0 }
30
+ end
31
+
32
+ end
33
+ end
34
+
@@ -8,8 +8,8 @@ module RubySMB
8
8
  class RrpUnicodeString < BinData::Primitive
9
9
  endian :little
10
10
 
11
- uint16 :buffer_length, initial_value: -> { buffer.to_s == "\0" ? 0 : buffer.actual_count * 2 }
12
- uint16 :maximum_length, initial_value: -> { buffer.to_s == "\0" ? 0 : buffer.max_count * 2 }
11
+ uint16 :buffer_length
12
+ uint16 :maximum_length
13
13
  ndr_lp_str :buffer
14
14
 
15
15
  def get
@@ -18,16 +18,19 @@ module RubySMB
18
18
 
19
19
  def set(buf)
20
20
  self.buffer = buf
21
- self.buffer_length = self.buffer.to_s == "\0" ? 0 : self.buffer.actual_count * 2
22
- self.maximum_length = self.buffer.to_s == "\0" ? 0 : self.buffer.max_count * 2
21
+ self.buffer_length = self.buffer == :null ? 0 : self.buffer.referent.actual_count * 2
22
+ # Don't reset maximum_length if the buffer is NULL to make sure we can
23
+ # set it independently of the buffer size
24
+ return if self.maximum_length > 0 && self.buffer == :null
25
+ self.maximum_length = self.buffer.referent.max_count * 2
23
26
  end
24
27
  end
25
28
 
26
29
  # A pointer to a RRP_UNICODE_STRING structure
27
- class PrrpUnicodeString < Ndr::NdrTopLevelFullPointer
30
+ class PrrpUnicodeString < Ndr::NdrPointer
28
31
  endian :little
29
32
 
30
- rrp_unicode_string :referent, onlyif: -> { !is_a_null_pointer? }
33
+ rrp_unicode_string :referent, onlyif: -> { self.referent_id != 0 }
31
34
  end
32
35
 
33
36
  end
@@ -0,0 +1,479 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Svcctl
4
+
5
+ UUID = '367abb81-9844-35f1-ad32-98f038001003'
6
+ VER_MAJOR = 2
7
+ VER_MINOR = 0
8
+
9
+ # Operation numbers
10
+ CLOSE_SERVICE_HANDLE = 0x0000
11
+ CONTROL_SERVICE = 0x0001
12
+ QUERY_SERVICE_STATUS = 0x0006
13
+ CHANGE_SERVICE_CONFIG_W = 0x000B
14
+ OPEN_SC_MANAGER_W = 0x000F
15
+ OPEN_SERVICE_W = 0x0010
16
+ QUERY_SERVICE_CONFIG_W = 0x0011
17
+ START_SERVICE_W = 0x0013
18
+
19
+
20
+ class ScRpcHandle < Ndr::NdrContextHandle; end
21
+
22
+
23
+ #################################
24
+ # Constants #
25
+ #################################
26
+
27
+
28
+ ################
29
+ # Service Access
30
+ # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/0d7a7011-9f41-470d-ad52-8535b47ac282
31
+
32
+ # In addition to all access rights in this table, SERVICE_ALL_ACCESS
33
+ # includes Delete (DE), Read Control (RC), Write DACL (WD), and Write
34
+ # Owner (WO) access, as specified in ACCESS_MASK (section 2.4.3) of
35
+ # [MS-DTYP].
36
+ SERVICE_ALL_ACCESS = 0x000F01FF
37
+ # Required to change the configuration of a service.
38
+ SERVICE_CHANGE_CONFIG = 0x00000002
39
+ # Required to enumerate the services installed on the server.
40
+ SERVICE_ENUMERATE_DEPENDENTS = 0x00000008
41
+ # Required to request immediate status from the service.
42
+ SERVICE_INTERROGATE = 0x00000080
43
+ # Required to pause or continue the service.
44
+ SERVICE_PAUSE_CONTINUE = 0x00000040
45
+ # Required to query the service configuration.
46
+ SERVICE_QUERY_CONFIG = 0x00000001
47
+ # Required to request the service status.
48
+ SERVICE_QUERY_STATUS = 0x00000004
49
+ # Required to start the service.
50
+ SERVICE_START = 0x00000010
51
+ # Required to stop the service.
52
+ SERVICE_STOP = 0x00000020
53
+ # Required to specify a user-defined control code.
54
+ SERVICE_USER_DEFINED_CONTROL = 0x00000100
55
+ # Required for a service to set its status.
56
+ SERVICE_SET_STATUS = 0x00008000
57
+
58
+ # Specific access types for Service Control Manager object:
59
+
60
+ # Required to lock the SCM database.
61
+ SC_MANAGER_LOCK = 0x00000008
62
+ # Required for a service to be created.
63
+ SC_MANAGER_CREATE_SERVICE = 0x00000002
64
+ # Required to enumerate a service.
65
+ SC_MANAGER_ENUMERATE_SERVICE = 0x00000004
66
+ # Required to connect to the SCM.
67
+ SC_MANAGER_CONNECT = 0x00000001
68
+ # Required to query the lock status of the SCM database.
69
+ SC_MANAGER_QUERY_LOCK_STATUS = 0x00000010
70
+ # Required to call the RNotifyBootConfigStatus method.
71
+ SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00000020
72
+
73
+
74
+ ##############
75
+ # Service Type
76
+
77
+ # A driver service. These are services that manage devices on the system.
78
+ SERVICE_KERNEL_DRIVER = 0x00000001
79
+ # A file system driver service. These are services that manage file
80
+ # systems on the system.
81
+ SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
82
+ # A service that runs in its own process.
83
+ SERVICE_WIN32_OWN_PROCESS = 0x00000010
84
+ # A service that shares a process with other services.
85
+ SERVICE_WIN32_SHARE_PROCESS = 0x00000020
86
+
87
+ # The service can interact with the desktop. Only
88
+ # SERVICE_WIN32_OWN_PROCESS and SERVICE_INTERACTIVE_PROCESS OR
89
+ # SERVICE_WIN32_SHARE_PROCESS and SERVICE_INTERACTIVE_PROCESS can be
90
+ # combined.
91
+ SERVICE_INTERACTIVE_PROCESS = 0x00000100
92
+
93
+ ####################
94
+ # Service Start Type
95
+
96
+ # Starts the driver service when the system boots up. This value is valid
97
+ # only for driver services.
98
+ SERVICE_BOOT_START = 0x00000000
99
+ # Starts the driver service when the system boots up. This value is valid
100
+ # only for driver services. The services marked SERVICE_SYSTEM_START are
101
+ # started after all SERVICE_BOOT_START services have been started.
102
+ SERVICE_SYSTEM_START = 0x00000001
103
+ # A service started automatically by the SCM during system startup.
104
+ SERVICE_AUTO_START = 0x00000002
105
+ # Starts the service when a client requests the SCM to start the service.
106
+ SERVICE_DEMAND_START = 0x00000003
107
+ # A service that cannot be started. Attempts to start the service result
108
+ # in the error code ERROR_SERVICE_DISABLED.
109
+ SERVICE_DISABLED = 0x00000004
110
+
111
+
112
+ #######################
113
+ # Service Error Control
114
+
115
+ # The severity of the error if this service fails to start during startup
116
+ # and the action the SCM takes if failure occurs.
117
+
118
+ # The SCM ignores the error and continues the startup operation.
119
+ SERVICE_ERROR_IGNORE = 0x00000000
120
+ # The SCM logs the error in the event log and continues the startup
121
+ # operation.
122
+ SERVICE_ERROR_NORMAL = 0x00000001
123
+ # The SCM logs the error in the event log. If the last-known good
124
+ # configuration is being started, the startup operation continues.
125
+ # Otherwise, the system is restarted with the last-known good
126
+ # configuration.
127
+ SERVICE_ERROR_SEVERE = 0x00000002
128
+ # The SCM SHOULD log the error in the event log if possible. If the
129
+ # last-known good configuration is being started, the startup operation
130
+ # fails. Otherwise, the system is restarted with the last-known good
131
+ # configuration.
132
+ SERVICE_ERROR_CRITICAL = 0x00000003
133
+
134
+
135
+ #########################################
136
+ # Change Service Config specific constant
137
+
138
+ # Service type, start or error control does not change.
139
+ SERVICE_NO_CHANGE = 0xFFFFFFFF
140
+
141
+
142
+ ################
143
+ # Current State
144
+
145
+ SERVICE_PAUSED = 0x00000007
146
+ SERVICE_PAUSE_PENDING = 0x00000006
147
+ SERVICE_CONTINUE_PENDING = 0x00000005
148
+ SERVICE_RUNNING = 0x00000004
149
+ SERVICE_STOP_PENDING = 0x00000003
150
+ SERVICE_START_PENDING = 0x00000002
151
+ SERVICE_STOPPED = 0x00000001
152
+
153
+ ###################
154
+ # Controls Accepted
155
+
156
+ # The control codes that the service accepts and processes in its handler
157
+ # function. One or more of the following values can be set. By default,
158
+ # all services accept the SERVICE_CONTROL_INTERROGATE value. A value of
159
+ # zero indicates that no controls are accepted.
160
+
161
+ # Service can reread its startup parameters without being stopped and
162
+ # restarted. This control code allows the service to receive
163
+ # SERVICE_CONTROL_PARAMCHANGE notifications.
164
+ SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
165
+ # Service can be paused and continued. This control code allows the
166
+ # service to receive SERVICE_CONTROL_PAUSE and SERVICE_CONTROL_CONTINUE
167
+ # notifications.
168
+ SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
169
+ # Service is notified when system shutdown occurs. This control code
170
+ # enables the service to receive SERVICE_CONTROL_SHUTDOWN notifications
171
+ # from the server.
172
+ SERVICE_ACCEPT_SHUTDOWN = 0x00000004
173
+ # Service can be stopped. This control code allows the service to receive
174
+ # SERVICE_CONTROL_STOP notifications.
175
+ SERVICE_ACCEPT_STOP = 0x00000001
176
+ # Service is notified when the computer's hardware profile changes.
177
+ SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
178
+ # Service is notified when the computer's power status changes.
179
+ SERVICE_ACCEPT_POWEREVENT = 0x00000040
180
+ # Service is notified when the computer's session status changes.
181
+ SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
182
+ # The service can perform preshutdown tasks. SERVICE_ACCEPT_PRESHUTDOWN
183
+ # is sent before sending SERVICE_CONTROL_SHUTDOWN to give more time to
184
+ # services that need extra time before shutdown occurs.
185
+ SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
186
+ # Service is notified when the system time changes.
187
+ SERVICE_ACCEPT_TIMECHANGE = 0x00000200
188
+ # Service is notified when an event for which the service has registered
189
+ # occurs.
190
+ SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
191
+
192
+ ###################
193
+ # Controls
194
+
195
+ # Notifies a paused service that it SHOULD resume. The
196
+ # SERVICE_PAUSE_CONTINUE access right MUST have been granted to the caller
197
+ # when the RPC control handle to the service record was created. The
198
+ # service record MUST have the SERVICE_ACCEPT_PAUSE_CONTINUE bit set in
199
+ # the ServiceStatus.dwControlsAccepted field of the service record.
200
+ SERVICE_CONTROL_CONTINUE = 0x00000003
201
+ # Notifies a service that it SHOULD report its current status information
202
+ # to the SCM. The SERVICE_INTERROGATE access right MUST have been granted
203
+ # to the caller when the RPC control handle to the service record was
204
+ # created.
205
+ SERVICE_CONTROL_INTERROGATE = 0x00000004
206
+ # Notifies a service that there is a new component for binding. The
207
+ # SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
208
+ # caller when the RPC control handle to the service record was created.
209
+ # The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set
210
+ # in the ServiceStatus.dwControlsAccepted field of the service record.
211
+ SERVICE_CONTROL_NETBINDADD = 0x00000007
212
+ # Notifies a network service that one of its bindings has been disabled.
213
+ # The SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
214
+ # caller when the RPC control handle to the service record was created.
215
+ # The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set
216
+ # in the ServiceStatus.dwControlsAccepted field of the service record.
217
+ SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
218
+ # Notifies a network service that a disabled binding has been enabled.
219
+ # The SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
220
+ # caller when the RPC control handle to the service record was created.
221
+ # The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set
222
+ # in the ServiceStatus.dwControlsAccepted field of the service record.
223
+ SERVICE_CONTROL_NETBINDENABLE = 0x00000009
224
+ # Notifies a network service that a component for binding has been
225
+ # removed. The SERVICE_PAUSE_CONTINUE access right MUST have been granted
226
+ # to the caller when the RPC control handle to the service record was
227
+ # created. The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE
228
+ # bit set in the ServiceStatus.dwControlsAccepted field of the service
229
+ # record.
230
+ SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
231
+ # Notifies a service that its startup parameters have changed. The
232
+ # SERVICE_PAUSE_CONTINUE access right MUST have been granted to the
233
+ # caller when the RPC control handle to the service record was created.
234
+ # The service record MUST have the SERVICE_ACCEPT_PARAMCHANGE bit set in
235
+ # the ServiceStatus.dwControlsAccepted field of the service record.
236
+ SERVICE_CONTROL_PARAMCHANGE = 0x00000006
237
+ # Notifies a service that it SHOULD pause. The SERVICE_PAUSE_CONTINUE
238
+ # access right MUST have been granted to the caller when the RPC control
239
+ # handle to the service record was created. The service record MUST have
240
+ # the SERVICE_ACCEPT_PAUSE_CONTINUE bit set in the
241
+ # ServiceStatus.dwControlsAccepted field of the service record.
242
+ SERVICE_CONTROL_PAUSE = 0x00000002
243
+ # Notifies a service that it SHOULD stop. The SERVICE_STOP access right
244
+ # MUST have been granted to the caller when the RPC control handle to the
245
+ # service record was created. The service record MUST have the
246
+ # SERVICE_ACCEPT_STOP bit set in the ServiceStatus.dwControlsAccepted
247
+ # field of the service record.
248
+ SERVICE_CONTROL_STOP = 0x00000001
249
+
250
+ require 'ruby_smb/dcerpc/svcctl/service_status'
251
+ require 'ruby_smb/dcerpc/svcctl/open_sc_manager_w_request'
252
+ require 'ruby_smb/dcerpc/svcctl/open_sc_manager_w_response'
253
+ require 'ruby_smb/dcerpc/svcctl/open_service_w_request'
254
+ require 'ruby_smb/dcerpc/svcctl/open_service_w_response'
255
+ require 'ruby_smb/dcerpc/svcctl/query_service_status_request'
256
+ require 'ruby_smb/dcerpc/svcctl/query_service_status_response'
257
+ require 'ruby_smb/dcerpc/svcctl/query_service_config_w_request'
258
+ require 'ruby_smb/dcerpc/svcctl/query_service_config_w_response'
259
+ require 'ruby_smb/dcerpc/svcctl/change_service_config_w_request'
260
+ require 'ruby_smb/dcerpc/svcctl/change_service_config_w_response'
261
+ require 'ruby_smb/dcerpc/svcctl/start_service_w_request'
262
+ require 'ruby_smb/dcerpc/svcctl/start_service_w_response'
263
+ require 'ruby_smb/dcerpc/svcctl/control_service_request'
264
+ require 'ruby_smb/dcerpc/svcctl/control_service_response'
265
+ require 'ruby_smb/dcerpc/svcctl/close_service_handle_request'
266
+ require 'ruby_smb/dcerpc/svcctl/close_service_handle_response'
267
+
268
+ # Open the SCM database on the specified server.
269
+ #
270
+ # @param rhost [String] the server's machine name
271
+ # @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the newly opened SCM database
272
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenSCManagerWResponse packet
273
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
274
+ def open_sc_manager_w(rhost, access = SERVICE_START | SERVICE_STOP | SERVICE_CHANGE_CONFIG | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS | SC_MANAGER_ENUMERATE_SERVICE)
275
+ open_sc_manager_w_request = OpenSCManagerWRequest.new(dw_desired_access: access)
276
+ open_sc_manager_w_request.lp_machine_name = rhost
277
+ open_sc_manager_w_request.lp_database_name = 'ServicesActive'
278
+ response = dcerpc_request(open_sc_manager_w_request)
279
+ begin
280
+ open_sc_manager_w_response = OpenSCManagerWResponse.read(response)
281
+ rescue IOError
282
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading OpenSCManagerWResponse'
283
+ end
284
+ unless open_sc_manager_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS
285
+ raise RubySMB::Dcerpc::Error::SvcctlError,
286
+ "Error returned when opening Service Control Manager (SCM): "\
287
+ "#{WindowsError::Win32.find_by_retval(open_sc_manager_w_response.error_status.value).join(',')}"
288
+ end
289
+ open_sc_manager_w_response.lp_sc_handle
290
+ end
291
+
292
+ # Creates an RPC context handle to an existing service record.
293
+ #
294
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the SCM database
295
+ # @param service_name [Srting] the ServiceName of the service record
296
+ # @param access [Integer] access right
297
+ # @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the found service record
298
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenServiceWResponse packet
299
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
300
+ def open_service_w(scm_handle, service_name, access = SERVICE_ALL_ACCESS)
301
+ open_service_w_request = OpenServiceWRequest.new(dw_desired_access: access)
302
+ open_service_w_request.lp_sc_handle = scm_handle
303
+ open_service_w_request.lp_service_name = service_name
304
+ response = dcerpc_request(open_service_w_request)
305
+ begin
306
+ open_sercice_w_response = OpenServiceWResponse.read(response)
307
+ rescue IOError
308
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading OpenServiceWResponse'
309
+ end
310
+ unless open_sercice_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS
311
+ raise RubySMB::Dcerpc::Error::SvcctlError,
312
+ "Error returned when opening #{service_name} service: "\
313
+ "#{WindowsError::Win32.find_by_retval(open_sercice_w_response.error_status.value).join(',')}"
314
+ end
315
+ open_sercice_w_response.lp_sc_handle
316
+ end
317
+
318
+ # Returns the current status of the specified service
319
+ #
320
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
321
+ # @return [RubySMB::Dcerpc::Svcctl::ServiceStatus] structure that contains the status information for the service
322
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryServiceStatusResponse packet
323
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
324
+ def query_service_status(svc_handle)
325
+ qss_request = QueryServiceStatusRequest.new
326
+ qss_request.h_service = svc_handle
327
+ response = dcerpc_request(qss_request)
328
+ begin
329
+ qss_response = QueryServiceStatusResponse.read(response)
330
+ rescue IOError
331
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceStatusResponse'
332
+ end
333
+ unless qss_response.error_status == WindowsError::Win32::ERROR_SUCCESS
334
+ raise RubySMB::Dcerpc::Error::SvcctlError,
335
+ "Error returned when querying service status: "\
336
+ "#{WindowsError::Win32.find_by_retval(qss_response.error_status.value).join(',')}"
337
+ end
338
+ qss_response.lp_service_status
339
+ end
340
+
341
+ # Returns the configuration parameters of the specified service
342
+ #
343
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
344
+ # @return [RubySMB::Dcerpc::Svcctl::QueryServiceConfigW] structure that contains the configuration parameters for the service
345
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryServiceConfigWResponse packet
346
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
347
+ def query_service_config(svc_handle)
348
+ qsc_request = QueryServiceConfigWRequest.new
349
+ qsc_request.h_service = svc_handle
350
+ qsc_request.cb_buf_size = 0
351
+ response = dcerpc_request(qsc_request)
352
+ begin
353
+ qsc_response = QueryServiceConfigWResponse.read(response)
354
+ rescue IOError
355
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceConfigWResponse'
356
+ end
357
+ if qsc_response.error_status == WindowsError::Win32::ERROR_INSUFFICIENT_BUFFER
358
+ qsc_request.cb_buf_size = qsc_response.pcb_bytes_needed
359
+ response = dcerpc_request(qsc_request)
360
+ begin
361
+ qsc_response = QueryServiceConfigWResponse.read(response)
362
+ rescue IOError
363
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceConfigWResponse'
364
+ end
365
+ end
366
+ unless qsc_response.error_status == WindowsError::Win32::ERROR_SUCCESS
367
+ raise RubySMB::Dcerpc::Error::SvcctlError,
368
+ "Error returned when querying service configuration: "\
369
+ "#{WindowsError::Win32.find_by_retval(qsc_response.error_status.value).join(',')}"
370
+ end
371
+ qsc_response.lp_service_config
372
+ end
373
+
374
+ # Changes a service's configuration parameters in the SCM database
375
+ #
376
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
377
+ # @param opts [Hash] configuration parameters to change
378
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a ChangeServiceConfigWResponse packet
379
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
380
+ def change_service_config_w(svc_handle, opts = {})
381
+ opts = {
382
+ h_service: svc_handle,
383
+ dw_service_type: opts[:service_type] || SERVICE_NO_CHANGE,
384
+ dw_start_type: opts[:start_type] || SERVICE_NO_CHANGE,
385
+ dw_error_control: opts[:error_control] || SERVICE_NO_CHANGE,
386
+ lp_binary_path_name: opts[:binary_path_name] || :null,
387
+ lp_load_order_group: opts[:load_order_group] || :null,
388
+ dw_tag_id: opts[:tag_id] || :null,
389
+ lp_dependencies: opts[:dependencies] || [],
390
+ lp_service_start_name: opts[:service_start_name] || :null,
391
+ lp_password: opts[:password] || [],
392
+ lp_display_name: opts[:display_name] || :null
393
+ }
394
+
395
+ csc_request = ChangeServiceConfigWRequest.new(opts)
396
+ response = dcerpc_request(csc_request)
397
+ begin
398
+ csc_response = ChangeServiceConfigWResponse.read(response)
399
+ rescue IOError
400
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading ChangeServiceConfigWResponse'
401
+ end
402
+ unless csc_response.error_status == WindowsError::Win32::ERROR_SUCCESS
403
+ raise RubySMB::Dcerpc::Error::SvcctlError,
404
+ "Error returned when changing the service configuration: "\
405
+ "#{WindowsError::Win32.find_by_retval(csc_response.error_status.value).join(',')}"
406
+ end
407
+ end
408
+
409
+ # Starts a specified service
410
+ #
411
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
412
+ # @param argv [Array<String>] arguments to the service (Array of
413
+ # strings). The first element in argv must be the name of the service.
414
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a StartServiceWResponse packet
415
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
416
+ def start_service_w(svc_handle, argv = [])
417
+ ss_request = StartServiceWRequest.new(h_service: svc_handle)
418
+ unless argv.empty?
419
+ ss_request.argc = argv.size
420
+ ndr_string_ptrsw = RubySMB::Dcerpc::Ndr::NdrStringPtrsw.new
421
+ ndr_string_ptrsw.elements = argv
422
+ ss_request.argv = ndr_string_ptrsw
423
+ end
424
+ response = dcerpc_request(ss_request)
425
+ begin
426
+ ss_response = StartServiceWResponse.read(response)
427
+ rescue IOError
428
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading StartServiceWResponse'
429
+ end
430
+ unless ss_response.error_status == WindowsError::Win32::ERROR_SUCCESS
431
+ raise RubySMB::Dcerpc::Error::SvcctlError,
432
+ "Error returned when starting the service: "\
433
+ "#{WindowsError::Win32.find_by_retval(ss_response.error_status.value).join(',')}"
434
+ end
435
+ end
436
+
437
+ # Send a control code to a specific service handle
438
+ #
439
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
440
+ # @param control [Integer] control code
441
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a ControlServiceResponse packet
442
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
443
+ def control_service(svc_handle, control)
444
+ cs_request = ControlServiceRequest.new(h_service: svc_handle, dw_control: control)
445
+ response = dcerpc_request(cs_request)
446
+ begin
447
+ cs_response = ControlServiceResponse.read(response)
448
+ rescue IOError
449
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading ControlServiceResponse'
450
+ end
451
+ unless cs_response.error_status == WindowsError::Win32::ERROR_SUCCESS
452
+ raise RubySMB::Dcerpc::Error::SvcctlError,
453
+ "Error returned when sending a control to the service: "\
454
+ "#{WindowsError::Win32.find_by_retval(cs_response.error_status.value).join(',')}"
455
+ end
456
+ end
457
+
458
+ # Releases the handle to the specified service or the SCM database.
459
+ #
460
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record or to the SCM database
461
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a CloseServiceHandleResponse packet
462
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
463
+ def close_service_handle(svc_handle)
464
+ csh_request = CloseServiceHandleRequest.new(h_sc_object: svc_handle)
465
+ response = dcerpc_request(csh_request)
466
+ begin
467
+ csh_response = CloseServiceHandleResponse.read(response)
468
+ rescue IOError
469
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading CloseServiceHandleResponse'
470
+ end
471
+ unless csh_response.error_status == WindowsError::Win32::ERROR_SUCCESS
472
+ raise RubySMB::Dcerpc::Error::SvcctlError,
473
+ "Error returned when closing the service: "\
474
+ "#{WindowsError::Win32.find_by_retval(csh_response.error_status.value).join(',')}"
475
+ end
476
+ end
477
+ end
478
+ end
479
+ end