Skip to content

Commit 54cf1ba

Browse files
committed
Use dcerpc_services
1 parent 3a2049e commit 54cf1ba

File tree

2 files changed

+94
-176
lines changed

2 files changed

+94
-176
lines changed

lib/msf/core/exploit/dcerpc_services.rb

Lines changed: 87 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ module Exploit::Remote::DCERPC_SERVICES
99

1010
NDR = Rex::Encoder::NDR
1111

12+
SERVICE_ALL_ACCESS = 0x0F01FF
13+
ERROR_SUCCESS = 0x0
14+
ERROR_SERVICE_EXISTS = 0x431
1215

1316
# Calls OpenSCManagerW() to obtain a handle to the service control manager.
1417
#
@@ -18,7 +21,7 @@ module Exploit::Remote::DCERPC_SERVICES
1821
#
1922
# @return [String] the handle to the service control manager or nil if
2023
# the call is not successful.
21-
def dce_openscmanagerw(dcerpc, rhost, access = 0xF003F)
24+
def dce_openscmanagerw(dcerpc, rhost, access = SERVICE_ALL_ACCESS)
2225
scm_handle = nil
2326
scm_status = nil
2427
stubdata =
@@ -29,7 +32,7 @@ def dce_openscmanagerw(dcerpc, rhost, access = 0xF003F)
2932
response = dcerpc.call(0x0f, stubdata)
3033
if response
3134
scm_status = response[20,4].unpack('V').first
32-
if scm_status == 0
35+
if scm_status == ERROR_SUCCESS
3336
scm_handle = response[0,20]
3437
end
3538
end
@@ -63,10 +66,11 @@ def dce_openscmanagerw(dcerpc, rhost, access = 0xF003F)
6366
# password3 [Fixnum]
6467
# password4 [Fixnum]
6568
#
66-
# @return [String] a handle to the created service.
69+
# @return [String, Integer] a handle to the created service, windows
70+
# error code.
6771
def dce_createservicew(dcerpc, scm_handle, service_name, display_name, binary_path, opts)
6872
default_opts = {
69-
:access => 0x0F01FF, # Maximum access.
73+
:access => SERVICE_ALL_ACCESS, # Maximum access.
7074
:type => 0x00000110, # Interactive, own process.
7175
:start => 0x00000003, # Start on demand.
7276
:errors => 0x00000000,# Ignore errors.
@@ -96,34 +100,40 @@ def dce_createservicew(dcerpc, scm_handle, service_name, display_name, binary_pa
96100
NDR.long(default_opts[:password2]) +
97101
NDR.long(default_opts[:password3]) +
98102
NDR.long(default_opts[:password4])
99-
response = dcerpc.call(0x0c, stubdata)
100-
if dcerpc.last_response and dcerpc.last_response.stub_data
101-
svc_handle = dcerpc.last_response.stub_data[4,20]
102-
svc_status = dcerpc.last_response.stub_data[20,4]
103-
end
103+
begin
104+
response = dcerpc.call(0x0c, stubdata)
105+
if response
106+
svc_status = response[20,4].unpack('V').first
104107

105-
if svc_status.to_i != 0
106-
svc_handle = nil
108+
if svc_status == ERROR_SUCCESS
109+
svc_handle = response[4,20]
110+
end
111+
end
112+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
113+
print_error("#{peer} - Error creating service: #{e}")
107114
end
108-
return svc_handle
115+
116+
return svc_handle, svc_status
109117
end
110118

111-
# Calls CloseHandle() to close a handle. Returns true on success, or false.
119+
# Calls CloseHandle() to close a handle.
112120
#
113121
# @param dcerpc [Rex::Proto::DCERPC::Client] the DCERPC client to use.
114122
# @param handle [String] the handle to close.
115123
#
116-
# @return [Boolean] true if the handle was successfully closed, or false if
117-
# not.
124+
# @return [Integer] Windows error code
118125
def dce_closehandle(dcerpc, handle)
119-
ret = false
120-
response = dcerpc.call(0x0, handle)
121-
if dcerpc.last_response and dcerpc.last_response.stub_data
122-
if dcerpc.last_response.stub_data[20,4].to_i == 0
123-
ret = true
126+
svc_status = nil
127+
begin
128+
response = dcerpc.call(0x0, handle)
129+
if response
130+
svc_status = response[20,4].unpack('V').first
124131
end
132+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
133+
print_error("#{peer} - Error closing service handle: #{e}")
125134
end
126-
return ret
135+
136+
svc_status
127137
end
128138

129139
# Calls OpenServiceW to obtain a handle to an existing service.
@@ -138,16 +148,19 @@ def dce_openservicew(dcerpc, scm_handle, service_name, access = 0xF01FF)
138148
svc_handle = nil
139149
svc_status = nil
140150
stubdata = scm_handle + NDR.wstring(service_name) + NDR.long(access)
141-
response = dcerpc.call(0x10, stubdata)
142-
if dcerpc.last_response and dcerpc.last_response.stub_data
143-
svc_handle = dcerpc.last_response.stub_data[0,20]
144-
svc_status = dcerpc.last_response.stub_data[20,4]
151+
begin
152+
response = dcerpc.call(0x10, stubdata)
153+
if response
154+
svc_status = response[20,4]
155+
if svc_status == ERROR_SUCCESS
156+
svc_handle = response[0,20]
157+
end
158+
end
159+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
160+
print_error("#{peer} - Error opening service handle: #{e}")
145161
end
146162

147-
if svc_status.to_i != 0
148-
svc_handle = nil
149-
end
150-
return svc_handle
163+
svc_handle
151164
end
152165

153166
# Calls StartService() on a handle to an existing service in order to start
@@ -159,18 +172,21 @@ def dce_openservicew(dcerpc, scm_handle, service_name, access = 0xF01FF)
159172
# @param magic1 [Fixnum] an unknown value.
160173
# @param magic2 [Fixnum] another unknown value.
161174
#
162-
# @return [Boolean] true if the service was successfully started, false if
163-
# it was not.
175+
# @return [Integer] Windows error code
164176
def dce_startservice(dcerpc, svc_handle, magic1 = 0, magic2 = 0)
165-
ret = false
177+
svc_status = nil
166178
stubdata = svc_handle + NDR.long(magic1) + NDR.long(magic2)
167-
response = dcerpc.call(0x13, stubdata)
168-
if dcerpc.last_response and dcerpc.last_response.stub_data
169-
if dcerpc.last_response.stub_data[0,4].to_i == 0
170-
ret = true
179+
180+
begin
181+
response = dcerpc.call(0x13, stubdata)
182+
if response
183+
svc_status = response[0,4].unpack('V').first
171184
end
185+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
186+
print_error("#{peer} - Error starting service: #{e}")
172187
end
173-
return ret
188+
189+
svc_status
174190
end
175191

176192
# Stops a running service.
@@ -179,8 +195,7 @@ def dce_startservice(dcerpc, svc_handle, magic1 = 0, magic2 = 0)
179195
# @param svc_handle [String] the handle of the service to stop (from
180196
# dce_openservicew()).
181197
#
182-
# @return [Boolean] true if the service was successfully stopped, false if
183-
# it was not.
198+
# @return [Integer] Windows error code
184199
def dce_stopservice(dcerpc, svc_handle)
185200
return dce_controlservice(dcerpc, svc_handle, 1)
186201
end
@@ -193,17 +208,19 @@ def dce_stopservice(dcerpc, svc_handle)
193208
# @param operation [Fixnum] the operation number to perform (1 = stop
194209
# service; others are unknown).
195210
#
196-
# @return [Boolean] true if the operation was successful, false if it was
197-
# not.
211+
# @return [Integer] Windows error code
198212
def dce_controlservice(dcerpc, svc_handle, operation)
199-
ret = false
200-
response = dcerpc.call(0x01, svc_handle + NDR.long(operation))
201-
if dcerpc.last_response and dcerpc.last_response.stub_data
202-
if dcerpc.last_response.stub_data[28,4].to_i == 0
203-
ret = true
213+
svc_status = nil
214+
begin
215+
response = dcerpc.call(0x01, svc_handle + NDR.long(operation))
216+
if response
217+
svc_status = dcerpc.last_response.stub_data[28,4].unpack('V').first
204218
end
219+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
220+
print_error("#{peer} - Error controlling service: #{e}")
205221
end
206-
return ret
222+
223+
svc_status
207224
end
208225

209226
# Calls DeleteService() to delete a service.
@@ -212,17 +229,19 @@ def dce_controlservice(dcerpc, svc_handle, operation)
212229
# @param svc_handle [String] the handle of the service to delete (from
213230
# dce_openservicew()).
214231
#
215-
# @return [Boolean] true if the service was successfully deleted, false if
216-
# it was not.
232+
# @return [Integer] Windows error code
217233
def dce_deleteservice(dcerpc, svc_handle)
218-
ret = false
219-
response = dcerpc.call(0x02, svc_handle)
220-
if dcerpc.last_response and dcerpc.last_response.stub_data
221-
if dcerpc.last_response.stub_data[0,4].to_i == 0
222-
ret = true
234+
svc_status = nil
235+
begin
236+
response = dcerpc.call(0x02, svc_handle)
237+
if response
238+
svc_status = response[0,4].unpack('V').first
223239
end
240+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
241+
print_error("#{peer} - Error deleting service: #{e}")
224242
end
225-
return ret
243+
244+
svc_status
226245
end
227246

228247
# Calls QueryServiceStatus() to query the status of a service.
@@ -236,14 +255,21 @@ def dce_deleteservice(dcerpc, svc_handle)
236255
# 2 if the service is stopped.
237256
def dce_queryservice(dcerpc, svc_handle)
238257
ret = 0
239-
response = dcerpc.call(0x06, svc_handle)
240-
if response[0,9] == "\x10\x00\x00\x00\x04\x00\x00\x00\x01"
241-
ret = 1
242-
elsif response[0,9] == "\x10\x00\x00\x00\x01\x00\x00\x00\x00"
243-
ret = 2
258+
259+
begin
260+
response = dcerpc.call(0x06, svc_handle)
261+
if response[0,9] == "\x10\x00\x00\x00\x04\x00\x00\x00\x01"
262+
ret = 1
263+
elsif response[0,9] == "\x10\x00\x00\x00\x01\x00\x00\x00\x00"
264+
ret = 2
265+
end
266+
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
267+
print_error("#{peer} - Error deleting service: #{e}")
244268
end
245-
return ret
269+
270+
ret
246271
end
247272

248273
end
249274
end
275+

0 commit comments

Comments
 (0)