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

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

## 183 statements

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#

19

20 import random

21 import string

22

23 from impacket.dcerpc.v5 import transport, srvs, scmr

24 from impacket import smb,smb3, LOG

25 from impacket.smbconnection import SMBConnection

26 from impacket.smb3structs import FILE_WRITE_DATA, FILE_DIRECTORY_FILE

27

28 class 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)])

32

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

37

38 self.__exeFile = exeFile

39

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

46

47 self.share = ''

48

49 def getShare(self):

50 return self.share

51

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()

61

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

68

69

70 def createService(self, handle, share, path):

71 LOG.info("Creating service %s on %s....." % (self.__service_name, self.connection.getRemoteHost()))

72

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'])

86

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']

97

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']

113

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()

130

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

153

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

211

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