Incomedia 5.0
Trovare il seriale corretto


5/09/2000

by "Niutron"

5/09/2000

 

UIC's Home Page

Published by Quequero


Non discutere mai con un idiota...

Bravo Niutron, � un buon tute su un argomento ancora mai trattato alla UIC (e lo so che il VB vi sta antipatico, ma c'� anche lui, quindi...:)

La gente potrebbe non notare la differenza.

UIC's form
E-mail: [email protected]
Niutron, UIN, #crack-it, #cracking4newbies
UIC's form

Difficolt�

( )NewBies (x)Intermedio ( )Avanzato ( )Master

 

Oggi imparerete un nuovo modo di proteggere i programmi in VB. Vedo che gi� il disgusto si delinea sulle vostre facce al solo nominare di questo linguaggio, ma vedremo di rendere piacevole anche ci� che non lo �. Importante: questo � il Visual Basic in formato p-code. 


Incomedia 5.0
Trovare il seriale corretto
Written by Niutron

Introduzione

Premetto che questo lavoro mi � costato mesi di faticose ricerche in internet sul formato di protezione p-code: per molto tempo non ho ricavato nulla finch� non ho incontrato il mitico JosephCo_, l'inventore del disassembler che ci permetter� di sproteggere Incomedia. Quindi lo ringrazio tantissimo. Ciao e GRAZIE JosephCo_!!

Tools usati

Ora imparerete ad usare un nuovo tools, ESSENZIALE se in futuro vi imbatterete in un programma in p-code VB: il mitico Exdec, che trovate all'indirizzo
http://members.xoom.com/c4n4ever/.space/. In questa directory, troverete tre file: a voi ne interessano solo due: "msdbg.zip", che contiene i simboli (vedremo dopo cosa sono) e "betaexdec.zip", il disassembler.
E non poteva mancare lui, Softice.

URL o FTP del programma

Non � reperibile in rete (credo), ed � disponibile solo su ordinazione alla societ�. disponibile in versione demo su alcuni CD-ROM di alcune riviste.

Notizie sul programma 

Allora, questo bel programmone non � altro che un costruttore di ipertesti, abbastanza potente, ma allo steso tempo semplice da utilizzare: � composto da 5 programmi diversi (tra cui anche quello per l'esportazione del lavoro su CD). Durante l'avvio del setup di installazione viene richiesto un codice, che viene generato dall'analisi di due numeri (vedi mo tra poco di che si tratta); si pu� scegliere di inserire il codice (ed in tal caso il prodotto � funzionante al 100%) altrimenti continuare senza codice, attivando la versione demo che prevede, ad esempio, l'impossibilit� di salvare, oppure salare fino ad un certo numero di pagine, ecc.. Nota: il seriale pu� essere inserito solo dal setup (non c'� un menu che ti permette di inserirlo dopo).

Essay

Allora, mettevi comodi perch� non sar� molto semplice (a meno che non vi intendiate gi� di p-code). Spero di non arrivare a scrivere un enciclopedia (scusa Que :))), ma alcuni concetti fondamentali devo darveli altrimenti 'sto tutorial serve solo a vedere come ho lavorato io, senza essere di aiuto a nessuno. Per questo motivo non partiremo direttamente con l'utilizzo del disassembler di JosephCo_, ma dall'inizio inizio.
INIZIAMO
Facciamo partire il programma di installazione ("Setup.exe") e ci appare subito la schermata che ci mostra due codici ("Codice programma" e "Codice computer") e ce ne richiede un terzo "Codice Utente". Se inserite il codice errato vi appare il messaggio con scritto "Il codice Utente inserito non � valido". Chi � suicida, pu� tentare di fare "bpx hmemcpy". La vita non � abbastanza lunga per permetterci di esaminare tutte le call che ci sono. Quindi dobbiamo cambiare strategia. Controlliamo con Filemon, per vedere se c'� qualcosa di interessante. Facciamolo partire ed escludiamo i processi che possono disturbarci (Explorer, Kernel32, ...) e lanciamo di nuovo "Setup.exe" .... Cavoli! Quanta roba. Vabb� cominciamo a vedere le informazioni che ci sono fornite e ... aspetta un attimo. Guardate tra i nomi dei processi: oltre a "Setup.exe" � presente un altro file "Imsetup.exe". Tremendo sospetto! Perch�?? Guardate il nome: IMsetup = IncoMedia. Questo file � localizzato (lo si vede dal FileMon) in "C:\WINDOWS\SYSTEM\", ed � il vero file del programma di installazione, ovvero, il file "Setup.exe" ha una funzione di copertura: richiama infatti "Imsetup.exe", che rappresenta il vero obiettivo.
Piccola parentesi: sempre con Filemon, si ottiene un'altra informazione interessante: sempre in "C:\WINDOWS\SYSTEM\", � presente un file chiamato fxlbl50g.ocx che contiene il "Codice programma": se rimuovete tale file, il setup ne crea un'altro con un diverso codice. (Spunto per creare un Keygen). Il codice computer penso venga calcolato una volta sola, ma non so per certo da dove.
Ora che sappiano qual'� il vero obiettivo, non ci resta che concentrarci su "Imsetup.exe". Apriamo Win32DASM (con patch per il VB) e disassembliamo "Imsetup.exe" e... arggghhh. �String Data Reference� non � disponibile. Orrore e disgusto! Che fare? Possiamo provare con le �Imported Function�, ma non ricaveremmo niente di buono: solo VB e VB e VB.
Ma ecco che interviene il nostro JosephCo_ con il suo disassembler Exdec!
Prima di iniziare occorrono due parole: come configurarlo, come funziona e brevi cenni sul p-code.
 
CONFIGURARE EXDEC --> Estraete il contenuto dei due file zip che avete scaricato nella stessa cartella: il file "betaexdec.zip" � una versione (ma va?) beta del programma, che � in continuo aggiornamento, quindi ogni tanto visitate il sito per ottenere l'ultima release. All'interno del file zip troverete anche crackme di esempio e tutorial su come sproteggerli e su come funziona il p-code (leggeteveli tutti, anche se capite tutto in questo tutorial). Nell'altro file .zip si trovano i simboli, che sono quelli che dovrete caricare in SofIce. All'interno del file zip ne troverete 2: Msvbvm50.nms e Msvbvm60.nms. Avrete gi� capito che se volete reversare un'applicazione in VB5 userete Msvbvm50.nms, se in VB6 userete Msvbvm60.nms. A noi interessa Msvbvm50.nms. Quindi fate partire Loader32 (caricatore di simboli per SoftIce) che si trova nella cartella di SoftIce con il nome di "Loader32.exe". Cliccate sull'icona "Apri" (la prima a sinistra) e selezionate Msvbvm50.nms; poi premete l'icona subito dopo "Apri" per caricare i simboli. Infine chiudete Loader32.
Ora eseguite "Exdec.exe" e selezionate "File", "Disassemble Prog" (non selezionate l'icona con al cartella: serve per aprire il formato TXT di un listato decompilato e salvato) e selezionate "Imsetup.exe" e ... voil�, ecco il nostro listato. Ma come vi ho detto, il p-code � tutta un'altra cosa: quello che vedete non � ASM, quindi frenate il vostro entusiasmo.
 
CENNI SUL P-CODE --> Premetto che non mi soffermer� a lungo sulla spiegazione del p-code perch� troverete molte informazioni nel file "betaexdec.zip". Detto questo vi dico subito che il p-code � una cosa che non avete mai visto prima ed � TOTALMENTE (ed intendo TOTALMENTE) diversa dal codice ASM. Se osservate il listato prodotto da Exdec, noterete che gli indirizzi (indirizzi esadecimali) sono raggruppati in procedure che vengono identificate cos�: 
 
Proc: xxxxxx                                    <-- xxxxxx rappresenta l'indirizzo
 

414EF0: 7f ILdI2                                <-- Esempio di codice p-code

414EF3: 1c BranchF: 414F75                      <-- Esempio di codice p-code (salta a 414f75 se � falso)

414EF6: 04 FLdRfVar local_0086                  <-- Esempio di codice p-code

414EF9: 07 FMemLdRf                             <-- Esempio di codice p-code

414EFE: 24 NewIfNullPr 4056f4 (classSetupDef)   <-- Esempio di codice p-code

 

il funzionamento delle Proc � simile a quello delle call, con la differenza che tute le call terminano con RET (che in exdec corrispondono a ExitProc), mentre le Proc possono non avere questo parametro.
Nell'esempio sopra riportato notate che dopo l'indirizzo esadecimale (e i due punti) c'� una sequenza che ricorda il linguaggio ASCII: nel p-code questo rappresenta il nome che segue nel codice! Mi spiego. "7F = ILdI2" oppure "1c = BranchF" oppure "04 = FLdRfVar". Chiaro?
In mezzo a questi esempi, una particolare attenzione va data al comando BranchX (che in ASM equivale a JZ o JNZ), dove X pu� essere T (true) o F (false).
Ricordatevi, SEMPRE, che ASM � diverso da P-CODE, quindi un'istruzione che sembra scontata in ASM, in P-CODE pu� volere dire tutt'altra cosa. Vi faccio un esempio. In Sice, quando si analizza il p-code, per controllare la vostra posizione dovete sempre monitorare ESI (codice ESAdecimale): questo vi serve per sincronizzare la vostra posizione in Sice con quella nel disassembler, dato che il codice che vi appare � totalmente diverso. Sempre relativamente a Sice, va detto che anche i breakpoint vanno maneggiati in maniera diversa: una volta caricato il simbolo � necessario mettere il bpx su questo simbolo PRIMA DI AVVIARE IL PROGRAMMA, ponendo "bpx doexdisp"; poi si avvia il programma e, non appena si torna in softice si pone un "bpm" (non "bpx") sull'indirizzo desiderato (esempio: "bpm 413bd8").
Per questi motivi prestate attenzione alle istruzione che contengono parti tipo MOV EAX, 004175F6: in EAX non troverete nulla, ma se guardate sul disassembler potreste incontrare qualcosa di molto utile...
INIZIO REVERSING --> Dopo aver disassemblato il file cercate la stringa di errore "Il codice Utente inserito non � valido"; la troverete all'indirizzo 413C33. Il codice precedente � il seguente:
 
Proc: 413c80

413BD8: 04 FLdRfVar local_008C

413BDB: 21 FLdPrThis

413BDC: 0f VCallAd (object 6 )

413BDF: 19 FStAdFunc local_0088

413BE2: 08 FLdPr local_0088

413BE5: 0d VCallHresult ����

413BEA: 6c ILdRf local_008C

413BED: 0a ImpAdCallFPR4: _rtcR8ValFromBstr

413BF2: 74 FStFPR8 local_009C

413BF5: 04 FLdRfVar local_0092

413BF8: 6f FLdFPR8 local_009C

413BFB: e8 CI4R8

413BFC: 59 PopTmpLdAdStr local_0090

413BFF: 05 ImpAdLdRf: 421030

413C02: 24 NewIfNullPr 4027cc (classProtection)

413C05: 0d VCallHresult FORM::LoadProp                                          <-- Attenzione qui (vedere spiegazione)

413C0A: 6b FLdI2 local_0092

413C0D: 08 FLdPr local_param_0008

413C10: 8e MemStI2 local_param_0034

413C13: 2f FFree1Str local_008C

413C16: 1a FFree1Ad local_0088

413C19: 08 FLdPr local_param_0008

413C1C: 89 MemLdI2 local_param_0034

413C1F: f4 LitI2_Byte: 0x0 0 (.)

413C21: c6 EqI2

413C22: 1c BranchF: 413C64                                                      <-- Salta se... e dove salta? Dopo la stringa di errore!

413C25: 27 LitVar_Missing

413C28: 27 LitVar_Missing

413C2B: 27 LitVar_Missing

413C2E: f5 LitI4: 0x10 16 (....)

413C33: 3a LitVarStr: ( local_00AC ) Il codice Utente inserito non � valido.    <-- Stringa di errore

 
Controllate l'indirizzo 413C22: contiene un salto a 413C64, che si trova dopo il messaggio di errore, quindi prima di questa istruzione , da qualche parte, avviene il controllo per il codice esatto. E questo controllo avviene a 413C05. Mi chiedete: "Come si fa a dirlo?". Riposta: innanzitutto perch� tutta l'altra parte di codice � composta da istruzioni inutili (servono al programma, ma a noi non interessano) e poi perch� a questo indirizzo si trova una chiamata ad una dll esterna (faccio notare che poteva essere anche agli indirizzi 413BE5 e 413BED, ma nel 90% dei casi la call che nasconde i seriali � quella che precede il jump. Quindi dobbiamo mettere nei breakpoint a questa chiamata.
CTRL-D per entrare in Sice, digitiamo "bpx doexdisp" e facciamo partire il setup. Subito riappare Sice, togliamo i breakpoint ("bc *" o "bd *") e poniamo il nostro "bpm 413C05"; appare la richiesta del seriale, dove noi metteremo un numero a caso minore di 11 lettere altrimenti vi collassa il programma (bug?) e premiamo "Ok". Softice poppa (se non � cos� molto probabilemte non avete caricato il simbolo: rileggete il tutorial e controllate). Incominciamo a steppare con F10 cercando un "Call EAX" o "Call[EAX]", che indicano la chiamata alla Call che stiamo cercando. Quando la trovate entrate con F8 all'interno della Call e vedrete il seguente codice:

XOR EAX, EAX

MOV EDX, 00416A54                                               <-- !!!

PUSH _MethCallEngine

RET

Se vi ricordate cosa ho detto all'inizio, capirete che quel 00416A54 � in realt� una Proc (se scrivete "D 00416A54) non vedrete nulla. Quindi dobbiamo cercare questo indirizzo nel listato disassemblato, che ci appare cos�:

Proc: 416a54

 

............................

416956: 0a ImpAdCallFPR4: _rtcR8ValFromBstr

41695B: e8 CI4R8

41695C: 71 FStR4 local_00E8

41695F: 32 FFreeStr

416966: 36 FFreeVar

41696F: 00 LargeBos

416971: 6c ILdRf local_00E8

416974: 6c ILdRf local_00E4

416977: 80 ILdI4: local_param_000C

41697A: 0b ImpAdCallI2: pp_writecf                                <-- Chiamata a pppwin32.dll

41697F: 70 FStI2 local_013A

416982: 3c SetLastSystemError

416983: 6b FLdI2 local_013A

416986: 70 FStI2 local_0086

...........................

4169A3: 1a FFree1Ad local_0140

4169A6: 1c BranchF: 416A48                                        <--- Salta l'errore, quindi il controllo del codice � andato bene.

............................

4169D4: 27 LitVar_Missing

4169D7: 27 LitVar_Missing

4169DA: f5 LitI4: 0x10 16 (....)

4169DF: 1b LitStr: Errore nel controllo del codice Utente:

 
L'istruzione che ci interessa si trova in 41697A, dove viene eseguito il controllo del seriale. Ancora una volta: "Come si fa a dirlo?". Riposta: bisogna guardasi attorno. Se notate, all'indirizzo 4169DF, appare la stringa di un errore durante il controllo del codice: il salto avviene all'indirizzo 4169A6. Questo salto non indica se il codice � giusto o sbagliato, ma che il controllo per determinare se � giusto o sbagliato, � stato eseguito correttamente; quindi poco prima deve essere stato eseguito il check del serial. Come detto prima, la call che precede il salto �  nel 90% dei casi, la "colpevole".
Quindi dobbiamo mettere un "bpm 41697A", ma per farlo dobbiamo uscire dal Setup e rifare i passaggi iniziali ("bpx doexdisp", avviare il programma, quando Sice poppa, "bc *" o "bd *", mettere "bpm 41697A"); inseriamo il nostro serial e premiamo "Ok". Sice poppa, F10 e noi ci ritroviamo in questo codice:
 
PUSH EAX
PUSH ECX
PUSH EDX
CALL 02BB43F0
MOVSX EAX,AL
ADD ESP, AC
RET
 
L'unica strada � entrare in quella call (vedete nient'altro di interessante?) e FINALMENTE (ve lo dico io!) siamo dentro la call che contiene il controllo del seriale. I pi� esperti possono tentare di trovarlo da soli, mentre per chi vuole saperlo subito, il controllo termina in questo codice:
cmp esi, ecx
JZ (Salta a POP EDI, evitando lo XOR)                            <-- Se il seriale � esatto salta lo Xor
CMP AL, 12
JLE XXXXXXX
                                           <-- � il jump che compie il ciclo.
XOR AL, AL
POP EDI
POP ESI
POP EBX
RET
� fatta!!! Ormai � tutto chiaro: il primo CMP (quello che evita lo XOR), � quello che contiene i due seriali: il nostro (in ECX) e quello corretto (in ESI). Il secondo CMP � quello che ci rimanda indietro modificando il seriale fino a che non compie 12 giri.
Quindi dobbiamo vedere cosa c'� in ESI e in ECX, ma siamo in p-code, non dimenticatelo: se facessimo "d ESI" o "d ECX" vedremmo solo "?????????????", che indicano che i numeri che sono dentro ECX e ESI non si trovano quelli indirizzi. Ma neanche con "? ESI" "? ECX", poich� Sice ci fornirebbe indicazioni che non ci servono (abbiamo caricato i simboli per exdec, ricordate?): infatti apparirebbe qualcosa tipo "Unsigned Long = ..........". E allora? Dobbiamo utilizzare che ci permetta di vedere in memoria cosa c'�. Prima di caricare il simbolo per exdec, il comando era "?"; ora il comando � "?#": punto interrogativo con attaccato il cancelletto (ALT GR + �).
Scrivete dunque "?# ESI" per vedere il seriale corretto e "?# ECX" per vedere il vostro inserito.
                                                                                                                 Niutron
Note finali

Spero siate riusciti a capire come ho agito; certamente, questo tutorial non verr� mai preso come guida al p-code, per� ho tentato di fare il meglio possibile. Se avete domande, (o se volete segnalare errori o aggiunte) c'� il mio indirizzo e-mail. Cerco inoltre volonterosi reverser che contribuiscano alla creazione di un KeyGen. Ancora una volta ringrazio il mio supervisore JosephCo_, senza il quale non avrei mai capito il funzionamento di questa protezione. Grazie Jo!

Disclaimer

Vi ricordo 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: all'interno del tutorial non ho mai menzionato nulla che possa istigarvi ad utilizzare impropriamente quanto imparato. 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.