|   | 
	
	
	
		| Exposing the Secret of Decrypting Network Passwords | 
	
		   |  	
    
    
		
		| 
		
			
			
		
		 | 
	
	
		   |  	
	
	
		
	
		  |  	
		
	
		| 
		
	 | 
	
	
		|   | 
	
	
		|   | 
	
	
	
		
	
		  |  	
	
		 | 
	
	
		|   | 
	
	
		
	
		  |  	
	
	
		Windows provides 'Credential Store' 
			framework to store the network based passwords in a secure encrypted 
			format. This provides convenient and reliable mechanism to store the 
			passwords for network logins so that user don't have to enter the 
			password every time while accessing the network resources.  
			
			Not only Windows uses it to store network authentication passwords, 
			but also other applications such as Outlook, Windows Live Messenger, 
			Remote Destktop, GMail Notifier etc uses the same mechanism for 
			storing their login passwords.
			 
			Windows also allows applications to seamlessly manage this 
			'Credential Store' using Credential Management API functions 
			[ Reference 2] such as 
			CredEnumerate, CredRead, CredWrite, CredProtect, CredUnprotect, 
			CredDelete etc.   | 
	
	
  |  	
  |  	
	
		
	
	  |  	
	
		Windows 'Credential Store' 
			keeps the user 
			credentials in the encrypted format at user specific locations. The 
			storage mechanism is slightly different for XP and Vista/Win7 
			platforms. 
			 
			  | 
			
	  
	
	
	 
	
	
				
	
		 
		  |  	 
		
	
		| On Windows XP, the encrypted user credentials are stored in the 
		hidden file called 'Credentials' inside both APPDATA and LOCALAPPDATA 
		locations mentioned below. |  
		
  |  	 
		
	
		APPDATA Location - C:\Documents and Settings\<username>\Application 
		Data\Microsoft\Credentials\<user sid>\ 
		 
		LOCALAPPDATA Location - C:\Documents and Settings\<username>\Local 
		Settings\Application Data\Microsoft\Credentials\<user sid>\ 
		 |  
		
	  |  	 
	
		 
		  |  	 
	
		| Vista onwards, the user credentials are stored in the multiple files 
		with random name (generated using GUID) inside both APPDATA and 
		LOCALAPPDATA locations mentioned below. (There will be separate 
		credential file for each of the network accounts) |  
		
			  |  	 
		
	
		APPDATA Location - 
		C:\Users\<username>\AppData\Roaming\Microsoft\Credentials\ 
		 
		LOCALAPPDATA Location - 
		C:\Users\<username>\AppData\Local\Microsoft\Credentials\  |  
		
	  |  	 
		
	
	
	
	 
	
	
	 | 
		
	
		
		 Based on type of password and application, 
			one of these locations are chosen to store the corresponding 
			credential file. For example,
			Windows Live Messenger & Remote Desktop login passwords are stored at LOCALAPPDATA location and all 
		other type of passwords are stored at APPDATA location. 
			 
			These credential files are hidden and 
			not visible even if you have enabled 'show hidden files/folders' in 
			the folder settings. To view these files, use the command prompt and 
			navigate to the above locations and then issue the 'dir /a' command.  
			 
			Each of these credential file begins with standard signature at the 
			beginning of the file which can used for its verification. Here are the first 16 
			bytes representing the identity of such credential file.  |  	
		
		
		| 0x01, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01, 0x15, 0xD1, 0x11, 
		0x8C, 0x7A, 0x00, 0xC0 | 
	
	  |  	
	  |  	
	
		
	
	  |  	
	
		Windows 'Credential Store' supports different type of network 
		passwords. Each type uses different kind of encryption and storage 
		mechanism. Also each type of password requires different level of access 
		privileges for decryption.  
		 
		Here are the primary types.... | 
	
	
		
		
			- Generic Password 
 
			- Domain Password
 
			- Domain Visible Password / .NET Passport
 
			- Certificates
 
		 
		 | 
	
	
		| 'Domain Password' type provides highest level of security as these 
		passwords can only be managed by a specific system process called 
		LSASS.exe. No other process, even though 
		it is running as administrator can decrypt such passwords. All network 
		authenticaiton, Remote Desktop and Outlook exchange server login 
		passwords belongs to this type. 
		
		 
		'Generic Password' type is used to store all user specific credentials 
		and only that user can decrypt such passwords. Internet Explorer (basic 
		& digest authentication) and Windows Live Messenger uses this method to 
		store their login credentials.  
		
		'Domain Visible Password' is similar to 'Generic Password' mechanism. 
		However in case of 'Generic Password' both username & password are 
		encrypted and for 'Domain Visible Password' only password is 
		encrypted. Also both types use different salt as entropy for decryption 
		of the password. MSN messenger 7.0 uses this method to store the login 
		passwords with the name as '.Net Passport'
		 
		 | 
	
	
		|   | 
	
	
		|   | 
	
	
		
	
	  |  	
	
		Generic network passwords are user specific and can be decrypted 
		only in the security context of corresponding user. As mentioned earlier 
		Windows Credential Management [Reference 2] 
		functions can be used to manage these passwords.  
		 
		Here is the sample code which demonstrates listing all the 
		generic passwords and then decrypting them using 
		CryptUnprotectData 
		function. 
		 
		 | 
	
	
		void EnumerateGenericNetworkPassword() 
		{ 
		DATA_BLOB DataIn; 
		DATA_BLOB DataOut; 
		DATA_BLOB OptionalEntropy; 
		tmpSalt[37]; 
		char *strSalt={"abe2869f-9b47-4cd9-a358-c22904dba7f7"}; 
		 
		char strURL[1024]; 
		char strCredentials[1024]; 
		char strUsername[1024]; 
		char strPassword[1024]; 
		 
		//Create the entropy/salt required for decryption... 
		for(int i=0; i< 37; i++) 
		 
		tmpSalt[i] = (short int)(strSalt[i] * 4); 
		 
		OptionalEntropy.pbData = (BYTE *)&tmpSalt; 
		OptionalEntropy.cbData = 74; 
		 
		DWORD Count; 
		PCREDENTIAL *Credential; 
		 
		//Now enumerate all http stored credentials.... 
		if(CredEnumerate(NULL,0,&Count,&Credential)) 
		{ 
		 
		for(int i=0;i<Count;i++) 
		 
		{ 
		 
		   
		if( Credential[i]->Type == CRED_TYPE_GENERIC) 
		   
		{ 
		      
		DataIn.pbData = (BYTE *)Credential[i]->CredentialBlob; 
		      
		DataIn.cbData = Credential[i]->CredentialBlobSize; 
		 
		      
		if(CryptUnprotectData(&DataIn, NULL,  
                             &OptionalEntropy, 
		NULL, 
                             NULL,0,&DataOut)) 
		      
		{ 
		        
		//Extract username & password from credentails (username:password) 
		        
		sprintf_s(strCredentials, 1024, "%S", DataOut.pbData); 
		 
		        
		char *ptr = strchr(strCredentials, ':'); 
		        
		*ptr = '\0'; 
		         strcpy_s(strUsername, 1024, strCredentials); 
		        
		ptr++; 
		         strcpy_s(strPassword, 1024, ptr); 
		 
		        
		printf("Generic Network Password account details, 
                Username=%s, 
		Password=%s", strUsername, strPassword); 
		 
		      
		} 
		 
		    
		} 
		 
		 
		} // End of FOR loop 
		 
		 
		CredFree(Credential); 
		} 
		 
		} //End of function 
		 | 
	
	
		|   | 
	
	
		The above code uses the 
		CredEnumerate function to go through all the 
		stored network password accounts for current user. Next it checks if the 
		account type is CRED_TYPE_GENERIC. If generic type of account is found 
		then it decrypts the user credential data using the CryptUnprotectData 
		function which is part of Windows Crypto API package.[reference 
		3] Upon successful decryption it contains both username and 
		password in the clear text separated by semicolon.  
		 | 
	
	
		|   | 
	
	
		|   | 
	
	
		
	
	  |  	
	
		This method uses the similar mechanism as the generic type to 
		encrypt the password. Only difference is that here different salt is 
		used to encrypt/decrypt the credentials. Also in this case only password is 
		encrypted rather than both username & password pair as in case of 
		generic method. 
		 
		Here is the modified working code for decrypting this type of network passwords 
		 | 
	
	
		 
		void EnumerateDotNetPassportPassword() 
		{ 
		DATA_BLOB DataIn; 
		DATA_BLOB DataOut; 
		DATA_BLOB OptionalEntropy; 
		tmpSalt[37]; 
		char *strSalt={"82BD0E67-9FEA-4748-8672-D5EFE5B779B0"}; 
		 
		char strCredentials[1024]; 
		char strUsername[1024]; 
		char strPassword[1024]; 
		 
		//Create the entropy/salt required for decryption... 
		for(int i=0; i< 37; i++) 
		tmpSalt[i] = (short int)(strSalt[i] * 4); 
		 
		OptionalEntropy.pbData = (BYTE *)&tmpSalt; 
		OptionalEntropy.cbData = 74; 
		 
		DWORD Count; 
		PCREDENTIAL *Credential; 
		 
		//Now enumerate all http stored credentials.... 
		if(CredEnumerate(NULL,0,&Count,&Credential)) 
		{ 
		 
		for(int i=0;i<Count;i++) 
		 
		{ 
		   
		if( Credential[i]->Type == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD) 
		   
		{ 
		      
		DataIn.pbData = (BYTE *)Credential[i]->CredentialBlob; 
		      
		DataIn.cbData = Credential[i]->CredentialBlobSize; 
		 
		      
		sprintf_s(strUsername, 1024, "%S", Credential[i]->UserName); 
		 
		      
		if(CryptUnprotectData(&DataIn, NULL,  
                             &OptionalEntropy, 
		NULL,NULL,0,&DataOut)) 
		      
		{ 
		          
		//Decrypted data contains password in clear text 
		          
		sprintf_s(strPassword, 1024, "%S", DataOut.pbData); 
		 
		          
		printf(".Net Passport Account details,  
                  Username=%s, Password=%s", 
		strUsername, strPassword); 
		 
		      
		} 
		 
		    
		} 
		 
		 
		} // End of FOR loop 
		 
		 
		CredFree(Credential); 
		} 
		 
		} //End of function 
		 | 
	
	
		|   | 
	
	
		The above code uses the CredEnumerate function to go through all the 
		stored network password accounts for current user. Next it checks if the 
		account type is CRED_TYPE_DOMAIN_VISIBLE_PASSWORD. If such an account is 
		found then it decrypts the password data using the CryptUnprotectData 
		function. Upon successful decryption it contains the password in clear 
		text.  
		 
		This method is also termed as '.Net Passport' because it is mainly used 
		by MSN Messenger which stored its login password with the name as '.Net 
		Passport'.  | 
	
	
		|   | 
	
	
		|   | 
	
	
		
	
	  |  	
	
		Domain network password method uses more stricter technique for 
		encrypting the credentials thus providing better security over other 
		methods. Only system process, LSASS.EXE can encrypt or decrypt 
		these kind of passwords. LSASS is a Windows core system process 
		responsible for enforcing the security and executing various security 
		oriented tasks.  
		 
		So in order to decrypt domain passwords one has to perform decryption in 
		the context of LSASS process. This can be achieved by injecting remote 
		thread into LSASS process using CreateRemoteThread function [Reference 
		1]. This is 
		similar to the technique used by pwdump tool to dump the LM/NTLM hashes 
		for the user accounts on the system. 
		 
		Once the thread is injected, it can use the special undocumented function 
		LsaICryptUnprotectData exported from Lsasrv.dll to decrypt the 
		credentials buffer. Here is the prototype of the function 
		LsaICryptUnprotectData. | 
	
	
		
		 
		typedef int (WINAPI *LPFUN_LSAICRYPTUNPROTECTDATA)  
		( 
		   
		LPBYTE 
		encCredData, 
		   
		DWORD encCredDataSize, 
		   
		DWORD reserved1, 
		   
		DWORD reserved2, 
		   
		DWORD reserved3, 
		   
		DWORD reserved4, 
		   
		DWORD dwFlags, 
		   
		DWORD reserved5, 
		   
		LPBYTE *decCredData, 
		   
		LPDWORD decCredDataSize 
		); 
		 
		 | 
	
	
		| This function takes the credential buffer (credential file found in one 
		of the store locations) & its size as input and returns the decrypted 
		credential buffer. This decrypted buffer starts with the header whose 
		structure is given below | 
	
	
		 
		struct DecryptedDataHeader 
		{ 
		   
		DWORD dwHeaderId; //0x01 for XP & 0x30 for Vista/Win7 
		   
		DWORD dwBufferSize; //size of the entire decrypted data 
		}; 
		 
		 | 
	
	
		Here first field contains the signature and second field indictes 
		the size of entire decrypted buffer. 
		 
		After the header follows the network password structure for each of the stored accounts. This structure can represent any type of network 
		password accounts and not just the domain password. However username & 
		password is decrypted only for domain accounts and for all other types 
		password is kept in the encrypted format.  
		 
		The contents of this structure is given below. The internal fields of the 
		structure varies slightly for Vista/Win7 from XP. Hence care needs to be 
		taken while decoding this decrypted data on XP and Vista/Win7 
		platforms. 
		 
		[ Note : All the structure information presented below is derived based 
		on the reverse engineering work. So things may slightly differ from real 
		stuff ] | 
	
	
		 
		// For Windows XP 
		struct DecryptedNetAccount 
		{ 
		DWORD dwItemSize; //total size of this item for XP 
		DWORD dwUnknown; 
		DWORD dwType; 
		DWORD dwFileTimeLowDate; 
		DWORD dwFileTimeHighDate; 
		DWORD dwZero; 
		DWORD dwPersist; //3 => enterprise 2=> local machine  
		char unknown[12]; 
		DWORD dwCredNameSize; 
		char strCredName[dwCredNameSize];  
		DWORD dwCommentSize;  
		char strComment[dwCommentSize]; 
		DWORD dwAliasSize;  
		char strAlias[dwAliasSize];  
		DWORD dwUserNameSize;  
		char strUserName[dwUserNameSize];  
		DWORD dwPasswordSize; 
		char password[dwPasswordSize];  
		char padding[unknown]; //To make next entry aligned on 8th byte 
		}; 
		 
		 
		// For Vista & Windows 7 
		struct DecryptedNetAccountVista 
		{ 
		DWORD dwZero; 
		DWORD dwType; 
		DWORD dwzero; 
		DWORD dwFileTimeLowDate; 
		DWORD dwFileTimeHighDate; 
		DWORD dwSomeSize; 
		DWORD dwPersist; //3 => enterprise 2=> local machine  
		char unknown[12]; 
		DWORD dwCredNameSize; 
		char strCredName[dwCredNameSize];  
		DWORD dwCommentSize;  
		char strComment[dwCommentSize]; 
		DWORD dwAliasSize;  
		char strAlias[dwAliasSize];  
		DWORD dwUnknownSize; // only for vista/win7 
		char strUnknown[dwUnknownSize]; //only for vista/win7 
		DWORD dwUserNameSize;  
		char strUserName[dwUserNameSize];  
		DWORD dwPasswordSize; 
		char password[dwPasswordSize];  
		}; 
		 
		 | 
	
	
		The above structure is of variable length and depends upon the length of 
		the varoius text fields. Each of these text fields are NULL terminated UNICODE strings 
		except the password field. Also at the end of each structure, extra padding 
		(On windows XP only) bytes are added so as to align next entry on 8 byte boundary.
		 
		 
		On Vista/Windows 7 platform, only one network account is stored per 
		credential file.  
		 
		Here is the sample code to decode this decrypted credential data and 
		display the username/password information for all the stored domain 
		password accounts. | 
	
	
		 
		// Check for valid signature 
		dwHeaderId = decDataBuffer->dwHeaderId 
		if( dwHeaderId != 0x1 && dwHeaderId != 0x30 ) 
		{ 
		 
		printf("\n Decrypted data is not valid, mismatch in the header"); 
		 
		return; 
		} 
		 
		 
		//Set the index to first entry 
		index = sizeof(DecryptedDataHeader); 
		 
		 
		while( index < dwBufferSize ) 
		{ 
		 
		  
		DecryptedDataItem *decDataItem = (DecryptedDataItem*) &pDecData[index]; 
		 
		  
		if( decDataItem->index == CRED_TYPE_DOMAIN_PASSWORD ) 
		  
		{ 
		     
		printf("\n Network Name = %S", decDataItem->strCredName); 
		 
		    
		//move index to username field and print it 
		    
		printf("\n Username = %S ", decDataItem->strUserName); 
		 
		    
		//next move to password field and print it out... 
		    
		WideCharToMultiByte(CP_ACP, 0,  
                         decDataItem->strPassword, 
		 
                         decDataItem->dwPasswordSize, 
		 
                         strPassword, 1000, NULL, NULL ); 
		    
		printf("\n Password = %s ", strPassword); 
		 
		   
		} 
		 
		   
		//move to next password entry for XP platform 
    if( XP platform ) 
		      index = index + decDataItem->dwItemSize 
    else  
      break;  //for vista/win7 only one account 
		per credential file is stored 
		} 
		 
		 | 
	
	
		The above code first verifies if the decrypted data is valid by 
		comparing the signature bytes in the header. Next it loops through each 
		of the structure of domain password type and prints the network name, 
		username & password in clear text. 
		 
		Also note that the decrypted buffer from LsaICryptUnprotectData contains data for 
		all type of network passwords, not just the domain type. But the 
		password for other types is still in the encrypted format which can be further 
		decrypted using the same procedure as explained earlier for respective 
		types. | 
	
	
		|   | 
	
	
		|   | 
	
	
		
	
  |  	
	
		| NetworkPasswordDecryptor is the free tool to 
		instantly recover all the network 
		passwords stored in the 'Credential Store' of Windows. It support 
		recovery of all type of network passwords on all platforms starting from 
		Windows XP to latest Windows 7. | 
	
	
		|   | 
	
	
		
		  | 
	
	
		|   | 
	
	
		This is a standalone application and it does not require any 
		installation. One can just run it out of box and it will recover all the 
		stored network passwords instantly.  
		 
		From application perspective, it can recover following passwords | 
	
	
		
		
			- All network authentication passwords.
 
			- Basic/Digest authentication passwords stored by Internet Explorer
 
			- Google login password stored by GMail Notifier
 
			- Remote Desktop stored passwords.
 
			- Exchange server login passwords stored by Outlook.
 
			- Login passwords of Windows Live Messenger
 
		 
		 | 
	
	
		NetworkPasswordDecryptor also allows you to delete any of the stored 
		passwords from 'Credential Store' with just one click. This is useful if 
		the password has changed or if the user has accidently saved the 
		important password. 
		 
		Also it provides option to save the decrypted network password list to 
		TEXT or HTML format.  | 
	
	
		|   | 
	
	
		|   | 
	
	
		
	
  |  	
	
		
		
			- Three Ways to Inject Your Code into Another Process
 
			- 
			Windows Credential Manager Functions
 
			- 
			Windows Cryptography Functions
			
 
		 
		 | 
	
	
		|   | 
	
	
		|   | 
	
	
		
	
		  |  	
		
	
		| 
		
	 | 
	
		
	
	
		|   | 
	
	
		|   | 
	
	
		|   | 
	
	
		|   | 
	
	
		|   | 
	
	
		|   |