|  | 
	
	
		| Exposing the Password Secrets of Digsby | 
	
	
	  |  | 
  
  			|  | 
	
	 |  | 
	
	
	
	
		
	
		 |  | 
		
	
		|  | 
	
		|  | 
	
	
	
		
	
	
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
		 |  | 
	
		| 
			Digsby is is one 
			of the popular instant messenger of recent times with IM client, 
			Email Notification & Social Networking all in one software.  
			Digsby has a multi protocol IM client that lets you chat with 
			all your friends on AIM, MSN, Yahoo, ICQ, Google Talk, and Jabber 
			with one buddy list.It has an email notification tool that alerts
			you of new email and lets you perform quick actions. 
			
			
			 | 
	
		|  | 
	
	
	
		| Its social networking feature lets you manage all your feeds from 
		popular social networking sites such as Twitter,
		Facebook etc at one place while you are chatting with 
		your friends. | 
	
		|  | 
		
		|  | 
	
		
	
		
		
		 |  | 
	
		| Like most instant messengers, Digsby 
			also stores the user account details including passwords in the 
			local repository for subsequent logins so that user do not have to 
			enter the password every time. Note that the password is stored only 
			if user has selected 'Save Password' at login time.
 Latest 
			versions of Digsby (Build 83 - r28550 as of this writing) stores 
			main account password in the 'logininfo.yaml' file 
			at following location,
 | 
		 |  | 
	
		| [Windows XP] C:\Documents and Settings\<user_name>\Local 
		Settings\Application Data\Digsby
 
 [Windows Vista & Windows 7]
 C:\Users\<user_name>\AppData\Local\Digsby
 | 
	
		 |  | 
		 | Earlier versions of Digsby used to save 
			the password in the 'Digsby.dat' file at following location, | 
 |  | 
		 
			| [Windows XP] C:\Documents and 
			Settings\<user_name>\Application Data\Digsby
 
 [Windows Vista & 
			Windows 7]
 C:\Users\<user_name>\AppData\Roaming\Digsby
 | 
 |  | 
		 | Here is the typical format (taken from 
			logininfo.yaml) in which account name & encrypted password is stored 
			for each stored user account. | 
 |  | 
	 
		| users: ? !python/unicode diguser
 :
 password: !binary |
 IXWaxceUOVd6Eg2E=
 
 autologin: False
 save: True
 username: !python/unicode diguser
 | 
 |  | 
	
		| Here the "username:" & "password:" for each account is listed and 
		they can appear in any sequence. Also 'save:' field indicates if the 
		password for this account is stored or not. Digsby encrypts the 
		password for better security and encodes it with BASE64 before storing 
		it into above file. 
 Note that Digsby stores only main IM 
		account password locally and all other IM account passwords (such as 
		Yahoo, Gmail, AIM) are stored on the server.
 | 
	
		|  | 
	
		|  | 
	
	
		
	
		 |  | 
	
		| As mentioned above, Digsby uses 
			special algorithm to encrypt the main account password which is 
			stored in BASE64 format in the password file. Once you retrieve the 
			encoded password, decode it using BASE64 algorithm. Resulting text 
			is nothing but encrypted password with the same length as original 
			plain text password. So merely decoding the password, you will come 
			to know about the length of password.
 It uses Product ID, OS 
			Install Date & Digsby Username combination to generate unique hash 
			which is later used in encryption of the password.
 
 Though 
			this encryption appears to be specific to system, one can easily use 
			current system's product id & install date and perform offline 
			password recovery on different system. This is especially useful and 
			typical case with forensic scenarios.
 | 
	
		|  | 
	
		|  | 
	
		
	
	 |  | 
	
		| Here are the detailed steps for 
			decrypting the encrypted Digsby account password.
 | 
	 |  | 
	
		
	
	 |  | 
	
		| As mentioned earlier, Digsby stores the 
		account password in 'logininfo.yaml' file. You need to retrieve the 
		Digsby username & associated password from this file. Then use the 
		BASE64 algorithm to decode it and get the encrypted password. 
 Username & associated password per account start with unique identifier "username:" & "password:" respectively.
 | 
	 |  | 
	
		
		
	
	 |  | 
	
	
		| Digsby uses local Product ID & Install 
		Date information along with Digsby username to generate the unique Hash. 
		These information is present at following registry location, 
 | 
	
		|  | 
	
		| HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion 
 DigitalProductId REG_BINARY
 InstallDate REG_DWORD
 
 | 
	
		|  | 
	
		| DigitalProductId is a binary array where 
		as InstallDate is a integer. You need to convert the InstallDate to 
		string format before using it. 
 Caution: On 64 bit systems, the 
		above key is present in the 64 bit hive only. Hence you need to use flag 
		KEY_WOW64_64KEY for 'Desired Access' to correctly read above registry 
		values. I was scratching my head for half a day to figure out why my 
		simple registry function is not able to read it.
 | 
	 |  | 
	
		
	
	 |  | 
		| Now simply combine Product ID, Install 
		Date & Digsby username in that order to form one complete string. | 
	 |  | 
	
		
	
	 |  | 
	 | Next compute SHA1 hash for the above 
		generated string. Here is the complete code example to create SHA1 hash 
		using Windows Cryptography Functions. 
 | 
 |  | 
		| BOOL GetSHA1Hash(char 
		*buffer, DWORD dwBufferSize, char *strSHA1Hash, int dwStrSize) {
 DWORD dwStatus = 0;
 HCRYPTPROV hProv = 0;
 HCRYPTHASH hHash = 0;
 
 BYTE rgbHash[20];
 DWORD cbHash = 0;
 
 
 // Get handle to 
		the crypto provider
 if (!CryptAcquireContext(&hProv, NULL, NULL, 
		PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
 {
 printf("%s 
		CryptAcquireContext failed, Error=0x%.8x", __FUNCTION__, 
		GetLastError());
 return FALSE;
 }
 
 if 
		(!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
 {
 printf("%s 
		CryptCreateHash failed, Error=0x%.8x", __FUNCTION__, GetLastError());
 CryptReleaseContext(hProv, 0);
 return FALSE;
 }
 
 if 
		(!CryptHashData(hHash, (const BYTE*) buffer, dwBufferSize, 0))
 {
 printf("\n%s CryptHashData failed, Error=0x%.8x", __FUNCTION__, 
		GetLastError());
 
 CryptDestroyHash(hHash);
 CryptReleaseContext(hProv, 0);
 return FALSE;
 }
 
 cbHash = 20;
 if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0) == FALSE)
 {
 printf("%s CryptGetHashParam failed, Error=0x%.8x", __FUNCTION__, 
		GetLastError());
 CryptDestroyHash(hHash);
 CryptReleaseContext(hProv, 0);
 
 }
 
 printf("********** %s 
		Computed SHA1 hash (length=%d) successfully ", __FUNCTION__, cbHash);
 
 //Success, now copy the final SHA1 hash to input buffer
 memcpy(strSHA1Hash, rgbHash, cbHash);
 
 
 CryptDestroyHash(hHash);
 CryptReleaseContext(hProv, 0);
 
 return 
		TRUE;
 }
 
 | 
	 |  | 
	
	
	 | On successful completion, we get the 
		SHA1 
		hash which is of 20 bytes. This hash is used as the key for decryption 
		of main Digsby password. | 
 |  | 
	
	
	 |  | 
	
	
	 
		 	
	
	
 |  | 
	
	
	 | Here we will use the previously generated 
		SHA1 hash to decrypt the encrypted password. 
 The below 
		code generates new hash of size 256 bytes from the SHA1 hash.
 
 | 
 |  | 
	
	
	 
		| BYTE b, d =0; BYTE 
		num, bTemp, bHash;
 BYTE newHashData[256];
 
 for(i=0; i<256; 
		i++)
 newHashData[i]=i;
 
 for(i=0, j=0; i<256; i++)
 {
 bTemp = num = newHashData[i];
 
 bHash = byteSHA1Hash[j];
 
 num 
		= num + bHash;
 num = num + d;
 num = num & 0xff;
 
 d = 
		num;
 
 b = newHashData[d];
 newHashData[i] = b;
 newHashData[d] = bTemp;
 
 j = j+1;
 
 if(j >= 20) j=0;
 
 }
 | 
 |  | 
	
	 
		| Finally it uses newly generated hash 
		('newHashData') to successfully decrypt the earlier decoded password 
		('byteDecPassword') from the file in Step 1. 
 | 
	
	
	 |  | 
	
	 
		| //check out this thing BYTE s=1;
 BYTE 
		x=0, c;
 
 //byteDecPassword = based64 decoded password from the 
		file
 //dwDecPasswdLen = length of decoded password
 
 //
 //main password decryptor loop
 //
 
 {
 bTemp = newHashData[s];
 
 x = x + bTemp;
 x = x & 0xFF;
 
 b = 
		newHashData[x];
 
 newHashData[s] = b;
 newHashData[x] = bTemp;
 
 s = s + 1;
 s = s & 0xFF;
 
 b = b + bTemp;
 b = b & 
		0xFF;
 
 c = newHashData[b];
 
 //decrypted 
		password stored at same location
 byteDecPassword[i] = 
		byteDecPassword[i] ^ c;
 
 i++;
 dwDecPasswdLen--;
 
 }
 while( dwDecPasswdLen > 0 );
 
 //null terminate the password 
		string
 byteDecPassword[i]=0;
 
 printf("Decrypted password is %s", 
		byteDecPassword);
 
 
 | 
	
	
	 |  | 
	
	 
		| In each stage of the loop, each encrypted 
		character from decoded password is decrypted and put back into the same 
		location. At the end, variable byteDecPassword will contain the final 
		decrypted Digsby password. 
 
 | 
	
	
	 
		| Now here is the interesting thing, Guess the 
		name for above algorithm and get your name printed here ! | 
	
	
		
		|  | 
	
		|  | 
	
		
	
	 |  | 
 	
	
		|  
		
			|   | DigsbyPasswordDecryptor 
			is a dedicated tool to recover account passwords stored by Digsby. 
			It can automatically detect the correct secret password file based 
			on installed version of Digsby and then decrypt all the stored account passwords on the fly. |  | 
	 |  | 
	
	
		|   | 
 |  | 
	
	
		| DigsbyPasswordDecryptor is a portable tool which does not require 
		installation and work across wide range of platforms starting from 
		Windows XP to Windows 7. You can also use our other tool, 
		IMPasswordDecryptor 
		to recover the Digsby passwords along with other instant messenger 
		passwords. | 
	
		|  | 
	
		|  | 
		
	
		
	
		 |  | 
		| Above article explains in detail how Digsby stores the account 
		password using its own proprietary encryption algorithm and shows how 
		one can manually decrypt such password to recover the original 
		password. 
 Note that above decryption process is based on latest 
		version of Digsby Messenger (Build 83 - r28550) and it may 
		change with upcoming versions of the Messenger.
 | 
	
		|  | 
	
		|  | 
	
		
	
		 |  | 
		
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
		|  |