CRITTOGRAFIA SPICCIOLA E TUTORIAL BANALI


28/10/1999

by Alga

 

 

UIC's Home Page

Published by Quequero

Sappiamo pochissimo, eppure � sbalorditivo quanto sappiamo, e ancor pi� sbalorditivo quanta potenza ci dia quel poco.

Bertrand Russel

Crittografia spicciola? Si, in fondo l'algoritmo utilizzato non era di grossa difficolt� "quache xor"...Ma arrivare a capirlo da capo a fondo � stato certamente frutto di un lavoro minuzioso e complesso come � solito alla nostra carissima Olga, nulla da dire quindi sul tutorial, se non che: IMPARATE, quello che Olga ci mette a disposizione � sempre materiale di grandissima importanza perch� non credo che in Italia ci sia reverser in grado di spiegare tanto chiaramente qualcosa come lo fa lei (e qua vorrei tornare alle nostre vecchie mail dove parlavamo di quel personaggio "Guida", ricordi vero?) Brava ancora una volta, e ti ringrazio per darci una mano, ciauz Alguzza :)

Epproprio sui nostri programmi lo dovevate usare, quel poco?

Stirling Technologies Ltd


UIC's form   UIC's form

Difficolt�

Tutte aggirate o superate! J

 

Questa � la versione integrale di un tutorial scritto nell'ottobre del 1999 e pubblicato i primi di novembre sul sito di RingZero (ove ancora si trova). I riferimenti a fOSSiL sono dovuti al fatto che all'epoca della pubblicazione il Password Extractor di fOSSiL non era ancora stato rilasciato (lo fu circa una settimana dopo la pubblicazione del tut). L'aggettivo "integrale" si riferisce solo ad una banalissima variazione del testo effettuata da kill3xx su mia esplicita richiesta, e relativa al modo in cui avevo ottenuto la versione trial (chiesta, con tanto di nome, cognome, indirizzo Email, etc., a Stirling Technologies), per il timore che potessi venire perseguita legalmente. Ma il fatto che ormai quella versione sia obsoleta, il fatto di essere divenuta molto pi� temeraria e soprattutto la consapevolezza di quanto Stirling Technologies se ne freghi di me, mi hanno spinto a lasciare il testo originale (anche se penso che a voi freghi ancor meno che a Stirling Technologies).

Poich�, come gi� accennato (e come � d'altra parte evidente a chi segua un p� l'evoluzione dei prodotti InstallShield) la versione di Package For The Web cui il tut si riferisce � obsoleta, il tut potrebbe essere considerato poco attuale. Probabilmente lo �, ma esso voleva (e vuole a maggior ragione adesso) essere la scusa per introdurre alcuni semplici concetti base di crittologia. Inoltre, sebbene non mi sia pi� assolutamente curata di quella che � stata l'evoluzione dello schema di protezione descritto nel seguito, ho la sensazione che esso possa comunque essere un'ottima base di partenza per chi volesse accingersi a studiare le implementazioni pi� recenti.




La decrittazione dei files di Package For The Web 2.1

CRITTOGRAFIA SPICCIOLA E TUTORIAL BANALI

Written by Alga

Introduzione


Stirling Technologies Ltd. comincia a farmi un po' di antipatia…no, non � vero; ci� che penso in realt� � che Stirling Technologies Ltd. stia semplicemente preparandosi a quella che sar� la nuova situazione internazionale, tra un anno circa, in fatto di protezioni software e leggi correlate. In pratica, prevedo tempi duri per noi piccoli reversers; spero di sbagliarmi...vedremo!

L'Antefatto
Una volta esisteva InstallShield Package For The Web, quello con l'icona della scatolina rossa gi� aperta (…ricordate?), e tutti erano felici. Poi cominciarono a venire fuori le nuove versioni, quelle con la scatola marrone (orribile!), che si apriva, e molti non furono pi� tanto felici. Il motivo dell'infelicit� per� non risiedeva tanto nell'estetica dell'icona, quanto nel fatto che nelle prime versioni di PFTW bastava, se esse erano protette da password, cambiare qualche salto condizionale qui e l�, lanciare il programma, aspettare il messaggio 'The package has been successfully delivered!', e ritrovarsi i file decompattati nella directory in cui era posto il file PFTW; cos�, se qualche piccolo (o piccola!) reverser doveva 'lavorare' sul programma, poteva subito concentrarsi sul target, senza dover perdere troppo tempo per aggirare quella che era, tutto sommato, una stupida protezione.

Le nuove versioni cominciarono a rendere la vita un po' pi� complicata a tutti; un certo Ivanopulo (bravo ragazzo, non lo conosco personalmente, ma mi ha dato l'impressione di voler rendere complicate anche le cose semplici J), aveva fatto un bel programmetto per il brute force attack, e cos� per i pi� pigri (o per i lamers, direbbe qualcuno), il problema era risolto; ma le versioni nuove presentarono un altro problema, analizzato nel seguito, che rese inutilizzabile il programmetto. Comparve allora un patcher di un certo Pepper, che consentiva di patchare l'EXE originale, ma comparve anche (purtroppo per Pepper) Package For The Web ver. 2.04. Gli EXE generati da questa versione si lasciavano patchare senza fiatare; una volta lanciati, il pulsante 'Continua' nella finestra di dialogo della password risultava abilitato, il programma decompattava qualcosa, ed alla fine mostrava un MessageBox: 'There is not enough space on drive xxx to extract this package. Please free up 4096.00 MB and click Retry'.

Venne in aiuto della popolazione vessata il solito fOSSiL, che pare abbia un conto aperto con Stirling Technologies, con il suo Password Extractor; esso sembrava funzionare (sebbene non sempre, o non perfettamente) anche con la versione 2.04, e d'altra parte, lo stesso fOSSiL sosteneva che l 'estrattore funzionasse con le versioni fino alla 2.04 compresa; ma Stirling Technologies rispose con la versione 2.10; con questa il programma ha mostrato la corda, generando solo, al tentativo di estrazione, il messaggio 'Unsupported version or decryption problem. Send me this file plz…'

No, non avrei spedito mai il file a fOSSiL. Primo, perch� non avrei saputo dove trovarlo; secondo, perch� non era questo che in realt� mi interessava...

Tools usati


- il solito SoftICE
- un disassemblatore (W32Dasm assolver� egregiamente allo allo scopo)
- un editor esadecimale
- una tavola dei caratteri ASCII
- un convertitore di base/calcolatrice

URL o FTP del programma

La versione 2.1 non � pi� reperibile sui siti ftp di InstallShield
Nel momento in cui (ri)scrivo una copia pu� venire scaricata da qui, ma non so quanto durer�.

Notizie sul programma 

InstallShield Package For The Web � un wrapper per file eseguibili, o per gruppi di file comprendenti un eseguibile.
Viene tipicamente utilizzato con i file prodotti dagli installatori commerciali, InstallShield in particolare.
Poich� la compressione eseguita sull'insieme dei file pu� tradursi in una criptazione degli stessi, tale caratteristica � stata sfruttata nelle versioni di PTFW a partire dall'inizio del '99 per proteggere (eventualmente) con password i file compressi; ci� dovrebbe consentire (in teoria J) di tenere i packages su siti FTP pubblici consentendo a tutti il download, ma fornendo le password soltanto agli utenti legalmente autorizzati.

Que, ma perch� ti ostini ad inserire questa sezione nella quale sono costretta a ripetere cose ovvie che sanno tutti?
Hai ragione, mi sa che la elimino :) NdQue

Essay

In realt� tutta la descrizione precedente � solo una ricostruzione parziale, descritta e commentata in forma sufficientemente stupida, di una situazione che non ho vissuto personalmente, o che ho vissuto solo in parte, inserita per cercare di rendere pi� interessante un tutorial altrimenti banale (rileggendo, divengo cosciente di quanto il risultato sia penoso, ma non sono riuscita a fare di meglio. Sorry! J). Per quanto mi riguarda strettamente i fatti si sono svolti cos�:

1) Qualche tempo addietro mi ero effettivamente imbattuta in una delle prime versioni di PFTW (sempre quella con la scatolina rossa), e l'avevo in effetti 'convinta' a decompattare i file inserendo qualche jmp qui e l� (non entro nei dettagli perch� si era rivelata un'operazione estremamente elementare)

2) Recentemente, gironzolando su DEJA.COM (per motivi solo indirettamente attinenti al RevEng), mi era capitato di leggere diversi post di alcuni (sempre lamers, direbbe qualcuno, ma le definizioni 'spregiative' affibbiate a gente che non si conosce, e sulla base di una sola manifestazione comportamentale, mi hanno sempre dato fastidio) che chiedevano disperatamente password per decompattare, lamentandosi del mancato funzionamento dei vari password crackers; qualcuno sosteneva anche di aver provato a crackare il programma, ottenendo sempre e solo il fatidico 'There is not enough space on drive xxx to extract this package. Please free up 4096.00 MB and click Retry'

