Debian: Opera Password Recovery

Kausalität betrifft die Abfolge aufeinander bezogener Ereignisse und Zustände.
Ein Ereignis ist den Browser Opera seit wirklich langer Zeit zu nutzen und sich auch dabei gut zu fühlen.
Das andere Ereigniss ist der Moment in dem man mitbekommt das Facebook vielleicht Opera kauft. Die Wirkung kann man sich vorstellen ツ
Wenn man jetzt noch seine ganzen Passwörter in Opera gespeichert hat, ist man vor ein Problem mit einer Datei namens wand.dat gestellt. Man unterliegt dem Zwang bei einem vielleicht stattfindenden
Browserwechsel die Passwörter aus dieser Datei herauszubekommen.

Man könnte nun wine, Windows in einer virtuellen Maschine etc. installieren, ein Windowsprogramm aus obskuren Quellen dafür nutzen oder eine Datei unter Linux kompilieren und das ganze per Shell lösen.
Bei letzerer Wahl ist der Vorteil, man hat Einblick in die Source und ist sich sicher, dass die Passwörter in den eigenen Händen bleiben.

// sna@reteam.org - 6th of April 2005
// updated by theultramage@gmail.com - 12th of August 2009

#include "md5/md5.h" // TODO:from openssl/crypto
#include "des/des.h" // from openssl/crypto
#include <io.h> // filelength()
#include <memory.h>

#define MAX_DATA_SZ 1024

struct block
{
 unsigned int blocksize;
 unsigned int keysize;
 unsigned char key[DES_KEY_SZ]; // assume fixed size
 unsigned int datasize;
 unsigned char data[MAX_DATA_SZ]; // assume max. length
};

const unsigned char opera_salt[11] =
{
 0x83, 0x7D, 0xFC, 0x0F, 0x8E, 0xB3, 0xE8, 0x69, 0x73, 0xAF, 0xFF
};

unsigned int reverse(unsigned int value)
{
 unsigned char oldA[4], newA[4];
 memcpy(oldA, &value, 4);
 newA[0] = oldA[3];
 newA[1] = oldA[2];
 newA[2] = oldA[1];
 newA[3] = oldA[0];
 memcpy(&value, newA, 4);
 return value;
}

