Zoom Icon

Soluzione Crackme 28

From UIC

Crackme n.28 : Il secondo crackme scritto da BlackDruid, buon lavoro :))))

Contents


Soluzione Crackme 28
Author: ValerioSoft
Email: ValerioSoft(AT)tin.it
Website:
Date: 11/09/2007 (dd/mm/yyyy)
Level: Some skills are required
Language: Italian Image:Flag_Italian.gif
Comments: Per la dura carne del lupo servono solamente le zanne del cane. :-D



Introduzione

Ciaoooooooooo, benvenuti al mio nono tuteeeee??? Hey basta :-D


Tools


Notizie sul CrackMe N.23

Anche questo è un crackme scritto da BlackDruid che questa volta ha cercato di confonderci le idee!!!.

Regolamento:
Disassembly and patching are not allowed and not needed!!!!!!


Essay

Non smetterò mai di ripeterlo! Il primo passo essenziale è andare alla ricerca di un eventuale punto di attacco, andiamo quindi ad inserire nome e serial casuali (abbastanza lunghi) e come per magia ci compare il messaggio BAD JOB!. Controlliamo se compare nelle Referenced Text String.

Peccato!!! :-) Non sembra esserlo, come possiamo fare??? Beh non è l'unico modo disponibile, ne conosciamo un altro semplicissimo!!! Quale??? La funzione MessageBox ad esempio. Inseriamo un breakpoint su questa funzione presente nelle Intermodular Calls e proviamo a chiedere al druido. Ecco Olly entra in azione come previsto, ci troviamo all'istruzione 0041903A:


00419030 | FF7424 10 PUSH DWORD PTR SS:[ESP+10] // Style
00419034 | 50 PUSH EAX // Title
00419035 | FF7424 10 PUSH DWORD PTR SS:[ESP+10] // Text = BAD JOB!
00419039 | 51 PUSH ECX // hOwner
0041903A | FF15 6C244200 CALL DS:[&USER32.MessageBoxA] // MessageBoxA

A quanto pare non serve ai nostri scopi, ma mi fa sorgere un dubbio! Se il druido ha usato la funzione suddetta molto probabilmente avrà usato la GetWindowText per catturare i caratteri inseriti, proviamo a settare un breakpoint per vedere cosa succede e riavviamo tutto. Bene all'avvio c'è una prima chiamata che a quanto pare serve per cancellare eventuali caratteri nella textbox del nome e del serial.


0041C367 PUSH EAX // Count => 100 (256.)
0041C368 LEA EAX,[LOCAL.64] //
0041C36E PUSH EAX // Buffer
0041C36F PUSH [ARG.1] // hWnd
0041C372 CALL DS:[&USER32.GetWindowTextA] // GetWindowTextA
0041C378 CMP EAX,ESI
0041C37A JNZ SHORT 0041C390
0041C37C PUSH [ARG.2] // String2
0041C37F LEA EAX,[LOCAL.64] //
0041C385 PUSH EAX // String1
0041C386 CALL DS:[&KERNEL32.lstrcmpA] // lstrcmpA
0041C38C TEST EAX,EAX
0041C38E JE SHORT 0041C39C
0041C390 PUSH [ARG.2] // Text
0041C393 PUSH [ARG.1] // hWnd
0041C396 CALL DS:[&USER32.SetWindowTextA] // SetWindowTextA

Dato che non serve ai nostri scopi eliminiamo questo breakpoint con F2, poi premiamo il tasto PLay di Olly per continuare l'esecuzione del programma. Inseriamo nome e serial casuali, poi chiediamo al druido!!! Bene Olly prende il controllo, ora non ci resta che analizzare la chiamata ed annotarci la locazione del buffer:


0041CC12 PUSH EAX // Buffer
0041CC13 PUSH ESI // hWnd
0041CC14 CALL DS:[&USER32.GetWindowTextA] // GetWindowTextA

Come si può notare la locazione del buffer è contenuta nel registro EAX ed è 008C6E98. Ora visualizziamo il contenuto della locazione con il comando d 008C6E98 ed eseguiamo la chiamata con F8. Ecco che compare il nostro neme inserito, adesso la cosa più semplice da fare è piazzare un breakpoint on memory access sui byte del nome ed avviare nuovamente l'esecuzione dell'applicazione. Olly prende il controllo su una piccola routine che conta il numero di caratteri del nome, se steppiamo con F8, dopo il RET arriviamo qui:


