'Parse the output from Invoke-Mimikatz to return credential sets.
This was directly stolen from the Empire project as well.'

def parse_mimikatz(self, data):

    creds = []
    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 password:
                    if ((username != '') and (password != '') and (password != '(null)')):
                        sid = ''
                        if hostDomain.startswith(domain.lower()):
                            domain = hostDomain
                            sid = domainSid
                        store = False
                        category = ''
                        if self.validate_ntlm(password):
                            credType = 'Hash'
                            category = 'NTLM    hash'
                            if (not username.endswith('$')):
                                store = True
                        else:
                            credType = 'Password'
                            category = 'System    password'
                            if (len(password) < 300):
                                store = True
                        result = {'Domain': domain, 'Login': username, credType: password, 'CredType': credType.lower(), 'Host': hostName, 'sid': sid, 'Category': category, 'uid': self.client.short_name()}
                        for c in creds:
                            if (c == result):
                                store = False
                        if store:
                            creds.append(result)
                    (username, domain, password) = ('', '', '')
    if (len(creds) == 0):
        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()
                    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({'Domain': domain, 'Login': user, 'Hash': krbtgtHash, 'Host': hostName, 'CredType': 'hash', 'sid': sid, 'Category': 'krbtgt    hash', 'uid': self.client.short_name()})
                except Exception as e:
                    pass
    if (len(creds) == 0):
        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({'Domain': domain, 'Login': user, 'Hash': userHash, 'Host': dcName, 'CredType': 'hash', 'SID': sid, 'Category': 'NTLM    hash', 'uid': self.client.short_name()})
    return creds
