CRITTOGRAFIA SPICCIOLA E TUTORIAL BANALI |
|
|
28/10/1999 |
by Alga |
|
|
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.
Introduzione |
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 |
Notizie sul programma |
Essay |
* 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
C0 F7 54 DB 8A A3 17 9B 01 C3 F8 14 9D 8A A3 17
B2 AC BC B9 FF FF FF FF 7A B1 A3 FC FF FF FF FF
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
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:
|
Disclaimer |