1###############################################################################
2#  Tested so far:
3#  hRCloseServiceHandleCall
4#  RControlService
5#  RDeleteService
6#  RLockServiceDatabase
7#  RQueryServiceObjectSecurity
8#  RQueryServiceStatus
9#  RUnlockServiceDatabase
10#  RNotifyBootConfigStatus
11#  RChangeServiceConfigW
12#  RCreateServiceW
13#  REnumDependentServicesW
14#  REnumServicesStatusW
15#  ROpenSCManager
16#  ROpenServiceW
17#  RQueryServiceConfigW
18#  RQueryServiceLockStatusW
19#  RStartServiceW
20#  CRGetServiceDisplayNameW
21#  RGetServiceKeyNameW
22#  REnumServiceGroupW
23#  RChangeServiceConfig2W
24#  RQueryServiceConfig2W
25#  RQueryServiceStatusEx
26#  REnumServicesStatusExW
27#  RNotifyServiceStatusChange
28#  RGetNotifyResults
29#  RCloseNotifyHandle
30#  RControlServiceExW
31#  RQueryServiceConfigEx
32#
33#  Not yet:
34#
35#  RSetServiceObjectSecurity
36#  RSetServiceStatus
37#  RCreateServiceWOW64W
38#
39# Shouldn't dump errors against a win7
40#
41################################################################################
42
43import unittest
44import ConfigParser
45from struct import unpack
46
47from impacket.dcerpc.v5 import transport
48from impacket.dcerpc.v5 import scmr, epm
49from impacket.dcerpc.v5.ndr import NULL
50from impacket.crypto import encryptSecret
51from impacket.uuid import string_to_bin
52from impacket import ntlm
53
54
55class SCMRTests(unittest.TestCase):
56    def changeServiceAndQuery(self, dce, cbBufSize, hService, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName):
57
58        try:
59            resp = scmr.hRChangeServiceConfigW( dce, hService, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
60
61            resp = scmr.hRQueryServiceConfigW(dce, hService)
62            resp.dump()
63            # Now let's compare all the results
64            if dwServiceType != scmr.SERVICE_NO_CHANGE:
65                self.assertTrue( resp['lpServiceConfig']['dwServiceType'] == dwServiceType )
66            if dwStartType != scmr.SERVICE_NO_CHANGE:
67                self.assertTrue( resp['lpServiceConfig']['dwStartType'] == dwStartType )
68            if dwErrorControl != scmr.SERVICE_NO_CHANGE:
69                self.assertTrue( resp['lpServiceConfig']['dwErrorControl'] == dwErrorControl )
70            if lpBinaryPathName != NULL:
71                self.assertTrue( resp['lpServiceConfig']['lpBinaryPathName'] == lpBinaryPathName )
72            if lpBinaryPathName != NULL:
73                self.assertTrue( resp['lpServiceConfig']['lpBinaryPathName'] == lpBinaryPathName )
74            if lpLoadOrderGroup != NULL:
75                self.assertTrue( resp['lpServiceConfig']['lpLoadOrderGroup'] == lpLoadOrderGroup )
76            #if lpDependencies != '':
77            #    self.assertTrue( resp['lpServiceConfig']['lpDependencies'] == lpDependencies[:-4]+'/\x00\x00\x00')
78            if lpServiceStartName != NULL:
79                self.assertTrue( resp['lpServiceConfig']['lpServiceStartName'] == lpServiceStartName )
80            if lpDisplayName != NULL:
81                self.assertTrue( resp['lpServiceConfig']['lpDisplayName'] == lpDisplayName )
82            #if lpdwTagId != scmr.SERVICE_NO_CHANGE:
83            #    if resp['lpServiceConfig']['dwTagId']['Data'] != lpdwTagId:
84            #        print "ERROR %s" % 'lpdwTagId'
85        except:
86            resp = scmr.hRDeleteService(dce, hService)
87            raise
88
89    def changeServiceAndQuery2(self, dce, info, changeDone):
90        serviceHandle = info['hService']
91        dwInfoLevel = info['Info']['Union']['tag']
92        cbBuffSize = 0
93        request = scmr.RQueryServiceConfig2W()
94        request['hService'] = serviceHandle
95        request['dwInfoLevel'] = dwInfoLevel
96        request['cbBufSize'] = cbBuffSize
97        try:
98            resp = dce.request(request)
99        except Exception, e:
100            if str(e).find('ERROR_INSUFFICIENT_BUFFER') <= 0:
101                raise
102            else:
103                resp = e.get_packet()
104
105        request['cbBufSize'] = resp['pcbBytesNeeded']
106        resp = dce.request(request)
107        arrayData = ''.join(resp['lpBuffer'])
108        if dwInfoLevel == 1:
109           self.assertTrue(arrayData[4:].decode('utf-16le') == changeDone)
110        elif dwInfoLevel == 2:
111           offset = unpack('<L', arrayData[4:][:4])[0]
112           self.assertTrue(arrayData[offset:][:len(changeDone)*2].decode('utf-16le') == changeDone)
113        elif dwInfoLevel == 3:
114           self.assertTrue( unpack('<L', arrayData)[0] == changeDone)
115        elif dwInfoLevel == 4:
116           self.assertTrue( unpack('<L', arrayData)[0] == changeDone)
117        elif dwInfoLevel == 5:
118           self.assertTrue( unpack('<L', arrayData)[0] == changeDone)
119        elif dwInfoLevel == 6:
120           changeDone = ''.join(changeDone).decode('utf-16le')
121           self.assertTrue(arrayData[4:].decode('utf-16le') == changeDone)
122        elif dwInfoLevel == 7:
123           self.assertTrue( unpack('<L', arrayData)[0] == changeDone)
124
125    def connect(self):
126        rpctransport = transport.DCERPCTransportFactory(self.stringBinding)
127        if len(self.hashes) > 0:
128            lmhash, nthash = self.hashes.split(':')
129        else:
130            lmhash = ''
131            nthash = ''
132        if hasattr(rpctransport, 'set_credentials'):
133            # This method exists only for selected protocol sequences.
134            rpctransport.set_credentials(self.username,self.password, self.domain, lmhash, nthash)
135        dce = rpctransport.get_dce_rpc()
136        #dce.set_max_fragment_size(32)
137        dce.connect()
138        if self.__class__.__name__ == 'TCPTransport':
139            dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)
140        dce.bind(scmr.MSRPC_UUID_SCMR)
141        #rpc = scmr.DCERPCSvcCtl(dce)
142        lpMachineName = 'DUMMY\x00'
143        lpDatabaseName = 'ServicesActive\x00'
144        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS | scmr.SC_MANAGER_ENUMERATE_SERVICE
145
146        resp = scmr.hROpenSCManagerW(dce,lpMachineName, lpDatabaseName, desiredAccess)
147        scHandle = resp['lpScHandle']
148
149        return dce, rpctransport, scHandle
150
151    def test_RChangeServiceConfig2W(self):
152        dce, rpctransport, scHandle  = self.connect()
153        lpServiceName = 'TESTSVC\x00'
154        lpDisplayName = 'DisplayName\x00'
155        dwDesiredAccess = scmr.SERVICE_ALL_ACCESS
156        dwServiceType = scmr.SERVICE_WIN32_OWN_PROCESS
157        dwStartType = scmr.SERVICE_DEMAND_START
158        dwErrorControl = scmr.SERVICE_ERROR_NORMAL
159        lpBinaryPathName = 'binaryPath\x00'
160        lpLoadOrderGroup = NULL
161        lpdwTagId = NULL
162        lpDependencies = NULL
163        dwDependSize = 0
164        lpServiceStartName = NULL
165        lpPassword = NULL
166        dwPwSize = 0
167        resp = scmr.hRCreateServiceW(dce, scHandle, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize)
168        resp.dump()
169        newHandle = resp['lpServiceHandle']
170        error = False
171        try:
172            request = scmr.RChangeServiceConfig2W()
173            request['hService'] = newHandle
174            request['Info']['dwInfoLevel'] = 1
175            request['Info']['Union']['tag'] = 1
176            request['Info']['Union']['psd']['lpDescription'] = u'betobeto\x00'
177            resp = dce.request(request)
178            resp.dump()
179            self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psd']['lpDescription'])
180            request['Info']['dwInfoLevel'] = 2
181            request['Info']['Union']['tag'] = 2
182            request['Info']['Union']['psfa']['lpRebootMsg'] = u'rebootMsg\00'
183            request['Info']['Union']['psfa']['lpCommand'] = u'lpCommand\00'
184            resp = dce.request(request)
185            resp.dump()
186            self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psfa']['lpRebootMsg'])
187            request['Info']['dwInfoLevel'] = 3
188            request['Info']['Union']['tag'] = 3
189            request['Info']['Union']['psda']['fDelayedAutostart'] = 1
190            resp = dce.request(request)
191            self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psda']['fDelayedAutostart'])
192            request['Info']['dwInfoLevel'] = 4
193            request['Info']['Union']['tag'] = 4
194            request['Info']['Union']['psfaf']['fFailureActionsOnNonCrashFailures'] = 1
195            resp = dce.request(request)
196            self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psfaf']['fFailureActionsOnNonCrashFailures'])
197            request['Info']['dwInfoLevel'] = 5
198            request['Info']['Union']['tag'] = 5
199            request['Info']['Union']['pssid']['dwServiceSidType'] = 1
200            resp = dce.request(request)
201            self.changeServiceAndQuery2(dce, request, request['Info']['Union']['pssid']['dwServiceSidType'])
202            request['Info']['dwInfoLevel'] = 6
203            request['Info']['Union']['tag'] = 6
204            request['Info']['Union']['psrp']['pRequiredPrivileges'] = list(u'SeAssignPrimaryTokenPrivilege\x00\x00'.encode('utf-16le'))
205            resp = dce.request(request)
206            self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psrp']['pRequiredPrivileges'])
207            request['Info']['dwInfoLevel'] = 7
208            request['Info']['Union']['tag'] = 7
209            request['Info']['Union']['psps']['dwPreshutdownTimeout'] = 22
210            resp = dce.request(request)
211            self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psps']['dwPreshutdownTimeout'])
212            request['Info']['dwInfoLevel'] = 8
213            request['Info']['Union']['tag'] = 8
214            #request.dump()
215            trigger = scmr.SERVICE_TRIGGER()
216            trigger['dwTriggerType'] = scmr.SERVICE_TRIGGER_TYPE_DOMAIN_JOIN
217            trigger['dwAction'] = scmr.SERVICE_TRIGGER_ACTION_SERVICE_START
218            trigger['pTriggerSubtype'] = string_to_bin(scmr.DOMAIN_JOIN_GUID)
219            item = scmr.SERVICE_TRIGGER_SPECIFIC_DATA_ITEM()
220            item['dwDataType'] = scmr.SERVICE_TRIGGER_DATA_TYPE_STRING
221            item['pData'] = list(u'FREEFLY\x00'.encode('utf-16le'))
222            #trigger['pDataItems'].append(item)
223            trigger['pDataItems'] = NULL
224            request['Info']['Union']['psti']['pTriggers'].append(trigger)
225            resp = dce.request(request)
226            #self.changeServiceAndQuery2(dce, request, '\x00')
227            request['Info']['dwInfoLevel'] = 9
228            request['Info']['Union']['tag'] = 9
229            request['Info']['Union']['pspn']['usPreferredNode'] = 22
230            # This one doesn't work
231            #resp = dce.request(request)
232            #self.changeServiceAndQuery2(dce, request, request['Info']['Union']['pspn']['usPreferredNode'])
233            request['Info']['dwInfoLevel'] = 10
234            request['Info']['Union']['tag'] = 10
235            request['Info']['Union']['psri']['eLowestRunLevel'] = 1
236            # This one doesn't work
237            #resp = dce.request(request)
238            #self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psri']['eLowestRunLevel'])
239            request['Info']['dwInfoLevel'] = 11
240            request['Info']['Union']['tag'] = 11
241            request['Info']['Union']['psma']['fIsManagedAccount'] = 1
242            # This one doesn't work
243            #resp = dce.request(request)
244            #self.changeServiceAndQuery2(dce, request, request['Info']['Union']['psma']['fIsManagedAccount'])
245
246        except Exception, e:
247            import traceback
248            traceback.print_exc()
249            print e
250            error = True
251            pass
252
253        resp = scmr.hRDeleteService(dce, newHandle)
254        resp = scmr.hRCloseServiceHandle(dce, newHandle)
255        resp = scmr.hRCloseServiceHandle(dce, scHandle)
256        if error:
257            self.assertTrue( 1 == 0 )
258
259    def test_REnumServicesStatusExW(self):
260        dce, rpctransport, scHandle  = self.connect()
261
262        request = scmr.REnumServicesStatusExW()
263        request['hSCManager'] = scHandle
264        request['InfoLevel'] = scmr.SC_STATUS_PROCESS_INFO
265        request['dwServiceType'] = scmr.SERVICE_WIN32_OWN_PROCESS
266        request['dwServiceState'] = scmr.SERVICE_STATE_ALL
267        request['lpResumeIndex'] = NULL
268        request['pszGroupName'] = NULL
269        request['cbBufSize'] = 0
270        #request.dump()
271        #print "\n"
272
273        # Request again with the right bufSize
274        try:
275            resp = dce.request(request)
276        except Exception, e:
277            if str(e).find('ERROR_MORE_DATA') <= 0:
278                raise
279            else:
280                resp = e.get_packet()
281        resp.dump()
282        request['cbBufSize'] = resp['pcbBytesNeeded']
283        resp = dce.request(request)
284        resp.dump()
285
286    def test_RQueryServiceStatusEx(self):
287        dce, rpctransport, scHandle  = self.connect()
288        lpServiceName = 'PlugPlay\x00'
289        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS
290
291        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
292        resp.dump()
293
294        serviceHandle = resp['lpServiceHandle']
295
296        request = scmr.RQueryServiceStatusEx()
297        request['hService'] = serviceHandle
298        request['InfoLevel'] = scmr.SC_STATUS_PROCESS_INFO
299        request['cbBufSize'] = 100
300
301        resp = dce.request(request)
302        array = ''.join(resp['lpBuffer'])
303        status = scmr.SERVICE_STATUS_PROCESS(array)
304        #status.dump()
305
306    # ToDo
307    def te_REnumServiceGroupW(self):
308        dce, rpctransport, scHandle  = self.connect()
309
310
311        dwServiceType = scmr.SERVICE_WIN32_OWN_PROCESS
312        dwServiceState = scmr.SERVICE_STATE_ALL
313        cbBufSize = 10
314        lpResumeIndex = 0
315        pszGroupName = 'RemoteRegistry\x00'
316
317        try:
318            resp = scmr.hREnumServiceGroupW(dce, scHandle, dwServiceType, dwServiceState, cbBufSize, lpResumeIndex, pszGroupName )
319            resp.dump()
320        except Exception, e:
321           if str(e).find('ERROR_SERVICE_DOES_NOT_EXISTS') <= 0:
322               raise
323
324        resp = scmr.hRCloseServiceHandle(dce, scHandle)
325
326    def test_RQueryServiceConfigEx(self):
327        dce, rpctransport, scHandle  = self.connect()
328        lpServiceName = 'RemoteRegistry\x00'
329        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS
330
331        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
332        resp.dump()
333        serviceHandle = resp['lpServiceHandle']
334
335        request = scmr.RQueryServiceConfigEx()
336        request['hService'] = serviceHandle
337        request['dwInfoLevel'] = 0x00000008
338        #request.dump()
339
340        resp = dce.request(request)
341        resp.dump()
342
343    # ToDo
344    def te_RControlServiceExW(self):
345        dce, rpctransport, scHandle  = self.connect()
346        lpServiceName = 'PlugPlay\x00'
347        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS
348
349        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
350        resp.dump()
351        serviceHandle = resp['lpServiceHandle']
352
353        request = scmr.RControlServiceExW()
354        request['hService'] = serviceHandle
355        request['dwControl'] = scmr.SERVICE_CONTROL_STOP
356        request['dwInfoLevel'] = 1
357        # This is not working, don't know exactly why
358        request['pControlInParams']['dwReason'] = 0x20000000
359        request['pControlInParams']['pszComment'] = 'nada\x00'
360        request['pControlInParams'] = NULL
361
362        resp = dce.request(request)
363
364        resp.dump()
365
366    # ToDo
367    def te_RNotifyServiceStatusChange(self):
368        dce, rpctransport, scHandle  = self.connect()
369        lpServiceName = 'PlugPlay\x00'
370        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS
371
372        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
373        resp.dump()
374        serviceHandle = resp['lpServiceHandle']
375
376        request = scmr.RNotifyServiceStatusChange()
377        request['hService'] =serviceHandle
378        request['NotifyParams']['tag']  = 1
379        request['NotifyParams']['pStatusChangeParam1']['dwNotifyMask'] = scmr.SERVICE_NOTIFY_RUNNING
380        request['pClientProcessGuid'] = '0'*16
381        #request.dump()
382        resp = dce.request(request)
383        resp.dump()
384
385        request = scmr.RCloseNotifyHandle()
386        request['phNotify'] = resp['phNotify']
387
388        resp = dce.request(request)
389        resp.dump()
390
391        request = scmr.RGetNotifyResults()
392        request['hNotify'] = resp['phNotify']
393
394        resp = dce.request(request)
395        resp.dump()
396
397    def test_RGetServiceDisplayNameW(self):
398        dce, rpctransport, scHandle  = self.connect()
399
400        lpServiceName = 'PlugPlay\x00'
401        lpcchBuffer = len(lpServiceName)+100
402
403        resp = scmr.hRGetServiceDisplayNameW(dce, scHandle, lpServiceName, lpcchBuffer)
404
405        resp = scmr.hRCloseServiceHandle(dce, scHandle)
406
407    def test_RGetServiceKeyNameW(self):
408        dce, rpctransport, scHandle  = self.connect()
409
410        lpDisplayName = 'Plug and Play\x00'
411        lpcchBuffer = len(lpDisplayName)+100
412
413        resp = scmr.hRGetServiceKeyNameW(dce, scHandle, lpDisplayName, lpcchBuffer)
414
415        resp = scmr.hRCloseServiceHandle(dce, scHandle)
416
417    def test_RStartServiceW(self):
418        dce, rpctransport, scHandle  = self.connect()
419
420        lpServiceName = 'PlugPlay\x00'
421        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS
422
423        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
424        resp.dump()
425        serviceHandle = resp['lpServiceHandle']
426
427        try:
428            resp = scmr.hRStartServiceW(dce, serviceHandle, 3, ['arg1\x00', 'arg2\x00', 'arg3\x00'] )
429        except Exception, e:
430           if str(e).find('ERROR_SERVICE_ALREADY_RUNNING') <= 0:
431               raise
432        resp = scmr.hRCloseServiceHandle(dce, scHandle)
433
434    def test_RQueryServiceLockStatusW(self):
435        dce, rpctransport, scHandle  = self.connect()
436
437        pcbBytesNeeded = 1000
438        resp = scmr.hRQueryServiceLockStatusW(dce, scHandle, pcbBytesNeeded)
439
440        resp = scmr.hRCloseServiceHandle(dce, scHandle)
441
442    def test_enumservices(self):
443        dce, rpctransport, scHandle  = self.connect()
444
445        #####################
446        # EnumServicesStatusW
447        dwServiceType = scmr.SERVICE_KERNEL_DRIVER | scmr.SERVICE_FILE_SYSTEM_DRIVER | scmr.SERVICE_WIN32_OWN_PROCESS | scmr.SERVICE_WIN32_SHARE_PROCESS
448        dwServiceState = scmr.SERVICE_STATE_ALL
449        cbBufSize = 0
450        resp = scmr.hREnumServicesStatusW(dce, scHandle, dwServiceType, dwServiceState)
451
452        resp = scmr.hRCloseServiceHandle(dce, scHandle)
453
454    def test_create_change_delete(self):
455        dce, rpctransport, scHandle  = self.connect()
456
457        #####################
458        # Create / Change /  Query / Delete a service
459        lpServiceName = 'TESTSVC\x00'
460        lpDisplayName = 'DisplayName\x00'
461        dwDesiredAccess = scmr.SERVICE_ALL_ACCESS
462        dwServiceType = scmr.SERVICE_WIN32_OWN_PROCESS
463        dwStartType = scmr.SERVICE_DEMAND_START
464        dwErrorControl = scmr.SERVICE_ERROR_NORMAL
465        lpBinaryPathName = 'binaryPath\x00'
466        lpLoadOrderGroup = NULL
467        lpdwTagId = NULL
468        lpDependencies = NULL
469        dwDependSize = 0
470        lpServiceStartName = NULL
471        lpPassword = NULL
472        dwPwSize = 0
473        resp = scmr.hRCreateServiceW(dce, scHandle, lpServiceName, lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize)
474        resp.dump()
475        newHandle = resp['lpServiceHandle']
476
477        # Aca hay que chequear cada uno de los items
478        cbBufSize = 0
479        try:
480            resp = scmr.hRQueryServiceConfigW(dce, newHandle)
481        except Exception, e:
482            if str(e).find('ERROR_INSUFFICIENT_BUFFER') <= 0:
483                raise
484            else:
485                resp = e.get_packet()
486
487        resp.dump()
488        cbBufSize = resp['pcbBytesNeeded']+100
489
490        # Now that we have cbBufSize, let's start changing everything on the service
491        dwServiceType = scmr.SERVICE_WIN32_SHARE_PROCESS
492        dwStartType = scmr.SERVICE_NO_CHANGE
493        dwErrorControl = scmr.SERVICE_NO_CHANGE
494        lpBinaryPathName = NULL
495        lpLoadOrderGroup = NULL
496        lpDependencies = NULL
497        dwDependSize = 0
498        lpServiceStartName = NULL
499        lpPassword = NULL
500        dwPwSize = 0
501        lpDisplayName = NULL
502        lpdwTagId = NULL
503
504        self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
505        dwServiceType = scmr.SERVICE_NO_CHANGE
506
507        dwStartType = scmr.SERVICE_DISABLED
508        self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
509        dwStartType = scmr.SERVICE_NO_CHANGE
510
511        dwErrorControl = scmr.SERVICE_ERROR_SEVERE
512        self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
513        dwErrorControl = scmr.SERVICE_NO_CHANGE
514
515        lpBinaryPathName = 'BETOBETO\x00'
516        self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
517        lpBinaryPathName = NULL
518
519        lpLoadOrderGroup = 'KKKK\x00'
520        self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
521        lpLoadOrderGroup = NULL
522
523        #lpdwTagId = [0]
524        #self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
525        #lpdwTagId = ''
526
527        lpDependencies = 'RemoteRegistry\x00\x00'.encode('utf-16le')
528        dwDependSize = len(lpDependencies)
529        self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
530        lpDependencies = NULL
531        dwDependSize = 0
532
533        lpServiceStartName = '.\\Administrator\x00'
534        self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
535        lpServiceStartName = NULL
536
537        if self.__class__.__name__ == 'SMBTransport':
538            lpPassword = 'mypwd\x00'.encode('utf-16le')
539            s = rpctransport.get_smb_connection()
540            key = s.getSessionKey()
541            lpPassword = encryptSecret(key, lpPassword)
542            dwPwSize = len(lpPassword)
543            self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
544            lpPassword = NULL
545            dwPwSize = 0
546
547            lpDisplayName = 'MANOLO\x00'
548            self.changeServiceAndQuery(dce, cbBufSize, newHandle, dwServiceType, dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, lpDependencies, dwDependSize, lpServiceStartName, lpPassword, dwPwSize, lpDisplayName)
549            lpDisplayName = NULL
550
551        resp = scmr.hRDeleteService(dce, newHandle)
552        resp = scmr.hRCloseServiceHandle(dce, newHandle)
553        resp = scmr.hRCloseServiceHandle(dce, scHandle)
554
555    def test_query(self):
556        dce, rpctransport, scHandle  = self.connect()
557
558        ############################
559        # Query Service Status / Enum Dependent
560        lpServiceName = 'PlugPlay\x00'
561        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS
562
563        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
564        resp.dump()
565
566        serviceHandle = resp['lpServiceHandle']
567
568        resp = scmr.hRQueryServiceStatus(dce, serviceHandle)
569
570        cbBufSize = 0
571        try:
572            resp = scmr.hREnumDependentServicesW(dce, serviceHandle, scmr.SERVICE_STATE_ALL,cbBufSize )
573            resp.dump()
574        except scmr.DCERPCSessionError, e:
575           if str(e).find('ERROR_MORE_DATA') <= 0:
576               raise
577           else:
578               resp = e.get_packet()
579
580        resp.dump()
581        cbBufSize = resp['pcbBytesNeeded']
582        resp = scmr.hREnumDependentServicesW(dce, serviceHandle, scmr.SERVICE_STATE_ALL,cbBufSize )
583        resp.dump()
584        resp = scmr.hRCloseServiceHandle(dce, serviceHandle)
585        resp = scmr.hRCloseServiceHandle(dce, scHandle)
586
587    def test_lock_unlock(self):
588        dce, rpctransport, scHandle  = self.connect()
589
590        resp = scmr.hRLockServiceDatabase(dce, scHandle)
591        lockHandle = resp['lpLock']
592        resp = scmr.hRUnlockServiceDatabase(dce, lockHandle)
593
594        resp = scmr.hRCloseServiceHandle(dce, scHandle)
595
596    def test_query_set_object_security(self):
597        dce, rpctransport, scHandle  = self.connect()
598
599        try:
600            resp = scmr.hRQueryServiceObjectSecurity(dce, scHandle, scmr.DACL_SECURITY_INFORMATION, 0)
601            resp.dump()
602        except Exception, e:
603           if str(e).find('rpc_s_access_denied') <= 0:
604               raise
605
606        resp = scmr.hRCloseServiceHandle(dce, scHandle)
607
608    def atest_notify_config(self):
609        dce, rpctransport, scHandle  = self.connect()
610        lpMachineName = 'DUMMY\x00'
611
612        try:
613            resp = scmr.hRNotifyBootConfigStatus(dce, lpMachineName, 0x0)
614            resp.dump()
615        except scmr.DCERPCSessionError, e:
616           if str(e).find('ERROR_BOOT_ALREADY_ACCEPTED') <= 0:
617               raise
618
619        resp = scmr.hRCloseServiceHandle(dce, scHandle)
620
621    def test_RControlServiceCall(self):
622        dce, rpctransport, scHandle  = self.connect()
623        lpServiceName = 'CryptSvc\x00'
624        desiredAccess = scmr.SERVICE_START | scmr.SERVICE_STOP | scmr.SERVICE_CHANGE_CONFIG | scmr.SERVICE_QUERY_CONFIG | scmr.SERVICE_QUERY_STATUS | scmr.SERVICE_ENUMERATE_DEPENDENTS
625
626        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
627        resp.dump()
628
629        serviceHandle = resp['lpServiceHandle']
630
631        try:
632            req = scmr.RControlService()
633            req['hService'] = serviceHandle
634            req['dwControl'] = scmr.SERVICE_CONTROL_STOP
635            resp = dce.request(req)
636        except Exception, e:
637            if str(e).find('ERROR_DEPENDENT_SERVICES_RUNNING') < 0 and str(e).find('ERROR_SERVICE_NOT_ACTIVE') < 0:
638                raise
639            pass
640
641        resp = scmr.hRCloseServiceHandle(dce, serviceHandle)
642        import time
643        time.sleep(1)
644        resp = scmr.hROpenServiceW(dce, scHandle, lpServiceName, desiredAccess )
645        resp.dump()
646
647        serviceHandle = resp['lpServiceHandle']
648
649        try:
650            resp = scmr.hRStartServiceW(dce, serviceHandle, 0, NULL )
651            resp.dump()
652        except Exception, e:
653            if str(e).find('ERROR_SERVICE_ALREADY_RUNNING') < 0:
654                raise
655        return
656
657class SMBTransport(SCMRTests):
658    def setUp(self):
659        SCMRTests.setUp(self)
660        configFile = ConfigParser.ConfigParser()
661        configFile.read('dcetests.cfg')
662        self.username = configFile.get('SMBTransport', 'username')
663        self.domain   = configFile.get('SMBTransport', 'domain')
664        self.serverName = configFile.get('SMBTransport', 'servername')
665        self.password = configFile.get('SMBTransport', 'password')
666        self.machine  = configFile.get('SMBTransport', 'machine')
667        self.hashes   = configFile.get('SMBTransport', 'hashes')
668        self.stringBinding = r'ncacn_np:%s[\pipe\svcctl]' % self.machine
669
670class TCPTransport(SCMRTests):
671    def setUp(self):
672        SCMRTests.setUp(self)
673        configFile = ConfigParser.ConfigParser()
674        configFile.read('dcetests.cfg')
675        self.username = configFile.get('TCPTransport', 'username')
676        self.domain   = configFile.get('TCPTransport', 'domain')
677        self.serverName = configFile.get('TCPTransport', 'servername')
678        self.password = configFile.get('TCPTransport', 'password')
679        self.machine  = configFile.get('TCPTransport', 'machine')
680        self.hashes   = configFile.get('TCPTransport', 'hashes')
681        #print epm.hept_map(self.machine, samr.MSRPC_UUID_SAMR, protocol = 'ncacn_ip_tcp')
682        self.stringBinding = epm.hept_map(self.machine, scmr.MSRPC_UUID_SCMR, protocol = 'ncacn_ip_tcp')
683
684# Process command-line arguments.
685if __name__ == '__main__':
686    import sys
687    if len(sys.argv) > 1:
688        testcase = sys.argv[1]
689        suite = unittest.TestLoader().loadTestsFromTestCase(globals()[testcase])
690    else:
691        suite = unittest.TestLoader().loadTestsFromTestCase(SMBTransport)
692        #suite = unittest.TestLoader().loadTestsFromTestCase(TCPTransport)
693        suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TCPTransport))
694    unittest.TextTestRunner(verbosity=1).run(suite)
695