Zoom Icon

Corso UIC Avanzato 02 Gotterdamerung

From UIC Archive

Secondo corso UIC Qualche trucco per la soluzione ;)

Contents


Corso UIC Avanzato 02 Gotterdamerung
Author: Gotterdamerung
Email: die.gotterdamerung(AT)gmail.com
Website:
Date: 22/08/2005 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Flag Italian.gif
Comments: Que: Grazie gotter, ottimo tutorial!!



Introduzione

Eccomi finalmente ad affrontare i corsi per studenti, e sono già al secondo!! :P


Tools

Per questo tutorial ci servirà un debugger qualsiasi per poter vedere il codice, ma molto più importante sarà avere un pizzico di astuzia e la conoscenza dello ZEN. Dimenticavo... un cervello funzionante è indispensabile! (Copyright degli aventi diritto :P)


Link e Riferimenti

La pagina dei Corsi per Studenti UIC


Essay

Questo corso è stato già strarisolto da un sacco di studenti, ma dopo averlo risolto per conto mio e aver controllato le soluzioni degli altri mi sono accorto che nessuno aveva detto una cosa fondamentale, inoltre ho trovato un piccolo trick per la registrazione; vado quindi a esporre questi due argomenti invece di risolvere normalmente il corso. (Que, scusa se mi faccio i caXXi miei :D )
Per affrontare questo tutorial è necessario leggersi le soluzioni precedenti, oppure aver già risolto il corso! Non pensate male, non sono uno sfaticato, ma penso che queste riflessioni dopo un lungo tutorial passerebbero inosservate.

Argomento 1: La lunghezza del nome

Non vi devo fare presente che anche su questo argomento sono state spese diverse parole, però si è sempre parlato della lunghezza _massima_ del nome, mai di quella minima, che, secondo me, è invece molto importante, e spero anche per voi dopo aver letto quello che vi vado a dire :)
Abbiamo notato che grazie ad un controllino il bravo Que ci presenta una finestrella contenente un errore se non viene inserito nessun username... ma perché?
Ebbene, come avete notato analizzando il codice (se non lo avete fatto tornate alle soluzioni precedenti!), esiste sì un limite massimo per il nome, pari a 4 caratteri, o almeno è quello su cui viene calcolato il seriale (poiché una Dword contiene 4 caratteri (ripeto, se non capite -> soluzioni già fatte!)) ma oltre al controllo sul nome vuoto, non esiste un controllo sulla lunghezza minima del nome!
Grazie a quelle due righe su cui il Que ha ripreso tanti studenti: mov edi,ecx; mul edi, durante la prima iterazione del ciclo, ovvero quando ecx è nullo, abbiamo già visto che la prima lettera genererà sempre lo stesso corrispondente nel seriale, ovvero 9, quindi, dato che il seriale è lungo esattamente quanto il nome, QUALSIASI nome di una sola lettera (ovvero qualsiasi lettera o carattere che vi passi per la tastiera) e il numero 9 costituiscono una coppia nome/seriale validi!!!
Abbiamo quindi un keymaker alternativo: void main (void)

 {
   printf("Inserisci un nome di una sola lettera: ");
   getchar();
   printf("Il seriale corrispondente e': 9\n :P :P :P");
 }

Questo conclude l'argomento; ovviamente l'importante non era trovare un nome e un seriale di un solo carattere, ma capire che se il seriale è ricavato dal nome, più corto è il nome e meno calcoli ci saranno fatti sopra (a volte) rendendo in questo modo molto più semplice lo studio di quello che accade durante la generazione del seriale.

Argomento 2: L'algoritmo di crittazione

Stavolta l'argomento è più serio... non è stato fatto notare molto (anche se qualcuno lo ha detto, scusate, ma non ricordo chi...) che il programma prende come carattere di fine stringa un byte posto a 00; questo è quello che provoca problemi se inserite un nome o un seriale troppo lungo, oppure se dopo uno lungo ne scrivete uno più corto (ci avevate mai provato?) perché il programma non ri-inizializza la zona di memoria dove scrive questi dati e quindi se trova altri byte, anche dopo quelli da noi immessi, che siano diversi da 00 continua nella sua analisi per la generazione del seriale.
Ma non è questo il problema che voglio trattare ora, magari guardatevelo con Olly, bensì quello inverso! Nella generazione del seriale infatti è presente una istruzione SHL 2 e una ROR 4, ma mentre la seconda istruzione non provoca perdita di bit, perché quelli spostati vengono riportati in cima, la prima CANCELLA i due bit più significativi del byte ottenuto finora, operazione che può portare all'azzeramento del byte che il programma sta 'crittando'.
Come 'e allora'??
Se il byte si azzera, al ciclo successivo, quando il seriale viene fatto rientrare tra 66h e 30h, trovando un byte azzerato prima della fine della stringa il ciclo terminerà prima di aver generato tutto il seriale, quindi fornendo un seriale corretto solo parzialmente (dal punto di vista della logica del programmatore, vero Que LOL NdQ ;)), ma funzionante!
Abbiamo detto e ridetto che il primo carattere del serial è e sempre sarà 9, quindi questa eccezione nel nostro caso può essere generata solo nei caratteri successivi al primo.
Prendendo in considerazione solo i tre cicli successivi al primo, ripassiamo cosa viene fatto per crittare il carattere da noi immesso:

     II ciclo      III ciclo      IV ciclo
    -------------------------------------
      xor 1         xor 2         xor 3
      mul 1         mul 2         mul 3
      -25           -25           -25
      +1            +2            +3
      xor 45        xor D1        xor FF
      +45           +D1           +FF
      shl 2         shl 2         shl 2
      ror 4         ror 4         ror 4
      -5            -5            -5

