ruby_smb 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/examples/anonymous_auth.rb +3 -3
- data/examples/append_file.rb +10 -8
- data/examples/authenticate.rb +9 -5
- data/examples/delete_file.rb +8 -6
- data/examples/enum_registry_key.rb +5 -4
- data/examples/enum_registry_values.rb +5 -4
- data/examples/list_directory.rb +8 -6
- data/examples/negotiate_with_netbios_service.rb +9 -5
- data/examples/net_share_enum_all.rb +6 -4
- data/examples/pipes.rb +11 -12
- data/examples/query_service_status.rb +64 -0
- data/examples/read_file.rb +8 -6
- data/examples/read_registry_key_value.rb +6 -5
- data/examples/rename_file.rb +9 -7
- data/examples/tree_connect.rb +7 -5
- data/examples/write_file.rb +9 -7
- data/lib/ruby_smb/client.rb +72 -43
- data/lib/ruby_smb/client/negotiation.rb +1 -0
- data/lib/ruby_smb/dcerpc.rb +2 -0
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +209 -44
- data/lib/ruby_smb/dcerpc/request.rb +13 -0
- data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
- data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
- data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
- data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
- data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
- data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
- data/lib/ruby_smb/dispatcher/base.rb +1 -1
- data/lib/ruby_smb/dispatcher/socket.rb +1 -1
- data/lib/ruby_smb/field/stringz16.rb +17 -1
- data/lib/ruby_smb/nbss/session_header.rb +4 -4
- data/lib/ruby_smb/smb1/file.rb +2 -10
- data/lib/ruby_smb/smb1/pipe.rb +2 -0
- data/lib/ruby_smb/smb2/file.rb +25 -17
- data/lib/ruby_smb/smb2/pipe.rb +3 -0
- data/lib/ruby_smb/smb2/tree.rb +9 -3
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +161 -60
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
- data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +215 -41
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
- data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +7 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +60 -6
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +7 -0
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +35 -1
- metadata +72 -2
- metadata.gz.sig +0 -0
@@ -27,12 +27,25 @@ 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
|
32
34
|
choice 'Srvsvc', selection: -> { opnum } do
|
33
35
|
net_share_enum_all RubySMB::Dcerpc::Srvsvc::NET_SHARE_ENUM_ALL, host: -> { host rescue '' }
|
34
36
|
string :default
|
35
37
|
end
|
38
|
+
choice 'Svcctl', selection: -> { opnum } do
|
39
|
+
open_sc_manager_w_request RubySMB::Dcerpc::Svcctl::OPEN_SC_MANAGER_W
|
40
|
+
open_service_w_request RubySMB::Dcerpc::Svcctl::OPEN_SERVICE_W
|
41
|
+
query_service_status_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_STATUS
|
42
|
+
query_service_config_w_request RubySMB::Dcerpc::Svcctl::QUERY_SERVICE_CONFIG_W
|
43
|
+
change_service_config_w_request RubySMB::Dcerpc::Svcctl::CHANGE_SERVICE_CONFIG_W
|
44
|
+
start_service_w_request RubySMB::Dcerpc::Svcctl::START_SERVICE_W
|
45
|
+
control_service_request RubySMB::Dcerpc::Svcctl::CONTROL_SERVICE
|
46
|
+
close_service_handle_request RubySMB::Dcerpc::Svcctl::CLOSE_SERVICE_HANDLE
|
47
|
+
string :default
|
48
|
+
end
|
36
49
|
string :default
|
37
50
|
end
|
38
51
|
|
@@ -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
|
12
|
-
uint16 :maximum_length
|
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
|
22
|
-
|
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::
|
30
|
+
class PrrpUnicodeString < Ndr::NdrPointer
|
28
31
|
endian :little
|
29
32
|
|
30
|
-
rrp_unicode_string :referent, onlyif: -> {
|
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
|