class Rex::Proto::DCERPC::SVCCTL::Client

Attributes

dcerpc_client[RW]

Public Class Methods

new(dcerpc_client) click to toggle source
# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 19
def initialize(dcerpc_client)
  self.dcerpc_client = dcerpc_client
end

Public Instance Methods

changeservicedescription(svc_handle, service_description) click to toggle source

Calls ChangeServiceConfig2() to change the service description.

@param svc_handle [String] the service handle to change. @param service_description [String] the service description.

@return [Integer] Windows error code

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 138
def changeservicedescription(svc_handle, service_description)
  svc_status = nil
  stubdata =
    svc_handle +
    NDR.long(SERVICE_CONFIG_DESCRIPTION) +
    NDR.long(1) + # lpInfo -> *SERVICE_DESCRIPTION
    NDR.long(0x0200) + # SERVICE_DESCRIPTION struct
    NDR.long(0x04000200) +
    NDR.wstring(service_description)
  begin
    response = dcerpc_client.call(CHANGE_SERVICE_CONFIG2_W, stubdata) # ChangeServiceConfig2
    svc_status = error_code(response)
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error changing service description : #{e}")
  end

  svc_status
end
closehandle(handle) click to toggle source

Calls CloseHandle() to close a handle.

@param handle [String] the handle to close.

@return [Integer] Windows error code

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 163
def closehandle(handle)
  svc_status = nil
  begin
    response = dcerpc_client.call(CLOSE_SERVICE_HANDLE, handle)
    if response
      svc_status = error_code(response[20,4])
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error closing service handle: #{e}")
  end

  svc_status
end
controlservice(svc_handle, operation) click to toggle source

Controls an existing service.