Siccome vengono spostati a sinistra gli ultimi 2 bit, avremo che 4 sono le possibili combinazioni di avere un byte finale nullo, ovvero che prima dello SHL ci sia uno di questi byte: 00010100 (14h); 01010100 (54h); 10010100 (94h); 11010100 (D4h), questi perché il ROR 4 è in particolare scambia i primi 4 bit con gli altri 4, quindi dopo lo SHL dei 4 byte qui sopra otterremo sempre 50h e dopo il ROR 4 questo diventerà 05h che grazie all'ultima sottrazione diventerà un bello 00.
Per sapere quali caratteri inserire nel nome per ottenere uno di questi byte basta fare le operazioni inverse rispetto all'algoritmo partendo dall'operazione subito prima di SHL 2, ovvero dove conosciamo quale byte usare, quindi a questo punto facciamo un bel tabellone e vediamo cosa succede facendo tornare questi quattro byte in cima alla catena di crittaggio :)

   ==============================================
   |  II ciclo  |  14h  |  54h  |  94h  |  D4h  |
   |------------+-------+-------+-------+-------|
   |    -45     |  CFh  |  0Fh  |  4Fh  |  8Fh  |
   |   xor 45   |  8Ah  |  4Ah  |  0Ah  |  CAh  |
   |    -1      |  89h  |  49h  |  09h  |  C9h  |
   |    +25     |  AEh  |  6Eh  |  2Eh  |  EEh  |
   |   div 1    |  AEh  |  6Eh  |  2Eh  |  EEh  |
   |   xor 1    |  AFh  |  6Fh  |  2Fh  |  EFh  |
   |------------+-------+-------+-------+-------|
   |   ASCII    |   ?   |  'o'  |  '/'  |   ?   |
   ==============================================
   ==============================================
   |  III ciclo |  14h  |  54h  |  94h  |  D4h  |
   |------------+-------+-------+-------+-------|
   |    -D1     |  43h  |  83h  |  C3h  |  03h  |
   |   xor D1   |  92h  |  52h  |  12h  |  D2h  |
   |    -2      |  90h  |  50h  |  10h  |  D0h  |
   |    +25     |  B5h  |  75h  |  35h  |  F5h  |
   |   div 2    |  imp  |  imp  |  imp  |  imp  |
   |   xor 2    |  ---  |  ---  |  ---  |  ---  |
   |------------+-------+-------+-------+-------|
   |   ASCII    |  ---  |  ---  |  ---  |  ---  |
   ==============================================
   ==============================================
   |  IV ciclo  |  14h  |  54h  |  94h  |  D4h  |
   |------------+-------+-------+-------+-------|
   |    -FF     |  15h  |  55h  |  95h  |  D5h  |
   |   xor FF   |  EAh  |  AAh  |  6Ah  |  2Ah  |
   |    -3      |  E7h  |  A7h  |  67h  |  27h  |
   |    +25     |  0Ch  |  1Ch  |  8Ch  |  4Ch  |
   |   div 3    |  04h  |  imp  |  imp  |  imp  |
   |   xor 3    |  07h  |  ---  |  ---  |  ---  |
   |------------+-------+-------+-------+-------|
   |   ASCII    |   ?   |  ---  |  ---  |  ---  |
   ==============================================

OK, siamo tornati in cima e possiamo vedere che nel secondo ciclo siamo riusciti a risalire a tutti e quattro i byte, anche se solamente due sono inseribili da tastiera (veramente grazie alla tabella ASCII potremmo inserire anche gli altri due, ma quando il prog fa il GetWindowTextA se controllate il buffer noterete che vengono presi dei valori diversi; immagino che dipenda dall'encoding del testo, ma non ne sono assolutamente sicuro), quindi inserendo in seconda posizione una 'o' o un '/' il ciclo di generazione del seriale si fermerà dopo aver generato solo il primo carattere, che abbiamo detto essere 9.
Nel secondo ciclo troviamo un div 2, che ci dà delle rotture di scatole, infatti i risultati non sono propriamente impossibili, ma danno un resto!
Questi risultati non possono essere accettati perché in realtà dobbiamo considerare che la routine di crittazione esegue un'operazione MUL 2 dopo la quale qualsiasi byte sarà pari... e come notate nessun byte prima del DIV 2 è pari...
Nel terzo ciclo la stessa solfa: possiamo risalire ad uno, che però non è digitabile da tastiera e gli altri tre danno dei resti nella divisione, quindi non sono accettabili.

Eccoci, ho finito di esporre quello che ho trovato di particolare in questo programmino... adesso sotto con il prossimo corso!

See ya on the last days...
-=Götterdämerung=-


Note Finali

Vorrei ringraziare veramente TANTISSIMO Quequero, ovviamente, per tutta la UIC e quello che ho imparato grazie ad essa, e AndreaGeddon, per i suoi crackme e perché risponde alle mie mail da niubbo.
Un saluto e un ringraziamento anche a tutto il chan #crack-it con cui riesco ad avere relazioni (solo verbali!).


Disclaimer

Vorrei ricordare che il software va comprato e non rubato, se volete registrare questo programma rivolgetevi all'iguana di Que. Non mi ritengo responsabile per eventuali problemi mentali dovuti all'uso improprio di questo tutorial in combinazione con il prog di Que. Questo documento è stato scritto per farvi capire che anche se non sembra tutto è importante e lo ZEN aiuta in ogni frangente della vita.

Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.