Keygen EMU8086
From UIC
Keygen EMU8086
Contents |
| Keygen EMU8086 | |
|---|---|
| Author: | Andrew10111989 |
| Email: | none |
| Website: | none |
| Date: | 12/06/2010 (dd/mm/yyyy) |
| Level: |
|
| Language: | Italian |
| Comments: | |
Tools
Link e Riferimenti
Introduzione
In questo tutorial proveremo a creare un keygen per un compilatore assembly, è un ottimo programma, gira tranquillamente su Seven e ha un aspetto molto più user-friendly dei vari tasm, masm, ecc… si chiama emu8086 (versione 4.08) e presenta un limite di utilizzo di 14 giorni. Questo non è un tutorial ASM né tantomeno di ollydbg, dovete essere ben preparati su questi due argomenti perché molte cose le prenderò per scontate…
Essay
Una volta avviato il programma presenta un nag-screen con al centro un grosso pulsante per effettuare la registrazione, clicchiamoci sopra e vediamo apparire un form di registrazione con due campi; Nome Licenza e Chiave di Registrazione. Proviamo a mettere dei dati casuali, tipo Andrew e 111222333444, click su OK e una finestra ci avvisa che il codice inserito non è corretto ( non ci speravamo più di tanto alla fine ^^ ). Bene, prima di attaccare con le maniere forti il programma in questione, diamo un’ occhiata al PEiD, l’ eseguibile risulta essere compilato in Microsoft Visual Basic 5.0/6.0 ( un compilatore ASM scritto in VB lol :P ), questo come vedremo sarà un punto a nostro favore perché le funzioni matematiche, logiche, e di manipolazione delle stringhe verranno tutte richiamate dalla DLL MSVBVM60, e i loro nomi saranno abbastanza espliciti per capire a cosa servono… Ok, ora che abbiamo qualche info in più apriamo il caro olly ( io userò la versione 1.10 ), proviamo a lanciare l’eseguibile emu8086 ma c’è qualcosa che non va, il debugger si blocca, e il programma non vuole saperne di avviarsi! No problem, chiudiamo olly, eseguiamo emu8086, apriamo la finestra di registrazione, quindi riapriamo olly e dal menu File->Attach selezioniamo il processo (C:\emu8086\emu8086.exe nel mio caso), F9 o Run, e siamo pronti per davvero… A questo punto proviamo a settare qualche bps, da Command Line provo il mio preferito, bp GetWindowTextA, Nome:Andrew Key:111222333444 ( per ora mettete solo caratteri, niente numeri o altri simboli, anzi se inserite anche voi Andrew rendete il tutto più semplice ), click su OK, e voilà eccoci nella nostra USER32.GetWindowTextA, facciamo qualche colpo di ctrl-F9 ed F8 per steppare velocemente le chiamate fra la libreria di VB (MSVBVM60) e la User32, ad un certo punto finalmente rientriamo nel modulo emu8086, precisamente all’ indirizzo-istruzione
A questo punto steppiamo velocemente con F8 vedendo scorrere nello stack i nostri dati inseriti nel form, arriviamo senza troppi se e ma fino all’ indirizzo
Dopo questa call ci sono due mov, un test e un salto condizionato, provando a steppare fino al salto vedremo da olly che Jump is Taken, un gran peccato perché proprio sotto avevamo il codice che stampava:
Mentre con questo salto finiamo a
005D939B . BA 480A4500 MOV EDX,emu8086.00450A48 ; UNICODE "wrong registration key."
Bene abbiamo capito che in quella call avviene ciò che fa la differenza fra giusto e sbagliato, bene o male, registrato o fottuto . Alt-B e togliamo il bp al GetWindowTextA, impostiamone invece uno all’ indirizzo 005D8E26, quindi continuiamo l’esecuzione del programma con F9, OK sulla finestra di errore e di nuovo l’OK alla registrazione. Ora se tutto è andato bene siamo di nuovo in
Questa volta con F7 entriamo nella chiamata e vediamo che succede… Prima di arrivare al punto critico abbiamo una miriade di istruzioni che copiano qua e là i nostri dati, non sembrano istruzioni che facciano calcoli o algoritmi, quindi semplicemente controlliamo ogni qual volta viene eseguita una call che non sia una funzione della MSVBVM60 per vedere se succede qualcosa di strano… Per motivi spazio-temporali vi indico subito che il nostro obiettivo è situato in
Ricordiamo anche questo indirizzo, una volta arrivati qui infatti prima di entrare nella chiamata proviamo ad eseguire con F8 lo step successivo, e date un’ occhiata alla Stack window… Beh interessante, il nostro ESP punta a
Ma salendo su, quindi scendendo come indirizzi guarda un po’ cosa esce…
Non fate quello che state pensando di fare!!! Non vorrete rovinarvi tutto il bello vero :D ???!! Ebbene si ragazzi, quello non è nient’ altro che il nostro seriale scritto in chiaro nello Stack! Non male come fishing eh? Per il momento fidatevi che è il seriale giusto ( se avete messo come nome Andrew ), non provatelo altrimenti registrate il programma e addio KeyGen … E’ chiaro che dentro quella call avvengano processi interessanti… Togliamo tutti i bps, e impostiamone uno solo su 005DA697, di nuovo eseguiamo il programma, rifacciamo OK sul form di registrazione ed eccoci sulla call incriminata. Questa volta F7 e arriviamo in un’altra sezione di codice, nemmeno qui si nota nulla di interessante, a colpi di F8 vediamo di capire quando viene generato questo benedetto seriale, cascata di F8 fino a
Dopo questa chiamata spunta il nostro seriale nello Stack, siamo di nuovo al punto giusto, ci siamo quasi non vi angosciate :D , solita formula: via tutti i bps, bp su 005DAA36 , Run, quindi di nuovo OK e siamo su 005DAA36, F7 per entrarci, e vediamo un po’ che succede:
.
.
.
005DAB41 . C745 FC 020000>MOV DWORD PTR SS:[EBP-4],2
005DAB48 . 6A FF PUSH -1
005DAB4A . FF15 F8104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaOnErr>; MSVBVM60.__vbaOnError
005DAB50 . C745 FC 030000>MOV DWORD PTR SS:[EBP-4],3
005DAB57 . BA A40C4500 MOV EDX,emu8086.00450CA4 ; UNICODE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
005DAB5C . 8D4D A4 LEA ECX,DWORD PTR SS:[EBP-5C]
005DAB5F . FF15 28134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCo>; MSVBVM60.__vbaStrCopy
005DAB65 . C745 FC 040000>MOV DWORD PTR SS:[EBP-4],4
005DAB6C . BA E00C4500 MOV EDX,emu8086.00450CE0 ; UNICODE "QW10PASDFGHJKLZXCVBNMERTYU"
005DAB71 . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
005DAB74 . FF15 28134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCo>; MSVBVM60.__vbaStrCopy
005DAB7A . C745 FC 050000>MOV DWORD PTR SS:[EBP-4],5
005DAB81 . BA 1C0D4500 MOV EDX,emu8086.00450D1C ; UNICODE "Z9RTASDF01823ASJFSD1234346GFHPLMASDR613412QWERX"
005DAB86 . 8D4D D4 LEA ECX,DWORD PTR SS:[EBP-2C]
005DAB89 . FF15 28134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCo>; MSVBVM60.__vbaStrCopy
005DAB8F . C745 FC 060000>MOV DWORD PTR SS:[EBP-4],6
005DAB96 . BA 800D4500 MOV EDX,emu8086.00450D80 ; UNICODE "JKASERKKN837C3FRTQZX"
005DAB9B . 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-50]
005DAB9E . FF15 28134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrCo>; MSVBVM60.__vbaStrCopy
Caspita la situazione si fa interessante, mettevi comodi, chi deve andare in bagno lo faccia ora, armatevi di birra e patatine, coca e pop corn o nachos, perchè inizia lo spettacolo :P Come prima cosa vi consiglio di fare tasto destro sullo Stack e selezionare “Lock stack”, in questo modo potete evitare lo scorrimento dello stack ogni volta che il codice chiama una push o una pop e concentrare l’attenzione invece sulla parte di stack subito sopra l’indirizzo puntato da EBP…
0012D8BC 72A26C30 MSVBVM60.__vbaStrMove
0012D8C0 7294A296 MSVBVM60.__vbaInStr
0012D8C4 00000000
0012D8C8 00000000
0012D8CC 00000000
0012D8D0 00000000
0012D8D4 00000000
0012D8D8 00000000
0012D8DC 00000000
0012D8E0 00000000
0012D8E4 00000000
0012D8E8 00000000
0012D8EC 00000000
0012D8F0 00000000
0012D8F4 00000000
0012D8F8 00000000
0012D8FC 00000000
0012D900 00000000
0012D904 00004008
0012D908 00000000
0012D90C 0012D968 ASCII "LP5"
0012D910 00000000
0012D914 00000000
0012D918 00000000
0012D91C 00000000
0012D920 00000000
0012D924 00000000
0012D928 00000000
0012D92C 00000000
0012D930 00000000
0012D934 00000000
0012D938 00000000
0012D93C 00000000
0012D940 00000000
0012D944 0036B7A4 UNICODE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
0012D948 00000000
0012D94C 00000000
0012D950 0036B834 UNICODE "JKASERKKN837C3FRTQZX"
0012D954 00354FAC
0012D958 00000000
0012D95C 00000000
0012D960 00000000
0012D964 00000000
0012D968 0035504C UNICODE "Andrew"
0012D96C 00000000
0012D970 00000000
0012D974 0032A12C UNICODE "Z9RTASDF01823ASJFSD1234346GFHPLMASDR613412QWERX"
0012D978 0036B7EC UNICODE "QW10PASDFGHJKLZXCVBNMERTYU"
0012D97C 00000000
0012D980 0012DA34 Pointer to next SEH record
0012D984 004199B6 SE handler
0012D988 0012D8BC
0012D98C 00415AE8 emu8086.00415AE8
0012D990 00000000
0012D994 FFFFFFFF
0012D998 00000020
0012D99C 00000008
0012D9A0 /0012DA54 --------------------------------------------------------------------->EBP
0012D9A4 |005DAA3B RETURN to emu8086.005DAA3B from emu8086.005DAAF0
Questo print dello Stack l’ ho effettuato con il debugger fermo all’indirizzo
Da adesso in poi:
Con Buffer1 intenderò la stringa: Z9RTASDF01823ASJFSD1234346GFHPLMASDR613412QWERX ( 0012D974 nello stack )
Con Buffer2 la stringa: QW10PASDFGHJKLZXCVBNMERTYU ( 0012D978 nello stack )
Con Buffer3 la stringa: JKASERKKN837C3FRTQZX ( 0012D950 nello stack )
Nelle chiamate precedenti quelle belle stringhe sono state copiate da qualche parte in memoria, e nello Stack sono stati salvati gli indirizzi di memoria, vediamo ora di commentare il pezzo di codice successivo:
005DABE4 . 8D45 94 LEA EAX,DWORD PTR SS:[EBP-6C]
005DABE7 . 50 PUSH EAX
005DABE8 . FF15 38104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrVa>
005DABEE . 8BD0 MOV EDX,EAX
005DABF0 . 8D4D A8 LEA ECX,DWORD PTR SS:[EBP-58]
005DABF3 . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DABF9 . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DABFC . FF15 34104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeV>
005DAC02 . C745 FC 090000>MOV DWORD PTR SS:[EBP-4],9
005DAC09 . 8D4D A8 LEA ECX,DWORD PTR SS:[EBP-58]
005DAC0C . 51 PUSH ECX
005DAC0D . E8 1EDCF6FF CALL emu8086.00548830 ;ANDREW = WERDNA
005DAC12 . 8BD0 MOV EDX,EAX
005DAC14 . 8D4D A8 LEA ECX,DWORD PTR SS:[EBP-58]
005DAC17 . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DAC1D . C745 FC 0A0000>MOV DWORD PTR SS:[EBP-4],0A
005DAC24 . 66:C745 DC 010>MOV WORD PTR SS:[EBP-24],1
005DAC2A . C745 FC 0B0000>MOV DWORD PTR SS:[EBP-4],0B
005DAC31 . 66:C745 CC 010>MOV WORD PTR SS:[EBP-34],1
005DAC37 . C745 FC 0C0000>MOV DWORD PTR SS:[EBP-4],0C
005DAC3E . 66:C745 AC 000>MOV WORD PTR SS:[EBP-54],0 ;seta [EBP-54] a 1
I punti salienti sono:
005DABDE -> rtcUpperCaseVar Prende il nome inserito ed esegue l’uppercase dei caratteri, cioè li imposta tutti in maiuscolo, quindi Andrew = ANDREW.
005DAC12 -> questa call inverte il nome in maiuscolo, quindi ANDREW = WERDNA.
005DAC3E -> questa è una variabile booleana che vedremo cambiare valore da 0 a 1, ora è settata a 1.
Bene in questi primi passi sembra proprio che voglia manipolare la nostra stringa, da adesso inizia l’algoritmo principale di creazione del seriale, vediamo le prossime istruzioni:
005DAC4B . 0FBF75 DC MOVSX ESI,WORD PTR SS:[EBP-24] ;[EBP-24] contiene l’indice dove prelevare
005DAC4F . 8B55 A8 MOV EDX,DWORD PTR SS:[EBP-58] ;il prossimo carattere del nome inserito
005DAC52 . 52 PUSH EDX ;mette nello stack il puntatore a WERDNA
005DAC53 . FF15 3C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaLenBs>;richiama la funzione vb per la lunghezza di una stringa
005DAC59 . 33DB XOR EBX,EBX ;azzera EBX
005DAC5B . 3BF0 CMP ESI,EAX ;confronta ESI = 1 con EAX = 6
005DAC5D . 0F9FC3 SETG BL ;setta BL a 1 se ESI > EAX
005DAC60 . 0FBF75 CC MOVSX ESI,WORD PTR SS:[EBP-34] ;[EBP-34] contiene l’indice del prossimo
005DAC64 . 8B45 B0 MOV EAX,DWORD PTR SS:[EBP-50] ;carattere che devo scrivere
005DAC67 . 50 PUSH EAX ;pusho nello stack il puntatore a Buffer3
005DAC68 . FF15 3C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaLenBs>;richiama la funzione vb per la lunghezza di una stringa
005DAC6E . 33C9 XOR ECX,ECX ;azzero ECX
005DAC70 . 3BF0 CMP ESI,EAX ;confronto ESI = 1 con EAX = 20
005DAC72 . 0F9FC1 SETG CL ;setto CL a 1 se ESI > EAX
005DAC75 . 0BD9 OR EBX,ECX ;basta che uno fra BL e CL sia settato
005DAC77 . 85DB TEST EBX,EBX ;a 1 per terminare questa fase di algoritmo
005DAC79 . 0F85 E6020000 JNZ emu8086.005DAF65 ;salto se ho terminato
005DAC7F . C745 FC 0E0000>MOV DWORD PTR SS:[EBP-4],0E
005DAC86 . 8B55 A4 MOV EDX,DWORD PTR SS:[EBP-5C]
005DAC89 . 8995 4CFFFFFF MOV DWORD PTR SS:[EBP-B4],EDX
005DAC8F . C785 44FFFFFF >MOV DWORD PTR SS:[EBP-BC],8
005DAC99 . C745 9C 010000>MOV DWORD PTR SS:[EBP-64],1
005DACA0 . C745 94 020000>MOV DWORD PTR SS:[EBP-6C],2
005DACA7 . 8D45 A8 LEA EAX,DWORD PTR SS:[EBP-58]
005DACAA . 8985 6CFFFFFF MOV DWORD PTR SS:[EBP-94],EAX
005DACB0 . C785 64FFFFFF >MOV DWORD PTR SS:[EBP-9C],4008
005DACBA . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DACBD . 51 PUSH ECX
005DACBE . 0FBF55 DC MOVSX EDX,WORD PTR SS:[EBP-24] ;metto in EDX l’ indice del carattere da
005DACC2 . 52 PUSH EDX ;estrarre dal nome WERDNA e lo pusho
005DACC3 . 8D85 64FFFFFF LEA EAX,DWORD PTR SS:[EBP-9C]
005DACC9 . 50 PUSH EAX ;pusho nello stack il puntatore al nome WERDNA
005DACCA . 8D4D 84 LEA ECX,DWORD PTR SS:[EBP-7C]
005DACCD . 51 PUSH ECX
005DACCE . FF15 70114000 CALL DWORD PTR DS:[<&MSVBVM60.#632>] ;salva l'n-simo carattere della stringa
005DACD4 . 6A 01 PUSH 1 ; nell' indirizzo di memoria puntato in 0012D92C
005DACD6 . 8D95 44FFFFFF LEA EDX,DWORD PTR SS:[EBP-BC]
005DACDC . 52 PUSH EDX
005DACDD . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DACE0 . 50 PUSH EAX
005DACE1 . 6A 00 PUSH 0
005DACE3 . 8D8D 74FFFFFF LEA ECX,DWORD PTR SS:[EBP-8C]
005DACE9 . 51 PUSH ECX
005DACEA . FF15 B8124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaInStr> ;salva la posizione dell' n-simo carattere
005DACF0 . 50 PUSH EAX ; nell' alfabeto in ecx (W = 23 = 17h), quindi lo salva in 0012D91C
005DACF1 . FF15 DC124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaI2Var>;
005DACF7 . 66:8945 D0 MOV WORD PTR SS:[EBP-30],AX
005DACFB . 8D95 74FFFFFF LEA EDX,DWORD PTR SS:[EBP-8C]
005DAD01 . 52 PUSH EDX
005DAD02 . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DAD05 . 50 PUSH EAX
005DAD06 . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DAD09 . 51 PUSH ECX
005DAD0A . 6A 03 PUSH 3
005DAD0C . FF15 50104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeV>; MSVBVM60.__vbaFreeVarList
005DAD12 . 83C4 10 ADD ESP,10
005DAD15 . C745 FC 0F0000>MOV DWORD PTR SS:[EBP-4],0F
005DAD1C . 66:837D D0 00 CMP WORD PTR SS:[EBP-30],0 ;confronta la posizione del primo carattere
005DAD21 . 0F8E DB010000 JLE emu8086.005DAF02 ;(per w = 23d = 17h) con 0, salta se è minore o uguale
005DAD27 . C745 FC 100000>MOV DWORD PTR SS:[EBP-4],10 ;quindi salta se non è una lettera dell’alfabeto!
005DAD2E . 66:837D AC 01 CMP WORD PTR SS:[EBP-54],1 ;confronta [EBP-54] con 1, salta se è diversa.
005DAD33 . 0F85 AB000000 JNZ emu8086.005DADE4
005DAC44 -> questo indirizzo è importante perchè il ciclo che esegue l’algortimo di codifica ricomincia sempre da questo indirizzo. 005DAC4B -> il valore nello Stack a
Viene salvato in ESI.
005DAC4F -> copio l’indirizzo che contiene il nome manipolato in EDX.
005DAC53 -> viene richiamata la funzione vbaBStrLen, e prima viene pushato l’indirizzo di WERDNA, il vostro nome manipolato, indovinate cosa fa questa funzione? Bravi, calcola la lunghezza della stringa e salva il valore in EAX.
Nelle istruzioni successive avviene il confronto fra ESI (1) e EAX (6) che setta BL a 1 se ESI > EAX, quindi esegue la stessa operazione considerando come stringa il Buffer3 ( se non sapete a cosa mi riferisco non siete stati attenti, tornate su! ) , EAX = 14h = 20 ( la lunghezza della stringa ) e riesegue il compare fra ESI ed EAX, in questo caso setta CL a 1 se ESI > EAX, a questo punto fa l’OR fra BL e CL. Quindi TEST EBX,EBX e JNZ. Che significa in altre parole questa porzione di codice? In pratica se la lunghezza del seriale che sto scrivendo ( e vedremo dopo come ) è maggiore della lunghezza del mio nome (WERDNA = 6) oppure del Buffer3 ( = 20) finisce un certo algoritmo ed eventualmente si effettuano altre operazioni. Per farla breve, se avete inserito un nome lungo più di 20 caratteri, tronca l’algoritmo ai primi 20, mentre se è minore di 20, esegue un certo algoritmo sui caratteri del nome, e poi effettua un’ altra operazione che vedremo dopo. Ora dobbiamo capire cosa succede in questo ciclo.
Siamo arrivati a 005DAC79, per ora non si salta, quindi scendiamo in 005DACCE. Qui si richiama un’ altra funzione di VB, la Mid() o rctMidCharVar che restituisce una sottostringa a una data stringa specificando carattere di partenza e lunghezza. Non è proprio immediato capire come funziona questa funzione, e naturalmente non è nell’ interesse di Microsoft spiegare come operano le funzioni della MSVBVM60.dll, prima di chiamare la funzione però si pushano dei dati interessanti come
Che pusha nello stack il valore di edx che è 1, quindi la nostra sottostringa avrà inizio a partire dal primo carattere della stringa sorgente.
Facciamo una piccola forzatura e andiamo uno step avanti dopo la funzione Mid, ora in EAX abbiamo un indirizzo stack, 0012D924, a questo indirizzo dobbiamo aggiungere 8 byte, arriviamo a 0012D92C , questo indirizzo stack contiene un indirizzo di memoria, tasto destro su quest’ ultimo, “Follow in Dump” e nella finestra accanto troviamo che a quell’ indirizzo è salvata la W, ovvero il primo carattere della stringa WERDNA! Se vi chiedete come facevo a saperlo provate a chiedere a google cosa ne pensa della rctMidCharVar ;-) . Abbiamo capito che a ogni ciclo viene selezionato un carattere del nostro nome manipolato. Ma cosa ne fa l’algoritmo di questo carattere? Proseguiamo nella lettura del codice.
005DACEA -> ecco un’altra funzione di VB, la vbaInStrVar che prende in ingresso una stringa sorgente, una di destinazione, e dà in output l’indice della posizione della prima stringa nella seconda, se è presente, se no restituisce 0. Quali stringhe vengono passate alla funzione? Due indirizzi di Stack, uno molto prossimo alla stringa Alfabeto, e uno che contiene l’indirizzo della nostra lettera W … Risultato dell’operazione? Leggiamo ECX = 17h = 23, ovvero la posizione di W nell’ alfabeto! Bene le cose iniziano a farsi più chiare… Cosa se ne fa l’algoritmo di questo indice? Intanto lo salva in
Quindi a 005DAD1C confronta 17 con 0, e a 005DAD21 salta se 17 <= 0, OVVERO SE IL CARATTERE INSERITO NON E’ PRESENTE NELL’ALFABETO, QUINDI NON E’ UNA LETTERA! Questo è molto importante, perché come vedremo l’introduzione di numeri o altri simboli comporteranno piccole modifiche all’ algoritmo… W è presente nell’ alfabeto, quindi continuiamo nella discesa fino a 005DAD33 attraverso cui, dopo aver confrontato un indirizzo nello stack con 1, saltiamo a
005DADEB . 8B55 B4 MOV EDX,DWORD PTR SS:[EBP-4C]
005DADEE . 8995 4CFFFFFF MOV DWORD PTR SS:[EBP-B4],EDX
005DADF4 . C785 44FFFFFF >MOV DWORD PTR SS:[EBP-BC],8
005DADFE . C745 9C 010000>MOV DWORD PTR SS:[EBP-64],1
005DAE05 . C745 94 020000>MOV DWORD PTR SS:[EBP-6C],2
005DAE0C . 8D45 D4 LEA EAX,DWORD PTR SS:[EBP-2C]
005DAE0F . 8985 6CFFFFFF MOV DWORD PTR SS:[EBP-94],EAX
005DAE15 . C785 64FFFFFF >MOV DWORD PTR SS:[EBP-9C],4008
005DAE1F . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DAE22 . 51 PUSH ECX
005DAE23 . 0FBF55 D0 MOVSX EDX,WORD PTR SS:[EBP-30] ;pusha la posizione del carattere nell’alfabeto
005DAE27 . 52 PUSH EDX ;trovata prima con la InStr
005DAE28 . 8D85 64FFFFFF LEA EAX,DWORD PTR SS:[EBP-9C] ;pusha il puntatore al Buffer1 dal quale prelevare
005DAE2E . 50 PUSH EAX ;il carattere
005DAE2F . 8D4D 84 LEA ECX,DWORD PTR SS:[EBP-7C]
005DAE32 . 51 PUSH ECX
005DAE33 . FF15 70114000 CALL DWORD PTR DS:[<&MSVBVM60.#632>] ;seleziona il carattere in posizione pushata
005DAE39 . 8D95 44FFFFFF LEA EDX,DWORD PTR SS:[EBP-BC] ;dal Buffer1 di caratteri
005DAE3F . 52 PUSH EDX
005DAE40 . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DAE43 . 50 PUSH EAX
005DAE44 . 8D8D 74FFFFFF LEA ECX,DWORD PTR SS:[EBP-8C]
005DAE4A . 51 PUSH ECX
005DAE4B . FF15 D0124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCa>
005DAE51 . 50 PUSH EAX
005DAE52 . FF15 38104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrVa>
005DAE58 . 8BD0 MOV EDX,EAX
005DAE5A . 8D4D B4 LEA ECX,DWORD PTR SS:[EBP-4C]
005DAE5D . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DAE63 . 8D95 74FFFFFF LEA EDX,DWORD PTR SS:[EBP-8C]
005DAE69 . 52 PUSH EDX
005DAE6A . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DAE6D . 50 PUSH EAX
005DAE6E . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DAE71 . 51 PUSH ECX
005DAE72 . 6A 03 PUSH 3
005DAE74 . FF15 50104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeV>
005DAE7A . 83C4 10 ADD ESP,10
005DAE7D . C745 FC 150000>MOV DWORD PTR SS:[EBP-4],15
005DAE84 . 66:C745 AC 010>MOV WORD PTR SS:[EBP-54],1 ;setto [EBP-54] a 1, quindi ruoterò il Buffer2 2 volte
005DAE8A > C745 FC 170000>MOV DWORD PTR SS:[EBP-4],17 ;e il prossimo carattere sarà selezionato dal Buffer1
005DAE91 . 66:8B55 CC MOV DX,WORD PTR SS:[EBP-34] ;incremento [EBP-34] perchè ho scritto
005DAE95 . 66:83C2 01 ADD DX,1 ;il carattere
005DAE99 . 0F80 DD020000 JO emu8086.005DB17C
005DAE9F . 66:8955 CC MOV WORD PTR SS:[EBP-34],DX
005DAEA3 . C745 FC 180000>MOV DWORD PTR SS:[EBP-4],18
La prossima funzione che incontriamo è 005DAE33, un’altra Mid(), che parametri passa questa volta? Posizionandoci sulla funzione vediamo che nello stack, pushando da EDX c’è il valore 17h, ma da quale stringa seleziona il carattere? Iniziate a capire vero? Eseguiamo uno step con F8. In EAX abbiamo 0012D924, quindi sommando 8…
Cosa c’è a quest’ indirizzo?
Un 4… Qual’ è il 17h ovvero 23° carattere del Buffer1?? Un 4! Bene, le cose iniziano a farsi più chiare, abbiamo scoperto che il primo carattere calcolato è un 4, cosa succede adesso? Ora inizia la fase di rotazione delle stringhe di Buffer…
005DAEAD . 50 PUSH EAX
005DAEAE . E8 DD020000 CALL emu8086.005DB190 ;ruota il Buffer2
005DAEB3 . 8BD0 MOV EDX,EAX
005DAEB5 . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
005DAEB8 . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DAEBE . C745 FC 190000>MOV DWORD PTR SS:[EBP-4],19
005DAEC5 . 8D4D D4 LEA ECX,DWORD PTR SS:[EBP-2C]
005DAEC8 . 51 PUSH ECX
005DAEC9 . E8 C2020000 CALL emu8086.005DB190 ;ruota il Buffer1
005DAECE . 8BD0 MOV EDX,EAX
005DAED0 . 8D4D D4 LEA ECX,DWORD PTR SS:[EBP-2C]
005DAED3 . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DAED9 . C745 FC 1A0000>MOV DWORD PTR SS:[EBP-4],1A
005DAEE0 . 66:837D AC 01 CMP WORD PTR SS:[EBP-54],1
005DAEE5 . 75 1B JNZ SHORT emu8086.005DAF02
005DAEE7 . C745 FC 1B0000>MOV DWORD PTR SS:[EBP-4],1B
005DAEEE . 8D55 D8 LEA EDX,DWORD PTR SS:[EBP-28]
005DAEF1 . 52 PUSH EDX
005DAEF2 . E8 99020000 CALL emu8086.005DB190 ;ruota il Buffer2
005DAEF7 . 8BD0 MOV EDX,EAX
005DAEF9 . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
005DAEFC . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DAF02 > C745 FC 1E0000>MOV DWORD PTR SS:[EBP-4],1E
005DAF09 . 8D45 B0 LEA EAX,DWORD PTR SS:[EBP-50]
005DAF0C . 50 PUSH EAX
005DAF0D . E8 7E020000 CALL emu8086.005DB190 ;ruota il Buffer3
005DAF12 . 8BD0 MOV EDX,EAX
005DAF14 . 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-50]
005DAF17 . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DAF1D . C745 FC 1F0000>MOV DWORD PTR SS:[EBP-4],1F
005DAF24 . 0FBF4D AC MOVSX ECX,WORD PTR SS:[EBP-54]
005DAF28 . 85C9 TEST ECX,ECX
005DAF2A . 75 1B JNZ SHORT emu8086.005DAF47
005DAF2C . C745 FC 200000>MOV DWORD PTR SS:[EBP-4],20
005DAF33 . 8D55 B0 LEA EDX,DWORD PTR SS:[EBP-50]
005DAF36 . 52 PUSH EDX
005DAF37 . E8 54020000 CALL emu8086.005DB190 ;ruota il Buffer3
005DAF3C . 8BD0 MOV EDX,EAX
005DAF3E . 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-50]
005DAF41 . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DAF47 > C745 FC 220000>MOV DWORD PTR SS:[EBP-4],22
005DAF4E . 66:8B45 DC MOV AX,WORD PTR SS:[EBP-24] ;incrementa l’indice dal quale prelevare
005DAF52 . 66:05 0100 ADD AX,1 ;il prossimo carattere del nome
005DAF56 . 0F80 20020000 JO emu8086.005DB17C
005DAF5C . 66:8945 DC MOV WORD PTR SS:[EBP-24],AX
005DAF60 .^E9 DFFCFFFF JMP emu8086.005DAC44
Ogni CALL emu8086.005DB190 esegue questa operazione, data una stringa alla funzione, prende l’ultimo carattere della stringa e lo posiziona all’inizio. Esegue questa operazione sui 3 Buffer, alla fine di questa serie di istruzioni avremo nello stack:
0012D948 04708F14 UNICODE "WERDNA"
0012D94C 00000001
0012D950 04717D7C UNICODE "XJKASERKKN837C3FRTQZ"
0012D954 0471BC34
0012D958 00000000
0012D95C 00000000
0012D960 00000000
0012D964 00000000
0012D968 00193C4C UNICODE "Andrew"
0012D96C 00000002
0012D970 00000017
0012D974 0471AF64 UNICODE "XZ9RTASDF01823ASJFSD1234346GFHPLMASDR613412QWER"
0012D978 04717E54 UNICODE "YUQW10PASDFGHJKLZXCVBNMERT"
Il Buffer1 è ruotato di un carattere, il Buffer2 di 2 caratteri, il Buffer3 di 1 carattere.
Buffer1 stringa: XZ9RTASDF01823ASJFSD1234346GFHPLMASDR613412QWER ( 0012D974 nello stack )
Buffer2 stringa: YUQW10PASDFGHJKLZXCVBNMERT ( 0012D978 nello stack )
Buffer3 stringa: XJKASERKKN837C3FRTQZ ( 0012D950 nello stack )
Steppiamo sul JMP finale tornando su 005DAC44. Vediamo le differenze con il primo step. Innanzitutto ESI ora contiene 2, quindi funge da contatore, ma l’avevamo già intuito, arrivati a 005DACCE si passa alla funzione 2, quindi selezioniamo il secondo carattere di WERDNA, cioè la E. A 005DACEA si passa la E appena trovata e si trova la posizione 5 nell’ alfabeto, perfetto. Ora avviene una differenza con il primo passo. In
Il salto si era verificato, mentre questa volta il compare ha dato esito positivo e
Risultano essere uguali, infatti [EBP-54] ha cambiato valore in 005DAD2E ma cosa comporta questo?
005DAD40 . 8B55 B4 MOV EDX,DWORD PTR SS:[EBP-4C]
005DAD43 . 8995 4CFFFFFF MOV DWORD PTR SS:[EBP-B4],EDX
005DAD49 . C785 44FFFFFF >MOV DWORD PTR SS:[EBP-BC],8
005DAD53 . C745 9C 010000>MOV DWORD PTR SS:[EBP-64],1
005DAD5A . C745 94 020000>MOV DWORD PTR SS:[EBP-6C],2
005DAD61 . 8D45 D8 LEA EAX,DWORD PTR SS:[EBP-28]
005DAD64 . 8985 6CFFFFFF MOV DWORD PTR SS:[EBP-94],EAX
005DAD6A . C785 64FFFFFF >MOV DWORD PTR SS:[EBP-9C],4008
005DAD74 . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DAD77 . 51 PUSH ECX
005DAD78 . 0FBF55 D0 MOVSX EDX,WORD PTR SS:[EBP-30] ;pusha la posizione del carattere nell’alfabeto
005DAD7C . 52 PUSH EDX ;trovata prima con la InStr
005DAD7D . 8D85 64FFFFFF LEA EAX,DWORD PTR SS:[EBP-9C] ;pusha il puntatore al Buffer2 dal quale prelevare
005DAD83 . 50 PUSH EAX ;il carattere
005DAD84 . 8D4D 84 LEA ECX,DWORD PTR SS:[EBP-7C]
005DAD87 . 51 PUSH ECX
005DAD88 . FF15 70114000 CALL DWORD PTR DS:[<&MSVBVM60.#632>] ;seleziona il carattere in posizione pushata
005DAD8E . 8D95 44FFFFFF LEA EDX,DWORD PTR SS:[EBP-BC] ;dal Buffer2
005DAD94 . 52 PUSH EDX
005DAD95 . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DAD98 . 50 PUSH EAX
005DAD99 . 8D8D 74FFFFFF LEA ECX,DWORD PTR SS:[EBP-8C]
005DAD9F . 51 PUSH ECX
005DADA0 . FF15 D0124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCa>
005DADA6 . 50 PUSH EAX
005DADA7 . FF15 38104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrVa>
005DADAD . 8BD0 MOV EDX,EAX
005DADAF . 8D4D B4 LEA ECX,DWORD PTR SS:[EBP-4C]
005DADB2 . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DADB8 . 8D95 74FFFFFF LEA EDX,DWORD PTR SS:[EBP-8C]
005DADBE . 52 PUSH EDX
005DADBF . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DADC2 . 50 PUSH EAX
005DADC3 . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DADC6 . 51 PUSH ECX
005DADC7 . 6A 03 PUSH 3
005DADC9 . FF15 50104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeV>
005DADCF . 83C4 10 ADD ESP,10
005DADD2 . C745 FC 120000>MOV DWORD PTR SS:[EBP-4],12
005DADD9 . 66:C745 AC 000>MOV WORD PTR SS:[EBP-54],0 ;resetto [EBP-54] a 0, il Buffer2 ruoterà una sola volta
005DADDF . E9 A6000000 JMP emu8086.005DAE8A ;e il prossimo carattere sarà selezionato dal Buffer1
Questo è il nuovo pezzo di codice che eseguiamo adesso, in 005DAD88 abbiamo una nuova funzione Mid() alla quale si passa la posizione di E nell’alfabeto, ovvero 5, e cosa abbiamo di ritorno in EAX? 0012D924, + 8 =
Ovvero:
1??? Qual è il 5° carattere del nuovo Buffer2 ruotato? Un 1!!!
Procediamo su 005DADA0, dopo questa funzione spunta fuori nello stack il primo pezzo di chiave,
Che viene copiata quindi in:
Arrivati a 005DADDF si salta nuovamente qui
E ricomincia la fase di rotazione dei Buffer, vediamo alla fine cosa otteniamo. Velocemente F8 fino al JMP e quindi si torna in 005DAC44, come sono cambiati i nostri Buffer?
Buffer1 stringa: RXZ9RTASDF01823ASJFSD1234346GFHPLMASDR613412QWE ( 0012D974 nello stack )
Buffer2 stringa: TYUQW10PASDFGHJKLZXCVBNMER ( 0012D978 nello stack )
Buffer3 stringa: QZXJKASERKKN837C3FRT ( 0012D950 nello stack )
Il primo è ruotato sempre di 1, il 2 di un carattere e il 3 di uno solo. Questo è l’andamento, ogni volta che si crea una lettera di codice pescata una volta dal Buffer1, un’altra volta dal Buffer2, il Buffer1 ruota sempre di un carattere, il buffer2 ruota prima di 1 carattere, e alla lettera successiva di 2, il Buffer3 prima ruota di 2 e alla lettera successiva di 1, e così via… L’andamento di selezione dal Buffer1 o 2 all’ altro e di rotazione di 2 o 1 volta per il Buffer2 e 3 è dettato dalla variabile in [EBP-54] ovvero in 0012D94C . A questo punto l’algoritmo seleziona la R, posizione 12h nell’alfabeto, si pesca il 18° carattere dal buffer1 ( J ), si ruota Buffer1 di 1, Buffer2 di 2, Buffer3 di 1,
Buffer1 stringa: ERXZ9RTASDF01823ASJFSD1234346GFHPLMASDR613412QW ( 0012D974 nello stack )
Buffer2 stringa: ERTYUQW10PASDFGHJKLZXCVBNM ( 0012D978 nello stack )
Buffer3 stringa: TQZXJKASERKKN837C3FR ( 0012D950 nello stack )
e via di nuovo, seleziona D, posizione 4, seleziono il 4° carattere dal Buffer2 (Y) e ruoto, Buffer1 di 1, Buffer2 di 1, Buffer3 di 2. In questo modo otteniamo eseguendo altre 2 volte la procedura, questa situazione nello Stack:
0012D948 04708F14 UNICODE "WERDNA"
0012D94C 00000000
0012D950 04717E0C UNICODE "7C3FRTQZXJKASERKKN83"
0012D954 04708EEC UNICODE "41JY1B"
0012D958 00000000
0012D95C 00000000
0012D960 00000000
0012D964 00000000
0012D968 00193C4C UNICODE "Andrew"
0012D96C 00000007
0012D970 00000001
0012D974 0020A77C UNICODE "2QWERXZ9RTASDF01823ASJFSD1234346GFHPLMASDR61341"
0012D978 04717E54 UNICODE "VBNMERTYUQW10PASDFGHJKLZXC"
E mi ritrovo al solito inizio in
Cosa succede ora che abbiamo finito le lettere del nome manipolato WERDNA???
Innanzitutto il famoso compare di ESI con la lunghezza della stringa, restituisce che effettivamente abbiamo finito i caratteri,
005DAC4B . 0FBF75 DC MOVSX ESI,WORD PTR SS:[EBP-24]
005DAC4F . 8B55 A8 MOV EDX,DWORD PTR SS:[EBP-58]
005DAC52 . 52 PUSH EDX
005DAC53 . FF15 3C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaLenBs>
005DAC59 . 33DB XOR EBX,EBX
005DAC5B . 3BF0 CMP ESI,EAX ;ESI = 7 > EAX = 6
005DAC5D . 0F9FC3 SETG BL ;BL = 1
005DAC60 . 0FBF75 CC MOVSX ESI,WORD PTR SS:[EBP-34]
005DAC64 . 8B45 B0 MOV EAX,DWORD PTR SS:[EBP-50]
005DAC67 . 50 PUSH EAX
005DAC68 . FF15 3C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaLenBs>
005DAC6E . 33C9 XOR ECX,ECX
005DAC70 . 3BF0 CMP ESI,EAX
005DAC72 . 0F9FC1 SETG CL
005DAC75 . 0BD9 OR EBX,ECX
005DAC77 . 85DB TEST EBX,EBX
005DAC79 . 0F85 E6020000 JNZ emu8086.005DAF65
Quindi arrivati all’ ultima istruzione si salta e si arriva in questa nuova area di codice:
005DAF6C . 0FBF75 CC MOVSX ESI,WORD PTR SS:[EBP-34] ;in ESI abbiamo la posizione del prossimo carattere
005DAF70 . 8B4D B0 MOV ECX,DWORD PTR SS:[EBP-50] ;con WERDNS eravamo arrivati a scriverne 6,
005DAF73 . 51 PUSH ECX ;quindi ora ESI punta al 7°
005DAF74 . FF15 3C104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaLenBs>
005DAF7A . 3BF0 CMP ESI,EAX ;confront ESI con la lunghezza del Buffer3
005DAF7C . 0F8F B7000000 JG emu8086.005DB039
005DAF82 . C745 FC 250000>MOV DWORD PTR SS:[EBP-4],25
005DAF89 . 8B55 B4 MOV EDX,DWORD PTR SS:[EBP-4C]
005DAF8C . 8995 4CFFFFFF MOV DWORD PTR SS:[EBP-B4],EDX
005DAF92 . C785 44FFFFFF >MOV DWORD PTR SS:[EBP-BC],8
005DAF9C . C745 9C 010000>MOV DWORD PTR SS:[EBP-64],1
005DAFA3 . C745 94 020000>MOV DWORD PTR SS:[EBP-6C],2
005DAFAA . 8D45 B0 LEA EAX,DWORD PTR SS:[EBP-50]
005DAFAD . 8985 6CFFFFFF MOV DWORD PTR SS:[EBP-94],EAX
005DAFB3 . C785 64FFFFFF >MOV DWORD PTR SS:[EBP-9C],4008
005DAFBD . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DAFC0 . 51 PUSH ECX
005DAFC1 . 0FBF55 CC MOVSX EDX,WORD PTR SS:[EBP-34]
005DAFC5 . 52 PUSH EDX
005DAFC6 . 8D85 64FFFFFF LEA EAX,DWORD PTR SS:[EBP-9C]
005DAFCC . 50 PUSH EAX
005DAFCD . 8D4D 84 LEA ECX,DWORD PTR SS:[EBP-7C]
005DAFD0 . 51 PUSH ECX
005DAFD1 . FF15 70114000 CALL DWORD PTR DS:[<&MSVBVM60.#632>] ;seleziono un carattere in posizione ESI dal Buffer3
005DAFD7 . 8D95 44FFFFFF LEA EDX,DWORD PTR SS:[EBP-BC]
005DAFDD . 52 PUSH EDX
005DAFDE . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DAFE1 . 50 PUSH EAX
005DAFE2 . 8D8D 74FFFFFF LEA ECX,DWORD PTR SS:[EBP-8C]
005DAFE8 . 51 PUSH ECX
005DAFE9 . FF15 D0124000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaVarCa>
005DAFEF . 50 PUSH EAX
005DAFF0 . FF15 38104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrVa>
005DAFF6 . 8BD0 MOV EDX,EAX
005DAFF8 . 8D4D B4 LEA ECX,DWORD PTR SS:[EBP-4C]
005DAFFB . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>;copio il carattere trovato nella chiave
005DB001 . 8D95 74FFFFFF LEA EDX,DWORD PTR SS:[EBP-8C]
005DB007 . 52 PUSH EDX
005DB008 . 8D45 84 LEA EAX,DWORD PTR SS:[EBP-7C]
005DB00B . 50 PUSH EAX
005DB00C . 8D4D 94 LEA ECX,DWORD PTR SS:[EBP-6C]
005DB00F . 51 PUSH ECX
005DB010 . 6A 03 PUSH 3
005DB012 . FF15 50104000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaFreeV>
005DB018 . 83C4 10 ADD ESP,10
005DB01B . C745 FC 260000>MOV DWORD PTR SS:[EBP-4],26
005DB022 . 66:8B55 CC MOV DX,WORD PTR SS:[EBP-34] ;incremento [EBP-34] (quindi dopo ESI)
005DB026 . 66:83C2 01 ADD DX,1 ;per scrivere il prossimo carattere
005DB02A . 0F80 4C010000 JO emu8086.005DB17C
005DB030 . 66:8955 CC MOV WORD PTR SS:[EBP-34],DX
005DB034 .^E9 2CFFFFFF JMP emu8086.005DAF65 ;ricomincio il ciclo
Se vi state chiedendo a cosa servisse il buffer3, ecco la risposta, questo ciclo, come potrete vedere steppando man mano, non fa altro che copiare i caratteri mancanti al nostro codice 41JY1B quelli prelevati dal Buffer3, quindi all’inizio del ciclo avremo nello Stack:
0012D954 04708CE4 UNICODE "41JY1B"
E alla fine:
0012D954 04717D7C UNICODE "41JY1BQZXJKASERKKN83"
Da Q a 3 sono interamente copiati dal Buffer3! Una volta copiati questi caratteri, il salto
Che confronta ESI con la lunghezza del Buffer3 ci porta in questa parte di codice
005DB040 . 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
005DB043 . 66:8B08 MOV CX,WORD PTR DS:[EAX]
005DB046 . 66:83E9 01 SUB CX,1
005DB04A . 0F80 2C010000 JO emu8086.005DB17C
005DB050 . 66:898D 3CFFFF>MOV WORD PTR SS:[EBP-C4],CX
005DB057 . 66:C785 40FFFF>MOV WORD PTR SS:[EBP-C0],1
005DB060 . 66:C745 DC 010>MOV WORD PTR SS:[EBP-24],1
005DB066 . EB 15 JMP SHORT emu8086.005DB07D
005DB068 > 66:8B55 DC MOV DX,WORD PTR SS:[EBP-24]
005DB06C . 66:0395 40FFFF>ADD DX,WORD PTR SS:[EBP-C0]
005DB073 . 0F80 03010000 JO emu8086.005DB17C
005DB079 . 66:8955 DC MOV WORD PTR SS:[EBP-24],DX
005DB07D > 66:8B45 DC MOV AX,WORD PTR SS:[EBP-24]
005DB081 . 66:3B85 3CFFFF>CMP AX,WORD PTR SS:[EBP-C4]
005DB088 . 7F 24 JG SHORT emu8086.005DB0AE
005DB08A . C745 FC 290000>MOV DWORD PTR SS:[EBP-4],29
005DB091 . 8D4D B4 LEA ECX,DWORD PTR SS:[EBP-4C] ;carica la nostra chiave nello stack
005DB094 . 51 PUSH ECX
005DB095 . E8 F6000000 CALL emu8086.005DB190 ;è la funzione che sposta l’ultimo carattere all’inizio
005DB09A . 8BD0 MOV EDX,EAX
005DB09C . 8D4D B4 LEA ECX,DWORD PTR SS:[EBP-4C]
005DB09F . FF15 D0134000 CALL DWORD PTR DS:[<&MSVBVM60.__vbaStrMo>
005DB0A5 . C745 FC 2A0000>MOV DWORD PTR SS:[EBP-4],2A
005DB0AC .^EB BA JMP SHORT emu8086.005DB068
Questo codice prende il vostro seriale e lo ruota su se stesso per ben 63h volte! E sapete qual’ è l’effetto di tutto ciò? Prendere dal codice trovato prima il primo carattere e sbatterlo alla fine! Quindi 41JY1BQZXJKASERKKN83 diventa 1JY1BQZXJKASERKKN834 !!! Sembrerebbe che abbiamo tutte le carte in regola per creare il nostro KeyGen, manca una sola cosa, la gestione dei numeri e simboli! Cosa succede in questo caso??? Lascio a voi come compito per casa il “piacere” di capire cosa fa nel dettaglio l’algoritmo, se volete provarci da soli non leggete le prossime righe fin quando non avrete capito oppure vi sarete rotti :P … Bene se state leggendo vuol dire che avete già capito, forse, comunque diciamo che quando l’algoritmo incontra un altro simbolo non presente nell’alfabeto, non può selezionare il codice dai due buffer, allora cosa succede? Niente! Lo salta e non calcola nessun carattere al suo posto! Maaaaaaaaaaa… c’è una piccola difficoltà, che in presenza di questo carattere estraneo Buffer1 e 2 non ruotano, ma il 3°, quello che si copia alla fine SI! E di quanto ruota? Dipende dalla solita variabile in [EBP-54] ovvero 0012D94C nello stack, che cambia da 0 a 1 e viceversa ogni volta che un carattere viene calcolato da uno dei due Buffer!Quindi Buffer3 ruota di quanto aveva ruotato l’ultima volta che è stato cambiato un carattere, se l’ultima volta aveva ruotato di 1, ruota di 1, se aveva ruotato di 2 continua di 2! Ora finalmente possiamo scrivere il nostro KeyGen :D …
Keygen
Ho scelto il Vb.Net come piattaforma, ho creato un form con 2 TextBox e un pulsante, e questo è il codice, i commenti li includo nel sorgente stesso:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Buf1 As String = "Z9RTASDF01823ASJFSD1234346GFHPLMASDR613412QWERX"
Dim Buf2 As String = "QW10PASDFGHJKLZXCVBNMERTYU"
Dim Buf3 As String = "JKASERKKN837C3FRTQZX"
Dim Alfabeto As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim Seriale As String = ""
Dim Nome1 As String
Dim i As Integer
Dim EBP54 As Boolean = True
Dim Pos As Integer
Dim temp As String = ""
Nome1 = Nome.Text 'Leggo il nome
Nome1 = UCase(Nome1) 'Tutto maiuscolo
For i = Len(Nome1) To 1 Step -1
temp = temp & Mid(Nome1, i, 1) 'Lo inverto
Next
Nome1 = temp
For i = 1 To Len(Nome1)
Pos = InStr(Alfabeto, Mid(Nome1, i, 1)) 'Posizione del carattere nell'alfabeto
If Pos > 0 Then 'Se è un carattere
If EBP54 Then 'EBP54 è la variabile booleana che mi indica da quale Buffer pescare e quanto ruotare Buffer2 e 3
Seriale = Seriale & Mid(Buf1, Pos, 1) 'a turno seleziono da Buffer1 o 2
Else
Seriale = Seriale & Mid(Buf2, Pos, 1)
End If
Buf1 = Ruota(Buf1) 'ruoto il buffer1
Buf2 = Ruota(Buf2)
Buf3 = Ruota(Buf3)
If EBP54 Then 'a turno ruoto il Buffer2 di 1 e Buffer3 di 2 e viceversa
Buf2 = Ruota(Buf2)
Else
Buf3 = Ruota(Buf3)
End If
EBP54 = Not (EBP54) 'a ogni carattere si inverte di valore
Else
If EBP54 Then 'Se non è un carattere ruoto il Buffer3 di tante volte quanto l'ultima volta
Buf3 = Ruota(Buf3)
End If
Buf3 = Ruota(Buf3)
End If
Next
Seriale = Seriale & Mid(Buf3, Len(Seriale) + 1, Len(Buf3)) 'Aggiungo la parte mancante al seriale
Seriale = Mid(Seriale, 2, Len(Seriale)) & Mid(Seriale, 1, 1) 'Sposto il primo carattere alla fine
Serial.Text = Seriale
End Sub
Public Function Ruota(ByVal Stringa As String) As String
Stringa = Mid(Stringa, Len(Stringa), 1) & Mid(Stringa, 1, Len(Stringa) - 1)
Return Stringa
End Function
End Class
L’ unica accortezza che ho dimenticato e lascio a voi gestire è quando il nome inserito è più lungo del Buffer3!
Note Finali
Come avete potuto vedere la funzione non era sto granchè una volta scritta in Vb.Net, ma capire bene come funzionano le cose col reversing in tempi inferiori a ere geologiche e senza troppi esaurimenti nervosi, necessita una conoscenza dell’ assembly più che dignitosa, in questo caso le funzioni in Vb ci hanno dato una mano a capire cosa succedeva ogni volta, ma non sempre sarà così… Un saluto a tutti voi che avete avuto la pazienza di leggere fino alla fine, un ringraziamento finale a Evolution che ha trovato il byte per crackare l’eseguibile in 10 minuti, e a sparpacillon che altrettanto velocemente aveva fishato il seriale per il suo nome, e senza dei quali forse questo tutorial non avrebbe preso vita… Ciao e alla prossima! ^_^
A_19
Disclaimer
I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.
Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.