Coverage for /root/GitHubProjects/impacket/impacket/examples/serviceinstall.py : 7%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Impacket - Collection of Python classes for working with network protocols.
2#
3# SECUREAUTH LABS. Copyright (C) 2019 SecureAuth Corporation. All rights reserved.
4#
5# This software is provided under a slightly modified version
6# of the Apache Software License. See the accompanying LICENSE file
7# for more information.
8#
9# Description:
10# Service Install Helper library used by psexec and smbrelayx
11# You provide an already established connection and an exefile
12# (or class that mimics a file class) and this will install and
13# execute the service, and then uninstall (install(), uninstall().
14# It tries to take care as much as possible to leave everything clean.
15#
16# Author:
17# Alberto Solino (@agsolino)
18#
20import random
21import string
23from impacket.dcerpc.v5 import transport, srvs, scmr
24from impacket import smb,smb3, LOG
25from impacket.smbconnection import SMBConnection
26from impacket.smb3structs import FILE_WRITE_DATA, FILE_DIRECTORY_FILE
28class ServiceInstall:
29 def __init__(self, SMBObject, exeFile, serviceName='', binary_service_name=None):
30 self._rpctransport = 0
31 self.__service_name = serviceName if len(serviceName) > 0 else ''.join([random.choice(string.ascii_letters) for i in range(4)])
33 if binary_service_name is None:
34 self.__binary_service_name = ''.join([random.choice(string.ascii_letters) for i in range(8)]) + '.exe'
35 else:
36 self.__binary_service_name = binary_service_name
38 self.__exeFile = exeFile
40 # We might receive two different types of objects, always end up
41 # with a SMBConnection one
42 if isinstance(SMBObject, smb.SMB) or isinstance(SMBObject, smb3.SMB3):
43 self.connection = SMBConnection(existingConnection = SMBObject)
44 else:
45 self.connection = SMBObject
47 self.share = ''
49 def getShare(self):
50 return self.share
52 def getShares(self):
53 # Setup up a DCE SMBTransport with the connection already in place
54 LOG.info("Requesting shares on %s....." % (self.connection.getRemoteHost()))
55 try:
56 self._rpctransport = transport.SMBTransport(self.connection.getRemoteHost(),
57 self.connection.getRemoteHost(),filename = r'\srvsvc',
58 smb_connection = self.connection)
59 dce_srvs = self._rpctransport.get_dce_rpc()
60 dce_srvs.connect()
62 dce_srvs.bind(srvs.MSRPC_UUID_SRVS)
63 resp = srvs.hNetrShareEnum(dce_srvs, 1)
64 return resp['InfoStruct']['ShareInfo']['Level1']
65 except:
66 LOG.critical("Error requesting shares on %s, aborting....." % (self.connection.getRemoteHost()))
67 raise
70 def createService(self, handle, share, path):
71 LOG.info("Creating service %s on %s....." % (self.__service_name, self.connection.getRemoteHost()))
73 # First we try to open the service in case it exists. If it does, we remove it.
74 try:
75 resp = scmr.hROpenServiceW(self.rpcsvc, handle, self.__service_name+'\x00')
76 except Exception as e:
77 if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') >= 0:
78 # We're good, pass the exception
79 pass
80 else:
81 raise e
82 else:
83 # It exists, remove it
84 scmr.hRDeleteService(self.rpcsvc, resp['lpServiceHandle'])
85 scmr.hRCloseServiceHandle(self.rpcsvc, resp['lpServiceHandle'])
87 # Create the service
88 command = '%s\\%s' % (path, self.__binary_service_name)
89 try:
90 resp = scmr.hRCreateServiceW(self.rpcsvc, handle,self.__service_name + '\x00', self.__service_name + '\x00',
91 lpBinaryPathName=command + '\x00', dwStartType=scmr.SERVICE_DEMAND_START)
92 except:
93 LOG.critical("Error creating service %s on %s" % (self.__service_name, self.connection.getRemoteHost()))
94 raise
95 else:
96 return resp['lpServiceHandle']
98 def openSvcManager(self):
99 LOG.info("Opening SVCManager on %s....." % self.connection.getRemoteHost())
100 # Setup up a DCE SMBTransport with the connection already in place
101 self._rpctransport = transport.SMBTransport(self.connection.getRemoteHost(), self.connection.getRemoteHost(),
102 filename = r'\svcctl', smb_connection = self.connection)
103 self.rpcsvc = self._rpctransport.get_dce_rpc()
104 self.rpcsvc.connect()
105 self.rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
106 try:
107 resp = scmr.hROpenSCManagerW(self.rpcsvc)
108 except:
109 LOG.critical("Error opening SVCManager on %s....." % self.connection.getRemoteHost())
110 raise Exception('Unable to open SVCManager')
111 else:
112 return resp['lpScHandle']
114 def copy_file(self, src, tree, dst):
115 LOG.info("Uploading file %s" % dst)
116 if isinstance(src, str):
117 # We have a filename
118 fh = open(src, 'rb')
119 else:
120 # We have a class instance, it must have a read method
121 fh = src
122 f = dst
123 pathname = f.replace('/','\\')
124 try:
125 self.connection.putFile(tree, pathname, fh.read)
126 except:
127 LOG.critical("Error uploading file %s, aborting....." % dst)
128 raise
129 fh.close()
131 def findWritableShare(self, shares):
132 # Check we can write a file on the shares, stop in the first one
133 writeableShare = None
134 for i in shares['Buffer']:
135 if i['shi1_type'] == srvs.STYPE_DISKTREE or i['shi1_type'] == srvs.STYPE_SPECIAL:
136 share = i['shi1_netname'][:-1]
137 tid = 0
138 try:
139 tid = self.connection.connectTree(share)
140 self.connection.openFile(tid, '\\', FILE_WRITE_DATA, creationOption=FILE_DIRECTORY_FILE)
141 except:
142 LOG.debug('Exception', exc_info=True)
143 LOG.critical("share '%s' is not writable." % share)
144 pass
145 else:
146 LOG.info('Found writable share %s' % share)
147 writeableShare = str(share)
148 break
149 finally:
150 if tid != 0:
151 self.connection.disconnectTree(tid)
152 return writeableShare
154 def install(self):
155 if self.connection.isGuestSession():
156 LOG.critical("Authenticated as Guest. Aborting")
157 self.connection.logoff()
158 del self.connection
159 else:
160 fileCopied = False
161 serviceCreated = False
162 # Do the stuff here
163 try:
164 # Let's get the shares
165 shares = self.getShares()
166 self.share = self.findWritableShare(shares)
167 if self.share is None:
168 return False
169 self.copy_file(self.__exeFile ,self.share,self.__binary_service_name)
170 fileCopied = True
171 svcManager = self.openSvcManager()
172 if svcManager != 0:
173 serverName = self.connection.getServerName()
174 if self.share.lower() == 'admin$':
175 path = '%systemroot%'
176 else:
177 if serverName != '':
178 path = '\\\\%s\\%s' % (serverName, self.share)
179 else:
180 path = '\\\\127.0.0.1\\' + self.share
181 service = self.createService(svcManager, self.share, path)
182 serviceCreated = True
183 if service != 0:
184 # Start service
185 LOG.info('Starting service %s.....' % self.__service_name)
186 try:
187 scmr.hRStartServiceW(self.rpcsvc, service)
188 except:
189 pass
190 scmr.hRCloseServiceHandle(self.rpcsvc, service)
191 scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
192 return True
193 except Exception as e:
194 LOG.critical("Error performing the installation, cleaning up: %s" %e)
195 LOG.debug("Exception", exc_info=True)
196 try:
197 scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP)
198 except:
199 pass
200 if fileCopied is True:
201 try:
202 self.connection.deleteFile(self.share, self.__binary_service_name)
203 except:
204 pass
205 if serviceCreated is True:
206 try:
207 scmr.hRDeleteService(self.rpcsvc, service)
208 except:
209 pass
210 return False
212 def uninstall(self):
213 fileCopied = True
214 serviceCreated = True
215 # Do the stuff here
216 try:
217 # Let's get the shares
218 svcManager = self.openSvcManager()
219 if svcManager != 0:
220 resp = scmr.hROpenServiceW(self.rpcsvc, svcManager, self.__service_name+'\x00')
221 service = resp['lpServiceHandle']
222 LOG.info('Stopping service %s.....' % self.__service_name)
223 try:
224 scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP)
225 except:
226 pass
227 LOG.info('Removing service %s.....' % self.__service_name)
228 scmr.hRDeleteService(self.rpcsvc, service)
229 scmr.hRCloseServiceHandle(self.rpcsvc, service)
230 scmr.hRCloseServiceHandle(self.rpcsvc, svcManager)
231 LOG.info('Removing file %s.....' % self.__binary_service_name)
232 self.connection.deleteFile(self.share, self.__binary_service_name)
233 except Exception:
234 LOG.critical("Error performing the uninstallation, cleaning up" )
235 try:
236 scmr.hRControlService(self.rpcsvc, service, scmr.SERVICE_CONTROL_STOP)
237 except:
238 pass
239 if fileCopied is True:
240 try:
241 self.connection.deleteFile(self.share, self.__binary_service_name)
242 except:
243 try:
244 self.connection.deleteFile(self.share, self.__binary_service_name)
245 except:
246 pass
247 pass
248 if serviceCreated is True:
249 try:
250 scmr.hRDeleteService(self.rpcsvc, service)
251 except:
252 pass