github.com/Coalfire-Research/Slackor@v0.0.0-20191010164036-aa32a7f9250b/impacket/examples/dcomexec.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 # A similar approach to psexec but executing commands through DCOM. 9 # You can select different objects to be used to execute the commands. 10 # Currently supported objects are: 11 # 1. MMC20.Application (49B2791A-B1AE-4C90-9B8E-E860BA07F889) - Tested Windows 7, Windows 10, Server 2012R2 12 # 2. ShellWindows (9BA05972-F6A8-11CF-A442-00A0C90A8F39) - Tested Windows 7, Windows 10, Server 2012R2 13 # 3. ShellBrowserWindow (C08AFD90-F2A1-11D1-8455-00A0C91F3880) - Tested Windows 10, Server 2012R2 14 # 15 # Drawback is it needs DCOM, hence, I have to be able to access 16 # DCOM ports at the target machine. 17 # 18 # Original discovery by Matt Nelson (@enigma0x3): 19 # https://enigma0x3.net/2017/01/05/lateral-movement-using-the-mmc20-application-com-object/ 20 # https://enigma0x3.net/2017/01/23/lateral-movement-via-dcom-round-2/ 21 # 22 # Author: 23 # beto (@agsolino) 24 # Marcello (@byt3bl33d3r) 25 # 26 # Reference for: 27 # DCOM 28 # 29 # ToDo: 30 # [ ] Kerberos auth not working, invalid_checksum is thrown. Most probably sequence numbers out of sync due to 31 # getInterface() method 32 # 33 from __future__ import division 34 from __future__ import print_function 35 import argparse 36 import cmd 37 import logging 38 import ntpath 39 import os 40 import sys 41 import time 42 43 from six import PY3 44 from impacket import version 45 from impacket.dcerpc.v5.dcom.oaut import IID_IDispatch, string_to_bin, IDispatch, DISPPARAMS, DISPATCH_PROPERTYGET, \ 46 VARIANT, VARENUM, DISPATCH_METHOD 47 from impacket.dcerpc.v5.dcomrt import DCOMConnection 48 from impacket.dcerpc.v5.dcomrt import OBJREF, FLAGS_OBJREF_CUSTOM, OBJREF_CUSTOM, OBJREF_HANDLER, \ 49 OBJREF_EXTENDED, OBJREF_STANDARD, FLAGS_OBJREF_HANDLER, FLAGS_OBJREF_STANDARD, FLAGS_OBJREF_EXTENDED, \ 50 IRemUnknown2, INTERFACE 51 from impacket.dcerpc.v5.dtypes import NULL 52 from impacket.examples import logger 53 from impacket.smbconnection import SMBConnection, SMB_DIALECT, SMB2_DIALECT_002, SMB2_DIALECT_21 54 55 OUTPUT_FILENAME = '__' + str(time.time())[:5] 56 57 class DCOMEXEC: 58 def __init__(self, command='', username='', password='', domain='', hashes=None, aesKey=None, share=None, 59 noOutput=False, doKerberos=False, kdcHost=None, dcomObject=None): 60 self.__command = command 61 self.__username = username 62 self.__password = password 63 self.__domain = domain 64 self.__lmhash = '' 65 self.__nthash = '' 66 self.__aesKey = aesKey 67 self.__share = share 68 self.__noOutput = noOutput 69 self.__doKerberos = doKerberos 70 self.__kdcHost = kdcHost 71 self.__dcomObject = dcomObject 72 self.shell = None 73 if hashes is not None: 74 self.__lmhash, self.__nthash = hashes.split(':') 75 76 def getInterface(self, interface, resp): 77 # Now let's parse the answer and build an Interface instance 78 objRefType = OBJREF(b''.join(resp))['flags'] 79 objRef = None 80 if objRefType == FLAGS_OBJREF_CUSTOM: 81 objRef = OBJREF_CUSTOM(b''.join(resp)) 82 elif objRefType == FLAGS_OBJREF_HANDLER: 83 objRef = OBJREF_HANDLER(b''.join(resp)) 84 elif objRefType == FLAGS_OBJREF_STANDARD: 85 objRef = OBJREF_STANDARD(b''.join(resp)) 86 elif objRefType == FLAGS_OBJREF_EXTENDED: 87 objRef = OBJREF_EXTENDED(b''.join(resp)) 88 else: 89 logging.error("Unknown OBJREF Type! 0x%x" % objRefType) 90 91 return IRemUnknown2( 92 INTERFACE(interface.get_cinstance(), None, interface.get_ipidRemUnknown(), objRef['std']['ipid'], 93 oxid=objRef['std']['oxid'], oid=objRef['std']['oxid'], 94 target=interface.get_target())) 95 96 def run(self, addr): 97 if self.__noOutput is False: 98 smbConnection = SMBConnection(addr, addr) 99 if self.__doKerberos is False: 100 smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) 101 else: 102 smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, 103 self.__nthash, self.__aesKey, kdcHost=self.__kdcHost) 104 105 dialect = smbConnection.getDialect() 106 if dialect == SMB_DIALECT: 107 logging.info("SMBv1 dialect used") 108 elif dialect == SMB2_DIALECT_002: 109 logging.info("SMBv2.0 dialect used") 110 elif dialect == SMB2_DIALECT_21: 111 logging.info("SMBv2.1 dialect used") 112 else: 113 logging.info("SMBv3.0 dialect used") 114 else: 115 smbConnection = None 116 117 dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, 118 self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost) 119 try: 120 dispParams = DISPPARAMS(None, False) 121 dispParams['rgvarg'] = NULL 122 dispParams['rgdispidNamedArgs'] = NULL 123 dispParams['cArgs'] = 0 124 dispParams['cNamedArgs'] = 0 125 126 if self.__dcomObject == 'ShellWindows': 127 # ShellWindows CLSID (Windows 7, Windows 10, Windows Server 2012R2) 128 iInterface = dcom.CoCreateInstanceEx(string_to_bin('9BA05972-F6A8-11CF-A442-00A0C90A8F39'), IID_IDispatch) 129 iMMC = IDispatch(iInterface) 130 resp = iMMC.GetIDsOfNames(('Item',)) 131 resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_METHOD, dispParams, 0, [], []) 132 iItem = IDispatch(self.getInterface(iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) 133 resp = iItem.GetIDsOfNames(('Document',)) 134 resp = iItem.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) 135 pQuit = None 136 elif self.__dcomObject == 'ShellBrowserWindow': 137 # ShellBrowserWindow CLSID (Windows 10, Windows Server 2012R2) 138 iInterface = dcom.CoCreateInstanceEx(string_to_bin('C08AFD90-F2A1-11D1-8455-00A0C91F3880'), IID_IDispatch) 139 iMMC = IDispatch(iInterface) 140 resp = iMMC.GetIDsOfNames(('Document',)) 141 resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) 142 pQuit = iMMC.GetIDsOfNames(('Quit',))[0] 143 elif self.__dcomObject == 'MMC20': 144 iInterface = dcom.CoCreateInstanceEx(string_to_bin('49B2791A-B1AE-4C90-9B8E-E860BA07F889'), IID_IDispatch) 145 iMMC = IDispatch(iInterface) 146 resp = iMMC.GetIDsOfNames(('Document',)) 147 resp = iMMC.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) 148 pQuit = iMMC.GetIDsOfNames(('Quit',))[0] 149 else: 150 logging.fatal('Invalid object %s' % self.__dcomObject) 151 return 152 153 iDocument = IDispatch(self.getInterface(iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) 154 155 if self.__dcomObject == 'MMC20': 156 resp = iDocument.GetIDsOfNames(('ActiveView',)) 157 resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) 158 159 iActiveView = IDispatch(self.getInterface(iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) 160 pExecuteShellCommand = iActiveView.GetIDsOfNames(('ExecuteShellCommand',))[0] 161 self.shell = RemoteShellMMC20(self.__share, (iMMC, pQuit), (iActiveView, pExecuteShellCommand), smbConnection) 162 else: 163 resp = iDocument.GetIDsOfNames(('Application',)) 164 resp = iDocument.Invoke(resp[0], 0x409, DISPATCH_PROPERTYGET, dispParams, 0, [], []) 165 166 iActiveView = IDispatch(self.getInterface(iMMC, resp['pVarResult']['_varUnion']['pdispVal']['abData'])) 167 pExecuteShellCommand = iActiveView.GetIDsOfNames(('ShellExecute',))[0] 168 self.shell = RemoteShell(self.__share, (iMMC, pQuit), (iActiveView, pExecuteShellCommand), smbConnection) 169 170 if self.__command != ' ': 171 self.shell.onecmd(self.__command)[:5] 172 if self.shell is not None: 173 self.shell.do_exit('') 174 else: 175 self.shell.cmdloop() 176 except (Exception, KeyboardInterrupt) as e: 177 if logging.getLogger().level == logging.DEBUG: 178 import traceback 179 traceback.print_exc() 180 if self.shell is not None: 181 self.shell.do_exit('') 182 logging.error(str(e)) 183 if smbConnection is not None: 184 smbConnection.logoff() 185 dcom.disconnect() 186 sys.stdout.flush() 187 sys.exit(1) 188 189 if smbConnection is not None: 190 smbConnection.logoff() 191 dcom.disconnect() 192 193 class RemoteShell(cmd.Cmd): 194 def __init__(self, share, quit, executeShellCommand, smbConnection): 195 cmd.Cmd.__init__(self) 196 self._share = share 197 self._output = '\\' + OUTPUT_FILENAME 198 self.__outputBuffer = '' 199 self._shell = 'cmd.exe' 200 self.__quit = quit 201 self._executeShellCommand = executeShellCommand 202 self.__transferClient = smbConnection 203 self._pwd = 'C:\\windows\\system32' 204 self._noOutput = False 205 self.intro = '[!] Launching semi-interactive shell - Careful what you execute\n[!] Press help for extra shell commands' 206 207 # We don't wanna deal with timeouts from now on. 208 if self.__transferClient is not None: 209 self.__transferClient.setTimeout(100000) 210 self.do_cd('\\') 211 else: 212 self._noOutput = True 213 214 def do_shell(self, s): 215 os.system(s) 216 217 def do_help(self, line): 218 print(""" 219 lcd {path} - changes the current local directory to {path} 220 exit - terminates the server process (and this session) 221 put {src_file, dst_path} - uploads a local file to the dst_path (dst_path = default current directory) 222 get {file} - downloads pathname to the current local dir 223 ! {cmd} - executes a local shell cmd 224 """) 225 226 def do_lcd(self, s): 227 if s == '': 228 print(os.getcwd()) 229 else: 230 try: 231 os.chdir(s) 232 except Exception as e: 233 logging.error(str(e)) 234 235 def do_get(self, src_path): 236 try: 237 import ntpath 238 newPath = ntpath.normpath(ntpath.join(self._pwd, src_path)) 239 drive, tail = ntpath.splitdrive(newPath) 240 filename = ntpath.basename(tail) 241 fh = open(filename,'wb') 242 logging.info("Downloading %s\\%s" % (drive, tail)) 243 self.__transferClient.getFile(drive[:-1]+'$', tail, fh.write) 244 fh.close() 245 except Exception as e: 246 logging.error(str(e)) 247 os.remove(filename) 248 pass 249 250 def do_put(self, s): 251 try: 252 params = s.split(' ') 253 if len(params) > 1: 254 src_path = params[0] 255 dst_path = params[1] 256 elif len(params) == 1: 257 src_path = params[0] 258 dst_path = '' 259 260 src_file = os.path.basename(src_path) 261 fh = open(src_path, 'rb') 262 dst_path = dst_path.replace('/','\\') 263 import ntpath 264 pathname = ntpath.join(ntpath.join(self._pwd, dst_path), src_file) 265 drive, tail = ntpath.splitdrive(pathname) 266 logging.info("Uploading %s to %s" % (src_file, pathname)) 267 self.__transferClient.putFile(drive[:-1]+'$', tail, fh.read) 268 fh.close() 269 except Exception as e: 270 logging.critical(str(e)) 271 pass 272 273 def do_exit(self, s): 274 dispParams = DISPPARAMS(None, False) 275 dispParams['rgvarg'] = NULL 276 dispParams['rgdispidNamedArgs'] = NULL 277 dispParams['cArgs'] = 0 278 dispParams['cNamedArgs'] = 0 279 280 self.__quit[0].Invoke(self.__quit[1], 0x409, DISPATCH_METHOD, dispParams, 281 0, [], []) 282 return True 283 284 def emptyline(self): 285 return False 286 287 def do_cd(self, s): 288 self.execute_remote('cd ' + s) 289 if len(self.__outputBuffer.strip('\r\n')) > 0: 290 print(self.__outputBuffer) 291 self.__outputBuffer = '' 292 else: 293 self._pwd = ntpath.normpath(ntpath.join(self._pwd, s)) 294 self.execute_remote('cd ') 295 self._pwd = self.__outputBuffer.strip('\r\n') 296 self.prompt = self._pwd + '>' 297 self.__outputBuffer = '' 298 299 def default(self, line): 300 # Let's try to guess if the user is trying to change drive 301 if len(line) == 2 and line[1] == ':': 302 # Execute the command and see if the drive is valid 303 self.execute_remote(line) 304 if len(self.__outputBuffer.strip('\r\n')) > 0: 305 # Something went wrong 306 print(self.__outputBuffer) 307 self.__outputBuffer = '' 308 else: 309 # Drive valid, now we should get the current path 310 self._pwd = line 311 self.execute_remote('cd ') 312 self._pwd = self.__outputBuffer.strip('\r\n') 313 self.prompt = self._pwd + '>' 314 self.__outputBuffer = '' 315 else: 316 if line != '': 317 self.send_data(line) 318 319 def get_output(self): 320 def output_callback(data): 321 self.__outputBuffer += data.decode('utf-8') 322 323 if self._noOutput is True: 324 self.__outputBuffer = '' 325 return 326 327 while True: 328 try: 329 self.__transferClient.getFile(self._share, self._output, output_callback) 330 break 331 except Exception as e: 332 if str(e).find('STATUS_SHARING_VIOLATION') >=0: 333 # Output not finished, let's wait 334 time.sleep(1) 335 pass 336 elif str(e).find('Broken') >= 0: 337 # The SMB Connection might have timed out, let's try reconnecting 338 logging.debug('Connection broken, trying to recreate it') 339 self.__transferClient.reconnect() 340 return self.get_output() 341 self.__transferClient.deleteFile(self._share, self._output) 342 343 def execute_remote(self, data): 344 command = '/Q /c ' + data 345 if self._noOutput is False: 346 command += ' 1> ' + '\\\\127.0.0.1\\%s' % self._share + self._output + ' 2>&1' 347 348 logging.debug('Executing: %s' % command) 349 350 dispParams = DISPPARAMS(None, False) 351 dispParams['rgdispidNamedArgs'] = NULL 352 dispParams['cArgs'] = 5 353 dispParams['cNamedArgs'] = 0 354 arg0 = VARIANT(None, False) 355 arg0['clSize'] = 5 356 arg0['vt'] = VARENUM.VT_BSTR 357 arg0['_varUnion']['tag'] = VARENUM.VT_BSTR 358 arg0['_varUnion']['bstrVal']['asData'] = self._shell 359 360 arg1 = VARIANT(None, False) 361 arg1['clSize'] = 5 362 arg1['vt'] = VARENUM.VT_BSTR 363 arg1['_varUnion']['tag'] = VARENUM.VT_BSTR 364 if PY3: 365 arg1['_varUnion']['bstrVal']['asData'] = command 366 else: 367 arg1['_varUnion']['bstrVal']['asData'] = command.decode(sys.stdin.encoding) 368 369 arg2 = VARIANT(None, False) 370 arg2['clSize'] = 5 371 arg2['vt'] = VARENUM.VT_BSTR 372 arg2['_varUnion']['tag'] = VARENUM.VT_BSTR 373 arg2['_varUnion']['bstrVal']['asData'] = self._pwd 374 375 arg3 = VARIANT(None, False) 376 arg3['clSize'] = 5 377 arg3['vt'] = VARENUM.VT_BSTR 378 arg3['_varUnion']['tag'] = VARENUM.VT_BSTR 379 arg3['_varUnion']['bstrVal']['asData'] = '' 380 381 arg4 = VARIANT(None, False) 382 arg4['clSize'] = 5 383 arg4['vt'] = VARENUM.VT_BSTR 384 arg4['_varUnion']['tag'] = VARENUM.VT_BSTR 385 arg4['_varUnion']['bstrVal']['asData'] = '0' 386 dispParams['rgvarg'].append(arg4) 387 dispParams['rgvarg'].append(arg3) 388 dispParams['rgvarg'].append(arg2) 389 dispParams['rgvarg'].append(arg1) 390 dispParams['rgvarg'].append(arg0) 391 392 #print(dispParams.dump()) 393 394 self._executeShellCommand[0].Invoke(self._executeShellCommand[1], 0x409, DISPATCH_METHOD, dispParams, 395 0, [], []) 396 self.get_output() 397 398 def send_data(self, data): 399 self.execute_remote(data) 400 print(self.__outputBuffer) 401 self.__outputBuffer = '' 402 403 class RemoteShellMMC20(RemoteShell): 404 def execute_remote(self, data): 405 command = '/Q /c ' + data 406 if self._noOutput is False: 407 command += ' 1> ' + '\\\\127.0.0.1\\%s' % self._share + self._output + ' 2>&1' 408 409 dispParams = DISPPARAMS(None, False) 410 dispParams['rgdispidNamedArgs'] = NULL 411 dispParams['cArgs'] = 4 412 dispParams['cNamedArgs'] = 0 413 arg0 = VARIANT(None, False) 414 arg0['clSize'] = 5 415 arg0['vt'] = VARENUM.VT_BSTR 416 arg0['_varUnion']['tag'] = VARENUM.VT_BSTR 417 arg0['_varUnion']['bstrVal']['asData'] = self._shell 418 419 arg1 = VARIANT(None, False) 420 arg1['clSize'] = 5 421 arg1['vt'] = VARENUM.VT_BSTR 422 arg1['_varUnion']['tag'] = VARENUM.VT_BSTR 423 arg1['_varUnion']['bstrVal']['asData'] = self._pwd 424 425 arg2 = VARIANT(None, False) 426 arg2['clSize'] = 5 427 arg2['vt'] = VARENUM.VT_BSTR 428 arg2['_varUnion']['tag'] = VARENUM.VT_BSTR 429 if PY3: 430 arg2['_varUnion']['bstrVal']['asData'] = command 431 else: 432 arg2['_varUnion']['bstrVal']['asData'] = command.decode(sys.stdin.encoding) 433 434 arg3 = VARIANT(None, False) 435 arg3['clSize'] = 5 436 arg3['vt'] = VARENUM.VT_BSTR 437 arg3['_varUnion']['tag'] = VARENUM.VT_BSTR 438 arg3['_varUnion']['bstrVal']['asData'] = '7' 439 dispParams['rgvarg'].append(arg3) 440 dispParams['rgvarg'].append(arg2) 441 dispParams['rgvarg'].append(arg1) 442 dispParams['rgvarg'].append(arg0) 443 444 self._executeShellCommand[0].Invoke(self._executeShellCommand[1], 0x409, DISPATCH_METHOD, dispParams, 445 0, [], []) 446 self.get_output() 447 448 class AuthFileSyntaxError(Exception): 449 450 '''raised by load_smbclient_auth_file if it encounters a syntax error 451 while loading the smbclient-style authentication file.''' 452 453 def __init__(self, path, lineno, reason): 454 self.path=path 455 self.lineno=lineno 456 self.reason=reason 457 458 def __str__(self): 459 return 'Syntax error in auth file %s line %d: %s' % ( 460 self.path, self.lineno, self.reason ) 461 462 def load_smbclient_auth_file(path): 463 464 '''Load credentials from an smbclient-style authentication file (used by 465 smbclient, mount.cifs and others). returns (domain, username, password) 466 or raises AuthFileSyntaxError or any I/O exceptions.''' 467 468 lineno=0 469 domain=None 470 username=None 471 password=None 472 for line in open(path): 473 lineno+=1 474 475 line = line.strip() 476 477 if line.startswith('#') or line=='': 478 continue 479 480 parts = line.split('=',1) 481 if len(parts) != 2: 482 raise AuthFileSyntaxError(path, lineno, 'No "=" present in line') 483 484 (k,v) = (parts[0].strip(), parts[1].strip()) 485 486 if k=='username': 487 username=v 488 elif k=='password': 489 password=v 490 elif k=='domain': 491 domain=v 492 else: 493 raise AuthFileSyntaxError(path, lineno, 'Unknown option %s' % repr(k)) 494 495 return (domain, username, password) 496 497 # Process command-line arguments. 498 if __name__ == '__main__': 499 # Init the example's logger theme 500 logger.init() 501 print(version.BANNER) 502 503 parser = argparse.ArgumentParser(add_help = True, description = "Executes a semi-interactive shell using the " 504 "ShellBrowserWindow DCOM object.") 505 parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>') 506 parser.add_argument('-share', action='store', default = 'ADMIN$', help='share where the output will be grabbed from ' 507 '(default ADMIN$)') 508 parser.add_argument('-nooutput', action='store_true', default = False, help='whether or not to print the output ' 509 '(no SMB connection created)') 510 parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') 511 parser.add_argument('-object', choices=['ShellWindows', 'ShellBrowserWindow', 'MMC20'], nargs='?', default='ShellWindows', 512 help='DCOM object to be used to execute the shell command (default=ShellWindows)') 513 514 parser.add_argument('command', nargs='*', default = ' ', help='command to execute at the target. If empty it will ' 515 'launch a semi-interactive shell') 516 517 group = parser.add_argument_group('authentication') 518 519 group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') 520 group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') 521 group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' 522 '(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the ' 523 'ones specified in the command line') 524 group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' 525 '(128 or 256 bits)') 526 group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. If ' 527 'ommited it use the domain part (FQDN) specified in the target parameter') 528 group.add_argument('-A', action="store", metavar = "authfile", help="smbclient/mount.cifs-style authentication file. " 529 "See smbclient man page's -A option.") 530 531 if len(sys.argv)==1: 532 parser.print_help() 533 sys.exit(1) 534 535 options = parser.parse_args() 536 537 if ' '.join(options.command) == ' ' and options.nooutput is True: 538 logging.error("-nooutput switch and interactive shell not supported") 539 sys.exit(1) 540 541 if options.debug is True: 542 logging.getLogger().setLevel(logging.DEBUG) 543 else: 544 logging.getLogger().setLevel(logging.INFO) 545 546 import re 547 548 domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match( 549 options.target).groups('') 550 551 #In case the password contains '@' 552 if '@' in address: 553 password = password + '@' + address.rpartition('@')[0] 554 address = address.rpartition('@')[2] 555 556 try: 557 if options.A is not None: 558 (domain, username, password) = load_smbclient_auth_file(options.A) 559 logging.debug('loaded smbclient auth file: domain=%s, username=%s, password=%s' % (repr(domain), repr(username), repr(password))) 560 561 if domain is None: 562 domain = '' 563 564 if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: 565 from getpass import getpass 566 password = getpass("Password:") 567 568 if options.aesKey is not None: 569 options.k = True 570 571 executer = DCOMEXEC(' '.join(options.command), username, password, domain, options.hashes, options.aesKey, 572 options.share, options.nooutput, options.k, options.dc_ip, options.object) 573 executer.run(address) 574 except (Exception, KeyboardInterrupt) as e: 575 if logging.getLogger().level == logging.DEBUG: 576 import traceback 577 traceback.print_exc() 578 logging.error(str(e)) 579 sys.exit(0)