L8+ 5.2.8
(VB reversing con OllyDbg)

Data

by "Zero_G"

 

17/04/2004

UIC's Home Page

Published by Quequero

“To see a World in a grain of sand,

Come primo tutorial direi che va proprio bene, grazie Zero.

Hold Infinity in the palm of your hand,

And a Heaven in a wild flower,

Web Space: http://mio.discoremoto.virgilio.it/j_petrucci2000

E-mail: zero.g80 at gmail dot com

Account Passport .NET (MSN): j_petrucci@virgilio.it

And Eternity in an hour.”

- W.Blake -

Difficoltà

( )NewBies (X)Intermedio ( )Avanzato ( )Master

 

Introduzione

Salve a tutti! Questo è il mio primo tutorial (Que perdonami, sono davvero alle prime armi in questo senso, spero tu apprezzi i miei sforzi).

Si tratta di un intervento abbastanza semplice su un programma VB che spero sia d’aiuto alle persone che hanno avuto (o avranno) a che fare con programmi di questo tipo; la protezione è affidata in primis ad un controllo sulla presenza di un debugger ed in seguito ad una chiave di registrazione inseribile dall’interno del programma, generata in funzione dei propri dati personali. La cosa migliore in questi casi, come sempre, è quella di venire a capo dell’algoritmo che genera la chiave corretta in base a queste informazioni, ma purtroppo il tutorial che leggete è stato scritto in un periodo molto “busy”, e quindi per adesso illustro solamente come identificare la routine e patchare i controlli relativi al seriale usando OllyDbg. Ovviamente, se qualcuno si cimenterà poi a costruire anche un keygen… tanto meglio! A cosa serve la UIC se non ad imparare? J

PS: congratulazioni a Que per tutto l’impegno che metti in questo progetto: è grazie alla UIC che ho riscoperto la passione sopita per il Reverse Engineering ed ho capito che in Italia ci sono ancora persone che hanno voglia di imparare e di non aspettare che le cose cadano dal cielo (gratis).

Tools usati

OllyDbg 1.09 (al momento in cui scrivo, sul sito è presente anche una beta della versione 1.10)

IsDebuggerPresent plugin (nella pagina sono presenti anche molti altri utili plugin per OllyDbg. provateli)

[opzionale] VBDE 0.85 (per risalire agli offset delle funzioni VB)

                              (purtroppo questo programma non saprei davvero dirvi dove si trova, cmq nel tutorial non viene usato)

[opzionale] CodeFusion 3 (da usare per avere un eseguibile carino che patcha il file originale)

URL o FTP del programma

www.lottostatistica.com  (scaricate l8+ 5.2.8 versione full con possibilità di registrazione)

Notizie sul programma

L8+ è un software italiano scritto in VB in grado di fare elaborazioni statistiche e previsioni sulle estrazioni del Lotto, basandosi anche su un database delle estrazioni precedenti.

Essay

Ok, dopo le dovute premesse, cominciamo!

Per avere un’idea della protezione usata e di eventuali che appigli che ci permettono di risalire ad essa all’interno del codice, facciamo partire l8+ e dopo pochi secondi appare una finestra “Avvio in modalità FREE” che ci avverte (ma va?) che il programma non è stato registrato e che le sue funzionalità saranno limitate; dopo aver premuto OK ed aver o meno aggiornato il database delle estrazioni, il programma parte e sotto la voce “HELP” del menù scegliamo Registrazione.

Inserite pure i dati che preferite ed un codice qualsiasi tanto per vedere cosa succede; dopo aver premuto il pulsante Registra, appare la finestra “Errore – Chiave o dati errati” con la solita romanzina del programmatore a noi scapestrati; annotatevela da una parte, perché ci potrà servire in seguito. Bene, per adesso più di questo non possiamo fare… chiudete l8+, recatevi nella directory d’installazione (di solito “C:\Programmi\L8+52”) e fate una copia dell’eseguibile principale (“l8.exe”); dopodiché aprite OllyDbg e caricate il file originale.