00417557 PUSH DWORD PTR DS:[ESI] // String
00417559 CALL DS:[&KERNEL32.lstrlenA] // lstrlenA
0041755F MOV ECX,DS:[ESI]
00417561 MOV DS:[ECX-8],EAX // salva il numero di lettere del nome alla locazione 008C6E90
00417564 MOV ECX,DS:[ESI] // mette il ECX la locazione che contiene il nome

Ora piazziamo un breakpoint on memory access anche sul byte che contiene il numero di lettere del nome ovvero la locazione 008C6E90 e continuiamo l'esecuzione premendo Play.


0041CC54 MOV EAX,DS:[EAX-8] // mette in EAX la lunghezza del nome
0041CC57 CMP EAX,[ARG.3] // confronta la lunghezza del nome con il 15 decimale
0041CC5A JLE SHORT 0041CCB7 // salta se è minore o uguale a 15 (altrimenti errore)

Come si può intuire se il nome inserito ha più di 15 caratteri allora viene mostrato un messaggio di errore, in realtà se voi provate ad inserire un nome con più di 15 caratteri vi accorgete che il box non ve lo permette quindi è un controllo che inizialmente era stato previsto ma non viene mai utilizzato. Che bello l'assembler vero???? :-D

Dopo l'esecuzione della routine viene richiamata nuovamente la funzione GetWindowTextA per memorizzare il serial inserito:


0041CC12 PUSH EAX // Buffer
0041CC13 PUSH ESI // hWnd
0041CC14 CALL DS:[&USER32.GetWindowTextA] // GetWindowTextA

Prendiamo nota della locazione che si trova in EAX = 008C6EE8 e visualizziamola come in precedenza, poi avviamo l'esecuzione con F8 e piazziamo un breakpoint on memory access anche sul serial.Poi premiamo il tasto Play di Olly fino a quando non troviamo qualche istruzione che elabora i caratteri del nome o del serial. In questo caso troveremo per prima cosa la routine che conta i caratteri del serial, se steppiamo con F8 fino al RET e lo eseguiamo arriviamo qui:


00417557 PUSH DWORD PTR DS:[ESI] // /String
00417559 CALL DS:[&KERNEL32.lstrlenA] // \lstrlenA
0041755F MOV ECX,DS:[ESI]
00417561 MOV DS:[ECX-8],EAX // salva il numero di lettere del nome alla locazione 008C6EE0
00417564 MOV ECX,DS:[ESI] // mette il ECX la locazione che contiene il serial

Ora piazziamo un breakpoint on memory access anche sul byte che contiene il numero di lettere del serial ovvero la locazione 008C6EE0 e continuiamo l'esecuzione premendo Play.


0041CC54 MOV EAX,DS:[EAX-8] // mette in EAX la lunghezza del serial
0041CC57 CMP EAX,[ARG.3] // confronta la lunghezza del nome con il 15 decimale
0041CC5A JLE SHORT 0041CCB7 // salta se è minore o uguale a 15 (altrimenti errore)

Adesso riavviamo completamente l'applicazione ed arriviamo al punto in cui si piazza il breakpoint on memory access sul nome in memoria. Superiamo la routine che conta i caratteri del nome, poi superiamo la lettura del serial ed Olly prenderà nuovamente il controllo su un pezzo di codice che elabora il nome:


