def do_creds(self, line): filterTerm = line.strip() if filterTerm == "": creds = self.db.get_credentials() self.display_creds(creds) elif filterTerm.split()[0].lower() == "add": # add format: "domain username password <notes> <credType> <sid> args = filterTerm.split()[1:] if len(args) == 3: domain, username, password = args if validate_ntlm(password): self.db.add_credential("hash", domain, username, password) else: self.db.add_credential("plaintext", domain, username, password) else: print "[!] Format is 'add domain username password" return elif filterTerm.split()[0].lower() == "remove": args = filterTerm.split()[1:] if len(args) != 1 : print "[!] Format is 'remove <credID>'" return else: self.db.remove_credentials(args) self.db.remove_links(credIDs=args) elif filterTerm.split()[0].lower() == "plaintext": creds = self.db.get_credentials(credtype="plaintext") self.display_creds(creds) elif filterTerm.split()[0].lower() == "hash": creds = self.db.get_credentials(credtype="hash") self.display_creds(creds) else: creds = self.db.get_credentials(filterTerm=filterTerm) self.display_creds(creds)
def do_creds(self, line): filterTerm = line.strip() if filterTerm == "": creds = self.db.get_credentials() self.display_creds(creds) elif filterTerm.split()[0].lower() == "add": # add format: "domain username password <notes> <credType> <sid> args = filterTerm.split()[1:] if len(args) == 3: domain, username, password = args if validate_ntlm(password): self.db.add_credential("hash", domain, username, password) else: self.db.add_credential("plaintext", domain, username, password) else: print "[!] Format is 'add domain username password" return elif filterTerm.split()[0].lower() == "remove": args = filterTerm.split()[1:] if len(args) != 1 : print "[!] Format is 'remove <credID>'" return else: self.db.remove_credentials(args) self.db.remove_links(credIDs=args) elif filterTerm.split()[0].lower() == "plaintext": creds = self.db.get_credentials(credtype="plaintext") self.display_creds(creds) elif filterTerm.split()[0].lower() == "hash": creds = self.db.get_credentials(credtype="hash") self.display_creds(creds) else: creds = self.db.get_credentials(filterTerm=filterTerm) print "\nCredential(s):\n" print " CredID CredType Domain UserName Password" print " ------ -------- ------ -------- --------" credIDList = [] for cred in creds: credID = cred[0] credIDList.append(credID) credType = cred[1] domain = cred[2] username = cred[3] password = cred[4] print u" {}{}{}{}{}".format('{:<8}'.format(credID), '{:<12}'.format(credType), u'{:<17}'.format(domain.decode('utf-8')), u'{:<21}'.format(username.decode('utf-8')), u'{:<17}'.format(password.decode('utf-8'))) print "" print "\nAdmin Access to Host(s):\n" print " HostID IP Hostname Domain OS" print " ------ -- -------- ------ --" for credID in credIDList: links = self.db.get_links(credID=credID) for link in links: linkID, credID, hostID = link hosts = self.db.get_hosts(hostID) for host in hosts: hostID = host[0] ip = host[1] hostname = host[2] domain = host[3] os = host[4] print u" {}{}{}{}{}".format('{:<8}'.format(hostID), '{:<17}'.format(ip), u'{:<25}'.format(hostname.decode('utf-8')), u'{:<17}'.format(domain.decode('utf-8')), '{:<17}'.format(os)) print ""
def parse_mimikatz(self, data): """ Parse the output from Invoke-Mimikatz to return credential sets. This was directly stolen from the Empire project as well. """ # cred format: # credType, domain, username, password, hostname, sid creds = [] # regexes for "sekurlsa::logonpasswords" Mimikatz output regexes = [ "(?s)(?<=msv :).*?(?=tspkg :)", "(?s)(?<=tspkg :).*?(?=wdigest :)", "(?s)(?<=wdigest :).*?(?=kerberos :)", "(?s)(?<=kerberos :).*?(?=ssp :)", "(?s)(?<=ssp :).*?(?=credman :)", "(?s)(?<=credman :).*?(?=Authentication Id :)", "(?s)(?<=credman :).*?(?=mimikatz)" ] hostDomain = "" domainSid = "" hostName = "" lines = data.split("\n") for line in lines[0:2]: if line.startswith("Hostname:"): try: domain = line.split(":")[1].strip() temp = domain.split("/")[0].strip() domainSid = domain.split("/")[1].strip() hostName = temp.split(".")[0] hostDomain = ".".join(temp.split(".")[1:]) except: pass for regex in regexes: p = re.compile(regex) for match in p.findall(data): lines2 = match.split("\n") username, domain, password = "", "", "" for line in lines2: try: if "Username" in line: username = line.split(":", 1)[1].strip() elif "Domain" in line: domain = line.split(":", 1)[1].strip() elif "NTLM" in line or "Password" in line: password = line.split(":", 1)[1].strip() except: pass if username != "" and password != "" and password != "(null)": sid = "" # substitute the FQDN in if it matches if hostDomain.startswith(domain.lower()): domain = hostDomain sid = domainSid if validate_ntlm(password): credType = "hash" else: credType = "plaintext" # ignore machine account plaintexts if not (credType == "plaintext" and username.endswith("$")): creds.append((credType, domain, username, password, hostName, sid)) if len(creds) == 0: # check if we have lsadump output to check for krbtgt # happens on domain controller hashdumps for x in xrange(8, 13): if lines[x].startswith("Domain :"): domain, sid, krbtgtHash = "", "", "" try: domainParts = lines[x].split(":")[1] domain = domainParts.split("/")[0].strip() sid = domainParts.split("/")[1].strip() # substitute the FQDN in if it matches if hostDomain.startswith(domain.lower()): domain = hostDomain sid = domainSid for x in xrange(0, len(lines)): if lines[x].startswith("User : krbtgt"): krbtgtHash = lines[x + 2].split(":")[1].strip() break if krbtgtHash != "": creds.append(("hash", domain, "krbtgt", krbtgtHash, hostName, sid)) except Exception as e: pass if len(creds) == 0: # check if we get lsadump::dcsync output if '** SAM ACCOUNT **' in lines: domain, user, userHash, dcName, sid = "", "", "", "", "" for line in lines: try: if line.strip().endswith("will be the domain"): domain = line.split("'")[1] elif line.strip().endswith("will be the DC server"): dcName = line.split("'")[1].split(".")[0] elif line.strip().startswith("SAM Username"): user = line.split(":")[1].strip() elif line.strip().startswith("Object Security ID"): parts = line.split(":")[1].strip().split("-") sid = "-".join(parts[0:-1]) elif line.strip().startswith("Hash NTLM:"): userHash = line.split(":")[1].strip() except: pass if domain != "" and userHash != "": creds.append(("hash", domain, user, userHash, dcName, sid)) return self.uniquify_tuples(creds)
def parse_mimikatz(self, data): """ Parse the output from Invoke-Mimikatz to return credential sets. This was directly stolen from the Empire project as well. """ # cred format: # credType, domain, username, password, hostname, sid creds = [] # regexes for "sekurlsa::logonpasswords" Mimikatz output regexes = ["(?s)(?<=msv :).*?(?=tspkg :)", "(?s)(?<=tspkg :).*?(?=wdigest :)", "(?s)(?<=wdigest :).*?(?=kerberos :)", "(?s)(?<=kerberos :).*?(?=ssp :)", "(?s)(?<=ssp :).*?(?=credman :)", "(?s)(?<=credman :).*?(?=Authentication Id :)", "(?s)(?<=credman :).*?(?=mimikatz)"] hostDomain = "" domainSid = "" hostName = "" lines = data.split("\n") for line in lines[0:2]: if line.startswith("Hostname:"): try: domain = line.split(":")[1].strip() temp = domain.split("/")[0].strip() domainSid = domain.split("/")[1].strip() hostName = temp.split(".")[0] hostDomain = ".".join(temp.split(".")[1:]) except: pass for regex in regexes: p = re.compile(regex) for match in p.findall(data): lines2 = match.split("\n") username, domain, password = "", "", "" for line in lines2: try: if "Username" in line: username = line.split(":",1)[1].strip() elif "Domain" in line: domain = line.split(":",1)[1].strip() elif "NTLM" in line or "Password" in line: password = line.split(":",1)[1].strip() except: pass if username != "" and password != "" and password != "(null)": sid = "" # substitute the FQDN in if it matches if hostDomain.startswith(domain.lower()): domain = hostDomain sid = domainSid if validate_ntlm(password): credType = "hash" else: credType = "plaintext" # ignore machine account plaintexts if not (credType == "plaintext" and username.endswith("$")): creds.append((credType, domain, username, password, hostName, sid)) if len(creds) == 0: # check if we have lsadump output to check for krbtgt # happens on domain controller hashdumps for x in xrange(8,13): if lines[x].startswith("Domain :"): domain, sid, krbtgtHash = "", "", "" try: domainParts = lines[x].split(":")[1] domain = domainParts.split("/")[0].strip() sid = domainParts.split("/")[1].strip() # substitute the FQDN in if it matches if hostDomain.startswith(domain.lower()): domain = hostDomain sid = domainSid for x in xrange(0, len(lines)): if lines[x].startswith("User : krbtgt"): krbtgtHash = lines[x+2].split(":")[1].strip() break if krbtgtHash != "": creds.append(("hash", domain, "krbtgt", krbtgtHash, hostName, sid)) except Exception as e: pass if len(creds) == 0: # check if we get lsadump::dcsync output if '** SAM ACCOUNT **' in lines: domain, user, userHash, dcName, sid = "", "", "", "", "" for line in lines: try: if line.strip().endswith("will be the domain"): domain = line.split("'")[1] elif line.strip().endswith("will be the DC server"): dcName = line.split("'")[1].split(".")[0] elif line.strip().startswith("SAM Username"): user = line.split(":")[1].strip() elif line.strip().startswith("Object Security ID"): parts = line.split(":")[1].strip().split("-") sid = "-".join(parts[0:-1]) elif line.strip().startswith("Hash NTLM:"): userHash = line.split(":")[1].strip() except: pass if domain != "" and userHash != "": creds.append(("hash", domain, user, userHash, dcName, sid)) return self.uniquify_tuples(creds)