module RubySMB::Dcerpc::Svcctl
Constants
- CHANGE_SERVICE_CONFIG_W
- CLOSE_SERVICE_HANDLE
Operation numbers
- CONTROL_SERVICE
- OPEN_SC_MANAGER_W
- OPEN_SERVICE_W
- QUERY_SERVICE_CONFIG_W
- QUERY_SERVICE_STATUS
- SC_MANAGER_CONNECT
Required to connect to the SCM.
- SC_MANAGER_CREATE_SERVICE
Required for a service to be created.
- SC_MANAGER_ENUMERATE_SERVICE
Required to enumerate a service.
- SC_MANAGER_LOCK
Required to lock the SCM database.
- SC_MANAGER_MODIFY_BOOT_CONFIG
Required to call the RNotifyBootConfigStatus method.
- SC_MANAGER_QUERY_LOCK_STATUS
Required to query the lock status of the SCM database.
- SERVICE_ACCEPT_HARDWAREPROFILECHANGE
Service is notified when the computer's hardware profile changes.
- SERVICE_ACCEPT_PARAMCHANGE
Service can reread its startup parameters without being stopped and restarted. This control code allows the service to receive
SERVICE_CONTROL_PARAMCHANGE
notifications.- SERVICE_ACCEPT_PAUSE_CONTINUE
Service can be paused and continued. This control code allows the service to receive
SERVICE_CONTROL_PAUSE
andSERVICE_CONTROL_CONTINUE
notifications.- SERVICE_ACCEPT_POWEREVENT
Service is notified when the computer's power status changes.
- SERVICE_ACCEPT_PRESHUTDOWN
The service can perform preshutdown tasks.
SERVICE_ACCEPT_PRESHUTDOWN
is sent before sending SERVICE_CONTROL_SHUTDOWN to give more time to services that need extra time before shutdown occurs.- SERVICE_ACCEPT_SESSIONCHANGE
Service is notified when the computer's session status changes.
- SERVICE_ACCEPT_SHUTDOWN
Service is notified when system shutdown occurs. This control code enables the service to receive SERVICE_CONTROL_SHUTDOWN notifications from the server.
- SERVICE_ACCEPT_STOP
Service can be stopped. This control code allows the service to receive
SERVICE_CONTROL_STOP
notifications.- SERVICE_ACCEPT_TIMECHANGE
Service is notified when the system time changes.
- SERVICE_ACCEPT_TRIGGEREVENT
Service is notified when an event for which the service has registered occurs.
- SERVICE_ALL_ACCESS
In addition to all access rights in this table,
SERVICE_ALL_ACCESS
includes Delete (DE), Read Control (RC), Write DACL (WD), and Write Owner (WO) access, as specified in ACCESS_MASK (section 2.4.3) of [MS-DTYP].- SERVICE_AUTO_START
A service started automatically by the SCM during system startup.
- SERVICE_BOOT_START
Starts the driver service when the system boots up. This value is valid only for driver services.
- SERVICE_CHANGE_CONFIG
Required to change the configuration of a service.
- SERVICE_CONTINUE_PENDING
- SERVICE_CONTROL_CONTINUE
Notifies a paused service that it SHOULD resume. The
SERVICE_PAUSE_CONTINUE
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have theSERVICE_ACCEPT_PAUSE_CONTINUE
bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_CONTROL_INTERROGATE
Notifies a service that it SHOULD report its current status information to the SCM. The
SERVICE_INTERROGATE
access right MUST have been granted to the caller when the RPC control handle to the service record was created.- SERVICE_CONTROL_NETBINDADD
Notifies a service that there is a new component for binding. The
SERVICE_PAUSE_CONTINUE
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_CONTROL_NETBINDDISABLE
Notifies a network service that one of its bindings has been disabled. The
SERVICE_PAUSE_CONTINUE
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_CONTROL_NETBINDENABLE
Notifies a network service that a disabled binding has been enabled. The
SERVICE_PAUSE_CONTINUE
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_CONTROL_NETBINDREMOVE
Notifies a network service that a component for binding has been removed. The
SERVICE_PAUSE_CONTINUE
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have the SERVICE_ACCEPT_NETBINDCHANGE bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_CONTROL_PARAMCHANGE
Notifies a service that its startup parameters have changed. The
SERVICE_PAUSE_CONTINUE
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have theSERVICE_ACCEPT_PARAMCHANGE
bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_CONTROL_PAUSE
Notifies a service that it SHOULD pause. The
SERVICE_PAUSE_CONTINUE
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have theSERVICE_ACCEPT_PAUSE_CONTINUE
bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_CONTROL_STOP
Notifies a service that it SHOULD stop. The
SERVICE_STOP
access right MUST have been granted to the caller when the RPC control handle to the service record was created. The service record MUST have theSERVICE_ACCEPT_STOP
bit set in the ServiceStatus.dwControlsAccepted field of the service record.- SERVICE_DEMAND_START
Starts the service when a client requests the SCM to start the service.
- SERVICE_DISABLED
A service that cannot be started. Attempts to start the service result in the error code ERROR_SERVICE_DISABLED.
- SERVICE_ENUMERATE_DEPENDENTS
Required to enumerate the services installed on the server.
- SERVICE_ERROR_CRITICAL
The SCM SHOULD log the error in the event log if possible. If the last-known good configuration is being started, the startup operation fails. Otherwise, the system is restarted with the last-known good configuration.
- SERVICE_ERROR_IGNORE
The SCM ignores the error and continues the startup operation.
- SERVICE_ERROR_NORMAL
The SCM logs the error in the event log and continues the startup operation.
- SERVICE_ERROR_SEVERE
The SCM logs the error in the event log. If the last-known good configuration is being started, the startup operation continues. Otherwise, the system is restarted with the last-known good configuration.
- SERVICE_FILE_SYSTEM_DRIVER
A file system driver service. These are services that manage file systems on the system.
- SERVICE_INTERACTIVE_PROCESS
The service can interact with the desktop. Only
SERVICE_WIN32_OWN_PROCESS
andSERVICE_INTERACTIVE_PROCESS
ORSERVICE_WIN32_SHARE_PROCESS
andSERVICE_INTERACTIVE_PROCESS
can be combined.- SERVICE_INTERROGATE
Required to request immediate status from the service.
- SERVICE_KERNEL_DRIVER
A driver service. These are services that manage devices on the system.
- SERVICE_NO_CHANGE
Service type, start or error control does not change.
- SERVICE_PAUSED
Current State
- SERVICE_PAUSE_CONTINUE
Required to pause or continue the service.
- SERVICE_PAUSE_PENDING
- SERVICE_QUERY_CONFIG
Required to query the service configuration.
- SERVICE_QUERY_STATUS
Required to request the service status.
- SERVICE_RUNNING
- SERVICE_SET_STATUS
Required for a service to set its status.
- SERVICE_START
Required to start the service.
- SERVICE_START_PENDING
- SERVICE_STOP
Required to stop the service.
- SERVICE_STOPPED
- SERVICE_STOP_PENDING
- SERVICE_SYSTEM_START
Starts the driver service when the system boots up. This value is valid only for driver services. The services marked
SERVICE_SYSTEM_START
are started after allSERVICE_BOOT_START
services have been started.- SERVICE_USER_DEFINED_CONTROL
Required to specify a user-defined control code.
- SERVICE_WIN32_OWN_PROCESS
A service that runs in its own process.
- SERVICE_WIN32_SHARE_PROCESS
A service that shares a process with other services.
- START_SERVICE_W
- UUID
- VER_MAJOR
- VER_MINOR
Public Instance Methods
Changes a service's configuration parameters in the SCM database
@param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record @param opts [Hash] configuration parameters to change @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a ChangeServiceConfigWResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 380 def change_service_config_w(svc_handle, opts = {}) opts = { h_service: svc_handle, dw_service_type: opts[:service_type] || SERVICE_NO_CHANGE, dw_start_type: opts[:start_type] || SERVICE_NO_CHANGE, dw_error_control: opts[:error_control] || SERVICE_NO_CHANGE, lp_binary_path_name: opts[:binary_path_name] || :null, lp_load_order_group: opts[:load_order_group] || :null, dw_tag_id: opts[:tag_id] || :null, lp_dependencies: opts[:dependencies] || [], lp_service_start_name: opts[:service_start_name] || :null, lp_password: opts[:password] || [], lp_display_name: opts[:display_name] || :null } csc_request = ChangeServiceConfigWRequest.new(opts) response = dcerpc_request(csc_request) begin csc_response = ChangeServiceConfigWResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading ChangeServiceConfigWResponse' end unless csc_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when changing the service configuration: "\ "#{WindowsError::Win32.find_by_retval(csc_response.error_status.value).join(',')}" end end
Releases the handle to the specified service or the SCM database.
@param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record or to the SCM database @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a CloseServiceHandleResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 463 def close_service_handle(svc_handle) csh_request = CloseServiceHandleRequest.new(h_sc_object: svc_handle) response = dcerpc_request(csh_request) begin csh_response = CloseServiceHandleResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading CloseServiceHandleResponse' end unless csh_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when closing the service: "\ "#{WindowsError::Win32.find_by_retval(csh_response.error_status.value).join(',')}" end end
Send a control code to a specific service handle
@param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record @param control [Integer] control code @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a ControlServiceResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 443 def control_service(svc_handle, control) cs_request = ControlServiceRequest.new(h_service: svc_handle, dw_control: control) response = dcerpc_request(cs_request) begin cs_response = ControlServiceResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading ControlServiceResponse' end unless cs_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when sending a control to the service: "\ "#{WindowsError::Win32.find_by_retval(cs_response.error_status.value).join(',')}" end end
Open the SCM database on the specified server.
@param rhost [String] the server's machine name @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the newly opened SCM database @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenSCManagerWResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 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) open_sc_manager_w_request = OpenSCManagerWRequest.new(dw_desired_access: access) open_sc_manager_w_request.lp_machine_name = rhost open_sc_manager_w_request.lp_database_name = 'ServicesActive' response = dcerpc_request(open_sc_manager_w_request) begin open_sc_manager_w_response = OpenSCManagerWResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading OpenSCManagerWResponse' end unless open_sc_manager_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when opening Service Control Manager (SCM): "\ "#{WindowsError::Win32.find_by_retval(open_sc_manager_w_response.error_status.value).join(',')}" end open_sc_manager_w_response.lp_sc_handle end
Creates an RPC context handle to an existing service record.
@param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the SCM database @param service_name [Srting] the ServiceName of the service record @param access [Integer] access right @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the found service record @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenServiceWResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 300 def open_service_w(scm_handle, service_name, access = SERVICE_ALL_ACCESS) open_service_w_request = OpenServiceWRequest.new(dw_desired_access: access) open_service_w_request.lp_sc_handle = scm_handle open_service_w_request.lp_service_name = service_name response = dcerpc_request(open_service_w_request) begin open_sercice_w_response = OpenServiceWResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading OpenServiceWResponse' end unless open_sercice_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when opening #{service_name} service: "\ "#{WindowsError::Win32.find_by_retval(open_sercice_w_response.error_status.value).join(',')}" end open_sercice_w_response.lp_sc_handle end
Returns the configuration parameters of the specified service
@param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record @return [RubySMB::Dcerpc::Svcctl::QueryServiceConfigW] structure that contains the configuration parameters for the service @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryServiceConfigWResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 347 def query_service_config(svc_handle) qsc_request = QueryServiceConfigWRequest.new qsc_request.h_service = svc_handle qsc_request.cb_buf_size = 0 response = dcerpc_request(qsc_request) begin qsc_response = QueryServiceConfigWResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceConfigWResponse' end if qsc_response.error_status == WindowsError::Win32::ERROR_INSUFFICIENT_BUFFER qsc_request.cb_buf_size = qsc_response.pcb_bytes_needed response = dcerpc_request(qsc_request) begin qsc_response = QueryServiceConfigWResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceConfigWResponse' end end unless qsc_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when querying service configuration: "\ "#{WindowsError::Win32.find_by_retval(qsc_response.error_status.value).join(',')}" end qsc_response.lp_service_config end
Returns the current status of the specified service
@param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record @return [RubySMB::Dcerpc::Svcctl::ServiceStatus] structure that contains the status information for the service @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryServiceStatusResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 324 def query_service_status(svc_handle) qss_request = QueryServiceStatusRequest.new qss_request.h_service = svc_handle response = dcerpc_request(qss_request) begin qss_response = QueryServiceStatusResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading QueryServiceStatusResponse' end unless qss_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when querying service status: "\ "#{WindowsError::Win32.find_by_retval(qss_response.error_status.value).join(',')}" end qss_response.lp_service_status end
Starts a specified service
@param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record @param argv [Array<String>] arguments to the service (Array of
strings). The first element in argv must be the name of the service.
@raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a StartServiceWResponse
packet @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
# File lib/ruby_smb/dcerpc/svcctl.rb, line 416 def start_service_w(svc_handle, argv = []) ss_request = StartServiceWRequest.new(h_service: svc_handle) unless argv.empty? ss_request.argc = argv.size ndr_string_ptrsw = RubySMB::Dcerpc::Ndr::NdrStringPtrsw.new ndr_string_ptrsw.elements = argv ss_request.argv = ndr_string_ptrsw end response = dcerpc_request(ss_request) begin ss_response = StartServiceWResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading StartServiceWResponse' end unless ss_response.error_status == WindowsError::Win32::ERROR_SUCCESS raise RubySMB::Dcerpc::Error::SvcctlError, "Error returned when starting the service: "\ "#{WindowsError::Win32.find_by_retval(ss_response.error_status.value).join(',')}" end end