@@ -9,6 +9,9 @@ module Exploit::Remote::DCERPC_SERVICES
9
9
10
10
NDR = Rex ::Encoder ::NDR
11
11
12
+ SERVICE_ALL_ACCESS = 0x0F01FF
13
+ ERROR_SUCCESS = 0x0
14
+ ERROR_SERVICE_EXISTS = 0x431
12
15
13
16
# Calls OpenSCManagerW() to obtain a handle to the service control manager.
14
17
#
@@ -18,7 +21,7 @@ module Exploit::Remote::DCERPC_SERVICES
18
21
#
19
22
# @return [String] the handle to the service control manager or nil if
20
23
# the call is not successful.
21
- def dce_openscmanagerw ( dcerpc , rhost , access = 0xF003F )
24
+ def dce_openscmanagerw ( dcerpc , rhost , access = SERVICE_ALL_ACCESS )
22
25
scm_handle = nil
23
26
scm_status = nil
24
27
stubdata =
@@ -29,7 +32,7 @@ def dce_openscmanagerw(dcerpc, rhost, access = 0xF003F)
29
32
response = dcerpc . call ( 0x0f , stubdata )
30
33
if response
31
34
scm_status = response [ 20 , 4 ] . unpack ( 'V' ) . first
32
- if scm_status == 0
35
+ if scm_status == ERROR_SUCCESS
33
36
scm_handle = response [ 0 , 20 ]
34
37
end
35
38
end
@@ -63,10 +66,11 @@ def dce_openscmanagerw(dcerpc, rhost, access = 0xF003F)
63
66
# password3 [Fixnum]
64
67
# password4 [Fixnum]
65
68
#
66
- # @return [String] a handle to the created service.
69
+ # @return [String, Integer] a handle to the created service, windows
70
+ # error code.
67
71
def dce_createservicew ( dcerpc , scm_handle , service_name , display_name , binary_path , opts )
68
72
default_opts = {
69
- :access => 0x0F01FF , # Maximum access.
73
+ :access => SERVICE_ALL_ACCESS , # Maximum access.
70
74
:type => 0x00000110 , # Interactive, own process.
71
75
:start => 0x00000003 , # Start on demand.
72
76
:errors => 0x00000000 , # Ignore errors.
@@ -96,34 +100,40 @@ def dce_createservicew(dcerpc, scm_handle, service_name, display_name, binary_pa
96
100
NDR . long ( default_opts [ :password2 ] ) +
97
101
NDR . long ( default_opts [ :password3 ] ) +
98
102
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
104
107
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 } " )
107
114
end
108
- return svc_handle
115
+
116
+ return svc_handle , svc_status
109
117
end
110
118
111
- # Calls CloseHandle() to close a handle. Returns true on success, or false.
119
+ # Calls CloseHandle() to close a handle.
112
120
#
113
121
# @param dcerpc [Rex::Proto::DCERPC::Client] the DCERPC client to use.
114
122
# @param handle [String] the handle to close.
115
123
#
116
- # @return [Boolean] true if the handle was successfully closed, or false if
117
- # not.
124
+ # @return [Integer] Windows error code
118
125
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
124
131
end
132
+ rescue Rex ::Proto ::DCERPC ::Exceptions ::Fault => e
133
+ print_error ( "#{ peer } - Error closing service handle: #{ e } " )
125
134
end
126
- return ret
135
+
136
+ svc_status
127
137
end
128
138
129
139
# Calls OpenServiceW to obtain a handle to an existing service.
@@ -138,16 +148,19 @@ def dce_openservicew(dcerpc, scm_handle, service_name, access = 0xF01FF)
138
148
svc_handle = nil
139
149
svc_status = nil
140
150
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 } " )
145
161
end
146
162
147
- if svc_status . to_i != 0
148
- svc_handle = nil
149
- end
150
- return svc_handle
163
+ svc_handle
151
164
end
152
165
153
166
# 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)
159
172
# @param magic1 [Fixnum] an unknown value.
160
173
# @param magic2 [Fixnum] another unknown value.
161
174
#
162
- # @return [Boolean] true if the service was successfully started, false if
163
- # it was not.
175
+ # @return [Integer] Windows error code
164
176
def dce_startservice ( dcerpc , svc_handle , magic1 = 0 , magic2 = 0 )
165
- ret = false
177
+ svc_status = nil
166
178
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
171
184
end
185
+ rescue Rex ::Proto ::DCERPC ::Exceptions ::Fault => e
186
+ print_error ( "#{ peer } - Error starting service: #{ e } " )
172
187
end
173
- return ret
188
+
189
+ svc_status
174
190
end
175
191
176
192
# Stops a running service.
@@ -179,8 +195,7 @@ def dce_startservice(dcerpc, svc_handle, magic1 = 0, magic2 = 0)
179
195
# @param svc_handle [String] the handle of the service to stop (from
180
196
# dce_openservicew()).
181
197
#
182
- # @return [Boolean] true if the service was successfully stopped, false if
183
- # it was not.
198
+ # @return [Integer] Windows error code
184
199
def dce_stopservice ( dcerpc , svc_handle )
185
200
return dce_controlservice ( dcerpc , svc_handle , 1 )
186
201
end
@@ -193,17 +208,19 @@ def dce_stopservice(dcerpc, svc_handle)
193
208
# @param operation [Fixnum] the operation number to perform (1 = stop
194
209
# service; others are unknown).
195
210
#
196
- # @return [Boolean] true if the operation was successful, false if it was
197
- # not.
211
+ # @return [Integer] Windows error code
198
212
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
204
218
end
219
+ rescue Rex ::Proto ::DCERPC ::Exceptions ::Fault => e
220
+ print_error ( "#{ peer } - Error controlling service: #{ e } " )
205
221
end
206
- return ret
222
+
223
+ svc_status
207
224
end
208
225
209
226
# Calls DeleteService() to delete a service.
@@ -212,17 +229,19 @@ def dce_controlservice(dcerpc, svc_handle, operation)
212
229
# @param svc_handle [String] the handle of the service to delete (from
213
230
# dce_openservicew()).
214
231
#
215
- # @return [Boolean] true if the service was successfully deleted, false if
216
- # it was not.
232
+ # @return [Integer] Windows error code
217
233
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
223
239
end
240
+ rescue Rex ::Proto ::DCERPC ::Exceptions ::Fault => e
241
+ print_error ( "#{ peer } - Error deleting service: #{ e } " )
224
242
end
225
- return ret
243
+
244
+ svc_status
226
245
end
227
246
228
247
# Calls QueryServiceStatus() to query the status of a service.
@@ -236,14 +255,21 @@ def dce_deleteservice(dcerpc, svc_handle)
236
255
# 2 if the service is stopped.
237
256
def dce_queryservice ( dcerpc , svc_handle )
238
257
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 } " )
244
268
end
245
- return ret
269
+
270
+ ret
246
271
end
247
272
248
273
end
249
274
end
275
+
0 commit comments