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# 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#

16

17 import random

18 import string

19

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

21 from impacket import smb,smb3, LOG

22 from impacket.smbconnection import SMBConnection

23 from impacket.smb3structs import FILE_WRITE_DATA, FILE_DIRECTORY_FILE

24

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

29

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

34

35 self.__exeFile = exeFile

36

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

43

44 self.share = ''

45

46 def getShare(self):

47 return self.share

48

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

58

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

65

66

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

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

69

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

83

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

94

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

110

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

127

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

150

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

208

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