3) Parte di questi post riguardavano la nuova versione di InstallShield (la numero 6.0) ed ero curiosa di sapere se e quali differenze ci fossero rispetto alla 5.5, anche perch�, come ho gi� accennato, avevo (ed ho tuttora ) fondati (almeno per me) motivi di ritenere che cambiamenti sostanziali stessero avvenendo, cos� scaricando la nuova trial version avrei preso i due classici piccioni con una fava.

4) Ho riempito i moduli relativi alla trial version presso il sito di una ditta australiana che distribuisce InstallShield e ho scaricato il programma (56Megs L); mi � giunta la mail (automatizzata) che mi comunicava, oltre i ringraziamenti, la password per decompattare. Tre giorni dopo mi � giunta anche una mail da una certa Karen Nonricordoilcognome, responsabile di qualcosa di importante, che diceva pi� o meno: "Ciao Olga, come va? Come procede la tua prova? Scusa se non ti ho scritto subito, ma sono stata fuori per il weekend. Contattaci se hai bisogno".
Bene, grazie. Ancora non so, per la verit�. Sono contenta per te. No, non ho bisogno di nulla, grazie.

5) Ho messo da parte le mail, e sono andata a cercare, tra tutti i CD masterizzati che mi ritrovo (bolgia infernale!), tutti i password crackers che possedevo (e che non sapevo di possedere). Tra essi ho trovato il succitato programmetto di Ivanopulo, diverse versioni di quello di Pepper, ed il Password Extractor di fOSSiL. Le descrizioni e le date di rilascio di questi programmi sono alla base della stupida ricostruzione precedente.

6) Ho salvato un disassemblato dell'EXE che avevo scaricato e mi sono messa al lavoro



Brute Force Attack

La prima domanda che mi sono posta � stata: perch� nessuno, nei post, citava il programma di Ivanopulo? Nessuno lo conosceva, oppure non funziona pi�? Ho disassemblato il programmino, ho incrementato il limite di tempo (il limite di 100 secondi oltre il quale la ricerca veniva sospesa mi stava un po' stretto), l'ho lanciato. Dopo pi� di venti minuti non aveva trovato un bel nulla. Ho rifatto la stessa prova su un EXE generato da una vecchia versione di PFTW; dopo pochi secondi aveva gi� trovato una (strana) sequenza di caratteri, che tuttavia funzionava....Mi sa tanto di collisione NdQue Nella vecchia versione, per�, era presente un pulsante in meno nella finestra di dialogo per la password. Il programma di Ivanopulo si ferma quando trova qualcosa che abilita il pulsante; quindi deve usare IsWindowEnabled, pensai. Ed IsWindowEnabled deve conoscere l'identificatore del controllo; e se il programma si riferisce ad una versione pi� vecchia, l'identificatore � errato.

Dopo una rapida esplorazione con The Customiser, ed un'altrettanto rapida ricerca nel disassemblato e conseguente patch, la versione 'aggiornata' del programma ripartiva, e dopo pochi secondi si fermava, mostrando una strana sequenza di caratteri ed il pulsante 'Continua' abilitato. Alla pressione del pulsante, il programma chiedeva la directory per il decompattamento, faceva comparire la progress bar con "Unpacking files...", e quindi il messagebox 'There is not enough space on drive xxx to extract this package. Please free up 4096.00 MB and click Retry'


Le funzioni hash

Nel titolo del tutorial si parla di crittografia spicciola e tutorial banali; intendendo con questo che il tutorial tratta di un'operazione di reverse engineering tutto sommato semplice e banale, ma allo scopo di servire da occasione per introdurre qualche concetto (spicciolo) relativo alla crittografia.

Per chi non lo sapesse, una funzione hash � una funzione h che accetta in input stringhe (insiemi di bit) di lunghezza arbitraria l, e restituisce stringhe di lunghezza fissa n (n ovviamente varia in rapporto alla specifica funzione utilizzata). Poich� � possibile porre l > n (anzi, di solito le funzioni vengono proprio usate cos�), una delle caratteristiche delle funzioni hash � l'esistenza di collisione, cio� della possibilit� che due diversi input producano il medesimo output; ci� discende direttamente da l > n, in quanto in essa � implicita una relazione uno-a-molti (o, se preferite, perch� l > n implica anche l! > n!, e cio� perch� il numero di permutazioni consentite da l � maggiore di quelle consentite da n, o per quello che volete voi). Si dimostra che le probabilit� di collisione, in caso di l > n e di input equiprobabili, sono 2-n.

Le funzioni hash vengono divise in due grandi gruppi: le funzioni parametrizzate con chiave e quelle non parametrizzate con chiave; le prime trovano applicazioni, ad esempio, nelle procedure relative alla firma digitale, in cui l'output della funzione hash � l'impronta. Pi� in generale, le funzioni hash di ambedue i tipi vengono utilizate in svariati campi della crittografia; la loro utilit� � motivata dalle seguenti propriet�:


1) Sono facili da calcolare
2) Forniscono una sorta di compressione dei dati in uscita (appunto perch� di solito � l > n)
3) Il fatto che la funzione sia del tipo uno-a-molti implica che essa sia a senso unico; cio� � computazionalmente impossibile risalire all'input della funzione conoscendo l'output corrispondente e la funzione stessa.
4) E' computazionalmente impossibile trovare due input che condividano lo stesso output
5) Dato un determinato input, � impossibile calcolare un secondo input che condivida lo stesso output del primo
Per computazionalmente impossibile non si intende evidentemente un'impossibilit� assoluta, ma la difficolt� nel calcolare il risultato in tempi accettabili; per quanto riguarda le propriet� 4) e 5), l'entit� della difficolt� appare direttamente dipendente da n qualora venga usata una sorta di brute force attack

. L'impiego delle funzioni hash � comunque prevalentemente orientato alla convalida dell'input della funzione; le propriet� 3), 4) e 5) fanno si che, per n sufficientemente grande, l'output della funzione venga considerato infalsificabile; d'altra parte, l'informazione contenuta nell'output � effettivamente molto minore di quella originaria, e ci� non le rende utilizzabili per propositi di criptazione/decrittazione.

Funzioni hash e controllo della password

Come precedentemente accennato (e come sa bene chiunque abbia visto un file PFTW protetto da password) il dialogo richiesta password presenta, alla sua comparsa, un pulsante disabilitato, che viene abilitato quando viene immessa la password corretta o, perlomeno, quando il programma riconosce 'qualcosa' nella password immessa. Gli approcci che consentono di individuare il segmento di codice interessato possono essere diversi (dal bpx GetWindowText, alla ricerca in SICE della sequenza di caratteri immessa e successivo bpm sulla locazione, etc,); io personalmente tento sempre prima di ragionare un po' sul dead listing. In questo caso sappiamo che il programma, una volta riconosciuta la correttezza della password, molto verosimilmente chiamer� EnableWindow. Sono presenti solo due riferimenti a questa funzione, ed il pi� interessante appare senza dubbio questo:
* Reference To: USER32.GetDlgItem, Ord:00F3h
                                  |
:00404C55 FF1530D54100            Call dword ptr [0041D530]
:00404C5B 8945FC                  mov dword ptr [ebp-04], eax
:00404C5E 837DFC00                cmp dword ptr [ebp-04], 00000000
:00404C62 7417                    je 00404C7B  errore

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00404C4A(C)
|
:00404C64 8B5508                  mov edx, dword ptr [ebp+08]
:00404C67 52                      push edx passa qualcosa a...
:00404C68 E8E5FDFFFF              call 00404A52 ...QUESTO QUI... 
:00404C6D 83C404                  add esp, 00000004
:00404C70 50                      push eax ...che restituisce il flag...
:00404C71 8B45FC                  mov eax, dword ptr [ebp-04]
:00404C74 50                      push eax ...e passa l'handle prima di chiamare la funzione

* Reference To: USER32.EnableWindow, Ord:00B2h

:00404C75 FF1518D54100            Call dword ptr [0041D518]

mentre questa procedura � QUESTO QUI:

 * Referenced by a CALL at Addresses:
|:00404C68   , :00404CDB   , :00404DE1   , :00404E1F
|
:00404A52 55                      push ebp
:00404A53 8BEC                    mov ebp, esp
:00404A55 83EC08                  sub esp, 00000008

* Possible Reference to Dialog: DialogID_03EB, CONTROL_ID:0404, ""
                                  |
:00404A58 6804040000              push 00000404
:00404A5D 8B4508                  mov eax, dword ptr [ebp+08]
:00404A60 50                      push eax

* Reference To: USER32.GetDlgItem, Ord:00F3h
                                  |
:00404A61 FF1530D54100            Call dword ptr [0041D530]
:00404A67 8945F8                  mov dword ptr [ebp-08], eax
:00404A6A 837DF800                cmp dword ptr [ebp-08], 00000000
:00404A6E 743D                    je 00404AAD  errore
:00404A70 6880000000              push 00000080 128 caratteri max
:00404A75 8B0DF4A84100            mov ecx, dword ptr [0041A8F4]
:00404A7B 51                      push ecx indirizzo buffer
:00404A7C 8B55F8                  mov edx, dword ptr [ebp-08]
:00404A7F 52                      push edx handle

* Reference To: USER32.GetWindowTextA, Ord:013Fh
                                  |
