Advertisement
BaSs_HaXoR

Password Algorithms: Skype (Windows)

Jun 8th, 2016
3,765
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Insecurety Research
  2. We are spelling it wrong… You are DOING it wrong!
  3.  
  4. Password Algorithms: Skype (Windows)
  5. Posted on August 10, 2012 by dietrich
  6.  
  7. Introduction
  8.  
  9. There’s a fantastic article by Fabrice Desclaux and Kostya Kortchinsky which describes the encryption and structures used but doesn’t provide any code.
  10.  
  11. The article indicates it isn’t possible to decrypt the password which probably explains the lack of code by other people.
  12.  
  13. Taken from the article…
  14.  
  15. If told to, Skype will save in the config.xml file
  16.  
  17. The login MD5 hash (username\nskyper\password)
  18. The generated RSA private key
  19. The Skype encrypted corresponding RSA public key
  20. Everything is heavily encrypted, but in a symmetric way :)
  21. The following algorithms are used
  22.  
  23. CryptProtectData(), CryptUnprotectData()
  24. SHA-1
  25. AES-256
  26. “FastTrack Cipher”
  27. 1024+ bit RSA
  28.  
  29. Only an MD5 hash of password is stored in the user’s profile and it’s encrypted with AES-256
  30. Once hash is decrypted, the only recovery methods available are dictionary attack or variation of brute force.
  31.  
  32. 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)
  33.  
  34. Storage
  35.  
  36. There are 2 things required in order to dump the MD5 hash.
  37.  
  38. DPAPI blob :
  39. HKEY_CURRENT_USER\Software\Skype\ProtectedStorage
  40. Credentials ciphertext :
  41. %APPDATA%\Skype\<login id>\config.xml
  42. The DPAPI blob is just stored as binary and can be passed straight to CryptUnprotectData()
  43.  
  44. C:\>reg query HKCU\Software\Skype\ProtectedStorage
  45.  
  46. HKEY_CURRENT_USER\Software\Skype\ProtectedStorage
  47.     0    REG_BINARY    01000000D08C9DDF0115D1118C7A00C04FC297EB01000
  48. The Credentials are hexadecimal string stored in XML file
  49.  
  50. <?xml version="1.0"?>
  51. <config version="1.0" serial="66" timestamp="1344481520.27">
  52.   <Lib>
  53.     <Account>
  54.       <Credentials3>322EBDF6D922E91F7EB68
  55. As a result of the XML file I ended up using the following libraries from here:
  56.  
  57. libxml2-2.7.8.win32.zip
  58. iconv-1.9.2.win32.zip
  59. openssl-0.9.8a.win32.zip
  60. zlib-1.2.5.win32.zip
  61. Generation
  62.  
  63. The following demonstrates creation of the MD5 hash using OpenSSL
  64.  
  65. void GenHash(const char *id, const char *pwd) {
  66.     MD5_CTX ctx;
  67.     const char *skype = "\nskyper\n";
  68.     u_int8_t dgst[32];
  69.    
  70.     MD5_Init(&ctx);
  71.     MD5_Update(&ctx, id, strlen(id));
  72.     MD5_Update(&ctx, skype, strlen(skype));
  73.     MD5_Update(&ctx, pwd, strlen(pwd));
  74.     MD5_Final(dgst, &ctx);
  75.  
  76.     printf("\n  Login ID = %s"
  77.            "\n  Password = %s"
  78.            "\n  MD5 hash = ", id, pwd);
  79.    
  80.     for (int i = 0;i < 16;i++) {
  81.       printf("%02x", dgst[i]);
  82.     }
  83.     printf("\n");
  84. }
  85. .....
  86. C:\>skype_dump username password
  87.   ...
  88.   Login ID = username
  89.   Password = password
  90.   MD5 hash = 27f6a9d892475e6ce0391de8d2d893f7
  91. Recovery
  92.  
  93. To extract the Credentials ciphertext, you could read the contents of config.xml and scan for <Credentials3> and </Credentials3>
  94. Here, I’m using LibXML :P
  95.  
  96. bool GetCredentials(BYTE ciphertext[], std::string config_xml) {    
  97.     bool bFound = false;
  98.    
  99.     // try open config.xml
  100.     xmlTextReaderPtr reader;
  101.     reader = xmlReaderForFile(config_xml.c_str(), NULL, 0);
  102.    
  103.     // tested with Credentials2 or Credentials3
  104.     const xmlChar *credentials;
  105.     credentials = (const xmlChar*)"Credentials";
  106.  
  107.     if (reader != NULL) {
  108.    
  109.       // while nodes are available
  110.       while (xmlTextReaderRead(reader) == 1) {
  111.         // get name
  112.         const xmlChar *name;
  113.         name = xmlTextReaderConstName(reader);
  114.         if (name == NULL) continue;
  115.  
  116.         // equal to credentials we're searching for?
  117.         if (xmlStrncmp(credentials, name, xmlStrlen(credentials)) == 0) {
  118.  
  119.           // read the next value
  120.           if (xmlTextReaderRead(reader) == 1) {
  121.             const xmlChar *value;
  122.             value = xmlTextReaderConstValue(reader);
  123.            
  124.             for (int i = 0;i < 16;i++) {
  125.               sscanf((const char*)&value[i * 2], "%02x", &ciphertext[i]);
  126.             }
  127.             bFound = true;
  128.             break;
  129.           }
  130.         }
  131.       }
  132.       xmlFreeTextReader(reader);
  133.     }
  134.     xmlCleanupParser();
  135.     return bFound;
  136. }
  137. Obtain the salt which is passed to SHA-1 before being used to create AES key.
  138.  
  139. PBYTE GetSalt(DWORD &cbSalt) {
  140.     BYTE aBlob[2048];
  141.     DWORD cbSize = sizeof(aBlob);
  142.     const char skype_path[] = "Software\\Skype\\ProtectedStorage";
  143.    
  144.     LSTATUS lStatus = SHGetValue(HKEY_CURRENT_USER, skype_path,
  145.         "0", 0, aBlob, &cbSize);
  146.      
  147.     if (lStatus != ERROR_SUCCESS) {
  148.       printf("  Unable to open skype key : %08x", lStatus);
  149.       return NULL;
  150.     }
  151.  
  152.     DATA_BLOB in, out;
  153.    
  154.     in.pbData = aBlob;
  155.     in.cbData = cbSize;
  156.    
  157.     if (CryptUnprotectData(&in, NULL, NULL, NULL,
  158.         NULL, 0, &out)) {
  159.       cbSalt = out.cbData;
  160.       return out.pbData;
  161.     } else {
  162.       printf("  Unable to decrypt skype entry.");
  163.     }
  164.     return NULL;
  165. }
  166. Then with both the ciphertext and salt, we can decrypt MD5 hash…
  167.  
  168. void DecryptHash(PBYTE pbCipherText, PBYTE pbSalt, DWORD cbSalt) {
  169.    
  170.     SHA_CTX ctx;
  171.     AES_KEY key;
  172.    
  173.     u_int8_t dgst[40], buffer[AES_BLOCK_SIZE];
  174.    
  175.     memset(&buffer, 0, sizeof(buffer));
  176.    
  177.     // use counter mode + SHA-1 to generate key
  178.     for (ULONG i = 0;i < 2;i++) {
  179.       ULONG ulIndex = _byteswap_ulong(i);
  180.        
  181.       SHA1_Init(&ctx);
  182.       SHA1_Update(&ctx, &ulIndex, sizeof(ulIndex));
  183.       SHA1_Update(&ctx, pbSalt, cbSalt);
  184.       SHA1_Final(&dgst[i*20], &ctx);
  185.     }
  186.    
  187.     AES_set_encrypt_key(dgst, 256, &key);
  188.     AES_encrypt(buffer, buffer, &key);
  189.    
  190.     printf("\n  MD5 hash = ");
  191.    
  192.     // decrypt MD5 hash with XOR
  193.     for (int i = 0;i < 16;i++) {
  194.       printf("%02x", pbCipherText[i] ^ buffer[i]);
  195.     }
  196.     printf("\n");
  197. }
  198. Conclusion
  199.  
  200. If you want to know more about the internals of Skype, I’d strongly recommend the “Vanilla Skype” papers 1 and 2
  201.  
  202. It’s safe to say MD5 isn’t a good choice of algorithms for protecting passwords.
  203. Maybe as more recovery tools become available, Microsoft will revise the code to use something stronger.
  204. source code
  205.  
  206. 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.
  207. 15 THOUGHTS ON “PASSWORD ALGORITHMS: SKYPE (WINDOWS)
  208. Igor on November 4, 2012 at 10:51 am said:
  209. Could you give example what the output will be for some define values as you did for GenHash():
  210. C:\>skype_dump username password
  211. Login ID = username
  212. Password = password
  213. MD5 hash = 27f6a9d892475e6ce0391de8d2d893f7
  214.  
  215. 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.
  216.  
  217. Reply
  218.  
  219. dietrich
  220. on November 10, 2012 at 5:31 pm said:
  221. 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.
  222.  
  223. I’ll post source code to all articles in next couple of weeks.
  224.  
  225. Reply
  226. Igor on November 4, 2012 at 11:16 am said:
  227. And one more question:
  228. For AES there is need 32-byte key, but you use 40-byte.Why?
  229.  
  230. Reply ↓
  231.  
  232. dietrich
  233. on November 10, 2012 at 5:25 pm said:
  234. 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.
  235.  
  236. 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.
  237.  
  238. By the way, Linux version doesn’t encrypt hash at all.
  239.  
  240. Reply
  241. bortkmail on December 19, 2012 at 9:25 pm said:
  242. Hi there,
  243. 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.
  244.  
  245. I attached the source code of the sample program :
  246. http://codepad.org/811wtQAt
  247.  
  248. So this code give me a wrong md5 hash, and I don’t know why.
  249.  
  250. Thank you in advance.
  251.  
  252. Reply
  253.  
  254. dietrich
  255. on December 29, 2012 at 3:20 am said:
  256. Hi, sorry for late reply, didn’t see your post.
  257. I’ll be releasing source code for this later today.
  258.  
  259. Although there’s a hash dumper, I haven’t written a cracker but you should be able to write something.
  260.  
  261. Regards,
  262.  
  263. Reply ↓
  264. qolund on January 2, 2013 at 2:35 pm said:
  265. Hello.
  266.  
  267. You say that the Linux version does not provide encryption.
  268. Here is the beginning of my config.xml file, and I can’t find any credentials.
  269. A heavy grep of everything in my ~/.Skype/ folder of my password or “Credential” gives me nothing.
  270.  
  271. Do you know how the password is stored on Linux ?
  272. $ skype –version
  273. Skype 4.0.0.8
  274. Copyright (c) 2004-2012, Skype
  275.  
  276. $ head config.xml
  277.  
  278. 300
  279. 1800
  280. 63
  281. 1
  282.  
  283. Best regards, happy new year and thank you.
  284.  
  285. Reply
  286.  
  287. dietrich
  288. on January 2, 2013 at 3:12 pm said:
  289. 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.
  290.  
  291. Mine was located in the following file.
  292. /home/dietrich/.Skype/dietrich/config.xml
  293.  
  294. Check with your version and let me know how you get on.
  295.  
  296. cheers
  297.  
  298. Reply ↓
  299.  
  300. qolund
  301. on January 3, 2013 at 10:46 am said:
  302. I changed my password and then check differences between old and new config.xml file
  303.  
  304. The only affected line (timestamp excepted) is in the section “table_insert_history”
  305. the name of the xml value is a 64 hexa characters, and the values are not very cool.
  306.  
  307. It seems that the password isn’t in the config.xml anymore.
  308.  
  309. Reply
  310.  
  311. dietrich
  312. on January 4, 2013 at 8:50 am said:
  313. I installed 4.1.0.20 and for me the password hash is still stored in config.xml
  314. ‘Sign me in when Skype starts’ box is checked and I recreated profile.
  315.  
  316. Reply
  317. Robert on January 27, 2013 at 11:58 pm said:
  318. Hi there,
  319. 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?
  320. Thank you in advance.
  321.  
  322. Reply
  323. sooner on June 5, 2013 at 3:51 am said:
  324. Can you share this code?
  325.  
  326. Reply ↓
  327.  
  328. dietrich
  329. on June 11, 2013 at 4:52 pm said:
  330. Yes, check bottom of article.
  331.  
  332. Reply
  333. Rebwer on June 28, 2013 at 8:13 am said:
  334. 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”.
  335.  
  336. Using skype 6.5
  337.  
  338. Reply ↓
  339. oveckas on July 5, 2013 at 1:03 pm said:
  340. Hey,
  341. 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).
  342. 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).
  343.  
  344. Again, sorry for this dumb question, but I dont really understand cryptography that much.
  345.  
  346. Thank you in advance for your response.
  347.  
  348. //SRC: http://insecurety.net/?p=427
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement