Zoom Icon

Corso UIC Avanzato 02 Syscalo

From UIC Archive

Corso UIC Avanzato 02 Syscalo

Contents


Corso UIC Avanzato 02 Syscalo
Author: Syscalo
Email: [email protected]
Website: Home page
Date: 16/09/1999 (dd/mm/yyyy)
Level: Very Easy, if you can read this, you can do it
Language: Italian Flag Italian.gif
Comments:



Tools

  • Softice: è sufficiente questo.
  • wdasm: solo per stampare parte del listato per avere qualcosa da leggere al ..... ;))


Link e Riferimenti

Questo è il Corsi UIC Avanzati n°02 disponibile alla pagina Corsi per Studenti


Introduzione

Ho pensato di impostare il tutorial nel seguente modo:

  • spiegazione della generazione del seriale mantenendo solo le istruzioni necessarie.
  • spiegazione del perché sono state eliminate certe istruzioni.

Questo programma richiede nome e seriale: il seriale giusto viene generato dal nome e viene confrontato direttamente con il seriale inserito che non viene modificato in alcun modo (meno lavoro per noi ;) Ma allora siete dei lavativi???? :)


Essay

Cominciamo: come anticipato ora spiegherò l'algoritmo di generazione del seriale. Alcune osservazioni:

  • quando scrivo "salta alla label loc_xxxxxx" il valore xxxxxx è lo stesso che viene visualizzato in softice come indirizzo dell'istruzione a cui salterà.
  • le istruzioni jg e jl sono salti condizionati per numeri con segno. È importante ricordarselo quando si eseguono i confronti.
  • chr sta per carattere :)

Ecco il codice:

   	push   	00000019  caratteri max da leggere: in questo caso il 

valore è esagerato (credo volontariamente) visto che il max di chr inseribili nel campo nome del programma è 4

  	push   	0040219F // locazione in cui verrà salvato il nome inserito
  	push   	dword ptr [004020D7]   	
  	call   	GetWindowTextA // chiamata alla funzione per acquisire il nome
  	xor   	ecx,ecx // azzera il registro ecx

loc_401215: mov al, byte ptr [ecx+0040219F] carica in al il cod. ASCII dal 1° chr del nome

  	test   	eax, eax   	|
  	jz   	short loc_401279 // se il nome è terminato salta alla label loc_401279
  	xor   	al, cl // xora al con cl (che mantiene il conteggio dei chr)
  	mov   	edi, ecx // copia ecx in edi
  	mul   	edi  moltiplicazione senza segno: esegue eax×edi e 

salva il risultato in eax (da qui si capisce perché tutti i seriali generati iniziano per 9: infatti edi al primo ciclo è uguale a 0 quindi "annulla" l'effetto dell'acquisizione del 1° chr del nome azzerando eax)...quindi per Que e Due verrà generato lo stesso codice ;))

  	sub   	al, 25h // sottrae 25h ad al
  	add   	al, cl // somma cl ad al
  	xor   	al, byte ptr [ecx+00402000]  xora al con il byte 

all'indirizzo 00402000+ecx: in questo modo il valore con cui vengono xorati i chr varia per ognuno di essi. Per trovare i valori usati come maschera è sufficiente dare in softice il comando "d 00402000" e leggere i primi 4 byte visualizzati.(ovviamente in softice deve essere in esecuzione il file due.exe :)

  	add   	al, byte ptr [ecx+00402000] // somma ad al lo stesso valore con 

cui è stato xorato

  	shl   	al, 2 // esegue 2 shift a sinistra su al
  	ror   	al, 4  esegue 4 rotazioni a destra su al (queste sono 

operazioni logiche che servono a modificare un po' il valore di al, usate per variegare un po' le istruzioni invece di avere solo add e xor ;)

  	sub   	al, 5 // sottrae 5h ad al
  	mov   	byte ptr [ecx+0040218F], al  salva al alla locazione 

