View unanswered posts | View active topics It is currently 23 Nov 2009, 00:56



Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
 LSA Secrets and Windows 2008 
Author Message
-
-

Joined: 25 Sep 2008, 22:22
Posts: 4
Post LSA Secrets and Windows 2008
Greetings smart folks,

I've been working at redoing some LSA secrets code based on some comments mao had made here:

http://oxid.netsons.org/phpBB2/viewtopic.php?t=149

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. There have been substantial changes to the code surrounding these operations in lsasrv.dll (which is called by lsass.exe), such that I wonder about how this value is being handled these days.

Before I go looking over copious amounts of very complicated code to sort through this mess, I'm curious if anyone has any insights into how this value is now being used within Server 2008. 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. :)

--fizzgig


25 Sep 2008, 22:51
Profile WWW
..........
..........

Joined: 20 Oct 2006, 02:24
Posts: 596
Post 
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.


03 Oct 2008, 05:27
Profile
-
-

Joined: 25 Sep 2008, 22:22
Posts: 4
Post 
This is very useful, and I was beginning to see at least parts of this I guess. :) I am working on 2008 now and will make sure it works the same, but I suspect it does. If I ever bump into you somewhere mao, I owe you a beer. :)


03 Oct 2008, 22:50
Profile WWW
-
-

Joined: 06 Oct 2008, 03:38
Posts: 1
Post 
i only took a quick look, but it seems like i might have already implemented this in qforegsics


06 Oct 2008, 03:39
Profile
-
-

Joined: 25 Sep 2008, 22:22
Posts: 4
Post 
This does indeed seem to work on Win 2K8 - at least I get the valid NL$KM value back. I'm certain testing tomorrow will in fact give me the correct cache values - I think this was the hard part.


07 Oct 2008, 03:38
Profile WWW
-
-

Joined: 25 Sep 2008, 22:22
Posts: 4
Post 
The method used to store cached creds changed too, I see. I'm getting the same results as Cain, but it doesn't appear to be valid data. So close, yet so far. :)

I'll post if I find out how to work with this newer stuff.


07 Oct 2008, 17:37
Profile WWW
-
-

Joined: 05 Jan 2009, 18:16
Posts: 1
Post 
Guys, I'm struggling on this too, can you please explain what is 'bootkey' in Vista?
Also, I've done some research on cached credential format in Vista (hope to complete it soon) and will share this info.


05 Jan 2009, 18:30
Profile
-
-

Joined: 16 Apr 2009, 20:41
Posts: 4
Post 
Hi mao, thanks for the great information. Using that I am able to successfully get the NL$KM, however I am having trouble using the NL$KM to decrypt domain cached credentials as the method to encrypt them has clearly changed for Vista and on.

Do you have any insight (or code snippets) about the new scheme? They would be greatly appreciated!


16 Apr 2009, 20:46
Profile
.
.

Joined: 09 Mar 2009, 22:43
Posts: 17
Post 
the encryption now is same as before except there is extra "wrapping" using PBKDF 2.0

hash = PBKDF2( MD4 ( MD4 ($password).$username)), iterations )

by default, the iterations value is 10,240

this can also be used for kerberos

here is what you can do to research how it all works.
download the debugging symbols and use PDB plugin by determina, then all will be revealed in IDA Pro ;)

Code:
/*
* This function is used to derive PSK for WPA-PSK. For this protocol,
* iterations is set to 4096 and buflen to 32. This function is described in
* IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
*/