:00404A80 FF15E8D44100            Call dword ptr [0041D4E8]
:00404A86 A1F4A84100              mov eax, dword ptr [0041A8F4] adesso la password � qui
:00404A8B 50                      push eax passala alla...
:00404A8C E8F2230000              call 00406E83 ...funzione per la convalida
:00404A91 83C404                  add esp, 00000004
:00404A94 8945FC                  mov dword ptr [ebp-04], eax valore restituito
:00404A97 8B4DFC                  mov ecx, dword ptr [ebp-04] inseriscilo in ECX
:00404A9A 3B0D3C934100            cmp ecx, dword ptr [0041933C] e confrontalo con questo
:00404AA0 7507                    jne 00404AA9 sono diversi, salta
:00404AA2 B801000000              mov eax, 00000001 sono uguali,
:00404AA7 EB06                    jmp 00404AAF esci e ritorna per porre a 1 il flag di EnableWindow 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00404AA0(C)
|
:00404AA9 33C0                    xor eax, eax sono diversi,  EAX=0
:00404AAB EB02                    jmp 00404AAF esci e ritorna per porre a 0 il flag di EnableWindow 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00404A6E(C)
|
:00404AAD 33C0                    xor eax, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00404AA7(U), :00404AAB(U)
|
:00404AAF 8BE5                    mov esp, ebp
:00404AB1 5D                      pop ebp
:00404AB2 C3                      ret

 

sembra abbastanza chiaro: ogni volta che un carattere viene inserito nell'EditBox della password, il suo contenuto viene passato a 406E83, funzione che restituisce un valore in EAX. Quando questo risulta uguale al contenuto della locazione 41933C, il pulsante viene abilitato. Il metodo che viene usato per il controllo password non ha un'aria vagamente familiare?

1) Effettua il controllo su stringhe di lunghezza variabile (la password pu� avere lunghezza variabile, ed il controllo viene inoltre effettuato gi� all'immissione di un solo carattere)
2) Restituisce una stringa di lunghezza fissa (quattro byte, anche quando � stato immesso un solo carattere)
3) Fornisce una compressione dei dati originali (una password � di solito pi� lunga di quattro byte)
4) Il Brute Force Attack trova diverse sequenze che provocano l'abilitazione del pulsante (collisione)...Da qualche parte allora ce l'ho un cervello :) NdQue (scusa Olga, non ti disturbo pi� :); ci� non sorprende, in quanto con soli quattro byte, le possibilit� che due input equiprobabili generino lo stesso output sono 2-4 = 1/16.

Per quanto detto prima, ci� possiede anche le seguenti implicazioni (negative L):

1) L'output della funzione non verr� utilizzato per la decrittazione
2) La conoscenza dell'output della funzione (presente in 41933C) non ci consentir� in alcun modo di risalire alla password

Il contenuto della locazione 41933C viene determinato qui:

:00402F80 6A10                    push 00000010
:00402F82 6A00                    push 00000000
:00402F84 8B15B8A84100            mov edx, dword ptr [0041A8B8]
:00402F8A 52                      push edx
:00402F8B E850B80000              call 0040E7E0  QUI
:00402F90 83C40C                  add esp, 0000000C
:00402F93 A33C934100              mov dword ptr [0041933C], eax
:00402F98 EB76                    jmp 00403010

la funzione in 40E7E0 non fa altro che decrittare l'output della funzione, precalcolato da PFTW in fase di generazione dell'EXE e memorizzato al suo interno in forma criptata, come stringa numerica; precauzione eccessiva ed inutile, a mio avviso, considerando che, da esso non � possibile risalire alla password e che, come vedremo, la soluzione finale si rivela, tutto sommato, realmente semplice. Il reversing della funzione in 40E7E0 sarebbe perci� un lavoro inutile e noioso e noi, pigri, lo tralasceremo.

I crackers sono pigri
Perch�, diciamoci la verit�, i crackers sono veramente pigri, e sperano sempre di trovare, con un colpo di...fortuna, qualche metodo che consenta di ottenere il risultato desiderato senza effettuare un reale reversing delle procedure esaminate; come prendere lo stipendio senza lavorare, insomma (ma se si � capito poco della roba con cui si ha a che fare, non si potr� poi scrivere un tutorial J). Io chiaramente non faccio eccezione, e cos�, contro ogni evidenza logica, mi sono chiesta: "e se passassi direttamente in EAX il contenuto della locazione 41933C, per esempio in 404A8C?". Beh, non succede niente; proviamo a cercare altre occorrenze di 41933C. Troviamo questa:

* Referenced by a CALL at Addresses:
|:00404A11   , :00404E2F   , :0040528F   , :004053EA   , :00405D8E
|
:00404155 55                      push ebp
:00404156 8BEC                    mov ebp, esp
:00404158 81EC18020000            sub esp, 00000218
:0040415E 833DB8A8410000          cmp dword ptr [0041A8B8], 00000000
:00404165 7430                    je 00404197 nessuna password inserita, esce
:00404167 A1F4A84100              mov eax, dword ptr [0041A8F4]  password 
:0040416C 50                      push eax passata alla funzione hash
:0040416D E8112D0000              call 00406E83 calcola
:00404172 83C404                  add esp, 00000004
:00404175 8945FC                  mov dword ptr [ebp-04], eax output funzione
:00404178 8B4DFC                  mov ecx, dword ptr [ebp-04]
:0040417B 3B0D3C934100            cmp ecx, dword ptr [0041933C] confronta
:00404181 7414                    je 00404197 continua se uguali

* Possible Reference to String Resource ID=00035: "Security error! Invalid password."
                                  |
:00404183 C7053093410023000000    mov dword ptr [00419330], 00000023
:0040418D A130934100              mov eax, dword ptr [00419330]
:00404192 E9CC010000              jmp 00404363

come � facile verificare, il codice � assolutamente sovrapponibile al precedente. Poich� la pigrizia tenta sempre di avere il sopravvento, mi sono chiesta ancora: "e se aggiungessi qualche istruzione alla funzione hash che restituisca in EAX il contenuto di 41933C?" Ho percorso la nidificazione delle chiamate da 406E83 fin quando sono giunta qui:

:0040EA25 8A10                    mov dl, byte ptr [eax]
:0040EA27 8A5801                  mov bl, byte ptr [eax+01]
:0040EA2A 40                      inc eax
:0040EA2B 8819                    mov byte ptr [ecx], bl
:0040EA2D 40                      inc eax
:0040EA2E 41                      inc ecx
:0040EA2F 8811                    mov byte ptr [ecx], dl
:0040EA31 41                      inc ecx
:0040EA32 4E                      dec esi
:0040EA33 75F0                    jne 0040EA25
:0040EA35 5B                      pop ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040EA18(C)
|
:0040EA36 5E                      pop esi
:0040EA37 C3                      ret


:0040EA38 90                      nop
:0040EA39 90                      nop
:0040EA3A 90                      nop
:0040EA3B 90                      nop
:0040EA3C 90                      nop
:0040EA3D 90                      nop
:0040EA3E 90                      nop
:0040EA3F 90                      nop

ed ho variato la routine in questo modo:

:0040EA25 8A10                    mov dl, byte ptr [eax]
:0040EA27 8A5801                  mov bl, byte ptr [eax+01]
:0040EA2A 40                      inc eax
:0040EA2B 8819                    mov byte ptr [ecx], bl
:0040EA2D 40                      inc eax
:0040EA2E 41                      inc ecx
:0040EA2F 8811                    mov byte ptr [ecx], dl
:0040EA31 41                      inc ecx
:0040EA32 4E                      dec esi
:0040EA33 75F0                    jne 0040EA25
:0040EA35 5B                      pop ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040EA18(C)
|
:0040EA36 A13C934100              mov eax, dword ptr [0041933C]
:0040EA3B 894508		  mov dword ptr [ebp+08], eax
:0040EA3E 5E                      pop esi
:0040EA3F C3                      ret

   

Al riavvio del programma, il pulsante 'Continua' risultava abilitato. Ho inserito caratteri random nell'EditBox, sono andata avanti ed ho ottenuto il trito 'There is not enough space on drive xxx to extract this package. Please free up 4096.00 MB and click Retry'. Beh, in realt� proprio quello che avrei dovuto aspettarmi, perch� cos� tutto ci� che sono riuscita ad ottenere � la riproduzione di ci� che avviene con il brute force attack: l'output esatto della funzione hash convalida la password, ma ci� non serve per la decrittazione, che si avvale comunque del contenuto dell'EditBox, per cui caratteri random=niente decrittazione.

La pigrizia non paga.

Per� il lavoro fatto non � stato inutile. Innanzitutto, la variazione della routine che esegue la funzione hash risulter� indispensabile per la decodifica delle password (a meno che non si voglia usare il programma di Ivanopulo 'aggiornato' - operazione che potrebbe rivelarsi di una lentezza esasperante - o scrivere qualcosa 'from scratch' che automatizzi la procedura); e poi, la ricerca degli altri riferimenti alla funzione hash ha avuto il vantaggio di proiettarci direttamente nella routine che contiene la chiamata alla funzione che esegue il reale ciclo di decrittazione...