0040170D MOV ESI,DS:[EBX+5C] // mette in ESI la locazione del nome
00401710 MOV AL,DS:[ESI-8] // mette in AL il numero di caratteri del nome
00401713 CMP AL,0A // confronta AL con 10 decimale
00401715 MOV SS:[ESP+C],AL // salva il numero di caratteri alla locazione 12F8FC
00401719 JB 004017A9 // salta se il numero di caratteri del nome è minore di 10
0040171F MOV EAX,SS:[ESP+C]
00401723 MOV EDI,DS:[42D098] // mette in edi la locazione 00B10000
00401729 AND EAX,0FF
0040172E MOV ECX,EAX
00401730 MOV EDX,ECX
00401732 SHR ECX,2 // setta il numero di iterazioni del REP
00401735 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] // copia in 00B10000 le 2 doubleword di ESI
00401737 MOV ECX,EDX
00401739 XOR EDX,EDX
0040173B AND ECX,3
0040173E REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] // copia le restanti 3 lettere del nome
// in 00B10000<br />
00401740 MOV ECX,DS:[42D098] // mette in ECX la locazione 00B10000 che contiene il nome
00401746 MOV DS:[EAX+ECX],DL // aggiunge il byte 00 alla stringa
// in 00B10000<br />
00401749 MOV ESI,DS:[EBX+60] // mette in ESI la locazione del serial
0040174C MOV AL,DS:[ESI-8] // mette il AL il numero di caratteri del serial
0040174F CMP AL,0A // confronta il numero di caratteri del serial con 10
00401751 MOV SS:[ESP+C],AL // salva il numero di caratteri in 0012F8FC
00401755 JB SHORT 0040179C // salta se il numero di caratteri del serial è minore di 10
00401757 MOV EAX,SS:[ESP+C]
0040175B MOV EDI,0042D078 // mette in EDI la locazione 0042D078
00401760 AND EAX,0FF
00401765 PUSH EDX
00401766 MOV ECX,EAX
00401768 PUSH EDX
00401769 MOV EBX,ECX
0040176B PUSH EDX
0040176C SHR ECX,2 // prepara ECX con il numero di iterazioni
0040176F REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] // copia in 0042D078 le 2 doubleword di ESI
00401771 MOV ECX,EBX
00401773 PUSH EDX
00401774 AND ECX,3
00401777 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] // copia le restanti 3 lettere del serial
// in 0042D078<br />
00401779 MOV DS:[EAX+42D078],DL
0040177F MOV EDX,DS:[42D0C0] // mette in EDX la locazione 08B203C0

Vi annuncio in esclusiva che questo pezzo di codice elabora il nome inserito ma non serve ad un bel niente ai fini della risoluzione del crackme, il druido ha pensato bene di confondere un pò le acque.

Adesso non ci resta che analizzare cosa succede al serial quindi ripetiamo lo stesso procedimento effettuato sul nome:


0040176F REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] // copia in 0042D078 le 2 doubleword di ESI
00401771 MOV ECX,EBX
00401773 PUSH EDX
00401774 AND ECX,3
00401777 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] // copia le restanti 3 lettere del serial
// in 0042D078<br />
00401779 MOV DS:[EAX+42D078],DL
0040177F MOV EDX,DS:[42D0C0] // mette in EDX la locazione 08B203C0

Il serial viene copiato alla locazione 0042D078, ora è questa la locazione da controllare quindi piazziamo un breakpoint on memory access sull'intero serial e premiamo il tasto Play diverse volte fino a quando arriviamo qui:


004019AE MOV BL,DS:[42D078]
004019B4 REPNE SCAS BYTE PTR ES:[EDI] // decrementa ECX fino a quando non si incontra il byte 00
// in 00B10000
004019B6 MOV AL,DS:[42D09C] // mette in AL la lettera della locazione 0042D09C
004019BB MOV EDX,6 // mette 6 in EDX
004019C0 NOT ECX // nega ECX
004019C2 DEC ECX // decrementa ECX
004019C3 MOV EDI,ECX // copia ECX in EDI
004019C5 XOR ECX,ECX // azzera ECX
004019C7 CMP AL,BL // confronta AL (byte a noi sconosciuto) con BL (1o byte
// del serial)
004019C9 MOV DS:[42B0C0],CL
004019CF JNZ SHORT 004019DD // salta se non sono uguali
004019D1 MOV BYTE PTR DS:[42B0C0],42 // reimposta la locazione 0042B0C0 con il valore 42
004019D8 MOV EDX,8 // mette il valore 8 in EDX
004019DD XOR EAX,EAX // azzera EAX
004019DF CMP EDI,ECX // confronta il numero di lettere del nome cifrato con ECX
004019E1 JLE SHORT 00401A3D // salta se è minore o uguale
004019E3 PUSH EBP
004019E4 MOV EBP,DS:[42D0C8]
004019EA SUB ESI,0042D078 // sottrae 0042D078 a 00B10000
004019F0 CMP EBP,2 // confronta EBP con 2
004019F3 JE SHORT 00401A13 // salta se sono uguali
004019F5 MOV BL,DS:[EAX+42D078] // mette la prima lettera del serial in BL
004019FB XOR BL,42 // xora BL con 42
004019FE CMP DS:[ESI+EAX+42D078],BL // confronta la prima lettera del nome cifrato con BL
00401A05 JE SHORT 00401A0C // salta se sono uguali
00401A07 OR EDI,FFFFFFFF // mette EDI in errore
00401A0A JMP SHORT 00401A37 // salta all'istruzione 00401A37
00401A0C '''MOV EDX,7''' // mette 7 in EDX
00401A11 JMP SHORT 00401A37 // salta all'istruzione 00401A37
00401A13 MOV BL,DS:[EAX+42D078] // mette in BL la prima lettera del nome cifrato
00401A19 MOV DS:[42B0C0],CL // azzera il byte della locazione 0042B0C0
00401A1F CMP BL,DS:[ESI+EAX+42D078] // confronta BL con il byte della locazione 0042D078
00401A26 MOV EDX,6 // mette 6 in EDX
00401A2B JE SHORT 00401A32 // salta se sono uguali
00401A2D OR EDI,FFFFFFFF // rappresenta l'errore
00401A30 JMP SHORT 00401A37
00401A32 MOV EDX,9 // mette 9 in EDX
00401A37 INC EAX // incrementa EAX
00401A38 CMP EAX,EDI // confronta EAX con EDI
00401A3A JL SHORT 004019F0 // salta se EAX è minore di EDI
00401A3C POP EBP
00401A3D PUSH ECX // lParam
00401A3E MOV ECX,DS:[42D0C0]
00401A44 PUSH EDX // wParam
00401A45 PUSH 464 // Message = MSG(464)
00401A4A PUSH ECX // hWnd => 1F02BE
00401A4B MOV DWORD PTR DS:[42D0C8],1
00401A55 CALL DS:[&USER32.PostMessageA] // PostMessageA