0040218F+ecx (serve per riprendere il codice per le modifiche successive) A

  	inc   	ecx // incrementa ecx di 1 (conteggio # chr)
  	jmp   	short loc_401215  salta alla label loc_401215 (in 

pratica riesegue le istruzioni precedenti fino alla terminazione del nome)

loc_401279: xor ecx, ecx // azzera ecx loc_40127B: mov al, byte ptr [ecx+0040218F] carica in al il valore modificato nel ciclo precedente (vedere A )

  	test   	al, al
  	jz   	loc_401331  se il nome (modificato) è terminato salta 

alla label loc_401331. Alla label loc_401331 ci sono parte delle istruzioni inutili. Queste fanno delle elaborazioni sul codice ma salvano il risultato in locazioni di memoria che non vengono cagate per niente nel controllo finale: in sostanza il codice generato dal nome rimane invariato! Dopo queste istruzioni si passerà all'acquisizione del seriale da noi inserito e al controllo con il codice generato dal nome. ( vedere X )

  	cmp   	al, 66h 
  	jg   	loc_40131B  confronta al con 66h e se è maggiore salta
alla label loc_40131B ( B )

loc_401291: cmp al, 30h |

  	jl   	loc_401326  confronta al con 30h e se è minore salta 

alla label loc_401326 ( C ) loc_401299: inc ecx // incrementa di 1 ecx (conteggio chr)

  	mov   	byte ptr [ecx+004021A7], al  salva al (eventualmente 

modificato) alla locazione 004021A7+ecx (avendo incrementato ecx prima di questa istruzione il codice generato dal nome avrà inizio dalla locazione 004021A8 che è quella che poi viene letta al momento del confronto con il seriale inserito)

  	jmp   	short loc_40127B  salta alla label loc_40217B (ripete 

le istruzioni precedenti fino alla fine del nome)

loc_40131B: sub al, 12h // sottrae 12h ad al

  	cmp   	al, 66h 
  	jg   	short loc_40131B  se al è maggiore di 66h salta alla 

label loc_40131B (in pratica continua a sottrarre 12h ad al fino a quando diventa minore di 66h)

  	jmp   	loc_401291  riprende l'esecuzione dall'istruzione 

successiva a quella che ha generato il salto a loc_40131B ( vedere B )

loc_401326: add al, 18h // somma 18h ad al

  	cmp   	al, 30h 
  	jl   	short loc_401326  se al è minore di 30h salta alla 

label loc_401326 (in pratica continua a sommare 18h ad al fino a quando diventa maggiore di 30h)

  	jmp   	loc_401299  riprende l'esecuzione dall'istruzione 

successiva a quella che ha generato il salto a loc_401326 ( vedere C )

Ok, la generazione del seriale è terminata. Ora spiegherò perché certe istruzioni sono state eliminate. Dovete avere sott'occhio il listato completo. Consideriamo il primo ciclo di istruzioni di elaborazione del seriale, cioè quello che inizia con la label loc_401215 e termina con l'istruzione jmp short loc_401215: in questo ciclo ci sono diverse istruzioni che modificano il registro bl (o ebx); bhe queste sono tutte inutili perché al termine del ciclo il risultato non viene salvato da nessuna parte (mentre il registro al si) ed inoltre nessuna di queste operazioni influenza il valore di al o condiziona in qualche modo il flusso del programma (per intenderci non ci sono istruzioni di controllo sul valore del registro bl che vadano ad esempio a condizionare dei salti). Dimenticavo: appena dopo la chiamata a GetWindowTextA viene effettuato un controllo sul primo chr; se questo è nullo viene visualizzato il messaggio "Wè son mica scemo!!! :)" che Que ha simpaticamente inserito per scoraggiare chiunque pensasse che il programma funzionasse anche senza codici :) (in realtà serve anche ad evitare che venga elaborato il nome se premiamo il tasto register senza inserire alcun valore nel campo nome) Per quanto riguarda il secondo ciclo (da loc_401279 a jmp short loc_40127B) questo è tutto da tenere, nessuna istruzione per confonderci ;) Il terzo ciclo invece è proprio stato creato SOLO per premere un po' di F8 in softice! Infatti, come accennato durante la spiegazione della generazione del seriale, è vero che qui vengono effettuate delle elaborazioni sul nome modificato e che vengono salvati i risultati, ma è anche vero che le locazioni di memoria dove vengono salvati, oltre a sovrascriversi a vicenda, non vengono considerate per niente dal programma quando deve effettuare il controllo per decidere se il nostro codice è buono o se siamo solo dei fannulloni che inseriscono numeri a caso sperando che funzioni ;)) Siamo arrivati al momento della verità: il superprogramma verifica la bontà del nostro seriale.