Prendetevi pure qualcosa da bere e/o da ascoltare mentre il codice viene analizzato (questi programmi in VB sono dei grossi pachidermi, incubo di ogni disassemblatore) […] Finita l’analisi preliminare, possiamo iniziare a cercare qualcosa riguardo al controllo del seriale: premiamo con il tasto destro del mouse all’interno della finestra CPU e scegliamo “Search for…” àAll referenced text strings”; apparirà la lista delle stringhe reperibili all’interno del programma. A questo punto, sempre con il tasto destro scegliamo “search for text…” e cerchiamo quella stringa (ve la siete scritta?) che appariva a seguito del codice sbagliato (“I dati di registrazione non sono corretti”); dopo alcuni riferimenti ASCII ed UNICODE (tipici nei programmi VB) troveremo un istruzione MOV che fa riferimento proprio a questa stringa (in questo caso l’indirizzo in questione è 006A19FD). Clicchiamo due volte per evidenziarlo nella finestra principale e settiamoci sopra un bel breakpoint premendo F2.

A questo punto, facciamo partire il programma con F9 dall’interno di OllyDbg e, sorpresa sorpresina, appare una simpatica finestra che ci dice che per “problemi di sicurezza” (hanno paura dei reversers, eh?) il programma non si può avviare; o seguite le istruzioni e contattate gli autori (e poi che li dite? Che stavate crackando il loro amato l8+?) oppure intuite che il programma si accorge della presenza del debugger: la seconda mi sembra la più sensata…

Dalla sezione “stuph” nel sito del forum di OllyDbg si possono scaricare vari plugin tra cui uno molto utile in questi casi: IsDebuggerPresent. Nelle API di Windows esiste funzione omonima che permette di verificare la presenza in memoria di un debugger tramite controllo su hooks tipici. Il plugin rende OllyDbg invisibile proprio a questo tipo di controllo. Quindi, chiudete OllyDbg, scaricate il file ed estraetelo nella directory dei plugin; dopodiché potete far ripartire il debugger e sotto il menù “Plugins” troverete il nuovo giocattolo: selezionate “Hide”, ricaricate l’eseguibile di l8+ ed assicuratevi anche che nel menù “OptionsàDebugging OptionsàExceptions” siano spuntate tutte le caselle; quest’ultimo accorgimento aumenta la trasparenza di OllyDbg ad altre procedure anti-debugger. Infine, fate ripartire l8+ con F9… trattenete il respiro… E’ andata? Bene! 1 a 0 per noi!

OllyDbg memorizza nei file .UDD lo stato di ogni eseguibile disassemblato, quindi il breakpoint che avevate settato prima dovrebbe essere ancora al suo posto; in caso contrario, ripetete la procedura della ricerca delle stringhe. Dove eravamo rimasti prima? Alla registrazione, quindi, adesso recatevi sotto il menù “Help” e scegliete appunto “Registrazione”.

SUGGERIMENTO: inserite dei nomi *significativi* (tipo “pippo”, “paperino”, “123456”, ecc…) in modo che li possiate facilmente riconoscere durante il debug.

Quando premerete il pulsante “Registra”, se tutto è andato bene, dovrebbe apparire evidenziando la linea incriminata. Guardando un po’ più in basso, troviamo:

  006A19FD  MOV   DWORD PTR SS:[EBP-B8],L8.00499200    ; UNICODE "I dati di registrazione non sono corretti.
 Verificare attentamente che
