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