github.com/n00py/Slackor@v0.0.0-20200610224921-d007fcea1740/impacket/examples/services.py (about) 1 #!/usr/bin/env python 2 # SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 3 # 4 # This software is provided under under a slightly modified version 5 # of the Apache Software License. See the accompanying LICENSE file 6 # for more information. 7 # 8 # [MS-SCMR] services common functions for manipulating services 9 # 10 # Author: 11 # Alberto Solino (@agsolino) 12 # 13 # Reference for: 14 # DCE/RPC. 15 # TODO: 16 # [ ] Check errors 17 from __future__ import division 18 from __future__ import print_function 19 import sys 20 import argparse 21 import logging 22 import codecs 23 24 from impacket.examples import logger 25 from impacket import version 26 from impacket.dcerpc.v5 import transport, scmr 27 from impacket.dcerpc.v5.ndr import NULL 28 from impacket.crypto import encryptSecret 29 30 31 class SVCCTL: 32 33 def __init__(self, username, password, domain, options, port=445): 34 self.__username = username 35 self.__password = password 36 self.__options = options 37 self.__port = port 38 self.__action = options.action.upper() 39 self.__domain = domain 40 self.__lmhash = '' 41 self.__nthash = '' 42 self.__aesKey = options.aesKey 43 self.__doKerberos = options.k 44 self.__kdcHost = options.dc_ip 45 46 if options.hashes is not None: 47 self.__lmhash, self.__nthash = options.hashes.split(':') 48 49 def run(self, remoteName, remoteHost): 50 51 stringbinding = r'ncacn_np:%s[\pipe\svcctl]' % remoteName 52 logging.debug('StringBinding %s'%stringbinding) 53 rpctransport = transport.DCERPCTransportFactory(stringbinding) 54 rpctransport.set_dport(self.__port) 55 rpctransport.setRemoteHost(remoteHost) 56 if hasattr(rpctransport, 'set_credentials'): 57 # This method exists only for selected protocol sequences. 58 rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey) 59 60 rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost) 61 self.doStuff(rpctransport) 62 63 def doStuff(self, rpctransport): 64 dce = rpctransport.get_dce_rpc() 65 #dce.set_credentials(self.__username, self.__password) 66 dce.connect() 67 #dce.set_max_fragment_size(1) 68 #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY) 69 #dce.set_auth_level(ntlm.NTLM_AUTH_PKT_INTEGRITY) 70 dce.bind(scmr.MSRPC_UUID_SCMR) 71 #rpc = svcctl.DCERPCSvcCtl(dce) 72 rpc = dce 73 ans = scmr.hROpenSCManagerW(rpc) 74 scManagerHandle = ans['lpScHandle'] 75 if self.__action != 'LIST' and self.__action != 'CREATE': 76 ans = scmr.hROpenServiceW(rpc, scManagerHandle, self.__options.name+'\x00') 77 serviceHandle = ans['lpServiceHandle'] 78 79 if self.__action == 'START': 80 logging.info("Starting service %s" % self.__options.name) 81 scmr.hRStartServiceW(rpc, serviceHandle) 82 scmr.hRCloseServiceHandle(rpc, serviceHandle) 83 elif self.__action == 'STOP': 84 logging.info("Stopping service %s" % self.__options.name) 85 scmr.hRControlService(rpc, serviceHandle, scmr.SERVICE_CONTROL_STOP) 86 scmr.hRCloseServiceHandle(rpc, serviceHandle) 87 elif self.__action == 'DELETE': 88 logging.info("Deleting service %s" % self.__options.name) 89 scmr.hRDeleteService(rpc, serviceHandle) 90 scmr.hRCloseServiceHandle(rpc, serviceHandle) 91 elif self.__action == 'CONFIG': 92 logging.info("Querying service config for %s" % self.__options.name) 93 resp = scmr.hRQueryServiceConfigW(rpc, serviceHandle) 94 print("TYPE : %2d - " % resp['lpServiceConfig']['dwServiceType'], end=' ') 95 if resp['lpServiceConfig']['dwServiceType'] & 0x1: 96 print("SERVICE_KERNEL_DRIVER ", end=' ') 97 if resp['lpServiceConfig']['dwServiceType'] & 0x2: 98 print("SERVICE_FILE_SYSTEM_DRIVER ", end=' ') 99 if resp['lpServiceConfig']['dwServiceType'] & 0x10: 100 print("SERVICE_WIN32_OWN_PROCESS ", end=' ') 101 if resp['lpServiceConfig']['dwServiceType'] & 0x20: 102 print("SERVICE_WIN32_SHARE_PROCESS ", end=' ') 103 if resp['lpServiceConfig']['dwServiceType'] & 0x100: 104 print("SERVICE_INTERACTIVE_PROCESS ", end=' ') 105 print("") 106 print("START_TYPE : %2d - " % resp['lpServiceConfig']['dwStartType'], end=' ') 107 if resp['lpServiceConfig']['dwStartType'] == 0x0: 108 print("BOOT START") 109 elif resp['lpServiceConfig']['dwStartType'] == 0x1: 110 print("SYSTEM START") 111 elif resp['lpServiceConfig']['dwStartType'] == 0x2: 112 print("AUTO START") 113 elif resp['lpServiceConfig']['dwStartType'] == 0x3: 114 print("DEMAND START") 115 elif resp['lpServiceConfig']['dwStartType'] == 0x4: 116 print("DISABLED") 117 else: 118 print("UNKNOWN") 119 120 print("ERROR_CONTROL : %2d - " % resp['lpServiceConfig']['dwErrorControl'], end=' ') 121 if resp['lpServiceConfig']['dwErrorControl'] == 0x0: 122 print("IGNORE") 123 elif resp['lpServiceConfig']['dwErrorControl'] == 0x1: 124 print("NORMAL") 125 elif resp['lpServiceConfig']['dwErrorControl'] == 0x2: 126 print("SEVERE") 127 elif resp['lpServiceConfig']['dwErrorControl'] == 0x3: 128 print("CRITICAL") 129 else: 130 print("UNKNOWN") 131 print("BINARY_PATH_NAME : %s" % resp['lpServiceConfig']['lpBinaryPathName'][:-1]) 132 print("LOAD_ORDER_GROUP : %s" % resp['lpServiceConfig']['lpLoadOrderGroup'][:-1]) 133 print("TAG : %d" % resp['lpServiceConfig']['dwTagId']) 134 print("DISPLAY_NAME : %s" % resp['lpServiceConfig']['lpDisplayName'][:-1]) 135 print("DEPENDENCIES : %s" % resp['lpServiceConfig']['lpDependencies'][:-1]) 136 print("SERVICE_START_NAME: %s" % resp['lpServiceConfig']['lpServiceStartName'][:-1]) 137 elif self.__action == 'STATUS': 138 print("Querying status for %s" % self.__options.name) 139 resp = scmr.hRQueryServiceStatus(rpc, serviceHandle) 140 print("%30s - " % self.__options.name, end=' ') 141 state = resp['lpServiceStatus']['dwCurrentState'] 142 if state == scmr.SERVICE_CONTINUE_PENDING: 143 print("CONTINUE PENDING") 144 elif state == scmr.SERVICE_PAUSE_PENDING: 145 print("PAUSE PENDING") 146 elif state == scmr.SERVICE_PAUSED: 147 print("PAUSED") 148 elif state == scmr.SERVICE_RUNNING: 149 print("RUNNING") 150 elif state == scmr.SERVICE_START_PENDING: 151 print("START PENDING") 152 elif state == scmr.SERVICE_STOP_PENDING: 153 print("STOP PENDING") 154 elif state == scmr.SERVICE_STOPPED: 155 print("STOPPED") 156 else: 157 print("UNKNOWN") 158 elif self.__action == 'LIST': 159 logging.info("Listing services available on target") 160 #resp = rpc.EnumServicesStatusW(scManagerHandle, svcctl.SERVICE_WIN32_SHARE_PROCESS ) 161 #resp = rpc.EnumServicesStatusW(scManagerHandle, svcctl.SERVICE_WIN32_OWN_PROCESS ) 162 #resp = rpc.EnumServicesStatusW(scManagerHandle, serviceType = svcctl.SERVICE_FILE_SYSTEM_DRIVER, serviceState = svcctl.SERVICE_STATE_ALL ) 163 resp = scmr.hREnumServicesStatusW(rpc, scManagerHandle) 164 for i in range(len(resp)): 165 print("%30s - %70s - " % (resp[i]['lpServiceName'][:-1], resp[i]['lpDisplayName'][:-1]), end=' ') 166 state = resp[i]['ServiceStatus']['dwCurrentState'] 167 if state == scmr.SERVICE_CONTINUE_PENDING: 168 print("CONTINUE PENDING") 169 elif state == scmr.SERVICE_PAUSE_PENDING: 170 print("PAUSE PENDING") 171 elif state == scmr.SERVICE_PAUSED: 172 print("PAUSED") 173 elif state == scmr.SERVICE_RUNNING: 174 print("RUNNING") 175 elif state == scmr.SERVICE_START_PENDING: 176 print("START PENDING") 177 elif state == scmr.SERVICE_STOP_PENDING: 178 print("STOP PENDING") 179 elif state == scmr.SERVICE_STOPPED: 180 print("STOPPED") 181 else: 182 print("UNKNOWN") 183 print("Total Services: %d" % len(resp)) 184 elif self.__action == 'CREATE': 185 logging.info("Creating service %s" % self.__options.name) 186 scmr.hRCreateServiceW(rpc, scManagerHandle, self.__options.name + '\x00', self.__options.display + '\x00', 187 lpBinaryPathName=self.__options.path + '\x00') 188 elif self.__action == 'CHANGE': 189 logging.info("Changing service config for %s" % self.__options.name) 190 if self.__options.start_type is not None: 191 start_type = int(self.__options.start_type) 192 else: 193 start_type = scmr.SERVICE_NO_CHANGE 194 if self.__options.service_type is not None: 195 service_type = int(self.__options.service_type) 196 else: 197 service_type = scmr.SERVICE_NO_CHANGE 198 199 if self.__options.display is not None: 200 display = self.__options.display + '\x00' 201 else: 202 display = NULL 203 204 if self.__options.path is not None: 205 path = self.__options.path + '\x00' 206 else: 207 path = NULL 208 209 if self.__options.start_name is not None: 210 start_name = self.__options.start_name + '\x00' 211 else: 212 start_name = NULL 213 214 if self.__options.password is not None: 215 s = rpctransport.get_smb_connection() 216 key = s.getSessionKey() 217 try: 218 password = (self.__options.password+'\x00').encode('utf-16le') 219 except UnicodeDecodeError: 220 import sys 221 password = (self.__options.password+'\x00').decode(sys.getfilesystemencoding()).encode('utf-16le') 222 password = encryptSecret(key, password) 223 else: 224 password = NULL 225 226 227 #resp = scmr.hRChangeServiceConfigW(rpc, serviceHandle, display, path, service_type, start_type, start_name, password) 228 scmr.hRChangeServiceConfigW(rpc, serviceHandle, service_type, start_type, scmr.SERVICE_ERROR_IGNORE, path, 229 NULL, NULL, NULL, 0, start_name, password, 0, display) 230 scmr.hRCloseServiceHandle(rpc, serviceHandle) 231 else: 232 logging.error("Unknown action %s" % self.__action) 233 234 scmr.hRCloseServiceHandle(rpc, scManagerHandle) 235 236 dce.disconnect() 237 238 return 239 240 241 # Process command-line arguments. 242 if __name__ == '__main__': 243 244 # Init the example's logger theme 245 logger.init() 246 # Explicitly changing the stdout encoding format 247 if sys.stdout.encoding is None: 248 # Output is redirected to a file 249 sys.stdout = codecs.getwriter('utf8')(sys.stdout) 250 print(version.BANNER) 251 252 parser = argparse.ArgumentParser(add_help = True, description = "Windows Service manipulation script.") 253 254 parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>') 255 parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') 256 subparsers = parser.add_subparsers(help='actions', dest='action') 257 258 # A start command 259 start_parser = subparsers.add_parser('start', help='starts the service') 260 start_parser.add_argument('-name', action='store', required=True, help='service name') 261 262 # A stop command 263 stop_parser = subparsers.add_parser('stop', help='stops the service') 264 stop_parser.add_argument('-name', action='store', required=True, help='service name') 265 266 # A delete command 267 delete_parser = subparsers.add_parser('delete', help='deletes the service') 268 delete_parser.add_argument('-name', action='store', required=True, help='service name') 269 270 # A status command 271 status_parser = subparsers.add_parser('status', help='returns service status') 272 status_parser.add_argument('-name', action='store', required=True, help='service name') 273 274 # A config command 275 config_parser = subparsers.add_parser('config', help='returns service configuration') 276 config_parser.add_argument('-name', action='store', required=True, help='service name') 277 278 # A list command 279 list_parser = subparsers.add_parser('list', help='list available services') 280 281 # A create command 282 create_parser = subparsers.add_parser('create', help='create a service') 283 create_parser.add_argument('-name', action='store', required=True, help='service name') 284 create_parser.add_argument('-display', action='store', required=True, help='display name') 285 create_parser.add_argument('-path', action='store', required=True, help='binary path') 286 287 # A change command 288 create_parser = subparsers.add_parser('change', help='change a service configuration') 289 create_parser.add_argument('-name', action='store', required=True, help='service name') 290 create_parser.add_argument('-display', action='store', required=False, help='display name') 291 create_parser.add_argument('-path', action='store', required=False, help='binary path') 292 create_parser.add_argument('-service_type', action='store', required=False, help='service type') 293 create_parser.add_argument('-start_type', action='store', required=False, help='service start type') 294 create_parser.add_argument('-start_name', action='store', required=False, help='string that specifies the name of ' 295 'the account under which the service should run') 296 create_parser.add_argument('-password', action='store', required=False, help='string that contains the password of ' 297 'the account whose name was specified by the start_name parameter') 298 299 group = parser.add_argument_group('authentication') 300 301 group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') 302 group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') 303 group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' 304 '(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ' 305 'ones specified in the command line') 306 group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' 307 '(128 or 256 bits)') 308 309 group = parser.add_argument_group('connection') 310 311 group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. If ' 312 'ommited it use the domain part (FQDN) specified in the target parameter') 313 group.add_argument('-target-ip', action='store', metavar="ip address", help='IP Address of the target machine. If ' 314 'ommited it will use whatever was specified as target. This is useful when target is the NetBIOS ' 315 'name and you cannot resolve it') 316 group.add_argument('-port', choices=['139', '445'], nargs='?', default='445', metavar="destination port", 317 help='Destination port to connect to SMB Server') 318 319 if len(sys.argv)==1: 320 parser.print_help() 321 sys.exit(1) 322 323 options = parser.parse_args() 324 325 if options.debug is True: 326 logging.getLogger().setLevel(logging.DEBUG) 327 else: 328 logging.getLogger().setLevel(logging.INFO) 329 330 import re 331 332 domain, username, password, remoteName = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match( 333 options.target).groups('') 334 335 #In case the password contains '@' 336 if '@' in remoteName: 337 password = password + '@' + remoteName.rpartition('@')[0] 338 remoteName = remoteName.rpartition('@')[2] 339 340 if domain is None: 341 domain = '' 342 343 if options.target_ip is None: 344 options.target_ip = remoteName 345 346 if options.aesKey is not None: 347 options.k = True 348 349 if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: 350 from getpass import getpass 351 password = getpass("Password:") 352 353 services = SVCCTL(username, password, domain, options, int(options.port)) 354 try: 355 services.run(remoteName, options.target_ip) 356 except Exception as e: 357 if logging.getLogger().level == logging.DEBUG: 358 import traceback 359 traceback.print_exc() 360 logging.error(str(e))