Il ciclo di decrittazione
Questo � infatti il (riassunto del) listato della routine in cui � contenuto il segmento di codice precedentemente mostrato, commentato:

* Referenced by a CALL at Addresses:
|:00404A11   , :00404E2F   , :0040528F   , :004053EA   , :00405D8E
|
VERIFICA PASSWORD CON FUNZIONE HASH
:00404155 55                      push ebp
:00404156 8BEC                    mov ebp, esp
:00404158 81EC18020000            sub esp, 00000218
:0040415E 833DB8A8410000          cmp dword ptr [0041A8B8], 00000000
:00404165 7430                    je 00404197 nessuna password inserita, esce
:00404167 A1F4A84100              mov eax, dword ptr [0041A8F4]  password 
:0040416C 50                      push eax passata alla funzione hash
:0040416D E8112D0000              call 00406E83 calcola
:00404172 83C404                  add esp, 00000004
:00404175 8945FC                  mov dword ptr [ebp-04], eax output funzione
:00404178 8B4DFC                  mov ecx, dword ptr [ebp-04]
:0040417B 3B0D3C934100            cmp ecx, dword ptr [0041933C] confronta
:00404181 7414                    je 00404197 continua se uguali

* Possible Reference to String Resource ID=00035: "Security error! Invalid password."
                                  |
:00404183 C7053093410023000000    mov dword ptr [00419330], 00000023 codice errore? 
:0040418D A130934100              mov eax, dword ptr [00419330]
:00404192 E9CC010000              jmp 00404363
:...
:...
:...
SI PREPARA AD ESTRARRE FILE .PKG 
* Reference To: USER32.CreateDialogParamA, Ord:004Bh
                                  |
:004041C2 FF1528D54100            Call dword ptr [0041D528] barra di Reading package
:004041C8 8985E8FDFFFF            mov dword ptr [ebp+FFFFFDE8], eax handle of dialog box

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004041AA(U)
|
:004041CE 8B8DE8FDFFFF            mov ecx, dword ptr [ebp+FFFFFDE8]
:004041D4 890D4CA84100            mov dword ptr [0041A84C], ecx handle
:004041DA 8B154CA84100            mov edx, dword ptr [0041A84C]
:004041E0 52                      push edx lo pusha  per la barra di avanzamento
:004041E1 E84AFBFFFF              call 00403D30  UNPACKING 
:004041E6 83C404                  add esp, 00000004
:004041E9 A330934100              mov dword ptr [00419330], eax codice errore?
:004041EE 833D3093410000          cmp dword ptr [00419330], 00000000
:004041F5 0F85EF000000            jne 004042EA
:004041FB 833D4CA8410000          cmp dword ptr [0041A84C], 00000000
:00404202 7424                    je 00404228
:...
:...
:...

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00404202(C)
|
:00404228 833D2493410000          cmp dword ptr [00419324], 00000000
:0040422F 0F85B5000000            jne 004042EA

VERIFICA NUOVAMENTE SE UNA PWD SIA STATA INTRODOTTA
:00404235 8B0DF4A84100            mov ecx, dword ptr [0041A8F4] copia password
:0040423B 51                      push ecx
:0040423C 8D95ECFDFFFF            lea edx, dword ptr [ebp+FFFFFDEC]
:00404242 52                      push edx in ebp+fffffDEC

* Reference To: KERNEL32.lstrcpyA, Ord:029Bh
                                  |
:00404243 FF1510D44100            Call dword ptr [0041D410]
:00404249 8D85ECFDFFFF            lea eax, dword ptr [ebp+FFFFFDEC]
:0040424F 50                      push eax  e calcola la lunghezza

* Reference To: KERNEL32.lstrlenA, Ord:02A1h
                                  |
:00404250 FF1514D44100            Call dword ptr [0041D414]
:00404256 8945F4                  mov dword ptr [ebp-0C], eax
:00404259 837DF400                cmp dword ptr [ebp-0C], 00000000 se e' zero...
:0040425D 7E77                    jle 004042D6  ...salta, se non e' zero...
:0040425F C745F801000000          mov [ebp-08], 00000001 ...setta il flag e va avanti
:00404266 EB09                    jmp 00404271
:...
:...
:...
ASSEGNA IL NOME AL FILE .PKG E PONE IL FILE NELLA DIRECTORY 
:0040427C 8B45F8                  mov eax, dword ptr [ebp-08]
:0040427F 50                      push eax
:00404280 8B0D58A84100            mov ecx, dword ptr [0041A858] caratteri da sostituire nella stringa
:00404286 51                      push ecx per formare il path completo della directory temp

* Possible StringData Ref from Data Obj ->"%spftw%d.pkg"
                                  |
:00404287 683C624100              push 0041623C stringa + caratteri di controllo
:0040428C 8D95F0FEFFFF            lea edx, dword ptr [ebp+FFFFFEF0]
:00404292 52                      push edx buffer

* Reference To: USER32.wsprintfA, Ord:0264h
                                  |
:00404293 FF15C8D44100            Call dword ptr [0041D4C8] invia
:00404299 83C410                  add esp, 00000010
:0040429C 6A00                    push 00000000
:0040429E 8D85F0FEFFFF            lea eax, dword ptr [ebp+FFFFFEF0]
:004042A4 50                      push eax path completo della directory temp
:004042A5 E87ED0FFFF              call 00401328
:...
:...
:...
LEGGE ANCORA LA PASSWORD INTRODOTTA 
:004042B1 6A00                    push 00000000
:004042B3 6A00                    push 00000000
:004042B5 8B4DF4                  mov ecx, dword ptr [ebp-0C]
:004042B8 51                      push ecx lunghezza password
:004042B9 8D95ECFDFFFF            lea edx, dword ptr [ebp+FFFFFDEC]
:004042BF 52                      push edx password 
:004042C0 8D85F0FEFFFF            lea eax, dword ptr [ebp+FFFFFEF0]
:004042C6 50                      push eax buffer
:004042C7 E8942E0000              call 00407160 CHE COSA CHIAMA QUA???
:004042CC 83C414                  add esp, 00000014
:004042CF A330934100              mov dword ptr [00419330], eax codice errore?

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004042AF(C)
|
:004042D4 EB92                    jmp 00404268

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040425D(C), :0040427A(C)
|
DECOMPATTA IL FILE .PKG
:004042D6 8B0D4CA84100            mov ecx, dword ptr [0041A84C]  handle file .PKG  
:004042DC 51                      push ecx  lo pusha 
:004042DD E803F7FFFF              call 004039E5  ERRORE!!! 
:004042E2 83C404                  add esp, 00000004
:004042E5 A330934100              mov dword ptr [00419330], eax
:...
:...
:...

ELIMINA IL FILE .PKG CHE NON SERVE PIU' 
:0040431A 8B4DF8                  mov ecx, dword ptr [ebp-08]
:0040431D 51                      push ecx
:0040431E 8B1558A84100            mov edx, dword ptr [0041A858]
:00404324 52                      push edx

* Possible StringData Ref from Data Obj ->"%spftw%d.pkg"
                                  |
:00404325 684C624100              push 0041624C
:0040432A 8D85F0FEFFFF            lea eax, dword ptr [ebp+FFFFFEF0]
:...
:...
:...
:0040434F 8D95F0FEFFFF            lea edx, dword ptr [ebp+FFFFFEF0]
:00404355 52                      push edx

* Reference To: KERNEL32.DeleteFileA, Ord:004Eh
                                  |
:00404356 FF1578D34100            Call dword ptr [0041D378] elimina file .PKG

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040434D(C)
|
:0040435C EBA8                    jmp 00404306

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00404318(C)
|
:0040435E A130934100              mov eax, dword ptr [00419330] restituisce codice errore? 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00404192(U)
|
:00404363 8BE5                    mov esp, ebp
:00404365 5D                      pop ebp
:00404366 C3                      ret

  

il programma qui verifica la validit� della password (come � stato ripetuto fino alla nausea), indi estrae un file con estensione .PKG, verifica ancora che una password sia stata effettivamente introdotta, copia il file .PKG nella directory temporanea, legge ancora la password e la passa ad una funzione chiamata in 4042C7, poi passa l'handle del file .PKG ad un'altra funzione in 4042DD; in quest'ultima viene generato l'errore (come � facilmente verificabile con SICE). Alla fine, il file .PKG viene comunque eliminato, perch� non serve pi�.

Il file .PKG � quello che effettivamente contiene i file definitivi (il file di setup, i .CAB, etc.), oltrech� le informazioni necessarie per ricostruirle; in pratica, � un file autodecompattante che viene estratto dall'eseguibile principale (l'EXE generato da PFTW), ed � proprio questo ad essere memorizzato in forma criptata.

Bene, il fatto che venga passato l'handle di PKG alla funzione chiamata in 4042DD e che questa generi l'errore, sembra indicare che qui debba avvenire la decompattazione definitiva del .PKG; se esso non � stato correttamente decriptato, la decompattazione non pu� evidentemente avvenire. E dove deve avvenire la decriptazione se non in corrispondenza dell'unica funzione (oltre alla funzione hash) a cui viene passato come parametro la password stessa?

ecco il disassemblato di CHE COSA CHIAMA QUA???:

