Zoom Icon

Keygen EMU8086

From UIC

Keygen EMU8086

Contents


Keygen EMU8086
Author: Andrew10111989
Email: none
Website: none
Date: 12/06/2010 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Flag Italian.gif
Comments:



Tools

OllyDbg 1.10
PEiD 0.95


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

005D8697   . DBE2           FCLEX

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

005D8E26   . E8 35130000    CALL emu8086.005DA160

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:

005D8E9B   . 68 A0094500    PUSH emu8086.004509A0   ;  UNICODE "the software is successfully registered"

Mentre con questo salto finiamo a

005D9394   > C745 FC 2F0000>MOV DWORD PTR SS:[EBP-4],2F
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

005D8E26   . E8 35130000    CALL emu8086.005DA160

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

005DA697   . E8 D4000000    CALL emu8086.005DA770

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

0012DA68   0012DCD8

Ma salendo su, quindi scendendo come indirizzi guarda un po’ cosa esce…

0012DA20   0036B87C  UNICODE "1JY1BQZXJKASERKKN834"

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

005DAA36   . E8 B5000000    CALL emu8086.005DAAF0

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:

005DAAF0   $ 55             PUSH EBP
.
.
.
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…

0012D8B8   0012D904     ---------------------------------------------------------->ESP
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

005DABDE   . FF15 90114000  CALL DWORD PTR DS:[<&MSVBVM60.#528>]     ;  MSVBVM60.rtcUpperCaseVar

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:

005DABDE   . FF15 90114000  CALL DWORD PTR DS:[<&MSVBVM60.#528>]     ;  MSVBVM60.rtcUpperCaseVar Andrew = ANDREW
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:

005DAC44   > C745 FC 0D0000>MOV DWORD PTR SS:[EBP-4],0D
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

0012D97C   00000001

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

005DACC2   . 52             PUSH EDX

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

0012D91C   00000017

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

005DADE4   > C745 FC 140000>MOV DWORD PTR SS:[EBP-4],14
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…

0012D92C   002039EC

Cosa c’è a quest’ indirizzo?

002039EC  34      4

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…

005DAEAA   . 8D45 D8        LEA EAX,DWORD PTR SS:[EBP-28]
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:

0012D944   04717CA4  UNICODE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
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

005DAD33   . 0F85 AB000000  JNZ emu8086.005DADE4

Il salto si era verificato, mentre questa volta il compare ha dato esito positivo e

005DAD2E   . 66:837D AC 01  CMP WORD PTR SS:[EBP-54],1

Risultano essere uguali, infatti [EBP-54] ha cambiato valore in 005DAD2E ma cosa comporta questo?

005DAD39   . C745 FC 110000>MOV DWORD PTR SS:[EBP-4],11
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 =

0012D92C   002039EC

Ovvero:

002039EC  31       1

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,

0012D91C   04708EEC  UNICODE "41"

Che viene copiata quindi in:

0012D954   04708EEC  UNICODE "41"

Arrivati a 005DADDF si salta nuovamente qui

005DAE8A   > C745 FC 170000>MOV DWORD PTR SS:[EBP-4],17

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:

0012D944   04717CA4  UNICODE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
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

005DAC44   > C745 FC 0D0000>MOV DWORD PTR SS:[EBP-4],0D

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,

005DAC44   > C745 FC 0D0000>MOV DWORD PTR SS:[EBP-4],0D
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:

005DAF65   > C745 FC 240000>MOV DWORD PTR SS:[EBP-4],24
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:

0012D950   04717E0C  UNICODE "7C3FRTQZXJKASERKKN83"
0012D954   04708CE4  UNICODE "41JY1B"

E alla fine:

0012D950   04717E0C  UNICODE "7C3FRTQZXJKASERKKN83"
0012D954   04717D7C  UNICODE "41JY1BQZXJKASERKKN83"

Da Q a 3 sono interamente copiati dal Buffer3! Una volta copiati questi caratteri, il salto

005DAF7C   . 0F8F B7000000  JG emu8086.005DB039

Che confronta ESI con la lunghezza del Buffer3 ci porta in questa parte di codice

005DB039   > C745 FC 280000>MOV DWORD PTR SS:[EBP-4],28
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:


Public Class Form1

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.