Siamo giunti nel motore del crackme, tutto ruota intorno alla funzione PostMessageA ed al parametro wParam ovvero al valore contenuto in EDX, osservando il listato i valori possibili sono 6,7,8 e 9. La cosa più semplice da fare per capire cosa ha architettato il druido è giocare con questi valori quindi piazziamo un breakpoint on execution sulla locazione 00401A44 e riavviamo tutto.


valore 6: BAD JOB!
valore 7: TRY AGAIN
valore 8: ripete l'analisi del serial
valore 9: GOOD JOB!

Quindi dobbiamo regolare il flusso d'esecuzione delle istruzioni in modo tale da passare alla funzione PostMessageA il valore 9, ovvero EDX deve contenere il valore 9.


00401A30 JMP SHORT 00401A37
00401A32 MOV EDX,9 // mette 9 in EDX

Come si può notare prima del MOV c'è un salto incondizionato quindi l'unico modo per arrivare all'istruzione 00401A30 è grazie all'istruzione 00401A2B.


00401A11 JMP SHORT 00401A37 // salta all'istruzione 00401A37
00401A13 MOV BL,DS:[EAX+42D078] // mette in BL la prima lettera del nome cifrato
00401A19 MOV DS:[42B0C0],CL // azzera il byte della locazione 0042B0C0
00401A1F CMP BL,DS:[ESI+EAX+42D078] // confronta BL con il byte della locazione 0042D078
00401A26 MOV EDX,6 // mette 6 in EDX
00401A2B JE SHORT 00401A32 // salta se sono uguali

Anche in questo caso per arrivare all'istruzione 00401A13 è grazie all'istruzione 004019F3.


004019E4 MOV EBP,DS:[42D0C8]
004019EA SUB ESI,0042D078 // sottrae 0042D078 a 00B10000
004019F0 CMP EBP,2 // confronta EBP con 2
004019F3 JE SHORT 00401A13 // salta se sono uguali

L'unico modo per settare EDX = 9 è riuscire a settare EBP = 2, se guardate bene EBP viene settato con il valore contenuto alla locazione 0042D0C8. Bisogna capire adesso quale istruzione modifica la locazione 0042D0C8 inserendo il valore 2, quindi clicchiamo con il tasto destro del mouse sul codice e scegliamo Search for -&gt//All constants e nel box Hexadecimal inseriamo la locazione 0042D0C8 e premiamo il tasto OK. Ci compaiono a video tutte le istruzioni che contengono la suddetta locazione ma solo una va ad inserire il valore 2:


004018AC PUSH 0 // Case 8 of switch 00401847
004018AE PUSH 0
004018B0 PUSH 0
004018B2 PUSH 0
004018B4 PUSH 0042D09C
004018B9 PUSH 004019A0
004018BE MOV DWORD PTR DS:[42D0C8],2

Come ci suggerisce Olly, questo frammento di codice fa parte di un Case o Switch e guardate che valore ci porta li??? Si è proprio il valore 8!!!!

Quindi per far comparire la scritta GOOD JOB! occorre passare alla funzione PostMessageA prima il valore 8 e poi il 9!


004019C7 CMP AL,BL // confronta AL (byte a noi sconosciuto) con BL (1o byte
// del serial)
004019C9 MOV DS:[42B0C0],CL
004019CF JNZ SHORT 004019DD // salta se non sono uguali
004019D1 MOV BYTE PTR DS:[42B0C0],42 // reimposta la locazione 0042B0C0 con il valore 42
004019D8 MOV EDX,8 // mette il valore 8 in EDX
004019DD XOR EAX,EAX // azzera EAX
004019DF CMP EDI,ECX // confronta il numero di lettere del nome cifrato con ECX
004019E1 JLE SHORT 00401A3D // salta se è minore o uguale
004019E3 PUSH EBP
004019E4 MOV EBP,DS:[42D0C8]
004019EA SUB ESI,0042D078 // sottrae 0042D078 a 00B10000
004019F0 CMP EBP,2 // confronta EBP con 2
004019F3 JE SHORT 00401A13 // salta se sono uguali
004019F5 MOV BL,DS:[EAX+42D078] // mette la prima lettera del serial in BL
004019FB XOR BL,42 // xora BL con 42
004019FE CMP DS:[ESI+EAX+42D078],BL // confronta la prima lettera del nome cifrato con BL
00401A05 JE SHORT 00401A0C // salta se sono uguali
00401A07 OR EDI,FFFFFFFF // mette EDI in errore
00401A0A JMP SHORT 00401A37 // salta all'istruzione 00401A37

Osservate bene il pezzo di codice che vi ho proposto, per settare EDX con il valore 8 occorre superare un primo ostacolo ovvero AL e BL presenti all'istruzione 004019C7 devono essere uguali. BL contiene il primo byte del serial inserito mentre AL cosa contiene??? AL contiene qualcosa a noi sconosciuto quindi bisogna conoscere la locazione che setta AL:


004019B6 MOV AL,DS:[42D09C] // mette in AL la lettera della locazione 0042D09C

Ecco la locazione, ora riavviamo l'applicazione e controlliamo in memoria cosa c'è. Bene inizialmente è vuota!!! Ora piazziamo un breakpoint on memory access sul byte e premiamo il tasto Play di Olly, ci compare il box di registrazione, adesso inseiamo il nostro nome. Cacchio, Olly ha preso il controllo alla prima lettera inserita:


0040166C MOV EAX,SS:[ESP+C]
00401670 TEST EAX,80000000
00401675 JNZ SHORT 004016C8
00401677 AND EAX,0FF0000
0040167C CMP EAX,350000
00401681 JGE SHORT 004016C8
00401683 MOV AL,DS:[42B0C0] // mette in AL inizialmente il valore fisso 42
00401688 ADD DL,6 // somma alla lettera maiuscola inserita il valore 6
0040168B XOR DL,AL // xora DL con AL e mette il risultato in DL
0040168D MOV DS:[ECX+42D09C],DL // memorizza il risultato alla locazione 0042D09C+ECX
00401693 MOV AL,DS:[ECX+42D09C] // mette il valore precedentemente memorizzato in AL

00401699 CMP AL,30 // confronta AL con 30
0040169B JB SHORT 004016A1 // se è più piccolo salta
0040169D CMP AL,7A // confronta AL con 7A
0040169F JBE SHORT 004016AB // salta se AL è più piccolo o uguale a 7A
004016A1 ADD AL,21 // somma ad AL il valore 21
004016A3 MOV DS:[ECX+42D09C],AL // memorizza il risultato in 0042D09C+ECX
004016A9 JMP SHORT 00401693 // salta all'istruzione 00401693
004016AB MOV DL,DS:[42B0C0] // mette il valore contenuto alla locazione 0042B0C0
// in DL
004016B1 MOV BYTE PTR DS:[ECX+42D09D],0
004016B8 ADD DL,12 // somma 12 a DL
004016BB INC ECX // incrementa ECX
004016BC MOV DS:[42B0C0],DL // memorizza il nuovo valore di DL in 0042B0C0
004016C2 MOV DS:[42D0C4],ECX // salva in memoria il valore di ECX
004016C8 XOR EAX,EAX // azzera EAX
004016CA RETN 0C