* Referenced by a CALL at Address:
|:004042C7
|
:00407160 55                      push ebp
:00407161 8BEC                    mov ebp, esp
:00407163 83EC40                  sub esp, 00000040
:00407166 C745FC00000000          mov [ebp-04], 00000000
:0040716D C745F013358607          mov [ebp-10], 07863513 chiave per generare intermedio
:00407174 6A04                    push 00000004
:00407176 8D45F0                  lea eax, dword ptr [ebp-10]
:00407179 50                      push eax chiave per generare intermedio
:0040717A 8B4D10                  mov ecx, dword ptr [ebp+10]
:0040717D 51                      push ecx lunghezza
:0040717E 8B550C                  mov edx, dword ptr [ebp+0C]
:00407181 52                      push edx password
:00407182 E88B020000              call 00407412 CALCOLA INTERMEDIO
:00407187 83C410                  add esp, 00000010
:0040718A 8945F8                  mov dword ptr [ebp-08], eax  indirizzo intermedio
:0040718D 6A00                    push 00000000 null sotto W9x
:0040718F 6880000000              push 00000080 flags and attributes
:00407194 6A03                    push 00000003 creation distribution
:00407196 6A00                    push 00000000 security attributes
:00407198 6A01                    push 00000001 share mode
:0040719A 68000000C0              push C0000000 desired access
:0040719F 8B4508                  mov eax, dword ptr [ebp+08] PTFW1.PKG
:004071A2 50                      push eax nomefile

* Reference To: KERNEL32.CreateFileA, Ord:0031h
                                  |
:004071A3 FF15ECD34100            Call dword ptr [0041D3EC]
:004071A9 8945F4                  mov dword ptr [ebp-0C], eax
:004071AC 837DF4FF                cmp dword ptr [ebp-0C], FFFFFFFF
:004071B0 0F84BE010000            je 00407374  ERRORE
:004071B6 C745E000000000          mov [ebp-20], 00000000 inizializza quattro variabili
:004071BD C745E800000000          mov [ebp-18], 00000000
:004071C4 C745EC00000000          mov [ebp-14], 00000000
:004071CB C745DC00000000          mov [ebp-24], 00000000
:004071D2 8B4D18                  mov ecx, dword ptr [ebp+18]
:004071D5 51                      push ecx
:004071D6 8D55DC                  lea edx, dword ptr [ebp-24]
:004071D9 52                      push edx
:004071DA 8D45EC                  lea eax, dword ptr [ebp-14]
:004071DD 50                      push eax
:004071DE E88C020000              call 0040746F
:004071E3 83C40C                  add esp, 0000000C
:004071E6 8D4DE8                  lea ecx, dword ptr [ebp-18]
:004071E9 51                      push ecx ADDRESS OF HIGH ORDER WORD FOR FILE SIZE
:004071EA 8B55F4                  mov edx, dword ptr [ebp-0C]
:004071ED 52                      push edx handle

* Reference To: KERNEL32.GetFileSize, Ord:00EDh
                                  |
:004071EE FF15F0D34100            Call dword ptr [0041D3F0]
:004071F4 8945E0                  mov dword ptr [ebp-20], eax ADDRESS OF L.O. WORD FOR FILE SIZE 
:004071F7 6A00                    push 00000000 NULL: mapping creato senza alcun nome
:004071F9 8B45E0                  mov eax, dword ptr [ebp-20]
:004071FC 50                      push eax MAXIMUM SIZE LOW
:004071FD 8B4DE8                  mov ecx, dword ptr [ebp-18]
:00407200 51                      push ecx MAXIMUM SIZE HIGH
:00407201 8B55EC                  mov edx, dword ptr [ebp-14]
:00407204 52                      push edx protect
:00407205 6A00                    push 00000000 security attributes
:00407207 8B45F4                  mov eax, dword ptr [ebp-0C]
:0040720A 50                      push eax handle

* Reference To: KERNEL32.CreateFileMappingA, Ord:0032h
                                  |
:0040720B FF15F4D34100            Call dword ptr [0041D3F4]
:00407211 8945E4                  mov dword ptr [ebp-1C], eax handle
:00407214 837DE400                cmp dword ptr [ebp-1C], 00000000
:00407218 0F844C010000            je 0040736A errore
:0040721E C745D800000000          mov [ebp-28], 00000000 inizializza indirizzo base file mappato 
:00407225 6A00                    push 00000000 NULL = intero file
:00407227 6A00                    push 00000000
:00407229 6A00                    push 00000000
:0040722B 8B4DDC                  mov ecx, dword ptr [ebp-24]
:0040722E 51                      push ecx desired access
:0040722F 8B55E4                  mov edx, dword ptr [ebp-1C]
:00407232 52                      push edx handle del file che deve essere mappato in memoria

* Reference To: KERNEL32.MapViewOfFile, Ord:01A4h
                                  |
:00407233 FF15F8D34100            Call dword ptr [0041D3F8]
:00407239 8945D8                  mov dword ptr [ebp-28], eax indirizzo base file mappato
:0040723C 837DD800                cmp dword ptr [ebp-28], 00000000
:00407240 0F841A010000            je 00407360
:00407246 8B45D8                  mov eax, dword ptr [ebp-28]
:00407249 8945C4                  mov dword ptr [ebp-3C], eax indirizzo base file mappato
:0040724C C745D000000000          mov [ebp-30], 00000000 inizializza due variabili
:00407253 C745D400000000          mov [ebp-2C], 00000000
:0040725A 8B4DE8                  mov ecx, dword ptr [ebp-18]  maximum size HO 
:0040725D 0B4DE0                  or ecx, dword ptr [ebp-20] OR con maximum size LO 
:00407260 33D2                    xor edx, edx
:00407262 894DD0                  mov dword ptr [ebp-30], ecx MAXIMUM SIZE LO
:00407265 8955D4                  mov dword ptr [ebp-2C], edx
:00407268 C745C800000000          mov [ebp-38], 00000000 inizializza contatore byte da decrittare
:0040726F C745CC00000000          mov [ebp-34], 00000000
:00407276 EB12                    jmp 0040728A INIZIA CICLO DI DECRITTAZIONE

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407319(U)
|
:00407278 8B45C8                  mov eax, dword ptr [ebp-38]  contatore byte da decrittare
:0040727B 83C001                  add eax, 00000001
:0040727E 8B4DCC                  mov ecx, dword ptr [ebp-34]
:00407281 83D100                  adc ecx, 00000000
:00407284 8945C8                  mov dword ptr [ebp-38], eax incrementa contatore
:00407287 894DCC                  mov dword ptr [ebp-34], ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407276(U)
|
:0040728A 8B55CC                  mov edx, dword ptr [ebp-34]
:0040728D 3B55D4                  cmp edx, dword ptr [ebp-2C]
:00407290 0F8F88000000            jg 0040731E esce dal ciclo
:00407296 7C08                    jl 004072A0
:00407298 8B45C8                  mov eax, dword ptr [ebp-38]  contatore byte 
:0040729B 3B45D0                  cmp eax, dword ptr [ebp-30] compara con MAXIMUM SIZE LO
:0040729E 737E                    jnb 0040731E fine del ciclo

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407296(C)
|
:004072A0 8B4D14                  mov ecx, dword ptr [ebp+14]
:004072A3 81E1FF000000            and ecx, 000000FF
:004072A9 85C9                    test ecx, ecx
:004072AB 7437                    je 004072E4 QUI SALTA COMUNQUE
:004072E2 EB35                    jmp 00407319
:...
:...
:...

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004072AB(C)
|
:004072E4 8B4510                  mov eax, dword ptr [ebp+10]
:004072E7 99                      cdq CONVERTE EAX IN UN QUAD WORD
:004072E8 52                      push edx H.O. DOUBLEWORD 
:004072E9 50                      push eax L.O. DOUBLEWORD
:004072EA 8B45CC                  mov eax, dword ptr [ebp-34]
:004072ED 50                      push eax
:004072EE 8B4DC8                  mov ecx, dword ptr [ebp-38] contatore no. di byte (offset)
:004072F1 51                      push ecx
:004072F2 E8E9770000              call 0040EAE0 restituisce offset intermedio in EAX
:004072F7 8B55F8                  mov edx, dword ptr [ebp-08]  indirizzo intermedio
:004072FA 8A0402                  mov al, byte ptr [edx+eax] carattere no. EAX in AL
:004072FD 50                      push eax lo passa a 4073CF 
:004072FE 8B4DC8                  mov ecx, dword ptr [ebp-38] contatore no. di byte (offset)
:00407301 8B55C4                  mov edx, dword ptr [ebp-3C] indirizzo base file mappato
:00407304 8A040A                  mov al, byte ptr [edx+ecx] carattere no. ECX in AL
:00407307 50                      push eax lo passa a 4073CF 
:00407308 E8C2000000              call 004073CF DECRITTA UN BYTE DEL FILE .PKG  
:0040730D 83C408                  add esp, 00000008
:00407310 8B4DC8                  mov ecx, dword ptr [ebp-38] RIMETTE IL BYTE... 
:00407313 8B55C4                  mov edx, dword ptr [ebp-3C] ...DECRITTATO AL POSTO...
:00407316 88040A                  mov byte ptr [edx+ecx], al  ...DEL PRECEDENTE

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004072E2(U)
|
:00407319 E95AFFFFFF              jmp 00407278 chiude il ciclo

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00407290(C), :0040729E(C)
|
:0040731E 837D1800                cmp dword ptr [ebp+18], 00000000
:00407322 742B                    je 0040734F  QUI SALTA COMUNQUE 
:...
:...
:...

