This week only. Pastebin PRO Accounts Christmas Special! Don't miss out!Want more features on Pastebin? Sign Up, it's FREE!
Guest

opera unwand

By: a guest on Mar 11th, 2010  |  syntax: C++  |  size: 4.57 KB  |  views: 1,065  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // sna@reteam.org  - 6th of April 2005
  2.  
  3.  
  4. #include <cstdio>
  5. #include <iostream>
  6. #include <memory>
  7. #include <cstring>
  8.  
  9. #include <md5.h>
  10. #include <des.h>
  11.  
  12. const unsigned char opera_salt[11] =
  13. {
  14.         0x83, 0x7D, 0xFC, 0x0F, 0x8E, 0xB3, 0xE8, 0x69, 0x73, 0xAF, 0xFF
  15. };
  16.  
  17. int main(int argc, char **argv)
  18. {
  19.         if(argc != 2)
  20.         {
  21.                 std::cout << "Usage: unwand <opera wand file>" << std::endl;
  22.                 return 1;
  23.         }
  24.  
  25.         FILE *fdWand = fopen(argv[1], "rb");
  26.  
  27.         if(NULL == fdWand)
  28.         {
  29.                 perror("Failed to open file");
  30.                 return 1;
  31.         }
  32.  
  33.         fseek(fdWand, 0, SEEK_END);
  34.         unsigned long fileSize = ftell(fdWand);
  35.  
  36.         unsigned char *wandData = (unsigned char *)malloc(fileSize);
  37.  
  38.         if(NULL == wandData)
  39.         {
  40.                 fclose(fdWand);
  41.                 perror("Memory allocation failed");
  42.                 return 1;
  43.         }
  44.  
  45.         rewind(fdWand);
  46.         fread(wandData, fileSize, 1, fdWand);
  47.         fclose(fdWand);
  48.  
  49.         unsigned long wandOffset = 0;
  50.  
  51.         //
  52.         // main loop, find and process encrypted blocks
  53.         //
  54.  
  55.         while(wandOffset < fileSize)
  56.         {
  57.                 // find key length field at start of block
  58.                 unsigned char *wandKey = (unsigned char *)
  59.                         memchr(wandData + wandOffset, DES_KEY_SZ, fileSize - wandOffset);
  60.  
  61.                 if(NULL == wandKey)
  62.                 {
  63.                         break;
  64.                 }
  65.  
  66.                 wandOffset = ++wandKey - wandData;
  67.  
  68.                 // create pointers to length fields
  69.                 unsigned char *blockLengthPtr = wandKey - 8;
  70.                 unsigned char *dataLengthPtr = wandKey + DES_KEY_SZ;
  71.  
  72.                 if(blockLengthPtr < wandData || dataLengthPtr > wandData + fileSize)
  73.                 {
  74.                         continue;
  75.                 }
  76.  
  77.                 // convert big-endian numbers to native
  78.                 unsigned long
  79.                         blockLength  = *blockLengthPtr++ << 24;
  80.                         blockLength |= *blockLengthPtr++ << 16;
  81.                         blockLength |= *blockLengthPtr++ <<  8;
  82.                         blockLength |= *blockLengthPtr;
  83.  
  84.                 unsigned long
  85.                         dataLength  = *dataLengthPtr++ << 24;
  86.                         dataLength |= *dataLengthPtr++ << 16;
  87.                         dataLength |= *dataLengthPtr++ <<  8;
  88.                         dataLength |= *dataLengthPtr;
  89.  
  90.                 // as discussed in the article
  91.                 if(blockLength != dataLength + DES_KEY_SZ + 4 + 4)
  92.                 {
  93.                         continue;
  94.                 }
  95.  
  96.                 // perform basic sanity checks on data length
  97.                 if(dataLength > fileSize - (wandOffset + DES_KEY_SZ + 4)
  98.                         || dataLength < 8 || dataLength % 8 != 0)
  99.                 {
  100.                         continue;
  101.                 }
  102.  
  103.                 unsigned char
  104.                         hashSignature1[MD5_DIGEST_LENGTH],
  105.                         hashSignature2[MD5_DIGEST_LENGTH],
  106.                         tmpBuffer[256];
  107.  
  108.                 //
  109.                 // hashing of (salt, key), (hash, salt, key)
  110.                 //
  111.  
  112.                 memcpy(tmpBuffer, opera_salt, sizeof(opera_salt));
  113.                 memcpy(tmpBuffer + sizeof(opera_salt), wandKey, DES_KEY_SZ);
  114.  
  115.                 MD5(tmpBuffer, sizeof(opera_salt) + DES_KEY_SZ, hashSignature1);
  116.  
  117.                 memcpy(tmpBuffer, hashSignature1, sizeof(hashSignature1));
  118.                 memcpy(tmpBuffer + sizeof(hashSignature1),
  119.                         opera_salt, sizeof(opera_salt));
  120.  
  121.                 memcpy(tmpBuffer + sizeof(hashSignature1) +
  122.                         sizeof(opera_salt), wandKey, DES_KEY_SZ);
  123.  
  124.                 MD5(tmpBuffer, sizeof(hashSignature1) +
  125.                         sizeof(opera_salt) + DES_KEY_SZ, hashSignature2);
  126.  
  127.                 //
  128.                 // schedule keys. key material from hashes
  129.                 //
  130.  
  131.                 DES_key_schedule key_schedule1, key_schedule2, key_schedule3;
  132.  
  133.                 DES_set_key_unchecked((const_DES_cblock *)&hashSignature1[0],
  134.                         &key_schedule1);
  135.  
  136.                 DES_set_key_unchecked((const_DES_cblock *)&hashSignature1[8],
  137.                         &key_schedule2);
  138.  
  139.                 DES_set_key_unchecked((const_DES_cblock *)&hashSignature2[0],
  140.                         &key_schedule3);
  141.  
  142.                 DES_cblock iVector;
  143.                 memcpy(iVector, &hashSignature2[8], sizeof(DES_cblock));
  144.  
  145.                 unsigned char *cryptoData = wandKey + DES_KEY_SZ + 4;
  146.  
  147.                 //
  148.                 // decrypt wand data in place using 3DES-CBC
  149.                 //
  150.  
  151.                 DES_ede3_cbc_encrypt(cryptoData, cryptoData, dataLength,
  152.                         &key_schedule1, &key_schedule2, &key_schedule3, &iVector, 0);
  153.  
  154.                 if(0x00 == *cryptoData || 0x08 == *cryptoData)
  155.                 {
  156.                         std::wcout << L"<null>" << std::endl;
  157.                 }
  158.                 else
  159.                 {
  160.                         // remove padding (data padded up to next block)
  161.                         unsigned char *padding = cryptoData + dataLength - 1;
  162.                         memset(padding - (*padding - 1), 0x00, *padding);
  163.  
  164.                         // std::wcout << (wchar_t *)cryptoData << std::endl;
  165.                        
  166.                         // dump byte-aligned data[dataLength] little endian UTF-16 as UTF-8.
  167.                         for (int i = 0; i < dataLength; i+=2) {
  168.                                 int uch = cryptoData[i];
  169.                                 uch = uch | cryptoData[i+1];
  170.                                 if (uch == 0) break;
  171.                                 if (uch > 0x7FF)
  172.                                 std::cout << (unsigned char) (((uch >> 12) & 0xF) | 0xE0)
  173.                                 << (unsigned char) (((uch >> 6) & 0x3F) | 0x80)
  174.                                 << (unsigned char) ((uch & 0x3F) | 0x80);
  175.                                 else if (uch > 0x7F)
  176.                                 std::cout << (unsigned char) (((uch >> 6) & 0x1F) | 0xC0)
  177.                                 << (unsigned char) ((uch & 0x3F) | 0x80);
  178.                                 else std::cout << (unsigned char) uch;
  179.                         }
  180.                         std::cout << std::endl;
  181.                        
  182.                 }
  183.  
  184.                 wandOffset = wandOffset + DES_KEY_SZ + 4 + dataLength;
  185.         }
  186.  
  187.         free(wandData);
  188.         return 0;
  189. }
clone this paste RAW Paste Data