Ecco il cuoricino del crackme, adesso si spiega perchè è così semplice individuare il serial. Cosa succede??? Piazziamo un breakpoint on execution sull'istruzione 00401683 e riavviamo tutto da capo. Ad ogni pressione di un tasto nel box di inserimento del nome viene effettuata una conversione a runtime. Ogni qual volta inseriamo una lettera, questa viene memorizzata in EDX in formato esadecimale corrispondente al valore della lettera maiuscola, ad esempio se s'inserisce la lettera v questa viene memorizzata come lettera V e quindi in memoria compare il valore esadecimale 56. Poi al valore viene sommato il 6 ed il risultato viene xorato con il valore di AL. Il risultato dello xor viene ulteriormente elaborato. Fino a che il valore risulta minore di 30 (hex) gli viene sommato il valore 21 (hex), successivamente si verifica se il valore è minore o uguale a 7A (hex), in caso positivo esce dal ciclo altrimenti gli somma 21 (hex) e si ricomincia. All'uscita da questo ciclo al valore 42 (hex) viene sommato il 12 (hex) ed il risultato viene memorizzato nella locazione 0042B0C0 che serve ad inizializzare il valore di AL per lo xor iniziale con la lettera inserita.

Guardiamo un esempio concreto per le prime 2 lettere del mio nome inserite:


Inserisco la lettera '''v''' = 56

56 + 6 = 5C
5C xor 42 = 1E
1E < 30 ??? SI
1E + 21 = 3F
3F < 30 ??? NO
3F <= 7A ??? SI

3F è la prima lettera
42 + 12 = 54 (nuovo valore memorizzato in 0042B0C0)

La prima lettera del serial è '''?''' ovvero rappresentata dal valore 3F.

Premo il tasto Play ed inserisco la lettera '''a''' = 41

41 + 6 = 47
47 xor 54 = 13
13 < 30 ??? SI
13 + 21 = 34
34 < 30 ??? NO
34 <= 7A ??? SI

34 è la seconda lettera
54 + 12 = 66 (nuovo valore memorizzato in 0042B0C0)

e così via per tutto il nome inserito

Alla fine si ottiene ?44356=>MM0 ovvero il seriale completo.

Il seriale generato permette di passare alla funzione PostMessageA prima il valore 8 e poi al successivo controllo il valore 9. That's All Falks


Il KeyGen

In base ai calcoli effettuati per la generazione del serial è molto semplice creare un Keygen in linguaggio C. Bastano infatti una manciata di istruzioni, guardate il listato seguente :


&#35;include <stdio.h>
&#35;include <string.h>

int main()
{
char nome[15];
unsigned int i;
int valore = 0x42;

printf("\n\n\nKeygen CrackMe N.29 coded by ValerioSoft\n\n");
printf("-----------------------------------------------------------------------\n");
printf("ATTENZIONE: Inserire un nome costituito solo da lettere alfabetiche!!!\n");
printf("ATTENZIONE: Il nome deve avere minimo 10 caratteri e massimo di 15!!!\n");
printf("-----------------------------------------------------------------------\n\n");
printf("Inserisci un nome: ");
scanf("%s", nome);

while (strlen(nome) > 15 || strlen(nome) < 10) {
printf("\nAttenzione il nome inserito non rispetta la lunghezza attesa!\n\n");
printf("Inserisci un nome: ");
scanf("%s", nome);
}

// converto il nome in lettere maiuscole
strupr(nome);

for(i=0; i<strlen(nome); i++) {
nome[i] = nome[i] + 0x06;
nome[i] = nome[i] ^ valore;
while (nome[i] < 0x30 || nome[i] > 0x7A) {
nome[i] += 0x21;
}
valore += 0x12;
}

printf("\n\nSERIAL: %s", nome);

// attende un carattere qualsiasi in ingresso
scanf("%s", nome);

return 0;
}


Note Finali

Un saluto caloroso a va a tutta la UIC!!!
Ciaoooooooooooooooooo alla proximaaaaaaaaa

ValerioSoft


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 malevoli 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.