RILASCIA GLI HANDLE 
:0040734F C745FC01000000          mov [ebp-04], 00000001
:00407356 8B55D8                  mov edx, dword ptr [ebp-28]
:00407359 52                      push edx

* Reference To: KERNEL32.UnmapViewOfFile, Ord:0253h
                                  |
:0040735A FF15FCD34100            Call dword ptr [0041D3FC]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407240(C)
|
:00407360 8B45E4                  mov eax, dword ptr [ebp-1C]
:00407363 50                      push eax

* Reference To: KERNEL32.CloseHandle, Ord:0018h
                                  |
:00407364 FF1524D44100            Call dword ptr [0041D424]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407218(C)
|
:0040736A 8B4DF4                  mov ecx, dword ptr [ebp-0C]
:0040736D 51                      push ecx

* Reference To: KERNEL32.CloseHandle, Ord:0018h
                                  |
:0040736E FF1524D44100            Call dword ptr [0041D424]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004071B0(C)
|
:00407374 8B55F8                  mov edx, dword ptr [ebp-08]
:00407377 8955C0                  mov dword ptr [ebp-40], edx
:0040737A 8B45C0                  mov eax, dword ptr [ebp-40]
:0040737D 50                      push eax
:0040737E E84D770000              call 0040EAD0
:00407383 83C404                  add esp, 00000004
:00407386 8B45FC                  mov eax, dword ptr [ebp-04]
:00407389 8BE5                    mov esp, ebp
:0040738B 5D                      pop ebp
:0040738C C3                      ret

Riepilogando: la password viene utilizzata per generare, insieme ad una chiave aggiuntiva 'hardcoded', un codice intermedio; ci� avviene nella routine 407412 chiamata in 407182. Indi il file da decrittare viene mappato in memoria, viene letto byte per byte e decrittato utilizzando il codice intermedio, decrittazione che avviene nella routine 4073CF, chiamata in 407308; ogni byte del file, individuato utilizzando l'indirizzo di mappatura come base ed il contatore come offset, ha un corrispettivo nell'intermedio. Il corrispettivo viene individuato sempre dall'offset (contatore). Il byte decrittato viene quindi sostituito al byte originario nel file mappato in memoria, e tutto procede ciclicamente fino alla fine del file.

Il metodo usato per la creazione dell'intermedio � di una banalit� sconvolgente:

CALCOLA INTERMEDIO