void pbkdf2(unsigned char key[], size_t key_len,
            unsigned char salt[],size_t salt_len,
            unsigned int rounds,
            unsigned char digest[])
{
        unsigned char ipad[SHA_CBLOCK+1];
        unsigned char opad[SHA_CBLOCK+1];

        unsigned char tmp_hash[SHA_DIGEST_LENGTH];

        SHA_CTX tctx1,tctx2;
        SHA_CTX ctx1,ctx2;

        if(key_len > SHA_CBLOCK) {
          SHA1_Init(&ctx1);
          SHA1_Update(&ctx1,key,key_len);
          SHA1_Final(tmp_hash,&ctx1);

          key_len = SHA_DIGEST_LENGTH;
          key = tmp_hash;
        }

        for(size_t i = 0;i < SHA_CBLOCK;i++) {
          ipad[i] = 0x36;
          opad[i] = 0x5c;
        }

        for(size_t i = 0;i < key_len;i++) {
          ipad[i] ^= key[i];
          opad[i] ^= key[i];
        }
       
        SHA1_Init(&tctx1);
        SHA1_Init(&tctx2);

        SHA1_Update(&tctx1,ipad,SHA_CBLOCK);
        SHA1_Update(&tctx2,opad,SHA_CBLOCK);

        memcpy(&ctx1,&tctx1,sizeof(SHA_CTX));
        memcpy(&ctx2,&tctx2,sizeof(SHA_CTX));

        SHA1_Update(&ctx1,salt,salt_len);
        SHA1_Final(tmp_hash,&ctx1);

        SHA1_Update(&ctx2,tmp_hash,SHA_DIGEST_LENGTH);
        SHA1_Final(tmp_hash,&ctx2);

        memcpy(digest,tmp_hash,SHA_DIGEST_LENGTH);

        for(unsigned int i = 1;i < rounds;i++)
        {
          memcpy(&ctx1,&tctx1,sizeof(SHA_CTX));
          memcpy(&ctx2,&tctx2,sizeof(SHA_CTX));

          SHA1_Update(&ctx1,tmp_hash,SHA_DIGEST_LENGTH);
          SHA1_Final(tmp_hash,&ctx1);

          SHA1_Update(&ctx2,tmp_hash,SHA_DIGEST_LENGTH);
          SHA1_Final(tmp_hash,&ctx2);
         
          for(int j = 0;j < 5;j++)
            ((unsigned int*)digest)[j] ^= ((unsigned int*)tmp_hash)[j];
        }
}


19 Apr 2009, 05:07
Profile
-
-

Joined: 16 Apr 2009, 20:41
Posts: 4
Post 
Hi bus_driver,

The encryption scheme doesn't seem to be quite the same, the RC4 decryption that works for XP and previous is not successfully decrypting the cached credential (no user names / domain names etc are visible after decryption).

You do bring up a separate question I had been wondering about, I had read that 10240 was the default iterations for the PBKDF2 however I'm not sure where that number is specified. I had assumed it would be in the encrypted section of the cached credential however since I haven't managed to decrypt successfully I haven't been able to check on that.

The more pressing question to me is where does the salt come from for the PBKDF2? For normal PBKDF use we need:
* key
* salt
* rounds

The rounds, as you described, are normally 10240. Key is likely the normal MD4 ( MD4 ($password).$username) hash you described before, but where does the salt come from? Is it the Cipher key (0x40 - 0x50 of the domain cached credential), some version of the hashed username, or something else entirely?


20 Apr 2009, 20:05
Profile
-
-

Joined: 21 Apr 2009, 04:59
Posts: 3
Post 
Based on how PBKDF2 is set up compared to MD4, i would guess the set up bus_driver is indicating is the following:
key = $password
salt = $username
digest = MD4


21 Apr 2009, 23:33
Profile
-
-

Joined: 16 Apr 2009, 20:41
Posts: 4
Post 
Hi jmesmon,

As far as I can tell what bus_driver seems to be saying, and what is definitely said by http://www.passcape.com/domain_cached_passwords.htm, is that the PBKDF2 is done on top on the output of the MD4(MD4 ($password).$username)). According to the passcape.com article the hash function is SHA, my guess would be SHA256 based off the new LSA Secret encryption methodologies. Unfortunately, the article doesn't specify where the salt comes from.


22 Apr 2009, 01:44
Profile
-
-

Joined: 21 Apr 2009, 04:59
Posts: 3
Post 
Interesting. Unfortunately, it appears the link tom posted is broken (at least at my end), so i cannot read further on it.


22 Apr 2009, 05:14
Profile
..........
..........

Joined: 29 Mar 2008, 22:40
Posts: 4068
Location: Miskatonic U.
Post 
Remove the comma at the end... http://www.passcape.com/domain_cached_passwords.htm


22 Apr 2009, 19:17
Profile WWW
-
-

Joined: 21 Apr 2009, 04:59
Posts: 3
Post 
Should have noticed that...

Anyhow, the article does indicate that the hashing is done as tom stated. Anyone have anyluck determining the remaining unknowns? (SHA type, what the key is set to, what the salt is set to)


23 Apr 2009, 00:20
Profile
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by Vjacheslav Trushkin for Free Forums/DivisionCore.