Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Insecurety Research
- We are spelling it wrong… You are DOING it wrong!
- Password Algorithms: Skype (Windows)
- Posted on August 10, 2012 by dietrich
- Introduction
- There’s a fantastic article by Fabrice Desclaux and Kostya Kortchinsky which describes the encryption and structures used but doesn’t provide any code.
- The article indicates it isn’t possible to decrypt the password which probably explains the lack of code by other people.
- Taken from the article…
- If told to, Skype will save in the config.xml file
- The login MD5 hash (username\nskyper\password)
- The generated RSA private key
- The Skype encrypted corresponding RSA public key
- Everything is heavily encrypted, but in a symmetric way :)
- The following algorithms are used
- CryptProtectData(), CryptUnprotectData()
- SHA-1
- AES-256
- “FastTrack Cipher”
- 1024+ bit RSA
- Only an MD5 hash of password is stored in the user’s profile and it’s encrypted with AES-256
- Once hash is decrypted, the only recovery methods available are dictionary attack or variation of brute force.
- The information here applies to version 5.10.0.116 but should also work without hitch on some older versions (4.2 was also tested)
- Storage
- There are 2 things required in order to dump the MD5 hash.
- DPAPI blob :
- HKEY_CURRENT_USER\Software\Skype\ProtectedStorage
- Credentials ciphertext :
- %APPDATA%\Skype\<login id>\config.xml
- The DPAPI blob is just stored as binary and can be passed straight to CryptUnprotectData()
- C:\>reg query HKCU\Software\Skype\ProtectedStorage
- HKEY_CURRENT_USER\Software\Skype\ProtectedStorage
- 0 REG_BINARY 01000000D08C9DDF0115D1118C7A00C04FC297EB01000
- The Credentials are hexadecimal string stored in XML file
- <?xml version="1.0"?>
- <config version="1.0" serial="66" timestamp="1344481520.27">
- <Lib>
- <Account>
- <Credentials3>322EBDF6D922E91F7EB68
- As a result of the XML file I ended up using the following libraries from here:
- libxml2-2.7.8.win32.zip
- iconv-1.9.2.win32.zip
- openssl-0.9.8a.win32.zip
- zlib-1.2.5.win32.zip
- Generation
- The following demonstrates creation of the MD5 hash using OpenSSL
- void GenHash(const char *id, const char *pwd) {
- MD5_CTX ctx;
- const char *skype = "\nskyper\n";
- u_int8_t dgst[32];
- MD5_Init(&ctx);
- MD5_Update(&ctx, id, strlen(id));
- MD5_Update(&ctx, skype, strlen(skype));
- MD5_Update(&ctx, pwd, strlen(pwd));
- MD5_Final(dgst, &ctx);
- printf("\n Login ID = %s"
- "\n Password = %s"
- "\n MD5 hash = ", id, pwd);
- for (int i = 0;i < 16;i++) {
- printf("%02x", dgst[i]);
- }
- printf("\n");
- }
- .....
- C:\>skype_dump username password
- ...
- Login ID = username
- Password = password
- MD5 hash = 27f6a9d892475e6ce0391de8d2d893f7
- Recovery
- To extract the Credentials ciphertext, you could read the contents of config.xml and scan for <Credentials3> and </Credentials3>
- Here, I’m using LibXML :P
- bool GetCredentials(BYTE ciphertext[], std::string config_xml) {
- bool bFound = false;
- // try open config.xml
- xmlTextReaderPtr reader;
- reader = xmlReaderForFile(config_xml.c_str(), NULL, 0);
- // tested with Credentials2 or Credentials3
- const xmlChar *credentials;
- credentials = (const xmlChar*)"Credentials";
- if (reader != NULL) {
- // while nodes are available
- while (xmlTextReaderRead(reader) == 1) {
- // get name
- const xmlChar *name;
- name = xmlTextReaderConstName(reader);
- if (name == NULL) continue;
- // equal to credentials we're searching for?
- if (xmlStrncmp(credentials, name, xmlStrlen(credentials)) == 0) {
- // read the next value
- if (xmlTextReaderRead(reader) == 1) {
- const xmlChar *value;
- value = xmlTextReaderConstValue(reader);
- for (int i = 0;i < 16;i++) {
- sscanf((const char*)&value[i * 2], "%02x", &ciphertext[i]);
- }
- bFound = true;
- break;
- }
- }
- }
- xmlFreeTextReader(reader);
- }
- xmlCleanupParser();
- return bFound;
- }
- Obtain the salt which is passed to SHA-1 before being used to create AES key.
- PBYTE GetSalt(DWORD &cbSalt) {
- BYTE aBlob[2048];
- DWORD cbSize = sizeof(aBlob);
- const char skype_path[] = "Software\\Skype\\ProtectedStorage";
- LSTATUS lStatus = SHGetValue(HKEY_CURRENT_USER, skype_path,
- "0", 0, aBlob, &cbSize);
- if (lStatus != ERROR_SUCCESS) {
- printf(" Unable to open skype key : %08x", lStatus);
- return NULL;
- }
- DATA_BLOB in, out;
- in.pbData = aBlob;
- in.cbData = cbSize;
- if (CryptUnprotectData(&in, NULL, NULL, NULL,
- NULL, 0, &out)) {
- cbSalt = out.cbData;
- return out.pbData;
- } else {
- printf(" Unable to decrypt skype entry.");
- }
- return NULL;
- }
- Then with both the ciphertext and salt, we can decrypt MD5 hash…
- void DecryptHash(PBYTE pbCipherText, PBYTE pbSalt, DWORD cbSalt) {
- SHA_CTX ctx;
- AES_KEY key;
- u_int8_t dgst[40], buffer[AES_BLOCK_SIZE];
- memset(&buffer, 0, sizeof(buffer));
- // use counter mode + SHA-1 to generate key
- for (ULONG i = 0;i < 2;i++) {
- ULONG ulIndex = _byteswap_ulong(i);
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, &ulIndex, sizeof(ulIndex));
- SHA1_Update(&ctx, pbSalt, cbSalt);
- SHA1_Final(&dgst[i*20], &ctx);
- }
- AES_set_encrypt_key(dgst, 256, &key);
- AES_encrypt(buffer, buffer, &key);
- printf("\n MD5 hash = ");
- // decrypt MD5 hash with XOR
- for (int i = 0;i < 16;i++) {
- printf("%02x", pbCipherText[i] ^ buffer[i]);
- }
- printf("\n");
- }
- Conclusion
- If you want to know more about the internals of Skype, I’d strongly recommend the “Vanilla Skype” papers 1 and 2
- It’s safe to say MD5 isn’t a good choice of algorithms for protecting passwords.
- Maybe as more recovery tools become available, Microsoft will revise the code to use something stronger.
- source code
- This entry was posted in Algorithms, Passwords, Reverse Engineering, Security and tagged AES, algorithms, config.xml, CryptProtectData, DPAPI, hashing, md5, passwords, protectedstorage, Reverse Engineering, skype, XML by dietrich. Bookmark the permalink.
- 15 THOUGHTS ON “PASSWORD ALGORITHMS: SKYPE (WINDOWS)”
- Igor on November 4, 2012 at 10:51 am said:
- Could you give example what the output will be for some define values as you did for GenHash():
- C:\>skype_dump username password
- …
- Login ID = username
- Password = password
- MD5 hash = 27f6a9d892475e6ce0391de8d2d893f7
- I have an error, but I don’t understand in what part of program I should find it. The result MD5 Hash doesn’t coincide with the real.
- Reply ↓
- dietrich
- on November 10, 2012 at 5:31 pm said:
- The program I wrote called skype_dump.cpp allows you to generate hash with username and password. Without parameters, it just looks in local user profile.
- I’ll post source code to all articles in next couple of weeks.
- Reply ↓
- Igor on November 4, 2012 at 11:16 am said:
- And one more question:
- For AES there is need 32-byte key, but you use 40-byte.Why?
- Reply ↓
- dietrich
- on November 10, 2012 at 5:25 pm said:
- 20 bytes is the size of SHA-1 hash but 32-bytes are required for AES-256 key so we’re just concatenating 2 SHA-1 hashes, the last 8 bytes don’t matter.
- I suppose SHA-256 or something similar in size would seem like a more appropriate choice but SHA-1 was used instead, I have no idea why.
- By the way, Linux version doesn’t encrypt hash at all.
- Reply ↓
- bortkmail on December 19, 2012 at 9:25 pm said:
- Hi there,
- I have written a sample program by your article, but I don’t quite understand the result. Unfortunately, I haven’t got enough time to read the specs. It would be nice if you could help me to write an application which reverse the md5 hash of the stored password.
- I attached the source code of the sample program :
- http://codepad.org/811wtQAt
- So this code give me a wrong md5 hash, and I don’t know why.
- Thank you in advance.
- Reply ↓
- dietrich
- on December 29, 2012 at 3:20 am said:
- Hi, sorry for late reply, didn’t see your post.
- I’ll be releasing source code for this later today.
- Although there’s a hash dumper, I haven’t written a cracker but you should be able to write something.
- Regards,
- Reply ↓
- qolund on January 2, 2013 at 2:35 pm said:
- Hello.
- You say that the Linux version does not provide encryption.
- Here is the beginning of my config.xml file, and I can’t find any credentials.
- A heavy grep of everything in my ~/.Skype/ folder of my password or “Credential” gives me nothing.
- Do you know how the password is stored on Linux ?
- $ skype –version
- Skype 4.0.0.8
- Copyright (c) 2004-2012, Skype
- $ head config.xml
- 300
- 1800
- 63
- 1
- Best regards, happy new year and thank you.
- Reply ↓
- dietrich
- on January 2, 2013 at 3:12 pm said:
- Hmm, at the time of writing, my own version was 2.2.0.35 but it looks like it received a major update since then.
- Mine was located in the following file.
- /home/dietrich/.Skype/dietrich/config.xml
- Check with your version and let me know how you get on.
- cheers
- Reply ↓
- qolund
- on January 3, 2013 at 10:46 am said:
- I changed my password and then check differences between old and new config.xml file
- The only affected line (timestamp excepted) is in the section “table_insert_history”
- the name of the xml value is a 64 hexa characters, and the values are not very cool.
- It seems that the password isn’t in the config.xml anymore.
- Reply ↓
- dietrich
- on January 4, 2013 at 8:50 am said:
- I installed 4.1.0.20 and for me the password hash is still stored in config.xml
- ‘Sign me in when Skype starts’ box is checked and I recreated profile.
- Reply ↓
- Robert on January 27, 2013 at 11:58 pm said:
- Hi there,
- I would like to transfer a working account (autologin with forgotten password) from one PC to another. I copy whole HKEY_CURRENT_USER\Software\Skype\ and %APPDATA%\Skype\ and %APPDATA%\SkypePM\ but login fails. Do you have any idea what happens?
- Thank you in advance.
- Reply ↓
- sooner on June 5, 2013 at 3:51 am said:
- Can you share this code?
- Reply ↓
- dietrich
- on June 11, 2013 at 4:52 pm said:
- Yes, check bottom of article.
- Reply ↓
- Rebwer on June 28, 2013 at 8:13 am said:
- Do this still work or have skype updated their way of encrypting the password? I’m getting “Unable to obtain encrypted hash from config.xml”.
- Using skype 6.5
- Reply ↓
- oveckas on July 5, 2013 at 1:03 pm said:
- Hey,
- thank you for a very informative article. My question maybe a little bit dumb, but there is a thing that is confusing me a little bit. You mention that the MD5 hash consists of hash(username\nskyper\password).
- Does that mean that the output of your code(which again, Im very thankful for), is not hashed password but rather a combination of all these? Does it mean that if I run oclHashcat on this, it will not generate the password but rather the whole sequence?(username\nskyper\password).
- Again, sorry for this dumb question, but I dont really understand cryptography that much.
- Thank you in advance for your response.
- //SRC: http://insecurety.net/?p=427
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement