How windows performs integrity check before retrie

2019-06-11 04:28发布

问题:

Hi I have wonder how windows performs integrity check on the registry values before its going to read it.

While i am changing the cached domain credentials in the windows registry, I got those values from the following keys HKEY_LOCAL_MACHINE\SECURITY\CACHE\NL$1 ... NL$10.

I have decoded it with the NL$KM key values and dumped the Stored password hash. And i wish to change the hash with my own new generated hash. But Windows its bit tricky they have added a final checksum validation for validating it I hope but not sure. So its there any way to change the hash and act the system to work in offline when the system is not connected with domain.

Here is the code for doing this:

To do encrypt or decrypt the cache techniques varies depends on Windows OS Versions

int cryptData(LPBYTE in,LPBYTE out,DWORD dataSize,CRYPT_KEYS *keys,CRYPT_TYPE cType) {
 RC4_KEY rc4_ctx;
 AES_KEY aes_ctx;
 BYTE aes_iv[16];

 RtlMoveMemory(aes_iv,keys->aes_iv,sizeof(keys->aes_iv));

 switch(cType) {
  case ENCRYPT:
   if(keys->version<6) {
    HMAC(EVP_md5(),keys->nl$km,sizeof(keys->nl$km),keys->hmac_message,sizeof(keys->hmac_message),keys->rc4_key,NULL);
    RC4_set_key(&rc4_ctx,MD5_DIGEST_LENGTH,keys->rc4_key);
    RC4(&rc4_ctx,dataSize,in,out);
   }
   else {
    AES_set_encrypt_key(keys->nl$km,128,&aes_ctx);
    AES_cbc_encrypt(in,out,dataSize,&aes_ctx,aes_iv,AES_ENCRYPT);
   }    
   break;
  case DECRYPT:
   if(keys->version<6) {
    HMAC(EVP_md5(),keys->nl$km,sizeof(keys->nl$km),keys->hmac_message,sizeof(keys->hmac_message),keys->rc4_key,NULL);
    RC4_set_key(&rc4_ctx,MD5_DIGEST_LENGTH,keys->rc4_key);
    RC4(&rc4_ctx,dataSize,in,out);
   }
   else {
    AES_set_decrypt_key(keys->nl$km,128,&aes_ctx);
    AES_cbc_encrypt(in,out,dataSize,&aes_ctx,aes_iv,AES_DECRYPT);
   }
   break;
  }
return 0;

}

To Generate the new Password Hash: [FYI: Its reliable]

 HashGen hash(username,password,this->getOSVersion());

Replace the old password hash with new password hash & encrypt them again:

 RtlMoveMemory(decipheredData,hash.getHashDigest(),NTLM_HASH_SIZE);
 RtlZeroMemory(cipheredData,cachedAccount->cacheSize);

 cryptData(decipheredData,cipheredData,cachedAccount->cacheSize,&keys,ENCRYPT);
 RtlMoveMemory(cachedAccount->cache+96,cipheredData,cachedAccount->cacheSize-96);

Write them all in the registry back: [FYI: Working fine actually i am doing through the system account]

 HKEY    hOpenedKey;
 DWORD   status,nMaxLength; 
 if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"security\\cache",0,KEY_WRITE,&hOpenedKey) ) {
  int status = RegSetValueEx(hOpenedKey,L"nl$1",0,REG_BINARY,cachedAccount->cache,cachedAccount->cacheSize ); 
  if( status != ERROR_SUCCESS ) { 
   printf("cache Update failed ...");
   RegCloseKey( hOpenedKey );
  }
  else {
   RegCloseKey( hOpenedKey );
   printf("cache Updated successfully ...");
  }
 }

回答1:

There are two checksums one in the unenc section and one on the tail.