int wmain(int argc, wchar_t **argv)
{
 if(argc != 3)
 {
 printf("Usage: unwand <opera wand file> <output file>n");
 return 1;
 }

 FILE *fdWand = _wfopen(argv[1], L"rb");
 if(NULL == fdWand)
 {
 perror("Failed to open file");
 return 1;
 }

 unsigned long fileSize = filelength(fileno(fdWand));
 unsigned char *wandData = (unsigned char *)malloc(fileSize);

 if(NULL == wandData)
 {
 fclose(fdWand);
 perror("Memory allocation failed");
 return 1;
 }

 rewind(fdWand);
 fread(wandData, fileSize, 1, fdWand);
 fclose(fdWand);

 FILE* fdPass = _wfopen(argv[2], L"w, ccs=UTF-8");
 if( fdPass == NULL )
 {
 perror("Failed to open file");
 return 1;
 }

 // my file starts here ^^;
 unsigned long wandOffset = 36;

 // main loop, find and process encrypted blocks
 while(wandOffset < fileSize)
 {
 // try
 do
 {

 block b;
 block* pb = (block*)(wandData + wandOffset);

 // length of following data
 b.blocksize = reverse(pb->blocksize);
 b.blocksize += sizeof(b.blocksize);

 // key length and key
 b.keysize = reverse(pb->keysize);
 if( b.keysize != DES_KEY_SZ )
 break; // no match
 memcpy(b.key, pb->key, b.keysize);

 // data length and data
 b.datasize = reverse(pb->datasize);
 if( b.blocksize != sizeof(b.blocksize) + sizeof(b.keysize) + b.keysize + sizeof(b.datasize) + b.datasize )
 break; // no match
 memcpy(b.data, pb->data, b.datasize);

 // hashing of (salt, key) and (hash, salt, key)
 unsigned char hashSignature1[MD5_DIGEST_LENGTH];
 unsigned char hashSignature2[MD5_DIGEST_LENGTH];
 unsigned char tmpBuffer[256];

 memcpy(tmpBuffer, opera_salt, sizeof(opera_salt));
 memcpy(tmpBuffer + sizeof(opera_salt), b.key, DES_KEY_SZ);
 MD5(tmpBuffer, sizeof(opera_salt) + DES_KEY_SZ, hashSignature1);

 memcpy(tmpBuffer, hashSignature1, sizeof(hashSignature1));
 memcpy(tmpBuffer + sizeof(hashSignature1), opera_salt, sizeof(opera_salt));
 memcpy(tmpBuffer + sizeof(hashSignature1) + sizeof(opera_salt), b.key, DES_KEY_SZ);
 MD5(tmpBuffer, sizeof(hashSignature1) + sizeof(opera_salt) + DES_KEY_SZ, hashSignature2);

 // schedule keys. key material from hashes
 DES_key_schedule key_schedule1, key_schedule2, key_schedule3;
 DES_set_key_unchecked((const_DES_cblock *)&hashSignature1[0], &key_schedule1);
 DES_set_key_unchecked((const_DES_cblock *)&hashSignature1[8], &key_schedule2);
 DES_set_key_unchecked((const_DES_cblock *)&hashSignature2[0], &key_schedule3);

 // initialization vector from result of above code
 DES_cblock iVector;
 memcpy(iVector, &hashSignature2[8], sizeof(DES_cblock));

 // decrypt wand data in place using 3DES-CBC
 DES_ede3_cbc_encrypt(b.data, b.data, b.datasize, &key_schedule1, &key_schedule2, &key_schedule3, &iVector, DES_DECRYPT);

// printf("%4.4X - %u - %u - %un", wandOffset, b.blocksize, b.keysize, b.datasize);

 // zero-terminate string for safety
 wchar_t* text = (wchar_t *)b.data;
 text[b.datasize/2] = '\0';
/*
 for( unsigned int i = 0; i < b.datasize/2; ++i )
 if( text[i] == L'u0606' || text[i] == L'u0808' )
 text[i] = '\0'; // wtf...
*/
 // finally, write output
 fwprintf(fdPass, L"%sn", text);

 }
 while(0);
 // finally

 // crawl the data file byte by byte :)
 wandOffset++;
 }

 free(wandData);
 return 0;
}

Nun wird das ganze noch kompiliert und dann kann man seine Datei auslesen. Vorrausetzung dafür sind bei Debian installierte build-essentials und libssl-dev.

seraphyn@takeshi: ~/tmp $ g++ -Wall -o unwand -lssl unwand.cpp
seraphyn@takeshi: ~/tmp $ ./unwand ~/.opera/wand.dat >> Decryptoperawand

Opera, bitte verkaufe Dich nicht an Facebook.

2 Gedanken zu „Debian: Opera Password Recovery“

  1. leider nicht kompilierbar!

    ~/wand# g++ -Wall -o unwand -lssl decrypt.cpp
    decrypt.cpp:35:5: warning: second argument of ‘int main(int, wchar_t**)’ should be ‘char **’ [-Wmain]
    decrypt.cpp: In function ‘int main(int, wchar_t**)’:
    decrypt.cpp:43:39: error: ‘_wfopen’ was not declared in this scope
    decrypt.cpp:50:52: error: ‘filelength’ was not declared in this scope
    decrypt.cpp:138:31: error: ‘fwprintf’ was not declared in this scope

    Gruß

    Oliver

    • Kann ich mir bei einem Programm aus dem Jahre 2009 mit einem Post aus dem Jahr 2012 definitiv vorstellen, dass es nicht mehr geht.
      Sollte man auf eine neuen Versionsstand bringen. Du kannst ja dann den Code auf Github legen und den Link hier posten.
      Danke für die Information.

      Frohes Fest und einen guten Rutsch

Kommentare sind geschlossen.