* Referenced by a CALL at Address:
|:00407182
|
:00407412 55                      push ebp
:00407413 8BEC                    mov ebp, esp
:00407415 83EC08                  sub esp, 00000008
:00407418 53                      push ebx
:00407419 8B450C                  mov eax, dword ptr [ebp+0C] lunghezza password 
:0040741C 50                      push eax
:0040741D E87E770000              call 0040EBA0
:00407422 83C404                  add esp, 00000004
:00407425 8945FC                  mov dword ptr [ebp-04], eax indirizzo buffer intermedio
:00407428 C745F800000000          mov [ebp-08], 00000000 azzera contatore
:0040742F EB09                    jmp 0040743A inizia ciclo con iterazioni = lungh. pwd

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407465(U)
|               CHIUDI CICLO - INCREMENTA CONTATORE
:00407431 8B4DF8                  mov ecx, dword ptr [ebp-08]
:00407434 83C101                  add ecx, 00000001
:00407437 894DF8                  mov dword ptr [ebp-08], ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040742F(U)
|
:0040743A 8B55F8                  mov edx, dword ptr [ebp-08]  contatore
:0040743D 3B550C                  cmp edx, dword ptr [ebp+0C] ciclo finito?
:00407440 7D25                    jge 00407467 si, esci 
:00407442 8B4508                  mov eax, dword ptr [ebp+08] no, pwd base addr qui
:00407445 0345F8                  add eax, dword ptr [ebp-08] aggiungi offset (contatore)
:00407448 33C9                    xor ecx, ecx
:0040744A 8A08                    mov cl, byte ptr [eax] carattere corrente pwd 
:0040744C 8B45F8                  mov eax, dword ptr [ebp-08] contatore (no. d'ordine carattere)
:0040744F 99                      cdq  EDX = contatore  MOD(4)
:00407450 F77D14                  idiv [ebp+14]  cosi' l'offset della chiave sara' sempre min. di 4
:00407453 8B4510                  mov eax, dword ptr [ebp+10]  chiave
:00407456 33DB                    xor ebx, ebx
:00407458 8A1C10                  mov bl, byte ptr [eax+edx]  carattere corrente chiave
:0040745B 33CB                    xor ecx, ebx XOR CARATTERE PWD-CHIAVE
:0040745D 8B55FC                  mov edx, dword ptr [ebp-04] indirizzo base buffer in EDX
:00407460 0355F8                  add edx, dword ptr [ebp-08] base+offset (contatore)
:00407463 880A                    mov byte ptr [edx], cl memorizza carattere XORed
:00407465 EBCA                    jmp 00407431 chiudi ciclo 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00407440(C)
					ESCI
:00407467 8B45FC                  mov eax, dword ptr [ebp-04] indirizzo intermedio in EAX
:0040746A 5B                      pop ebx
:0040746B 8BE5                    mov esp, ebp
:0040746D 5D                      pop ebp
:0040746E C3                      ret

La generazione dell'intermedio avviene quindi eseguendo un OR esclusivo (XOR) tra un carattere della password ed il corrispondente carattere della chiave 'hardcoded'. Se la password � composta da un numero di caratteri maggiore di quattro (il numero di caratteri della chiave), la scansione della chiave ricomincia dall'inizio. Davvero una banalit� quindi; una banalit�, s�...ma senza la password non � possibile risalire all'intermedio.

Qualcosa da chiarire
Prima di passare all'analisi dell'algoritmo di decrittazione, resta per� ancora da chiarire un punto importante.

Quando il programma viene avviato validando una password errata, si dovrebbe ottenere il blocco del sistema, del programma, o un messaggio di errore del sistema operativo; ci� perch� il programma tenterebbe di avviare il decompattatore in .PKG, decompattatore che invece risulta inesistente (o meglio, composto da byte senza senso). Il programma invece 'sa' che la decriptazione � avvenuta in maniera errata; la domanda a questo punto �: come?

L'errore viene generato durante la chiamata a 406688 da 403B06; all'interno di questa routine il file viene rimappato (ormai �, o dovrebbe essere, decriptato) e ancora demappato. Ci� avviene con la chiamata a 4010D4 da 406715 (per questa volta sar� buona e vi risparmier� il codice); all'interno della procedura, subito dopo la mappatura del file, viene invocata una funzione, e se questa restituisce zero in EAX, il file viene demappato senza ulteriori operazioni. La procedura � questa:

HEADER CHECK

:00401000 55                      push ebp
:00401001 8BEC                    mov ebp, esp
:00401003 83EC0C                  sub esp, 0000000C
:00401006 C645F84D                mov [ebp-08], 4D M
:0040100A C645F953                mov [ebp-07], 53 S
:0040100E C645FA43                mov [ebp-06], 43 C
:00401012 C645FB46                mov [ebp-05], 46 F
:00401016 C645FC56                mov [ebp-04], 56 V
:0040101A C645FD41                mov [ebp-03], 41 A
:0040101E C645FE4C                mov [ebp-02], 4C L
:00401022 C645FF49                mov [ebp-01], 49 I
:00401026 C745F400000000          mov [ebp-0C], 00000000  contatore
:0040102D EB09                    jmp 00401038 inizia ciclo

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401058(U)
|
:0040102F 8B45F4                  mov eax, dword ptr [ebp-0C]
:00401032 83C001                  add eax, 00000001 incrementa contatore
:00401035 8945F4                  mov dword ptr [ebp-0C], eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040102D(U)
|
:00401038 837DF404                cmp dword ptr [ebp-0C], 00000004 ciclo finito?
:0040103C 7D1C                    jge 0040105A si, esci con uno in EAX 
:0040103E 8B4D08                  mov ecx, dword ptr [ebp+08] indirizzo base file mappato
:00401041 034DF4                  add ecx, dword ptr [ebp-0C]  offset (contatore)
:00401044 33D2                    xor edx, edx
:00401046 8A11                    mov dl, byte ptr [ecx] carattere ECXesimo del file in DL
:00401048 8B45F4                  mov eax, dword ptr [ebp-0C]  offset (contatore)
:0040104B 0FBE4C05F8              movsx ecx, byte ptr [ebp+eax-08] carattere di controllo
:00401050 3BD1                    cmp edx, ecx confronta
:00401052 7404                    je 00401058 chiudi il ciclo se uguale
:00401054 33C0                    xor eax, eax esci con zero in eax se diverso
:00401056 EB07                    jmp 0040105F

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401052(C)
|
:00401058 EBD5                    jmp 0040102F

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040103C(C)

:0040105A B801000000              mov eax, 00000001 OK, HEADER CORRETTAMENTE DECRIPTATO 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401056(U)
|
:0040105F 8BE5                    mov esp, ebp
:00401061 5D                      pop ebp
:00401062 C3                      ret

ci� vuol dire, in pratica, 'controlla che i primi quattro caratteri nel file decriptato siano M S C F; se non lo sono, la decriptazione non � andata a buon fine'...Beh, una tecnica diversa la potevano pure usare, cos� si scoprono da soli...NdQue

La pigrizia a questo punto � tornata a farsi sentire. Ho caricato il programma in SICE, ho inserito un bpx in 40731E, ho avviato il tutto ed inserito un password qualunque; quando � stata visualizzata la console di SICE, ho dato il comando d ebp-3c, poi ho inserito MSCF nella finestra dati ed ho premuto Ctrl-D. Dopo qualche secondo, al posto del messaggio di errore � comparso il DialogBox di Norton CrashGuard...Maledetto Norton CG, io lo odio, mi ha fatto crashare pi� lui il sistema che windows stesso, con il QueCG � tutta un'altra storia :) NdQue

PFTW stava tentando di avviare un decompattatore inesistente. Ed io ora sapevo che i primi quattro caratteri nel file correttamente decriptato sono sempre M S C F.


L'Algoritmo di Decrittazione
Scritto con le iniziali maiuscole sembra ancora pi� importante e misterioso; invece risulter� ancora pi� banale del precedente.

DECRITTA UN BYTE DEL FILE .PKG

* Referenced by a CALL at Address:
|:00407308
|
:004073CF 55                      push ebp
:004073D0 8BEC                    mov ebp, esp
:004073D2 8B4508                  mov eax, dword ptr [ebp+08] carattere da decrittare
:004073D5 25FF000000              and eax, 000000FF azzera i primi tre byte, e poi...
:004073DA 83E00F                  and eax, 0000000F ...HO nibble del byte 4 e lascia LO nibble
:004073DD C1E004                  shl eax, 04  sposta di 4 byte (un nibble) a sinistra 
:004073E0 8B4D08                  mov ecx, dword ptr [ebp+08] carattere da decrittare
:004073E3 81E1FF000000            and ecx, 000000FF azzera i primi tre byte, e poi...
:004073E9 81E1F0000000            and ecx, 000000F0 ...LO nibble del byte 4 e lascia HO nibble
:004073EF C1F904                  sar ecx, 04 sposta di 4 byte (un nibble) a destra
:004073F2 0BC1                    or eax, ecx qui  EAX=byte  con i nibble invertiti
:004073F4 884508                  mov byte ptr [ebp+08], al
:004073F7 8A5508                  mov dl, byte ptr [ebp+08]
:004073FA 32550C                  xor dl, byte ptr [ebp+0C] XOR byte-intermedio
:004073FD 885508                  mov byte ptr [ebp+08], dl e rimetti a posto
:00407400 8B4508                  mov eax, dword ptr [ebp+08]
:00407403 25FF000000              and eax, 000000FF azzera i primi tre byte, e poi... 
:00407408 F7D0                    not eax  NEGA
:0040740A 884508                  mov byte ptr [ebp+08], al e considera solo il primo byte
:0040740D 8A4508                  mov al, byte ptr [ebp+08] finalmente decriptato
:00407410 5D                      pop ebp
:00407411 C3                      ret

per coloro che non l'avessero capito, le istruzioni 4073D5-4073F4 sono l'intepretazione contorta data dal compilatore Visual C++ al concetto di 'inverti i due nibble del L.O. byte'. Una volta invertiti i nibble, viene eseguito un OR esclusivo (XOR) tra il byte da decriptare, ed il corrispondente byte dell'intermedio generato. Indi, il risultato viene negato. E per finire, viene considerato solo l'ultimo byte (cos� da scartare gli FFFF generati dalla negazione). Tutto qui.


Metodo di Vernam e Principio di Kirchoff
In realt�, la 'banalit�' degli algoritmi appena analizzati non � affatto farina del sacco di Stirling Technologies. Essi non sono altro che l'applicazione, leggermente modificata,del metodo di Vernam.

Il metodo di Vernam prende il nome dal suo ideatore, Gilbert Vernam per l'appunto, che lo utilizz� per la prime volta nel 1917. Si pu� dire che il metodo di Vernam sia uno dei cardini della crittografia moderna, ed � un esempio tipico di cifrario sequenziale sincrono.

La metodica originale era basata sull'uso di due nastri perforati di uguale lunghezza, di cui uno costituiva il testo in chiaro e l'altro la chiave, sui quali venva eseguito un OR esclusivo; un terzo nastro, sempre della stessa lunghezza, prodotto dall'operazione, costituiva il testo cifrato. Poich� l'OR esclusivo � un'operazione simmetrica, rieseguendo lo stesso XOR tra il testo cifrato e la chiave si otteneva nuovamente il testo in chiaro.

Il metodo di Vernam � considerato uno dei cardini della crittografia moderna poich� esso risulta teoricamente indecrittabile; infatti, se la chiave utilizzata � costituita da numeri casuali e possiede la stessa lunghezza del testo da cifrare, ogni informazione presente nel testo originario viene persa (poich� viene massimizzata l'entropia), e quindi non possono venire usati i metodi di attacco che si avvalgono della ricerca di sequenze ripetute. L'inviolabilit� viene meno nel caso in cui la chiave dovesse venire usata in pi� occasioni.

Il metodo di Vernam soddisfa inoltre pienamente il principio di Kerckhoffs: la sicurezza di una metodica di criptazione deve poter essere assicurata dalla segretezza della sola chiave, e non da quella dell'algoritmo usato. Il fatto di conoscere quale operazione sia stata effettuata per eseguire la cifratura non pu� cos� essere di nessun aiuto se non si conosce la chiave; la decrittazione di ogni byte richiederebbe infatti la risoluzione dell'equivalente di un'equazione con due incognite ed un solo termine noto: un'operazione matematicamente impossibile.

Un aspetto negativo del metodo di Vernam � costituito dalla lunghezza della chiave; la sua lunghezza pari a quella del testo in chiaro raddoppia infatti il numero di dati che devono venire trasmessi o conservati. I metodi escogitati per ovviare a questo inconveniente consistono nella 'creazione' matematica di chiavi della lunghezza necessaria partendo da elementi molto pi� piccoli; in pratica si usano spesso due chiavi diverse, di lunghezza l1 ed l2, dove l1 ed l2 sono due numeri che non condividono MCD; sequenze analoghe nel worm si ripresenteranno cos� con periodo l1 x l2.

Il metodo usato da PFTW � chiaramente analogo; l'operazione di XOR che esegue la criptazione/decrittazione � seguita (o preceduta) dalla negazione e dall'inversione dei nibble, mentre la chiave viene generata dalla password e dalla sequenza 13 35 86 07. Come accennavo prima, un 'Vernam modificato'. E, rispettando il Principio di Kerckhoffs, il metodo non ha soluzione.


La Password
A questo punto ho ceduto. Come si pu� ben vedere, tutte le operazioni, comprese quelle introdotte da Stirling Technologies, restano assolutamente reversibili. A partire dal risultato esatto, per�. E l'unico risultato esatto che conoscevo riguardava solo i primi quattro byte dell'header: MSCF. Troppo pochi. Cos�, ho messo da parte l'orgoglio e sono andata a riprendere la prima delle due mail ricevute dopo aver riempito il modulo, e che conteneva la password. La password era annefinch.

Ho ricaricato il programma in SICE, inserito nuovamente un bpx in 40731E, avviato il tutto ed immesso annefinch nell'EditBox; alla comparsa della console di SICE, il comando d ebp-3c ha mostrato questo:

4D 53 43 46 00 00 00 00 85 4E 5C 03 00 00 00 00 MSCF.....N\.....
2C 00 00 00 00 00 00 00 03 01 01 00 09 00 00 00	................

i primi quattro byte gi� noti, un dword uguale a zero, un dword 035C4E85 ed ancora un dword uguale a zero.

Ma io ricordavo di essermi gi� imbattuta nel valore 035C4E85, di sicuro. Era il L.O. dword restituito da GetFileSize. Ed il secondo dword era verosimilmente il dword H.O

. La situazione era radicalmente cambiata. Adesso avevo la possibilit� di risalire ad almeno dodici caratteri della password. Dopo aver posto un bpx in 407239, potevo leggere i primi quattro dword del file mappato, ancora criptato:

   0C 7F 45 BD A8 3A 71 B9 10 3C 8F 41 D9 A8 3A 71 

Il primo passo da fare � invertire i nibble di ogni byte:

C0 F7 54 DB 8A A3 17 9B 01 C3 F8 14 9D 8A A3 17 

Il secondo � negare i byte dell'header 'vero':

B2 AC BC B9 FF FF FF FF 7A B1 A3 FC FF FF FF FF 

Il terzo eseguire un XOR tra i byte corrispondenti dei due gruppi:


C0 F7 54 DB 8A A3 17 9B 01 C3 F8 14 9D 8A A3 17


XOR


B2 AC BC B9 FF FF FF FF 7A B1 A3 FC FF FF FF FF

=

72 5B E8 62 75 5C E8 64 7B 72 5B E8 62 75 5C E8


infine si esegue un altro XOR tra il risultato e la chiave 13 35 86 07:

72 5B E8 62 75 5C E8 64 7B 72 5B E8 62 75 5C E8


XOR


13 35 86 07 13 35 86 07 13 35 86 07 13 35 86 07

=

61 6E 6E 65 66 69 6E 63 68 47 DD EF 71 40 DA EF

a  n  n  e  f  i  n  c  h   -  -  -  -  -  -  -



Da notare che la lunghezza della password pu� venire ricavata dalla periodicit� delle cifre nell'intermedio e non nel risultato del calcolo finale. Infatti l'intermedio ha una periodicit� uguale alla lunghezza della password, mentre la chiave ha una lunghezza fissa di quattro byte; pertanto, se la password non ha una lunghezza di quattro (o di un multiplo di quattro) caratteri, la periodicit� viene persa.


La Conferma
Bene, adesso ci occorrerebbe una conferma. Prima per� riepiloghiamo le operazioni da compiere:

1) Patchare il programma in modo da abilitare perennemente il pulsante
2) Caricare il programma in SICE
3) Bpx 4071F4 -> eax = L.O. dword di filesize
4) Bpx 407239 -> d eax -> header file nella finestra dati
5) Calcolare il NOT di MSCF + 00000000 + lunghezza file (rilevata a 4071F4)
6) Invertire i nibble di ogni byte dell'header letto in corrispondenza di bpx 407239
7) Calcolare l'OR esclusivo tra i due
8) Calcolare l'OR esclusivo tra il risultato e la chiave 13 35 86 07

