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

Inherits:
Object
  • Object
show all
Includes:
Msf::Exploit::Windows_Constants, WindowsError::Win32
Defined in:
lib/rex/proto/dcerpc/svcctl/client.rb

Constant Summary

Constants included from Msf::Exploit::Windows_Constants

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dcerpc_client) ⇒ Client

Returns a new instance of Client.



22
23
24
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 22

def initialize(dcerpc_client)
  self.dcerpc_client = dcerpc_client
end

Instance Attribute Details

#dcerpc_clientObject

Returns the value of attribute dcerpc_client.



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

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



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

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
    elog('Error changing service description', error: 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



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

def closehandle(handle)
  svc_status = nil
  begin
    response = dcerpc_client.call(CLOSE_SERVICE_HANDLE, handle)
    if response
      svc_status = error_code(response)
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    elog('Error closing service handle', error: 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 (Integer)

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

Returns:

  • (Integer)

    Windows error code



274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 274

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
    elog('Error controlling service', error: 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 (Integer) — default: SERVICE_ALL_ACCESS

    the access level.

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

    the type of service.

  • :start (Integer) — default: SERVICE_DEMAND_START

    the start options.

  • :errors (Integer) — default: SERVICE_ERROR_IGNORE

    the error options.

  • :load_order_group (Integer) — default: 0

    the load order group.

  • :dependencies (Integer) — default: 0

    the dependencies of the service.

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

Returns:

  • (String, Integer)

    a handle to the created service, windows error code.



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
132
133
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 87

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)
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    elog('Error creating service', error: e)
  end

  if response
    svc_status = error_code(response[24,4])
    if svc_status == ERROR_SUCCESS
      svc_handle = response[4,20]
    end
  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



293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 293

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
    elog('Error deleting service', error: 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.



31
32
33
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 31

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



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

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
    elog('Error getting scm handle', error: 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 (Integer) (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.



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

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
    elog('Error opening service handle', error: e)
  end

  svc_handle
end

#queryservice(svc_handle) ⇒ Integer

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

Parameters:

  • svc_handle (String)

    the handle of the service (from #openservicew).

Returns:

  • (Integer)

    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.



314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 314

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
    elog('Error deleting service', error: e)
  end

  ret
end

#startservice(svc_handle, args = []) ⇒ 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).

  • args (Array) (defaults to: [])

    an array of arguments to pass to the service (or nil)

Returns:

  • (Integer)

    Windows error code



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 213

def startservice(svc_handle, args=[])
  svc_status = nil

  if args.empty?
    stubdata = svc_handle + NDR.long(0) + NDR.long(0)
  else
    # This is just an arbitrary "pointer" value, gonna match it to what the real version uses
    id_value = 0x00000200

    stubdata = svc_handle
    stubdata += NDR.long(args.length) + NDR.long(id_value) + NDR.long(args.length)

    # Encode an id value for each parameter
    args.each do
      id_value += 0x04000000
      stubdata += NDR.long(id_value)
    end

    # Encode the values now
    args.each do |arg|
      # We can't use NDR.uwstring here, because we need the "id" values to come first
      stubdata += NDR.long(arg.length + 1) + NDR.long(0) + NDR.long(arg.length + 1)

      # Unicode string
      stubdata += Rex::Text.to_unicode(arg + "\0")

      # Padding
      if((arg.length % 2) == 0)
        stubdata += Rex::Text.to_unicode("\0")
      end
    end
  end

  begin
    response = dcerpc_client.call(0x13, stubdata)
    if response
      svc_status = error_code(response)
    end
  rescue Rex::Proto::DCERPC::Exceptions::Fault => e
    elog('Error starting service', error: 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



263
264
265
# File 'lib/rex/proto/dcerpc/svcctl/client.rb', line 263

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