[ reiser @ 18.05.2010. 02:26 ] @
Mucim se vec par sati da razumem i dekriptujem Operin format u kome ona cuva passworde, ali ne ide..

Evo CPP koda koji to radi:

Code:

// sna@reteam.org  - 6th of April 2005


#include <cstdio>
#include <iostream>
#include <memory>

#include "md5.h"
#include "des.h"

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

int main(int argc, char **argv)
{
    if(argc != 2)
    {
        std::cout << "Usage: unwand <opera wand file>" << std::endl;
        return 1;
    }

    FILE *fdWand = fopen(argv[1], "rb");

    if(NULL == fdWand)
    {
        perror("Failed to open file");
        return 1;
    }

    fseek(fdWand, 0, SEEK_END);
    unsigned long fileSize = ftell(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);

    unsigned long wandOffset = 0;

    //
    // main loop, find and process encrypted blocks
    //

    while(wandOffset < fileSize)
    {
        // find key length field at start of block
        unsigned char *wandKey = (unsigned char *)
            memchr(wandData + wandOffset, DES_KEY_SZ, fileSize - wandOffset);

        if(NULL == wandKey)
        {
            break;
        }

        wandOffset = ++wandKey - wandData;

        // create pointers to length fields
        unsigned char *blockLengthPtr = wandKey - 8;
        unsigned char *dataLengthPtr = wandKey + DES_KEY_SZ;

        if(blockLengthPtr < wandData || dataLengthPtr > wandData + fileSize)
        {
            continue;
        }

        // convert big-endian numbers to native
        unsigned long
            blockLength  = *blockLengthPtr++ << 24;
            blockLength |= *blockLengthPtr++ << 16;
            blockLength |= *blockLengthPtr++ <<  8;
            blockLength |= *blockLengthPtr;

        unsigned long
            dataLength  = *dataLengthPtr++ << 24;
            dataLength |= *dataLengthPtr++ << 16;
            dataLength |= *dataLengthPtr++ <<  8;
            dataLength |= *dataLengthPtr;

        // as discussed in the article
        if(blockLength != dataLength + DES_KEY_SZ + 4 + 4)
        {
            continue;
        }

        // perform basic sanity checks on data length
        if(dataLength > fileSize - (wandOffset + DES_KEY_SZ + 4)
            || dataLength < 8 || dataLength % 8 != 0)
        {
            continue;
        }

        unsigned char
            hashSignature1[MD5_DIGEST_LENGTH],
            hashSignature2[MD5_DIGEST_LENGTH],
            tmpBuffer[256];

        //
        // hashing of (salt, key), (hash, salt, key)
        //

        memcpy(tmpBuffer, opera_salt, sizeof(opera_salt));
        memcpy(tmpBuffer + sizeof(opera_salt), wandKey, 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), wandKey, 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);

        DES_cblock iVector;
        memcpy(iVector, &hashSignature2[8], sizeof(DES_cblock));

        unsigned char *cryptoData = wandKey + DES_KEY_SZ + 4;

        //
        // decrypt wand data in place using 3DES-CBC
        //

        DES_ede3_cbc_encrypt(cryptoData, cryptoData, dataLength,
            &key_schedule1, &key_schedule2, &key_schedule3, &iVector, 0);

        if(0x00 == *cryptoData || 0x08 == *cryptoData)
        {
            std::wcout << L"<null>" << std::endl;
        }
        else
        {
            // remove padding (data padded up to next block)
            unsigned char *padding = cryptoData + dataLength - 1;
            memset(padding - (*padding - 1), 0x00, *padding);

            std::wcout << (wchar_t *)cryptoData << std::endl;
        }

        wandOffset = wandOffset + DES_KEY_SZ + 4 + dataLength;
    }

    free(wandData);
    return 0;
}


Sada bih ja ovo trebao da prebacim u Delphi, ali ne kontam. Na ovom linku ima objasnjenje formata u kome se cuvaju lozinke i tamo kazu:

Citat:
Opera Wand file consists of multiple encrypted blocks for each of the stored password entries. Each such encrypted block mainly consist of following fields,
Size of encrypted block (4 bytes)
DES Key Length ( 1 byte)
DES Key ( 8 bytes)
Size of encrypted data (4 bytes)
Encrypted Data


Po ovoj logici prva 4 bajta bi trebala da bude velicina celog bloka, etc etc... Ali:



Na ovoj slici gore moze da se vidi highlightovan jedan blok, i ova prva 4 bajta kazu da je velicina ostatka bloka 0x20, tj 32 bajta, sto je i tacno ako se izbroji.. Medjutim, sta je sa ovim bajtovima pre hajlajtovanog bloka ? Prva cetiri bajta su 0x00000002, sto je totalno nebulozno ako to treba da predstavlja velicinu ostatka tog bloka... Onda sam, po ovoj slici, pretpostavio da blokovi pocinju od 0x10 offseta u fajlu, a da su prvih 16 bajta signature fajla, sto je i u neku ruku logicno ako se pogledaju prva dva bloka (prvi pocinje od 0x10, a drugi je highlightovan), ali nije ni to to.. Evo recimo kako izgleda moj wand.dat iz Opere:




(sakrio sam neke bajtove da mi neko ne bi dekriptovao passworde :))

Na ovoj slici se vidi da blok pocinje od 0x24.. Konfjuzovan sam totalno sada, ako neko ima bilo kakav hint, go on. :)



[Ovu poruku je menjao reiser dana 18.05.2010. u 03:48 GMT+1]
[ EArthquake @ 18.05.2010. 20:24 ] @
poz reiser ,long time no see :)

kolko ja vidim (brzinski smao bacio pogled)

onaj memchr trazi DES_KEY_SZ , pa odatle pocinje parsiranje
sto je logicno , posto je duzina des kljuca uvek ista


znaci, nadje taj bajt, i od njega nastavlja da parsuje , uzima jedan po jedan deo
des kljuc, pa onda po velicini podataka i enc podatke i tako dalje

dakle , trazis prvo bajt sa vrednoscu 0x08 i nastavljas od njega , kad isparsiras sta treba , reversujes sifru i to , trazis sledeci bajt s vrednoscu 0x08 NAKON ovog isparsiranog dela , tvoj wand fajl se uklapa


btw i nije ti neka zastita sto si zasencio po jedan bajt :)
bacas me u iskusenje sad :)


[ reiser @ 18.05.2010. 20:35 ] @
Yeah, bas sam tebe trazio nocas na overthewire ali te nije bilo da mi pomognes oko ovoga :) Elem, uspeo sam da napisem algo koji dekriptuje sve ovo, pomogao mi je neki spanac odatle :)