Adesso scarichiamo, ad esempio, la versione FULL dell'ultima versione di PFTW dal sito FTP di InstallShield (non vi dir� come fare perch� non sarebbe giusto, e poi lo sapete tutti J). Il L.O. dword della lunghezza del file .PKG risulta 00 2B 4A 29; l'header del file criptato � 5F CE 75 CD 08 FA E0 D9 0A 4E 39 FB. Allora invertendo i nibble in ogni byte dell'header del file mappato si ottiene:

   F5 EC 57 DC 80 AF 0E 9D A0 E4 93 FB    
  
  invece i byte dell'header decriptato, negati, valgono:   
B2 AC BC B9 FF FF FF FF D6 B5 D4 FF 
   
  ed il primo XOR � allora: 
     47 40 EB 65 7F 50 F1 62 76 51 47 40 

Come � facile verificare, la password � lunga 10 caratteri; ed i caratteri sono:
 
47 40 EB 65 7F 50 F1 62 76 51

XOR

13 35 86 07 13 35 86 07 13 35

54 75 6D 62 6C 65 77 65 65 64
T  u   m   b    l    e    w  e   e   d
     
Verificando l'header generato da questo file  PFTW (e da altri ancora J), � possibile verificare, infine, come vi
sia la possibilit� di ricostruire password anche pi� lunghe di dodici caratteri, in quanto i tre successivi dword sono sempre 00 00 00 00 2C 00 00 00 00 00 00 00. Le password fino a 24 caratteri non hanno pi� segreti per noi (almeno fin quando Stirling Technologies non verr� a conoscenza di tutto ci�)!             
Note finali
Per la verit�, l'idea non era niente male. L'uso della funzione hash per la convalida della password, ma con una grande probabilit� di collisione, rende estremamente difficoltoso il brute force attack. E l'applicazione di una variante del metodo di Vernam per la decriptazione continua ad essere un principio valido; intendo dire, con questo, che il fatto che un'Alga qualunque sia riuscita ad aggirarlo non significa niente. O meglio, significa solo che l'applicazione del principio ha presentato punti deboli. Uno di questi � senza dubbio il fatto che una delle due chiavi per la generazione dell'intermedio � contenuta nel programma, ed in chiaro. Se si fossero utilizzate due password (una password ed un numero di serie, ad esempio), l'aggiramento della protezione sarebbe stato pi� complicato, e non sarebbe stato comunque possibile risalire alle password. Peraltro i rimanenti aspetti dell'applicazione del principio sembrano corretti. La chiave di quattro cifre e la password non presentano divisori comuni (possono essere usate password da nove o undici caratteri); e d'altra parte la ricerca di corrispondenze tra le periodicit� della chiave ed eventuali periodicit� nel file criptato (uno dei possibili attacchi alle varianti del metodo di Vernam che usano chiavi di lunghezza minore di quella della sequenza da criptare) sarebbe comunque problematica in un file mappato in memoria, ed i cui contenuti in chiaro non siano costituiti da testo.

Qualche volenteroso potrebbe scrivere qualcosa che automatizzi l'intera procedura di determinazione delle password, e funzioni quindi da Password Exctractor; per questo comunque non contate su di me , perch� mi sono realmente scocciata di questo stupido Package For The Web!!!

Per quanto riguarda l'InstallShield 6.0, ho (purtroppo)...Ma per fortuna per loro NdQue trovato la conferma alle mie supposizioni. Infatti Stirling Technologies, oltre a variare ancora il formato .CAB, ha apportato radicali modifiche alla struttura del compilatore, con il risultato che i vecchi, cari, file .INS non esistono pi�, ed al loro posto sono comparsi dei file .INX, che per�, ad un'analisi superficiale almeno, sembrano differire notevolmente dai loro predecessori (chiss� cosa ne pensa fOSSiL!). Inoltre, anche il metodo di protezione della trial version � di tutt'altra natura, in quanto le ridicole protezioni delle versioni precedenti sono state sostituite dalla pi� efficace InterLok (questi qui di InterLok s� mi stanno realmente antipatici! Appena avr� un po' pi� di tempo dovr� affrontare il problema alla base, perch� realmente non li sopporto! Spero che qualcuno mi aiuti...). Come dicevo in apertura, dobbiamo prepararci a tempi duri, in cui criptologia e packing costituiranno il nostro pane quotidiano. I tempi di compara input con password - salta se non sono uguali - altrimenti metti 1 in EAX sembrano lontani migliaia di anni...Chiss� se la legge di Moore � applicabile anche alla difficolt� delle protezioni, che ne dici Olga? :) NdQue

Infine, mi scuso per la prolissit� e per la pedanteria, ma cerco di illustrare minuziosamente ogni cosa. Se infatti scrivo qualcosa, non lo faccio per sentire altri che dicono "ma quant'� brava 'sta ragazza", ma per mettere a disposizione di altri quello che � stato il mio processo mentale (cos� come ho spesso avuto a mia disposizione quello di altri). Perch� quello che conta, alla fine, � solo il principio che ha ispirato il ragionamento; le password di Package For The Web cambieranno altre mille volte nei prossimi anni, mentre un ragionamento � come un diamante: � per sempre (bleah!).

Bene, qui finiva il tutorial originale; una settimana dopo compariva in giro il Password Extractor di fOSSiL relativo a questa versione, e cos� questo lavoro perdeva di importanza pratica. Se, come accenno in conclusione, un valore � conservato, esso risiede nel processo (sia "tecnico", sia mentale) che ha condotto alla soluzione, ed i cui principi generali potranno venire riapplicati, nel fatto che non � stato illustrato come disattivare efficacemente una protezione, ma come fare il reversing dello schema della protezione stessa; tuttavia, il giudizio ultimo in tal senso non pu� che spettare a Quequero. E questo non tanto perch� � il proprietario del sito (cosa che comunque ha anche la sua importanza J), quanto per l'impegno profuso nel mantenere il sito, impegno fatto di attenzione (legge davvero tutti i tutorial che gli vengono inviati!) e di competenza (pubblico tributo relativo all'ultimo tut su SEH). Non posso inoltre che essergli grata poich�, anzich� spazientirsi leggendo le ...zate che scrivo negli spazi riservati sul form a cose serie (ad es. "Difficolt�) o nel testo dei tutorial, mi elargisce (immeritate) lodi. Ciao Quequzzo.
Non � affatto vero che le mie lodi sono immeritate, tutt'altro, secondo me sono anche troppo poche rispetto al lavoro che ti addossi ogni qualvolta scrivi un tute, inoltre conosci bene la stima che ho nei tuoi confronti e che mi fa sentire sempre fiero di poter ospitare un tuo tutorial sul mio sito. E poi avevi qualche dubbio sul fatto che leggessi tutti i tutorial? :P ciauz Alguzza NdQue

Disclaimer

Bene, per una volta, ho la coscienza a posto. Infatti:

- non ho sprotetto alcun programma commerciale
- l'argomento ha riguardato un prodotto non pi� in vendita
- Stirling Technologies ha finalmente abolito il sito FTP al quale accedevano tutti, scaricando quello che volevano
- il Password Extractor di fOSSiL si trova dappertutto

quindi:

se troverete in giro un'applicazione in formato PFTW 2.1 protetta da password, la aprirete e la userete illegalmente per tutta la vita non sar� certo colpa mia
J