def test_parse_target(self): # Parse target returns a tuple with: domain, username, password, remote_name/address targets = { "": ("", "", "", ""), "HostName": ("", "", "", "HostName"), "UserName@HostName": ("", "UserName", "", "HostName"), "UserName:Password@HostName": ("", "UserName", "Password", "HostName"), "UserName:Pa$$word1234@HostName": ("", "UserName", "Pa$$word1234", "HostName"), "UserName:Password!#$@HostName": ("", "UserName", "Password!#$", "HostName"), "UserName:Passw@rd!#$@HostName": ("", "UserName", "Passw@rd!#$", "HostName"), "UserName:P@ssw@rd@!#$@HostName": ("", "UserName", "P@ssw@rd@!#$", "HostName"), "DOMAIN/UserName@HostName": ("DOMAIN", "UserName", "", "HostName"), "DOMAIN/:Password@HostName": ("DOMAIN", "", "Password", "HostName"), "DOMAIN/UserName:Password@HostName": ("DOMAIN", "UserName", "Password", "HostName"), "DOMAIN/UserName:Password/123@HostName": ("DOMAIN", "UserName", "Password/123", "HostName"), } for target, result in targets.items(): self.assertTupleEqual(parse_target(target), result)
def parse_target(args): domain, username, password, address = utils.parse_target(args.target) if args.target_ip is None: args.target_ip = address if domain is None: domain = '' if password == '' and username != '' and args.hashes is None and args.no_pass is False and args.aesKey is None: from getpass import getpass password = getpass("Password:") if args.aesKey is not None: args.k = True if args.hashes is not None: lmhash, nthash = args.hashes.split(':') else: lmhash = '' nthash = '' return domain, username, password, address, lmhash, nthash
def main(): # Init the example's logger theme logger.init() print(version.BANNER) parser = argparse.ArgumentParser(add_help = True, description = "SMB client implementation.") parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>') parser.add_argument('-file', type=argparse.FileType('r'), help='input file with commands to execute in the mini shell') parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') group = parser.add_argument_group('authentication') group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' '(KRB5CCNAME) based on target parameters. If valid credentials ' 'cannot be found, it will use the ones specified in the command ' 'line') group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication ' '(128 or 256 bits)') group = parser.add_argument_group('connection') group.add_argument('-dc-ip', action='store', metavar="ip address", help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in ' 'the target parameter') group.add_argument('-target-ip', action='store', metavar="ip address", help='IP Address of the target machine. If omitted it will use whatever was specified as target. ' 'This is useful when target is the NetBIOS name and you cannot resolve it') if len(sys.argv)==1: parser.print_help() sys.exit(1) options = parser.parse_args() if options.debug is True: logging.getLogger().setLevel(logging.DEBUG) # Print the Library's installation path logging.debug(version.getInstallationPath()) else: logging.getLogger().setLevel(logging.INFO) domain, username, password, address = parse_target(options.target) if options.target_ip is None: options.target_ip = address if domain is None: domain = '' if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: from getpass import getpass password = getpass("Password:"******"Executing commands from %s" % options.file.name) for line in options.file.readlines(): if line[0] != '#': print("# %s" % line, end=' ') shell.onecmd(line) else: print(line, end=' ') else: shell.cmdloop() except Exception as e: logging.debug("Exception:", exc_info=True) logging.error(str(e))
CODEC = 'utf-8' logging.warning("This will work ONLY on Windows >= Vista") if ''.join(options.command) == ' ': logging.error('You need to specify a command to execute!') sys.exit(1) if options.debug is True: logging.getLogger().setLevel(logging.DEBUG) # Print the Library's installation path logging.debug(version.getInstallationPath()) else: logging.getLogger().setLevel(logging.INFO) domain, username, password, address = parse_target(options.target) if domain is None: domain = '' if options.keytab is not None: Keytab.loadKeysFromKeytab(options.keytab, username, domain, options) options.k = True if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: from getpass import getpass password = getpass("Password:") if options.aesKey is not None: options.k = True
parser.print_help() sys.exit(1) options = parser.parse_args() # Init the example's logger theme logger.init(options.ts) if options.debug is True: logging.getLogger().setLevel(logging.DEBUG) # Print the Library's installation path logging.debug(version.getInstallationPath()) else: logging.getLogger().setLevel(logging.INFO) domain, username, password, remoteName = parse_target(options.target) if domain is None: domain = '' if options.target_ip is None: options.target_ip = remoteName if options.aesKey is not None: options.k = True if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: from getpass import getpass password = getpass('Password:') machine_role = MachineRole(username, password, domain, options.hashes, options.aesKey, options.k, options.dc_ip, int(options.port))
def run(self): if self.options.action.upper() == 'MASTERKEY': fp = open(options.file, 'rb') data = fp.read() mkf = MasterKeyFile(data) mkf.dump() data = data[len(mkf):] if mkf['MasterKeyLen'] > 0: mk = MasterKey(data[:mkf['MasterKeyLen']]) data = data[len(mk):] if mkf['BackupKeyLen'] > 0: bkmk = MasterKey(data[:mkf['BackupKeyLen']]) data = data[len(bkmk):] if mkf['CredHistLen'] > 0: ch = CredHist(data[:mkf['CredHistLen']]) data = data[len(ch):] if mkf['DomainKeyLen'] > 0: dk = DomainKey(data[:mkf['DomainKeyLen']]) data = data[len(dk):] if self.options.system and self.options.security and self.options.sid is None: # We have hives, let's try to decrypt with them self.getLSA() decryptedKey = mk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['UserKey']) if decryptedKey: print('Decrypted Backup key with UserKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(self.dpapiSystem['MachineKey']) if decryptedKey: print('Decrypted Backup key with MachineKey') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.system and self.options.security: # Use SID + hash # We have hives, let's try to decrypt with them self.getLSA() key1, key2 = self.deriveKeysFromUserkey( self.options.sid, self.dpapiSystem['UserKey']) decryptedKey = mk.decrypt(key1) if decryptedKey: print('Decrypted key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(key1) if decryptedKey: print('Decrypted Backup key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(key2) if decryptedKey: print('Decrypted key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = bkmk.decrypt(key2) if decryptedKey: print('Decrypted Backup key with UserKey + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key and self.options.sid: key = unhexlify(self.options.key[2:]) key1, key2 = self.deriveKeysFromUserkey(self.options.sid, key) decryptedKey = mk.decrypt(key1) if decryptedKey: print('Decrypted key with key provided + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return decryptedKey = mk.decrypt(key2) if decryptedKey: print('Decrypted key with key provided + SID') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.key: key = unhexlify(self.options.key[2:]) decryptedKey = mk.decrypt(key) if decryptedKey: print('Decrypted key with key provided') print('Decrypted key: 0x%s' % hexlify(decryptedKey).decode('latin-1')) return elif self.options.pvk and dk: pvkfile = open(self.options.pvk, 'rb').read() key = PRIVATE_KEY_BLOB(pvkfile[len(PVK_FILE_HDR()):]) private = privatekeyblob_to_pkcs1(key) cipher = PKCS1_v1_5.new(private) decryptedKey = cipher.decrypt(dk['SecretData'][::-1], None) if decryptedKey: domain_master_key = DPAPI_DOMAIN_RSA_MASTER_KEY( decryptedKey) key = domain_master_key[ 'buffer'][:domain_master_key['cbMasterKey']] print('Decrypted key with domain backup key provided') print('Decrypted key: 0x%s' % hexlify(key).decode('latin-1')) return elif self.options.sid and self.options.key is None: # Do we have a password? if self.options.password is None: # Nope let's ask it from getpass import getpass password = getpass("Password:"******"Password:"******"Password:"******"G$BCKUPKEY_PREFERRED", "G$BCKUPKEY_P"): buffer = crypto.decryptSecret( connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], keyname)) guid = bin_to_string(buffer) name = "G$BCKUPKEY_{}".format(guid) secret = crypto.decryptSecret( connection.getSessionKey(), lsad.hLsarRetrievePrivateData(dce, resp['PolicyHandle'], name)) keyVersion = struct.unpack('<L', secret[:4])[0] if keyVersion == 1: # legacy key backup_key = P_BACKUP_KEY(secret) backupkey = backup_key['Data'] if self.options.export: logging.debug( "Exporting key to file {}".format(name + ".key")) open(name + ".key", 'wb').write(backupkey) else: print("Legacy key:") print("0x%s" % hexlify(backupkey).decode('latin-1')) print("\n") elif keyVersion == 2: # preferred key backup_key = PREFERRED_BACKUP_KEY(secret) pvk = backup_key['Data'][:backup_key['KeyLength']] cert = backup_key['Data'][ backup_key['KeyLength']:backup_key['KeyLength'] + backup_key['CertificateLength']] # build pvk header (PVK_MAGIC, PVK_FILE_VERSION_0, KeySpec, PVK_NO_ENCRYPT, 0, cbPvk) header = PVK_FILE_HDR() header['dwMagic'] = 0xb0b5f11e header['dwVersion'] = 0 header['dwKeySpec'] = 1 header['dwEncryptType'] = 0 header['cbEncryptData'] = 0 header['cbPvk'] = backup_key['KeyLength'] backupkey_pvk = header.getData() + pvk # pvk blob backupkey = backupkey_pvk if self.options.export: logging.debug( "Exporting certificate to file {}".format(name + ".der")) open(name + ".der", 'wb').write(cert) logging.debug( "Exporting private key to file {}".format(name + ".pvk")) open(name + ".pvk", 'wb').write(backupkey) else: print("Preferred key:") header.dump() print("PRIVATEKEYBLOB:{%s}" % (hexlify(backupkey).decode('latin-1'))) print("\n") return elif self.options.action.upper() == 'CREDENTIAL': fp = open(options.file, 'rb') data = fp.read() cred = CredentialFile(data) blob = DPAPI_BLOB(cred['Data']) if self.options.key is not None: key = unhexlify(self.options.key[2:]) decrypted = blob.decrypt(key) if decrypted is not None: creds = CREDENTIAL_BLOB(decrypted) creds.dump() return else: # Just print the data blob.dump() elif self.options.action.upper() == 'VAULT': if options.vcrd is None and options.vpol is None: print( 'You must specify either -vcrd or -vpol parameter. Type --help for more info' ) return if options.vcrd is not None: fp = open(options.vcrd, 'rb') data = fp.read() blob = VAULT_VCRD(data) if self.options.key is not None: key = unhexlify(self.options.key[2:]) cleartext = None for i, entry in enumerate(blob.attributesLen): if entry > 28: attribute = blob.attributes[i] if 'IV' in attribute.fields and len( attribute['IV']) == 16: cipher = AES.new(key, AES.MODE_CBC, iv=attribute['IV']) else: cipher = AES.new(key, AES.MODE_CBC) cleartext = cipher.decrypt(attribute['Data']) if cleartext is not None: # Lookup schema Friendly Name and print if we find one if blob['FriendlyName'].decode( 'utf-16le')[:-1] in VAULT_KNOWN_SCHEMAS: # Found one. Cast it and print vault = VAULT_KNOWN_SCHEMAS[ blob['FriendlyName'].decode('utf-16le')[:-1]]( cleartext) vault.dump() else: # otherwise hexdump(cleartext) return else: blob.dump() elif options.vpol is not None: fp = open(options.vpol, 'rb') data = fp.read() vpol = VAULT_VPOL(data) vpol.dump() if self.options.key is not None: key = unhexlify(self.options.key[2:]) blob = vpol['Blob'] data = blob.decrypt(key) if data is not None: keys = VAULT_VPOL_KEYS(data) keys.dump() return elif self.options.action.upper() == 'UNPROTECT': fp = open(options.file, 'rb') data = fp.read() blob = DPAPI_BLOB(data) if self.options.key is not None: key = unhexlify(self.options.key[2:]) if self.options.entropy_file is not None: fp2 = open(self.options.entropy_file, 'rb') entropy = fp2.read() fp2.close() elif self.options.entropy is not None: entropy = b(self.options.entropy) else: entropy = None decrypted = blob.decrypt(key, entropy) if decrypted is not None: print('Successfully decrypted data') hexdump(decrypted) return else: # Just print the data blob.dump() print('Cannot decrypt (specify -key or -sid whenever applicable) ')
def main(): # Init the example's logger theme logger.init() print(version.BANNER) parser = argparse.ArgumentParser(add_help=True, description="SMB client implementation.") parser.add_argument( 'target', action='store', help='[[domain/]username[:password]@]<targetName or address>') parser.add_argument( '-file', type=argparse.FileType('r'), help='input file with commands to execute in the mini shell') parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON') group = parser.add_argument_group('authentication') group.add_argument('-hashes', action="store", metavar="LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH') group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)') group.add_argument( '-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file ' '(KRB5CCNAME) based on target parameters. If valid credentials ' 'cannot be found, it will use the ones specified in the command ' 'line') group.add_argument('-aesKey', action="store", metavar="hex key", help='AES key to use for Kerberos Authentication ' '(128 or 256 bits)') group = parser.add_argument_group('connection') group.add_argument( '-dc-ip', action='store', metavar="ip address", help= 'IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in ' 'the target parameter') group.add_argument( '-target-ip', action='store', metavar="ip address", help= 'IP Address of the target machine. If omitted it will use whatever was specified as target. ' 'This is useful when target is the NetBIOS name and you cannot resolve it' ) group.add_argument('-port', choices=['139', '445'], nargs='?', default='445', metavar="destination port", help='Destination port to connect to SMB Server') if len(sys.argv) == 1: parser.print_help() sys.exit(1) options = parser.parse_args() if options.debug is True: logging.getLogger().setLevel(logging.DEBUG) # Print the Library's installation path logging.debug(version.getInstallationPath()) else: logging.getLogger().setLevel(logging.INFO) domain, username, password, address = parse_target(options.target) if options.target_ip is None: options.target_ip = address if domain is None: domain = '' if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: from getpass import getpass password = getpass("Password:"******"Executing commands from %s" % options.file.name) for line in options.file.readlines(): if line[0] != '#': print("# %s" % line, end=' ') shell.onecmd(line) else: print(line, end=' ') else: shell.cmdloop() except Exception as e: if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() logging.error(str(e))
quotechar='|', quoting=csv.QUOTE_MINIMAL, lineterminator='\n') writer.writerow( ['Account', 'Name', 'Service', 'Description', 'System']) if options.debug is True: logging.getLogger().setLevel(logging.DEBUG) # Print the Library's installation path logging.debug(version.getInstallationPath()) else: logging.getLogger().setLevel(logging.INFO) import re domain, username, password, host = parse_target(options.target) # if multiple hosts specified if ',' in host: for target in host.split(','): hosts.append(target) else: hosts.append(host) if domain is None: domain = '' if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None: from getpass import getpass password = getpass("Password:")