@param svc_handle [String] the handle of the service (from {#openservicew}). @param operation [Fixnum] the operation number to perform (1 = stop

service; others are unknown).

@return [Integer] Windows error code

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 243
def controlservice(svc_handle, operation)
  svc_status = nil
  begin
    response = dcerpc_client.call(CONTROL_SERVICE, svc_handle + NDR.long(operation))
    if response
     svc_status =  error_code(response[28,4])
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error controlling service: #{e}")
  end

  svc_status
end
createservicew(scm_handle, service_name, display_name, binary_path, opts) click to toggle source

Calls CreateServiceW() to create a system service. Returns a handle to the service on success, or nil.

@param scm_handle [String] the SCM handle (from {#openscmanagerw}). @param service_name [String] the service name. @param display_name [String] the display name. @param binary_path [String] the path of the binary to run. @param opts [Hash] arguments for CreateServiceW() @option opts [Fixnum] :access (SERVICE_ALL_ACCESS) the access level. @option opts [Fixnum] :type (SERVICE_WIN32_OWN_PROCESS ||

SERVICE_INTERACTIVE_PROCESS) the type of service.

@option opts [Fixnum] :start (SERVICE_DEMAND_START) the start options. @option opts [Fixnum] :errors (SERVICE_ERROR_IGNORE) the error options. @option opts [Fixnum] :load_order_group (0) the load order group. @option opts [Fixnum] :dependencies (0) the dependencies of the service. @option opts [Fixnum] :service_start (0) @option opts [Fixnum] :password1 (0) @option opts [Fixnum] :password2 (0) @option opts [Fixnum] :password3 (0) @option opts [Fixnum] :password4 (0)

@return [String, Integer] a handle to the created service, windows

error code.
# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 84
def createservicew(scm_handle, service_name, display_name, binary_path, opts)
  default_opts = {
    :access => SERVICE_ALL_ACCESS,
    :type => SERVICE_WIN32_OWN_PROCESS || SERVICE_INTERACTIVE_PROCESS,
    :start => SERVICE_DEMAND_START,
    :errors => SERVICE_ERROR_IGNORE,
    :load_order_group => 0,
    :dependencies => 0,
    :service_start => 0,
    :password1 => 0,
    :password2 => 0,
    :password3 => 0,
    :password4 => 0
  }.merge(opts)

  svc_handle  = nil
  svc_status  = nil
  stubdata = scm_handle +
    NDR.wstring(service_name) +
    NDR.uwstring(display_name) +
    NDR.long(default_opts[:access]) +
    NDR.long(default_opts[:type]) +
    NDR.long(default_opts[:start]) +
    NDR.long(default_opts[:errors]) +
    NDR.wstring(binary_path) +
    NDR.long(default_opts[:load_order_group]) +
    NDR.long(default_opts[:dependencies]) +
    NDR.long(default_opts[:service_start]) +
    NDR.long(default_opts[:password1]) +
    NDR.long(default_opts[:password2]) +
    NDR.long(default_opts[:password3]) +
    NDR.long(default_opts[:password4])
  begin
    response = dcerpc_client.call(CREATE_SERVICE_W, stubdata)
    if response
      svc_status = error_code(response[24,4])

      if svc_status == ERROR_SUCCESS
        svc_handle = response[4,20]
      end
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error creating service: #{e}")
  end

  return svc_handle, svc_status
end
deleteservice(svc_handle) click to toggle source

Calls DeleteService() to delete a service.

@param svc_handle [String] the handle of the service (from {#openservicew}).

@return [Integer] Windows error code

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 262
def deleteservice(svc_handle)
  svc_status = nil
  begin
    response = dcerpc_client.call(DELETE_SERVICE, svc_handle)
    if response
      svc_status = error_code(response)
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error deleting service: #{e}")
  end

  svc_status
end
error_code(raw_error) click to toggle source

Returns the Windows Error Code in numeric format

@param raw_error [String] the raw error code in binary format.

@return [Integer] the Windows Error Code integer.

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 28
def error_code(raw_error)
  raw_error.unpack('V').first
end
openscmanagerw(rhost, access = SC_MANAGER_ALL_ACCESS) click to toggle source

Calls OpenSCManagerW() to obtain a handle to the service control manager.

@param rhost [String] the target host. @param access [Fixnum] the access flags requested.

@return [Array<String,Integer>] the handle to the service control manager or nil if

the call is not successful and the Windows error code
# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 39
def openscmanagerw(rhost, access = SC_MANAGER_ALL_ACCESS)
  scm_handle = nil
  scm_status = nil
  stubdata =
    NDR.uwstring("\\\\#{rhost}") +
    NDR.long(0) +
    NDR.long(access)
  begin
    response = dcerpc_client.call(OPEN_SC_MANAGER_W, stubdata)
    if response
      scm_status = error_code(response[20,4])
      if scm_status == ERROR_SUCCESS
        scm_handle = response[0,20]
      end
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error getting scm handle: #{e}")
  end

  [scm_handle, scm_status]
end
openservicew(scm_handle, service_name, access = SERVICE_ALL_ACCESS) click to toggle source

Calls OpenServiceW to obtain a handle to an existing service.

@param scm_handle [String] the SCM handle (from {#openscmanagerw}). @param service_name [String] the name of the service to open. @param access [Fixnum] the level of access requested (default is maximum).

@return [String, nil] the handle of the service opened, or nil on failure.

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 184
def openservicew(scm_handle, service_name, access = SERVICE_ALL_ACCESS)
  svc_handle = nil
  svc_status = nil
  stubdata = scm_handle + NDR.wstring(service_name) + NDR.long(access)
  begin
    response = dcerpc_client.call(OPEN_SERVICE_W, stubdata)
    if response
      svc_status = error_code(response[20,4])
      if svc_status == ERROR_SUCCESS
        svc_handle = response[0,20]
      end
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error opening service handle: #{e}")
  end

  svc_handle
end
queryservice(svc_handle) click to toggle source

Calls QueryServiceStatus() to query the status of a service.

@param svc_handle [String] the handle of the service (from {#openservicew}).

@return [Fixnum] Returns 0 if the query failed (i.e.: a state was returned

that isn't implemented), 1 if the service is running, and
2 if the service is stopped.
# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 283
def queryservice(svc_handle)
  ret = 0

  begin
    response = dcerpc_client.call(QUERY_SERVICE_STATUS, svc_handle)
    if response[0,9] == "\x10\x00\x00\x00\x04\x00\x00\x00\x01"
      ret = 1
    elsif response[0,9] == "\x10\x00\x00\x00\x01\x00\x00\x00\x00"
      ret = 2
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error deleting service: #{e}")
  end

  ret
end
startservice(svc_handle, magic1 = 0, magic2 = 0) click to toggle source

Calls StartService() on a handle to an existing service in order to start it. Returns true on success, or false.

@param svc_handle [String] the handle of the service (from {#openservicew}). @param magic1 [Fixnum] an unknown value. @param magic2 [Fixnum] another unknown value.

@return [Integer] Windows error code

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 211
def startservice(svc_handle, magic1 = 0, magic2 = 0)
  svc_status = nil
  stubdata = svc_handle + NDR.long(magic1) + NDR.long(magic2)

  begin
    response = dcerpc_client.call(0x13, stubdata)
    if response
      svc_status = error_code(response)
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    print_error("Error starting service: #{e}")
  end

  svc_status
end
stopservice(svc_handle) click to toggle source

Stops a running service.

@param svc_handle [String] the handle of the service (from {#openservicew}).

@return [Integer] Windows error code

# File lib/rex/proto/dcerpc/svcctl/packet.rb, line 232
def stopservice(svc_handle)
  dce_controlservice(svc_handle, SERVICE_CONTROL_STOP)
end