gentilkiwi / mimikatz

A little tool to play with Windows security
http://blog.gentilkiwi.com/mimikatz
18.98k stars 3.62k forks source link

Function kull_m_cred_create does not copy actual credentials blob size #436

Open BubbleMaker2089 opened 8 months ago

BubbleMaker2089 commented 8 months ago

I'm trying to decrypt credential related to my email account

mimikatz # dpapi::cred /in:C:\Users\<user>\AppData\Local\Microsoft\Credentials\<cred_name>
**BLOB**
  dwVersion          : 00000001 - 1
  guidProvider       : {guidProvider       }
  dwMasterKeyVersion : 00000001 - 1
  guidMasterKey      : {guidMasterKey      }
  dwFlags            : 20000000 - 536870912 (system ; )
  dwDescriptionLen   : 00000030 - 48
  szDescription      : Local Credential Data

  algCrypt           : 00006610 - 26128 (CALG_AES_256)
  dwAlgCryptLen      : 00000100 - 256
  dwSaltLen          : 00000020 - 32
  pbSalt             : <hex_data>
  dwHmacKeyLen       : 00000000 - 0
  pbHmackKey         :
  algHash            : 0000800e - 32782 (CALG_SHA_512)
  dwAlgHashLen       : 00000200 - 512
  dwHmac2KeyLen      : 00000020 - 32
  pbHmack2Key        : <hex_data>
  dwDataLen          : 00000f50 - 3920
  pbData             :  <hex_data>
  dwSignLen          : 00000040 - 64
  pbSign             :  <hex_data>

Decrypting Credential:
 * volatile cache: GUID:{c2bc45ee-c920-468d-b1a3-ecb7254a46c5};KeyHash:f9eb130c630784e996a2e9de17fe8134cf9c2a59;Key:available
**CREDENTIAL**
  credFlags      : 00000030 - 48
  credSize       : 00000f4e - 3918
  credUnk0       : 00000000 - 0

  Type           : 00000001 - 1 - generic
  Flags          : 00000000 - 0
  LastWritten    : 24.10.2023 5:05:40
  unkFlagsOrSize : 00000000 - 0
  Persist        : 00000002 - 2 - local_machine
  AttributeCount : 0000000b - 11
  unk0           : 00000000 - 0
  unk1           : 00000000 - 0
  TargetName     : LegacyGeneric:target=MicrosoftAccount:user=<email>
  UnkData        : (null)
  Comment        : PersistedCredential
  TargetAlias    : (null)
  UserName       : <email>
  **CredentialBlob : (null)**
  CredentialBlobSize : 0

In kuhl_m_dpapi_cred.c in function kuhl_m_dpapi_cred we have kull_m_cred_create invocation for non legacy cred and it does not know how to parse correct size of a blob. the size is 0, however it is not.
Is there any fixes for this?

BubbleMaker2089 commented 8 months ago

The line

cred->CredentialBlobSize = *(PDWORD) ((PBYTE) cred->UserName + cred->dwUserName);

results in zero length for credentials blob.

PKULL_M_CRED_BLOB kull_m_cred_create(PVOID data/*, DWORD size*/)
{
    PKULL_M_CRED_BLOB cred = NULL;
    if(cred = (PKULL_M_CRED_BLOB) LocalAlloc(LPTR, sizeof(KULL_M_CRED_BLOB)))
    {
        RtlCopyMemory(cred, data, FIELD_OFFSET(KULL_M_CRED_BLOB, TargetName));
        cred->TargetName = (LPWSTR) ((PBYTE) data + FIELD_OFFSET(KULL_M_CRED_BLOB, TargetName));
        cred->dwUnkData = *(PDWORD) ((PBYTE) cred->TargetName + cred->dwTargetName);
        cred->UnkData = (LPWSTR) ((PBYTE) cred->TargetName + cred->dwTargetName + sizeof(DWORD));
        cred->dwComment = *(PDWORD) ((PBYTE) cred->UnkData + cred->dwUnkData);
        cred->Comment = (LPWSTR) ((PBYTE) cred->UnkData + cred->dwUnkData + sizeof(DWORD));
        cred->dwTargetAlias = *(PDWORD) ((PBYTE) cred->Comment + cred->dwComment);
        cred->TargetAlias = (LPWSTR) ((PBYTE) cred->Comment + cred->dwComment + sizeof(DWORD));
        cred->dwUserName = *(PDWORD) ((PBYTE) cred->TargetAlias + cred->dwTargetAlias);
        cred->UserName = (LPWSTR) ((PBYTE) cred->TargetAlias + cred->dwTargetAlias + sizeof(DWORD));
        cred->CredentialBlobSize = *(PDWORD) ((PBYTE) cred->UserName + cred->dwUserName);
        cred->CredentialBlob = (PBYTE) cred->UserName + cred->dwUserName + sizeof(DWORD);
        kprintf(L"In kull_m_cred_create: %d\n", cred->CredentialBlobSize); // 0 size
        // kprintf(L"In kull_m_cred_create %*s" L"  CredentialBlob      : %d\n", L"", cred->CredentialBlob);

        if(cred->AttributeCount)
            kull_m_cred_attributes_create(((PBYTE) cred->CredentialBlob + cred->CredentialBlobSize + (cred->CredentialBlobSize & 1)), &cred->Attributes, cred->AttributeCount);         

        kull_m_string_ptr_replace(&cred->TargetName, cred->dwTargetName);
        kull_m_string_ptr_replace(&cred->TargetAlias, cred->dwTargetAlias);
        kull_m_string_ptr_replace(&cred->Comment, cred->dwComment);
        kull_m_string_ptr_replace(&cred->UnkData, cred->dwUnkData);
        kull_m_string_ptr_replace(&cred->UserName, cred->dwUserName);
        kull_m_string_ptr_replace(&cred->CredentialBlob, cred->CredentialBlobSize);
    }
    return cred;
}
BubbleMaker2089 commented 8 months ago

Maybe I'm wrong, because for the same type of credential for another service I have non-zero blob size. Is it correct that Outlook does not store a password in credential file anymore?