i dati siano stati inseriti c"

  006A1A07  MOV   DWORD PTR SS:[EBP-C0],EDI               

  006A1A0D  CALL  ESI                                  ; MSVBVM60.__vbaVarDup

  006A1A0F  LEA   EDX,DWORD PTR SS:[EBP-B0]               

  006A1A15  LEA   EAX,DWORD PTR SS:[EBP-A0]               

  006A1A1B  PUSH  EDX                                     

  006A1A1C  LEA   ECX,DWORD PTR SS:[EBP-90]               

  006A1A22  PUSH  EAX                                     

  006A1A23  PUSH  ECX                                     

  006A1A24  LEA   EDX,DWORD PTR SS:[EBP-80]               

  006A1A27  PUSH  4030                                    

  006A1A2C  PUSH  EDX                              

  006A1A2D  CALL  DWORD PTR DS:[<&MSVBVM60.#595>]      ; MSVBVM60.rtcMsgBox

Dato che OllyDbg ci segnala gentilmente che all’indirizzo 006A1A2D viene eseguita una chiamata alla funzione MsgBox del VB, evidentemente siamo al punto in cui il seriale inserito è stato ritenuto non valido e sta per essere visualizzato il MessageBox contenente la solita tiritera che abbiamo incontrato all’inizio; dovremmo cominciare a seguire il percorso all’indietro per risalire al punto in cui vengono letti i dati e calcolato il seriale giusto.

Poco più in alto nel codice troviamo anche la famigerata good boy section:

  006A1857  MOV   DWORD PTR SS:[EBP-C8],L8.00499198    ; UNICODE "Benvenuto tra gli utenti di L8+!"

  006A1861  MOV   DWORD PTR SS:[EBP-D0],EDI

  006A1867  CALL  ESI                                  ; MSVBVM60.__vbaVarDup; <&MSVBVM60.__vbaVarDup>

  006A1869  LEA   EDX,DWORD PTR SS:[EBP-C0]

  006A186F  LEA   ECX,DWORD PTR SS:[EBP-80]

  006A1872  MOV   DWORD PTR SS:[EBP-B8],L8.00499010    ; UNICODE "Registrazione effettuata con successo.
Il programma e' ora pienamente funzionante e privo di limitaz"

  006A187C  MOV   DWORD PTR SS:[EBP-C0],EDI

  006A1882  CALL  ESI                                  ; MSVBVM60.__vbaVarDup

  006A1884  LEA   EDX,DWORD PTR SS:[EBP-B0]

  006A188A  LEA   EAX,DWORD PTR SS:[EBP-A0]

  006A1890  PUSH  EDX

  006A1891  LEA   ECX,DWORD PTR SS:[EBP-90]

  006A1897  PUSH  EAX

  006A1898  PUSH  ECX

  006A1899  LEA   EDX,DWORD PTR SS:[EBP-80]

  006A189C  PUSH  40

  006A189E  PUSH  EDX

  006A189F  CALL  DWORD PTR DS:[<&MSVBVM60.#595>]      ; MSVBVM60.rtcMsgBox

SUGGERIMENTO: Quasi tutti i programmi Visual Basic compilati sono costituiti da sezioni adibite a funzioni da eseguire in caso di eventi ben precisi (la pressione di un pulsante, il click del mouse, ecc…); in generale queste sezioni sono intervallate da un certo numero di NOP (no operation, codice 90) e cominciano tutte con le stesse istruzioni: infatti, se saliamo verso l’alto nel codice, vedrete passare un sacco di riferimenti sospetti a “Utente”, “Provincia”, “Citta”, “CodiceReg”, ecc…, ed arriverete all’indirizzo 006A0BA0, dove con grande probabilità potete supporre che inizi la procedura relativa al click sul pulsante “Registra”:

  006A0B8A   |  ……………………………………………………………………………………………

  006A0B91   |  ……………………………………………………………………………………………                       

  006A0B92   8BE5         MOV   ESP,EBP                               ;  istruzioni della funzione precedente

  006A0B94   5D           POP   EBP                                   ;  0012E978

  006A0B95   \  C2 0400      RETN  4                                     ;  fine della funzione precedente_________________

  006A0B98      90           NOP                                         ;  inizio dei NOP di riempimento

  006A0B99      90           NOP                                         ;

  006A0B9A      90           NOP                                         ;

  006A0B9B      90           NOP                                         ;

  006A0B9C      90           NOP                                         ;

  006A0B9D      90           NOP                                         ;

  006A0B9E      90           NOP                                         ;

  006A0B9F      90           NOP                                         ;  fine dei NOP di riempimento____________________

  006A0BA0   /> 55           PUSH  EBP                                   ;  inizio della funzione pseudo-onRegistraClick

  006A0BA1   8BEC         MOV   EBP,ESP                               ;  seguono le inizializzazioni VB standard

  006A0BA3   83EC 0C      SUB   ESP,0C

  006A0BA6   68 26DB4000  PUSH  <JMP.&MSVBVM60.__vbaExceptHandler>    ;  SE handler installation

  006A0BAB   64:A1 000000>MOV   EAX,DWORD PTR FS:[0]

  006A0BB1   50           PUSH  EAX

  006A0BB2   64:8925 0000>MOV   DWORD PTR FS:[0],ESP                 

  006A0BB9   |  ……………………………………………………………………………………………

  006A0BBF   |  ……………………………………………………………………………………………

Bene, a questo punto potete piazzare un breakpoint direttamente alla riga 006A0BA0 per seguire meglio il flusso del programma subito la pressione del pulsante “Registra”; premete CTRL+F2 e poi F9 per riavviare l8+. Ritornate alla registrazione, inserite i dati di nuovo (noioso, vero?), premete “Registra” e voilà, siamo all’inizio della nostra funzione!

SUGGERIMENTO: in giro (non per strada, su Internet! J) si trovano utility (tipo VBDE 0.85 di IorIor) che decompilano direttamente i programmi VB, indicando a che indirizzo sono presenti le funzioni eseguite dopo gli eventi, proprio come quella che abbiamo trovato noi manualmente; purtroppo spesso i riferimenti non vengono rilevati correttamente a causa del calcolo errato del RVA ed altri inconvenienti, ed in ogni caso facendo come abbiamo visto noi si impara molto di più!

Cominciamo a scorrere con F8 le istruzioni tenendo sempre d’occhio i registri (riquadro in alto a DX) e lo stack (in basso a DX), in quanto se OllyDbg vedrà passare dalla memoria una stringa od un riferimento ad essa la evidenzierà in queste finestre ed anche a fianco alle relative istruzioni nel disassemblato.

Dopo tutte le menate di inizializzazione del VB (265 istruzioni! L) arriva finalmente il momento in cui il primo campo che abbiamo inserito (il nome; io ho scritto “PINCO”) viene caricato in memoria e ciò avviene all’indirizzo 006A0CBD; nel piccolo riquadro in basso sotto il disassmeblato viene mostrata una breve descrizione dell’istruzione corrente, ed infatti in questo caso c’è scritto: Stack SS:[0012E950]=001BD16C, (UNICODE “PINCO”), trasformando gli indirizzi relativi dell’istruzione 006A0CBD in quelli assoluti.

  006A0CB0  . PUSH  L8.00481030

  006A0CB5  . PUSH  EDI

  006A0CB6  . PUSH  EAX

  006A0CB7  . CALL  DWORD PTR DS:[<&MSVBVM60.__vbaHresult>    ; MSVBVM60.__vbaHresultCheckObj

  006A0CBD  > MOV   EAX,DWORD PTR SS:[EBP-1C]                 ; il nome viene caricato in EAX

  006A0CC0  . PUSH  EAX

  006A0CC1  . CALL  DWORD PTR DS:[<&MSVBVM60.#519>]           ; MSVBVM60.rtcTrimBstr

  006A0CC7  . MOV   EDX,EAX

  006A0CC9  . LEA   ECX,DWORD PTR SS:[EBP-20]

  006A0CCC  . CALL  DWORD PTR DS:[<&MSVBVM60.__vbaStrMove>    ; MSVBVM60.__vbaStrMove

  006A0CD2  . PUSH  EAX

  006A0CD3  . CALL  DWORD PTR DS:[<&MSVBVM60.__vbaLenBstr>    ; MSVBVM60.__vbaLenBstrB

  006A0CD9  . MOV   EDI,EAX

  006A0CDB  . LEA   ECX,DWORD PTR SS:[EBP-20]

Le istruzioni successive fanno vari lavoretti di prassi con il nome, ma niente di importante per i nostri fini (nei programmi in VB dovete abituarvi a scremare molto la grande di quantità di assembly che il compilatore crea). Se continuate fino all’indirizzo 006A0D08, troverete un JNZ che controlla che siano stati inseriti tutti i campi, infatti:

  006A0D02  .  ADD   ESP,18

  006A0D05  .  CMP   DI,BX

  006A0D08  ./-JNZ   SHORT L8.006A0D1C                        ; il campo corrente è vuoto ?

  006A0D0A  .| MOV   ECX,DWORD PTR SS:[EBP-18]                ; se no, rinizializza le variabili

  006A0D0D  .| MOV   EAX,1                                    ;

  006A0D12  .| ADD   ECX,EAX                                  ;

  006A0D14  .| MOV   DWORD PTR SS:[EBP-18],ECX                ;

  006A0D17 ^.| JMP   L8.006A0C4B                              ; e continua con il prossimo campo

  006A0D1C  .\>MOV   ESI,DWORD PTR DS:[<&MSVBVM60.__vbaVar>   ; altrimenti visualizza un MessageBox di errore

  006A0D22  .  MOV   ECX,80020004

  ……………………     ………………………………………………………………………………………………………………………

  ……………………     ………………………………………………………………………………………………………………………

  006A0D6D  .  LEA   ECX,DWORD PTR SS:[EBP-80]

  006A0D70  .  MOV   DWORD PTR SS:[EBP-B8],L8.00498E48        ; UNICODE "Non sono stati inseriti tutti i dati di registrazione."

  006A0D7A  .  MOV   DWORD PTR SS:[EBP-C0],EDI

  ……………………     ………………………………………………………………………………………………………………………

  ……………………     ………………………………………………………………………………………………………………………

  006A0D9C  .  PUSH  EDX

  006A0D9D  .  CALL  DWORD PTR DS:[<&MSVBVM60.#595>]          ; MSVBVM60.rtcMsgBox

Se abbiamo inserito tutti i campi della registrazione e continuiamo con il debug, ci accorgiamo quindi che il JMP verso 006A0C4B viene eseguito per ognuno di essa e la routine prosegue caricando anche tutti gli altri campi (Cognome, Indirizzo, ecc…). Per quante volte viene eseguito questo ciclo? Guardiamo poco più sotto l’indirizzo a cui tutte le volte ci riporta il JMP:

  006A0C4B  >  MOV   EAX,6

  006A0C50  .  CMP   WORD PTR SS:[EBP-18],AX

  006A0C54  .  JG    L8.006A0DA8

EAX (e quindi anche AX) diventa uguale a 6 e viene confrontato con l’area di memoria nello stack puntata da EBP-18: quando il debug si trova all’indirizzo 006A0C50, diamo un’occhiata nel riquadro sotto il disassemblato per vedere cosa è confrontato con 6… ma guarda un po’… OllyDbg dice: Stack SS:[0012E954] = 000x, dove x, se ci abbiamo fatto caso, valeva 0 quando abbiamo visto passare “PINCO”, 1 quando è stato caricato “PALLINO”, 2 mentre si caricava l’indirizzo, e così via; si può facilmente intuire (oppure lo si può verificare manualmente guardando quell’indirizzo nello stack in basso a dx) che quello sia proprio il contatore che permettere di scorrere i campi del form. Quando questo è arrivato a 7 vuol dire che tutti i 7 campi (si conta da 0 a 6) sono stati elaborati, ed è ora di passare alle successive istruzioni (in questo caso si salta all’indirizzo 006A0DA8).

Lasciando scorrere un po’ di cianfrusaglia, arriviamo sani e salvi all’indirizzo 006A0E18, dove finalmente vediamo comparire la stringa contenente il nome da noi inserito, che viene caricato in EAX, pushato nello stack per diventare parametro di vbaLenBstr, funzione che ne calcola la lunghezza e la scrive in EAX:

  006A0E18  >  MOV   EAX,DWORD PTR SS:[EBP-1C]

  006A0E1B  .  PUSH  EAX

  006A0E1C  .  CALL  DWORD PTR DS:[<&MSVBVM60.__vbaLenBstr>    ; MSVBVM60.__vbaLenBstr

  006A0E22  .  XOR   ECX,ECX                                   

  006A0E24  .  CMP   EAX,3                                     ; EAX == 3 ?

  006A0E27  .  SETL  CL

  006A0E2A  .  NEG   ECX

  006A0E2C  .  MOV   WORD PTR SS:[EBP-104],CX

  006A0E33  .  LEA   ECX,DWORD PTR SS:[EBP-1C]

  006A0E36  .  CALL  DWORD PTR DS:[<&MSVBVM60.__vbaFreeStr>    ; MSVBVM60.__vbaFreeStr

  006A0E3C  .  LEA   EDX,DWORD PTR SS:[EBP-40]

  006A0E3F  .  LEA   EAX,DWORD PTR SS:[EBP-3C]

  006A0E42  .  PUSH  EDX

  006A0E43  .  PUSH  EAX

  006A0E44  .  PUSH  2

  006A0E46  .  CALL  DWORD PTR DS:[<&MSVBVM60.__vbaFreeObj>    ; MSVBVM60.__vbaFreeObjList

  006A0E4C  .  ADD   ESP,0C

  006A0E4F  .  CMP   WORD PTR SS:[EBP-104],BX

  006A0E56  .  JE    L8.006A0EEC                               ; il salto si fa se il nome è più lungo di 3 caratteri

  ……………………     ………………………………………………………………………………………………………………………   ; altrimenti viene mostrato un MessageBox di errore

  ……………………     ………………………………………………………………………………………………………………………

  006A0E93  .  MOV   DWORD PTR SS:[EBP-B8],L8.00498EBC         ; UNICODE "Dati non corretti."

  ……………………     ………………………………………………………………………………………………………………………

  ……………………     ………………………………………………………………………………………………………………………

  006A0EC7  .  PUSH  ECX

  006A0EC8  .  CALL  DWORD PTR DS:[<&MSVBVM60.#595>]           ; MSVBVM60.rtcMsgBox

Dopodiché, se la lunghezza è maggiore di 3, dall’indirizzo 006A0E56 si prosegue con il flusso all’indirizzo 006A0EEC.

Il Ciarpame continua (stavolta con la “C” maiuscola perché non si vedono altro che chiamate alle API per 786 volte… L), fino a che giungiamo all’indirizzo 006A11E6, dove finalmente vediamo passare le nostre beneamate stringhe (ora capite perché vi avevo detto di non scrivere lettere a caso?) che vengono ripescate dalla memoria (se volete, potete controllarne il dump della memoria in basso a SX) e passate ad una funziona stranamente non VB (possiamo notare i dati anagrafici ordinati in fila come soldatini nello stack in basso a DX, ed in cima l’indirizzo di return della CALL)…

  006A11E6  >  MOV   EDX,DWORD PTR SS:[EBP-30]

  006A11E9  .  MOV   EAX,DWORD PTR SS:[EBP-2C]

  006A11EC  .  MOV   ECX,DWORD PTR SS:[EBP-28]

  006A11EF  .  PUSH  EDX                                        ; PUSH della stringa della provincia nello stack

  006A11F0  .  MOV   EDX,DWORD PTR SS:[EBP-24]

  006A11F3  .  PUSH  EAX                                        ; PUSH della stringa della località nello stack

  006A11F4  .  MOV   EAX,DWORD PTR SS:[EBP-20]

  006A11F7  .  PUSH  ECX                                        ; PUSH della stringa della CAP nello stack

  006A11F8  .  MOV   ECX,DWORD PTR SS:[EBP-1C]

  006A11FB  .  PUSH  EDX                                        ; PUSH della stringa dell’indirizzo nello stack

  006A11FC  .  PUSH  EAX                                        ; PUSH della stringa del cognome nello stack

  006A11FD  .  PUSH  ECX                                        ; PUSH della stringa del nome nello stack

  006A11FE  .  CALL  L8.0054B760                                ; chiamata alla funzione che calcola il seriale

IMMAGINE DELLO STACK (in basso a DX) PRIMA DELLA CHIAMATA ALLA FUNZIONE ALL’INDIRIZZO 006A11FE:

(ricordatevi che l’ordine degli argomenti “pushati” è inverso rispetto a quello accettato dalla funzione)

  0012E7B0  RETURN to L8.006A1203 from L8.0054B760   

  0012E7B4  UNICODE "PINCO"

  0012E7B8  UNICODE "PALLINO"

  0012E7BC  UNICODE "VIA XYZ"

  0012E7C0  UNICODE "06660"

  0012E7C4  UNICODE "HELL"

  0012E7C8  UNICODE "XX"

A questo punto, le strade sono due:

1)     premere comodamente F8 (step over) e sperare che il risultato della funzione venga scritto in chiaro in qualche registro o in una locazione di memoria facilmente rintracciabile.

2)     premere F7 (step into) e seguire passo passo la funzione cercando di capire le operazioni che vengono svolte sui nostri dati, in modo da ricostruirne l’algoritmo e creare eventualmente un keygen.

Bene, come accennato all’inizio, in questo tutorial mi limiterò a fare del mero serial fishing, ma i più volenterosi possono tranquillamente avventurarsi nella giungla di chiamate (AnsiValueBstr, MidCharBstr, LenBstr, ecc…) che questa funzione esegue; SUGGERIMENTO: il seriale è nella forma xxxx-xxxx-xxxx-xxxx, dove ogni x è una cifra da 0 a 9.

Per nostra fortuna, come di solito accade in VB, i risultati delle funzioni vengono piazzati nel registro EAX, ed anche in questo caso, se premiamo F8, lì vedremo apparire una stringa UNICODE nel formato sopra accennato. Ottimo! J siamo praticamente sicuri che una cosa del genere non possa che essere il codice che ci serve, infatti poco più avanti troviamo:

  006A11FE  .  CALL  L8.0054B760                                  ; funzione che calcola il seriale

  006A1203  .  MOV   EDX,EAX

  006A1205  .  LEA   ECX,DWORD PTR SS:[EBP-38]

  006A1208  .  CALL  DWORD PTR DS:[<&MSVBVM60.__vbaStrMove>]      ; MSVBVM60.__vbaStrMove

  006A120E  .  MOV   EDX,DWORD PTR SS:[EBP-34]

  006A1211  .  PUSH  EAX

  006A1212  .  PUSH  EDX

  006A1213  >  CALL  DWORD PTR DS:[<&MSVBVM60.__vbaStrCmp>>]      ; MSVBVM60.__vbaStrCmp

  ……………………     ………………………………………………………………………………………………………………………

  ……………………     ………………………………………………………………………………………………………………………

  006A1290  .  JE    L8.006A193E                                  ; good/bad boy jump

  006A1296  .  MOV   ECX,DWORD PTR DS:[ESI]

  006A1298  .  PUSH  ESI

  006A1299  .  CALL  DWORD PTR DS:[ECX+308]

La chiamata alla funzione StrCmp ha come parametri il seriale da noi inserito e quello calcolato dalla funzione precedente: beh, mi sembra sufficientemente chiaro che è questo il controllo decisivo che permette al programma di controllare se il nostro seriale è uguale a quello che si genera in base ai nostri dati.

Come ulteriore verifica, se scendiamo un altro po’ nel codice, ci accorgiamo che all’indirizzo 006A1290 c’è un salto condizionato: cliccando su quella riga con il mouse, OllyDbg ci indica che in questo caso (cioè con il seriale sbagliato) il salto verso verrà eseguito e premendo INVIO ci troveremo nella sezione (006A193E) in cui viene preparato il MessageBox di errore che abbiamo individuato all’inizio del tutorial. Il cerchio si è chiuso. J

Annotatevi il seriale, chiudete OllyDbg e riavviate l8+: nella finestra di registrazione inserite i dati di prima ed il numero che avete trovato e voilà! Un'altra recluta dell’esercito dei programmi VB è caduta sotto i colpi dell’artiglieria reverser

Note finali

Grazie a tutta la UIC ed a tutte le persone che la frequentano.

Grazie ai Dream Theater per comporre la musica che adoro. Ok questi li ringrazio anche io ;p NdQue

Grazie ad Escher per averci fatto vedere come si disegna l’infinito.

Grazie a Tolkien per aver dato vita al più fantastico ed epico dei mondi.

Disclaimer

Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly