Class: Rex::Proto::DCERPC::SVCCTL::Client

Inherits:
Object
  • Object
show all
Includes:
Constants::Windows
Defined in:
lib/rex/proto/dcerpc/svcctl/packet.rb

Constant Summary

Constants included from Constants::Windows

Constants::Windows::CHANGE_SERVICE_CONFIG2_W, Constants::Windows::CHANGE_SERVICE_CONFIG_W, Constants::Windows::CLOSE_SERVICE_HANDLE, Constants::Windows::CONTROL_SERVICE, Constants::Windows::CREATE_SERVICE_W, Constants::Windows::DELETE_SERVICE, Constants::Windows::ERROR_ACCESS_DENIED, Constants::Windows::ERROR_FILE_NOT_FOUND, Constants::Windows::ERROR_SERVICE_EXISTS, Constants::Windows::ERROR_SERVICE_REQUEST_TIMEOUT, Constants::Windows::ERROR_SUCCESS, Constants::Windows::OPEN_SC_MANAGER_W, Constants::Windows::OPEN_SERVICE_W, Constants::Windows::QUERY_SERVICE_STATUS, Constants::Windows::SC_MANAGER_ALL_ACCESS, Constants::Windows::SC_MANAGER_CONNECT, Constants::Windows::SC_MANAGER_CREATE_SERVICE, Constants::Windows::SC_MANAGER_ENUMERATE_SERVICE, Constants::Windows::SC_MANAGER_LOCK, Constants::Windows::SC_MANAGER_MODIFY_BOOT_CONFIG, Constants::Windows::SC_MANAGER_QUERY_LOCK_STATUS, Constants::Windows::SERVICE_ACCEPT_HARDWAREPROFILECHANGE, Constants::Windows::SERVICE_ACCEPT_NETBINDCHANGE, Constants::Windows::SERVICE_ACCEPT_PARAMCHANGE, Constants::Windows::SERVICE_ACCEPT_PAUSE_CONTINUE, Constants::Windows::SERVICE_ACCEPT_POWEREVENT, Constants::Windows::SERVICE_ACCEPT_PRESHUTDOWN, Constants::Windows::SERVICE_ACCEPT_SESSIONCHANGE, Constants::Windows::SERVICE_ACCEPT_SHUTDOWN, Constants::Windows::SERVICE_ACCEPT_STOP, Constants::Windows::SERVICE_ACCEPT_TIMECHANGE, Constants::Windows::SERVICE_ACCEPT_TRIGGEREVENT, Constants::Windows::SERVICE_ACTIVE, Constants::Windows::SERVICE_ALL_ACCESS, Constants::Windows::SERVICE_AUTO_START, Constants::Windows::SERVICE_BOOT_START, Constants::Windows::SERVICE_CHANGE_CONFIG, Constants::Windows::SERVICE_CONFIG_DELAYED_AUTO_START_INFO, Constants::Windows::SERVICE_CONFIG_DESCRIPTION, Constants::Windows::SERVICE_CONFIG_FAILURE_ACTIONS, Constants::Windows::SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, Constants::Windows::SERVICE_CONFIG_LAUNCH_PROTECTED, Constants::Windows::SERVICE_CONFIG_PREFERRED_NODE, Constants::Windows::SERVICE_CONFIG_PRESHUTDOWN_INFO, Constants::Windows::SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, Constants::Windows::SERVICE_CONFIG_SERVICE_SID_INFO, Constants::Windows::SERVICE_CONFIG_TRIGGER_INFO, Constants::Windows::SERVICE_CONTINUE_PENDING, Constants::Windows::SERVICE_CONTROL_CONTINUE, Constants::Windows::SERVICE_CONTROL_DEVICEEVENT, Constants::Windows::SERVICE_CONTROL_HARDWAREPROFILECHANGE, Constants::Windows::SERVICE_CONTROL_INTERROGATE, Constants::Windows::SERVICE_CONTROL_NETBINDADD, Constants::Windows::SERVICE_CONTROL_NETBINDDISABLE, Constants::Windows::SERVICE_CONTROL_NETBINDENABLE, Constants::Windows::SERVICE_CONTROL_NETBINDREMOVE, Constants::Windows::SERVICE_CONTROL_PARAMCHANGE, Constants::Windows::SERVICE_CONTROL_PAUSE, Constants::Windows::SERVICE_CONTROL_POWEREVENT, Constants::Windows::SERVICE_CONTROL_PRESHUTDOWN, Constants::Windows::SERVICE_CONTROL_SESSIONCHANGE, Constants::Windows::SERVICE_CONTROL_SHUTDOWN, Constants::Windows::SERVICE_CONTROL_STOP, Constants::Windows::SERVICE_CONTROL_TIMECHANGE, Constants::Windows::SERVICE_CONTROL_TRIGGEREVENT, Constants::Windows::SERVICE_DEMAND_START, Constants::Windows::SERVICE_DISABLED, Constants::Windows::SERVICE_ENUMERATE_DEPENDENTS, Constants::Windows::SERVICE_ERROR_IGNORE, Constants::Windows::SERVICE_INACTIVE, Constants::Windows::SERVICE_INTERACTIVE_PROCESS, Constants::Windows::SERVICE_INTERROGATE, Constants::Windows::SERVICE_NO_CHANGE, Constants::Windows::SERVICE_PAUSED, Constants::Windows::SERVICE_PAUSE_CONTINUE, Constants::Windows::SERVICE_PAUSE_PENDING, Constants::Windows::SERVICE_QUERY_CONFIG, Constants::Windows::SERVICE_QUERY_STATUS, Constants::Windows::SERVICE_RUNNING, Constants::Windows::SERVICE_RUNS_IN_SYSTEM_PROCESS, Constants::Windows::SERVICE_START, Constants::Windows::SERVICE_START_PENDING, Constants::Windows::SERVICE_STATE_ALL, Constants::Windows::SERVICE_STOP, Constants::Windows::SERVICE_STOPPED, Constants::Windows::SERVICE_STOP_PENDING, Constants::Windows::SERVICE_SYSTEM_START, Constants::Windows::SERVICE_USER_DEFINED_CONTROL, Constants::Windows::SERVICE_WIN32_OWN_PROCESS, Constants::Windows::STANDARD_RIGHTS_REQUIRED

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dcerpc_client) ⇒ Client

Returns a new instance of Client.



20
21
22
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 20

def initialize(dcerpc_client)
  self.dcerpc_client = dcerpc_client
end

Instance Attribute Details

#dcerpc_clientObject

Returns the value of attribute dcerpc_client.



18
19
20
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 18

def dcerpc_client
  @dcerpc_client
end

Instance Method Details

#changeservicedescription(svc_handle, service_description) ⇒ Integer

Calls ChangeServiceConfig2() to change the service description.

Parameters:

  • svc_handle (String)

    the service handle to change.

  • service_description (String)

    the service description.

Returns:

  • (Integer)

    Windows error code



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 139

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) ⇒ Integer

Calls CloseHandle() to close a handle.

Parameters:

  • handle (String)

    the handle to close.

Returns:

  • (Integer)

    Windows error code



164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 164

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) ⇒ Integer

Controls an existing service.

Parameters:

  • svc_handle (String)

    the handle of the service (from #openservicew).

  • operation (Fixnum)

    the operation number to perform (1 = stop service; others are unknown).

Returns:

  • (Integer)

    Windows error code



244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 244

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) ⇒ String, Integer

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

Parameters:

  • scm_handle (String)

    the SCM handle (from #openscmanagerw).

  • service_name (String)

    the service name.

  • display_name (String)

    the display name.

  • binary_path (String)

    the path of the binary to run.

  • opts (Hash)

    arguments for CreateServiceW()

Options Hash (opts):

  • :access (Fixnum) — default: SERVICE_ALL_ACCESS

    the access level.

  • :type (Fixnum) — default: SERVICE_WIN32_OWN_PROCESS || SERVICE_INTERACTIVE_PROCESS

    the type of service.

  • :start (Fixnum) — default: SERVICE_DEMAND_START

    the start options.

  • :errors (Fixnum) — default: SERVICE_ERROR_IGNORE

    the error options.

  • :load_order_group (Fixnum) — default: 0

    the load order group.

  • :dependencies (Fixnum) — default: 0

    the dependencies of the service.

  • :service_start (Fixnum) — default: 0
  • :password1 (Fixnum) — default: 0
  • :password2 (Fixnum) — default: 0
  • :password3 (Fixnum) — default: 0
  • :password4 (Fixnum) — default: 0

Returns:

  • (String, Integer)

    a handle to the created service, windows error code.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 85

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) ⇒ Integer

Calls DeleteService() to delete a service.

Parameters:

  • svc_handle (String)

    the handle of the service (from #openservicew).

Returns:

  • (Integer)

    Windows error code



263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 263

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) ⇒ Integer

Returns the Windows Error Code in numeric format

Parameters:

  • raw_error (String)

    the raw error code in binary format.

Returns:

  • (Integer)

    the Windows Error Code integer.



29
30
31
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 29

def error_code(raw_error)
  raw_error.unpack('V').first
end

#openscmanagerw(rhost, access = SC_MANAGER_ALL_ACCESS) ⇒ Array<String,Integer>

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

Parameters:

  • rhost (String)

    the target host.

  • access (Fixnum) (defaults to: SC_MANAGER_ALL_ACCESS)

    the access flags requested.

Returns:

  • (Array<String,Integer>)

    the handle to the service control manager or nil if the call is not successful and the Windows error code



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 40

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) ⇒ String?

Calls OpenServiceW to obtain a handle to an existing service.

Parameters:

  • scm_handle (String)

    the SCM handle (from #openscmanagerw).

  • service_name (String)

    the name of the service to open.

  • access (Fixnum) (defaults to: SERVICE_ALL_ACCESS)

    the level of access requested (default is maximum).

Returns:

  • (String, nil)

    the handle of the service opened, or nil on failure.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 185

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) ⇒ Fixnum

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

Parameters:

  • svc_handle (String)

    the handle of the service (from #openservicew).

Returns:

  • (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.



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 284

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) ⇒ Integer

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

Parameters:

  • svc_handle (String)

    the handle of the service (from #openservicew).

  • magic1 (Fixnum) (defaults to: 0)

    an unknown value.

  • magic2 (Fixnum) (defaults to: 0)

    another unknown value.

Returns:

  • (Integer)

    Windows error code



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 212

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) ⇒ Integer

Stops a running service.

Parameters:

  • svc_handle (String)

    the handle of the service (from #openservicew).

Returns:

  • (Integer)

    Windows error code



233
234
235
# File 'lib/rex/proto/dcerpc/svcctl/packet.rb', line 233

def stopservice(svc_handle)
  dce_controlservice(svc_handle, SERVICE_CONTROL_STOP)
end