loc_4012C8: push 19h // ( X )

  	push   	004021A3 
  	push   	dword ptr  [004020DB]
  	call   	GetWindowTextA  acquisisce il seriale da noi inserito; 

per vederne il cod. ASCII in softice: d 004021A3

  	xor   	ecx, ecx // azzera ecx
  	mov   	eax, dword ptr [ecx+004021A3]  carica in eax il seriale 

da noi inserito

  	mov   	ebx, dword ptr [ecx+004021A8] carica in ebx il seriale 

generato dal nostro nome (quindi se vi interessa solo trovare il vostro seriale arrivate fino qui e leggete il contenuto di ebx oppure usate il mio key generator

:)
  	inc   	ecx // incrementa di 1 ecx
  	cmp   	eax, ebx // confronta seriale inserito e seriale calcolato dal nome
  	jnz   	short loc_4012A2  se sono diversi salta a loc_4012A2 

(visualizza "Serial sbagliato :(" )

  	mov   	al, byte ptr [ecx+004021A3] // altrimenti carica in al il 2° chr del seriale inserito
  	mov   	bl, byte ptr [ecx+004021A8] // carica in bl il 2° chr del seriale calcolato dal nome
  	test   	al, al	|
  	jz   	short loc_401303  se al è uguale a 0 salta a loc_401303 

(visualizza "Chiave indovinata...Complimenti!!!") (in realtà questa condizione si verifica solo se il nome inserito è di una sola lettera (qualsiasi) e se il seriale inserito è 9; se non capite perché proprio 9 rileggete la descrizione della generazione del seriale)

  	cmp   	al, bl // altrimenti confronta al e bl
  	jnz   	short loc_4012A2  e se sono diversi salta a loc_4012A2 

(visualizza "Serial sbagliato :(" ) (questa condizione invece non si verificherà mai perché se arriviamo ad eseguirla vuol dire che seriale inserito e seriale calcolato sono uguali quindi è impossibile che i secondi chr siano diversi;

credo sia stata inserita per fare in modo di fregare il cracker poco attento (e 

un po' stantito...battutaccia :) che pensi di risolvere il tutto noppando i jump precedenti :)

  	jmp   	short loc_401303  salta all'istruzione successiva 

(visualizza "Chiave indovinata...Complimenti!!!")

loc_401303:// qui ci sono le istruzioni che visualizzano il messaggio "Chiave indovinata...Complimenti!!! Ci siamo! Potete rilassarvi, è tutto finito :)

Ciao a tutti

Syscalo


Note Finali

Spero che vada tutto bene e che sia comprensibile ciò che ho scritto.

Un saluto a tutta la UIC...

...e un fuck a Tiscali che nel momento in cui scrivo non mi permette di spedire la posta e di aggiornare i ng salutandomi con un messaggio di errore originale come "You have no permission to talk. Goodbye" (almeno più innovativo di quelli di windows )

Un ringraziamento va a Int19 che si è reso disponibile per un confronto su questa lezione! Poi ti spiegherò quale era il mio problema :-{


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.