Je l’avais pourtant suggéré lors de mon passage aux PHDays 2012 ; pour dumper les hashes et mot de passe, il suffirait d’aller lire les clés de (dé)chiffrement de LSASS pour éviter d’y injecter la librairie sekurlsa.

Personne ne l’a fait :(
même pas wce qui, en plus de copier certains patterns / concepts de mimikatz, injecte sournoisement la librairie wceaux.dll pour dumper les mots de passes via WDigest, parfois à l’aide d’un service…
Approche
Le déchiffrement des mots de passe est effectué directement par :
LsaUnprotectMemory – http://msdn.microsoft.com/library/windows/desktop/ff714510.aspx
Le chiffrement des mots de passe est quant à lui effectué par :
LsaProtectMemory – http://msdn.microsoft.com/library/windows/desktop/ff714509.aspx
Ces deux fonctions reposent sur : LsaEncryptMemory
Windows NT 5
- Algorithme :
RC4
Clé : dérivée depuisg_pRandomKey, de longueurg_cbRandomKey(256) - Algorithme :
DES
Clé :g_pDESXKey, de longueur 144
IV :g_Feedback, de longueur 8
Méthodologie
- Charger
lsasrv.dlldansmimikatz - Copier les 8 octets de
LSASS:lsasrv!g_Feedbackversmimikatz:lsasrv!g_Feedback - Copier les 4 octets (
DWORD) deLSASS:lsasrv!g_cbRandomKeyversmimikatz:lsasrv!g_cbRandomKey - Instancier un nouveau tableau de taille
mimikatz:lsasrv!g_cbRandomKeyoctets - Placer l’adresse de ce tableau dans
mimikatz:lsasrv!g_pRandomKey - Copier les
mimikatz:lsasrv!g_cbRandomKeyoctets ciblés parLSASS:lsasrv!g_pRandomKeyvers le tableau ciblé parmimikatz:lsasrv!g_pRandomKey - Instancier un nouveau tableau de taille 144 octets
- Placer l’adresse de ce tableau dans
mimikatz:lsasrv!g_pDESXKey - Copier les 144 octets ciblés par
LSASS:lsasrv!g_pDESXKeyvers le tableau ciblé parmimikatz:lsasrv!g_pDESXKey
Windows NT 6
- Algorithme :
3DES
Clé : référencée par le handleh3DesKey
IV :InitializationVector, de longueur 8 (sur 16) - Algorithme :
AES
Clé : référencée par le handlehAesKey
IV :InitializationVector, de longueur 16
Méthodologie
- Charger
lsasrv.dlldansmimikatz - Copier les 16 octets de
LSASS:lsasrv!InitializationVectorversmimikatz:lsasrv!InitializationVector - Appeler la fonction
mimikatz:lsasrv!LsaInitializeProtectedMemorypour initialiser correctement les handles de clésh3DesKeyethAesKey
Ces handles pointent vers des structures de ce types :typedef struct _KIWI_BCRYPT_KEY { DWORD size; DWORD type; PVOID unk0; PKIWI_BCRYPT_KEY_DATA cle; PVOID unk1; } KIWI_BCRYPT_KEY, *PKIWI_BCRYPT_KEY;avec
typedef struct _KIWI_BCRYPT_KEY_DATA { DWORD size; DWORD tag; DWORD type; DWORD unk0; DWORD unk1; DWORD unk2; DWORD unk3; PVOID unk4; BYTE data; /* etc... */ } KIWI_BCRYPT_KEY_DATA, *PKIWI_BCRYPT_KEY_DATA; - Copier les
LSASS:lsasrv!h3DesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA.sizeoctets deLSASS:lsasrv!h3DesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATAversmimikatz:lsasrv!h3DesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA - Copier les
(LSASS:lsasrv!hAesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA.size - 2*sizeof(PVOID))octets* deLSASS:lsasrv!hAesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATAversmimikatz:lsasrv!hAesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA
*il y a deux pointeurs internes à la fin de la structure AES, l’initialisation de départ fait qu’ils sont déjà corrects :)
Une fois ces opérations réalisées, la fonction LsaEncryptMemory fonctionne correctement ! Nous permettant ainsi de bénéficier du même déchiffrement que LSASS dans mimikatz…
mimikatz et sekurlsa sans injection ?
