Opera 7.54u
(e una vecchia promessa...)

Data

by "LordMoon"

 

30/4/2005

UIC's Home Page

Published by Quequero

Io non ho particolari talenti...sono solo appassionatamente curioso

Albert Einstein

Lord di complimenti te ne meriti non pochi, sei stato meticolosissimo e hai avuto una pazienza fuori del comune, bravo!

:-p :-p :-p :-p :-p :-p :-p :-p :-p :-p :-p :-p :-p :-p

Finch� il vin dia la terra,sempre all'acqua guera guerra!

 

Home page :nah
E-mail: bottonim@yahoo.it
Nick, UIN, canale IRC/EFnet frequentato:nessuno???

....

Difficoltà

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

 
 

Introduzione

Ben trovati a tutti...
oggi per mantenere una vecchia promessa parliamo di Opera..un browser veloce ...e che non me ne faccio nulla.
il tut lo divido in 3 parti:cracking,reversing e keygeneretor(che lo farete voi! ammesso che riesca a reversare correttamente tutte le protezioni incontrate..e francamente lo dico per la vostra salute mentale evitate anche solo di sperarci...)..Il tut mi � venuto un p� lunghetto ma soprattutto un p� intrecciato..non � per nulla difficile solo si perde il segno..
Beh sappiate che non � solo colpa mia...(Que indovina il perch�! :-p)

Tools usati


SoftIce (lui il solo, l'unico l'impareggiabile Sice)

OllyDbg (Mitico non ci sono altri termini)

OllyDump (Altrimenti come dumpiamo...??)

PeId (Ormai � un must)

IDA ..la donna della mia vita (dopo la solita Barbara.. :-p..)
un gran culo....(serve sempre nella vita...)

URL o FTP del programma

Dove scaricarlo immagino lo troverete facilmente....

Solo una cosa...questo tut riguarda la versione senza java...probabilmente � lo stesso...ma non ho verificato....

Essay

 
Bene si parte...

Per prima cosa.....senza neanche analizzare le protezioni vediamo quanto � tosto Opera...

se mi conoscete vi ricorderete che sono quello dei puntini e del cervello spento(almeno all'inizio)...quindi spengo il cervello e clicco su opera... e gi� che ci sono metto qualche puntino...qua e l�...

Appena il prog parte, appare una nag in alto con della noiosa publicit�..hey per� almeno mi f� scegliere che genere preferisco...uhm..gentili...!Nel men� Help c'� una voce:"REGISTER OPERA".Ci clicco sopra e mi chiede user,soci�t� e code!li metto a muzzo (avvio sice) metto qualche bpx su qualche api..per intenderci le solite e...no niente...uhm...vuoi vedere che ho trovato un programma protetto in un modo decente..?

Allora che fare?beh supponendo di averlo registrato...quando si riavvia dove legge il seriale corretto?dal registro o da un file...risposta ovvia!

Quindi parto dal File...bpx openfileA

...e si! Sice poppa...premo F5..F5 e opera si avvia...lo chiudo ...lo riapro e di nuovo F5,poi F11 e arrivo al primo jnz in opera...lo faccio saltare...e poi F5.Ehy non ho pi� pubblicit�....

Che protezione tosta...speriamo di non incontrarla mai pi�....

Quindi siccome non voglio scomodare sempre sice devo modificare quel jnz...(tanto per la cronaca � all'indirizzo 67BADE4E)...La domanda ovvia � quale file devo modificare?un occhiata con LordPe o qualunque altro editor del Pe mostra che � nel file Opera.dll..ed � packata con aspack(lo rivela PeID).Uffa!

E anche l'eseguibile opera.exe � packato..e anche tutte le altre librerie....

Conclusione potrei patcharlo al volo grazie ad un tutorial di beneder0 su "winamp 5.05 code injection" e sarebbe anche una bella soluzione se solo avessi un compilatore a portata di mano....sfortunatamente non ce l'ho.

Io non ho voglia di sbattermi e osservo che l'eseguibile � veramente piccolo...per quanto possa essere compresso non pu� essere troppo grande...quindi unpacco questo!

Per fare le cose bene...leggetevi i vari tutorial su come unpaccare Aspack 1.2..alla UIC ce ne sono almeno 2 stupendi.

Apro OllyDbg con OllyDump(cos� evito di sbattermi...non mi preoccupo neanche della IAT..lascio fare tutto a Olly...tanto questo eseguibile importa solo 10 o 12 funzioni...) trovo OEP steppando alla cieca e saltando i vari loop...e arrivo all'istruzione all'indirizzo 4153BA..poco prima di un ret...ancora qualche riga e voill� sono all'OEP (all'indirizzo 4011C0) quindi dumpo con ollydump e gli dico di ricostruire la IAT..aspetto qualche secondo e fine tutto fatto..grazie olly!!!:-D

Avvio il file dumpato e ci steppo dentro fino ad arrivare a LoadLibrary...se guardo cosa pusha prima trovo Opera.dll...bene qui � dove dice a opera.dll di unpaccarsi...subito dopo ci sono delle istruzioni che controllano il buon esito...

L'idea � di modificare ora,dopo che si � unpaccato in memoria la dll,quel jnz scrivendo qualche riga in assembly

per prima cosa costringo quel jmp a saltare sempre (all'indirizzo 401225)..dico quel jmp subito dopo LoadLibrary...poi all'indirizzo di arrivo scrivo in sice a eip:

mov edi,6374

mov 67BADE4E,di

xor edi,edi

jmp 401025

cosa f�..?semplice dico all'eseguibile subito dopo il LoadLibrary salta...fai edi=6374h(il valore di un jz a 63 + avanti scritto in opcode ovviamente)...poi metti questo valore all'indirizzo 67BADE4E(quello trovato prima)..poi azzera edi e ritorna dove eri prima (jmp 401025)...

Avvio e si!funge tutto....

Ok fine....della parte senza cervello.

Ora lo accendo e....non credo cambier� molto :-D ...l'ho lasciato l� dove era nell'ultimo tut..su una ragazza stupenda...)

cmq ora arriva la parte di reversing...o se preferite � appena finita l'introduzione...(non me ne faccio niente di crackare opera mi interessa vedere che protezioni ha e per farlo ho dovuto vedere quanto resisteva ad un attacco classico...)

Notate che qui cerco di reversare le protezioni di Opera contro un seriale fasullo...spero di beccarle tutte..in caso contrario..Beh..nessuno � infallibile...! :-D

Procediamo con ordine...abbiamo un programma e vogliamo reversarlo...per prima cosa serve una Strategia:

1)Cerchiamo un tutorial anche vecchio su questo programma.....e ahia nulla...cavolo stavolta niente aiuto tranne uno del 99/2000 che non mi serve a molto...

2)Analizziamo le protezioni......non c'� molto da dire ..� protetto con aspack,che si prende la briga di cancellare i breakpoint,di cancellare la IT,di rompere le scatole, ma almeno in questo caso non sembrano esserci protezioni anti debugger...

3)Studiamo contromisure alle protezioni...che fare??beh dumpiamo e poi ci pensa IDA...e gi� che ci sono...per dumpare uso il loader di ollydbg...per quanto riguarda i breakpoint...aspack li modifica all'avvio..ma solo quelli che riguardano il prog(cio� opera)...basta trovare un punto dove entrare poco dopo aspack e semplicemente risettarli da l� e dovrebbero funzionare..almeno fino a che non riavviamo il prog(in altre parole ci serve un api di wondows su cui brekkare...cos� gi� che ci siamo ci mangiamo un p� di miele(Ok riconosco che questa era pessima e anche datata...l'avranno gi� scritta in molti...!

4)Analizziamo il programma sprotetto.....Beh che dire ..IDA ..tu solamente tu...

5)decidiamo una strategia di attacco alle limitazioni...serve un cervello ..questo � un atto di pura creazione e di libera fantasia ...insomma puro ingegno

Dopo questa tabellina dei compitini...procediamo con il reversing...finalmente ci si diverte!

Compito n1...omissis!

Compito n2...gi� svolto!

Compito n3:

Ora mi tocca anche fari i compiti..sigh!che � sono tornato al liceo??Mah!

Visto che gli ostacoli sono nella libreria Opera.dll e stante il fatto che l'eseguibile dovreste averlo gi� unpackato prima...Unpackiamo Opera.Dll!Chiamiamo il fido Olly,gli facciamo caricare la nostra libreria e cerchiamo l'OEP..Lo troviamo all'indirizzo67E24BC9 ...per arrivarci leggetevi i tutorial oppure andate a caso e ogni volta che incontrate un jz o jnz mettete un bpx dove non arrivate(es:se incontrate un jz 445533 e z=0 allora non salta ma voi mettete un bel bpx all'indirizzo in cui sarebbe arrivato, in questo caso 445533.,.eh no! non � un numero di telefono..)vedrete che da qualche parte arrivate...se proprio volete arrivarci senza fare nulla basta mettere un bpx all'indirizzo 67F8A39A...

Ok siamo all'OEP..che facciamo...?OllyDump e dumpa tutto..e gi� che ci sei ricostruisci la IAT che non ho voglia di fermarmi prima che venga distrutta e dumparla da l�...Grande OllyDump riesce a fare tutto!!!

Ora basta Olly..� il momento di IDA! :-D

ma questo � un altro compito e quindi...:

Compito n4:

Lanciate Ida...gli dite di caricare la dll appena dumpata..togliete la crocietta su make import segment ,caricate le flirt che vi servono e .....aspettate..molto tempo....quasi 40 minuti sul mio pc.. SIGH!

Per prima cosa andiamo su imported function....siamo alla ricerca di qualche api che scriva in una finestrella..mi spiace hai sbagliato codice...!

e la troviamo..si chiama SetWindowTextW...(beh non arrabbiatevi sono sempre le stesse...)

Bene..proviamo..!clikkiamo su register,nome,soci�t� e code..e in sice bpx SetWindowTextW.poi invio!e sice poppa!:-D Ora da qui possiamo mettere tutti i bpx che vogliamo!e aspack non romper� pi�!

Siamo sempre alla ricerca della parte in cui f� il check del nostro code...

A rigore da SetWindowTextW basta procedere a ritroso per trovare il jz/jnz (sono sempre queste...in genere!) che ci interessa..oppure visto che nella introduzione ho spiegato come crackarlo modificando un jnz....basta arrivare alla call chiamata poco prima e analizzare quella!

Ma noi NO!Vogliamo la strada difficile..quella senza sapere nulla...vogliamo i muri...le scalate impossibili...le difficolt�.....insomma noi vogliamo andare sotto Names(in IDA) cercare Code e volare l� dove IDA ci indica..cio� semplicemente cliccarci sopra!

Che strada Difficile eh?

Ok siamo qui..da ora inizia il codice...mi iniziava a mancare...

.text:67CE14B5 push offset aRegister_code <--Siamo qui!
.text:67CE14BA call sub_67CC80FE
.text:67CE14BF push 1
.text:67CE14C1 lea ecx, [ebp+var_20]
.text:67CE14C4 pop edi
.text:67CE14C5 push edi
.text:67CE14C6 push edi
.text:67CE14C7 call sub_67BBC1A1
.text:67CE14CC push edi
.text:67CE14CD push edi
.text:67CE14CE lea ecx, [ebp+var_18]
.text:67CE14D1 call sub_67BBC1A1
.text:67CE14D6 push edi
.text:67CE14D7 push edi
.text:67CE14D8 lea ecx, [ebp+var_10]
.text:67CE14DB call sub_67BBC1A1
.text:67CE14E0 push 0FFFFFFFFh
.text:67CE14E2 lea ecx, [ebp+var_8]
.text:67CE14E5 push [ebp+var_10] -->addr del mio code
.text:67CE14E8 call sub_67BBA863
.text:67CE14ED push [ebp+var_8]-->addr mio code in ascii
.text:67CE14F0 call o_2_a_10C_... --> call incriminata
.text:67CE14F5 test eax, eax -->eax=zero?se si non salta
.text:67CE14F7 pop ecx         
.text:67CE14F8 jnz short loc_67CE1529->non salta?appare registered quindi eax deve essere zero!
Per la cronaca all'indirizzo 67CE14E5 ..salva l'indirizzo del mio code..scritto in formato unicode..mentre al 67CE14ED fa lo stesso in ascii...poi se provate con sice o Olly a mettere un bel bpx all'indirizzo 67CE14F5 e fate eax=zero o cmq non lo fate saltare appare Opera Registered!bene!sappiamo che il processo di registered � gestito dalla call all'indirizzo 67CE14F0 ,sappiamo che alla fine deve essere EAX=ZERO e sappiamo anche che l'unico valore richiamato dalla call � l'indirizzo del nostro code...!

Con sice potete anche notare che prima della call si ha  eax=zero...

Non vi poppa sice?certo perch� come avevo gi� detto bisogna prima entrare nel prog dopo che si � unpaccato e poi mettere l� tutti i bpx che volete..in pratica e questa � l'ultima volta che lo dico:bpx SetWindowTextW e poi cliccate su ok..sice poppa mettete tutti i bpx che volete e ci siamo capiti!

Andiamo ad analizzare la Call con quel nome assurdo...:Ricordate alla fine eax deve essere Zero!

Gi� che ci sono ho rinominato le call contenute con nomi + umani...

.text:67CE1552 push ebp
.text:67CE1553 mov ebp, esp
.text:67CE1555 sub esp, 18h
.text:67CE1558 call Func1CheckCode-->Questa non rompe
.text:67CE155D test eax, eax
.text:67CE155F jnz short loc_67CE159E-->meglio non saltare
.text:67CE1561 push [ebp+mio_code] -->mio code...
.text:67CE1564 lea eax, [ebp+Var_Indirizzo]-->un addr.
.text:67CE1567 push eax --> lo salva...
.text:67CE1568 call Func2CheckCode -->secondo check su code...
.text:67CE156D pop ecx -->recupera ecx
.text:67CE156E test eax, eax->deve essere eax=0 vedi dop
.text:67CE1570 pop ecx --> recupera ecx
.text:67CE1571 jnz short loc_67CE159E--> non  saltare...
.text:67CE1573 lea eax, [ebp+Var_Indirizzo]
.text:67CE1576 push eax
.text:67CE1577 call Func3CheckCode -->terzo check su code...
.text:67CE157C test eax, eax
.text:67CE157E pop ecx
.text:67CE157F jnz short loc_67CE159E--> non  saltare...
.text:67CE1581 lea eax, [ebp+Var_Indirizzo]
.text:67CE1584 push eax
.text:67CE1585 call Func4CheckCode -->quarto check su code...
.text:67CE158A test eax, eax
.text:67CE158C pop ecx
.text:67CE158D jnz short loc_67CE159E-->non deve saltare
.text:67CE158F push [ebp+mio_code]
.text:67CE1592 call sub_67D2193A
.text:67CE1597 neg eax --> nega eax ma se eax=0 resta 0
.text:67CE1599 pop ecx
.text:67CE159A sbb eax, eax
.text:67CE159C leave
.text:67CE159D retn


.text:67CE159E or eax, 0FFFFFFFFh-->fa eax diverso da 0
.text:67CE15A1 leave -->meglio non passare di qui...
.text:67CE15A2 retn

Come sempre si parte dal fondo...Siamo o non siamo REVERSER??vogliamo eax=zero..se passiamo da 67CE159E sicuramente non lo sar�...perch�?perch� se salta arriviamo all'OR e l� farebbe EAX OR FFFFFFFF e non pu� fare zero (se proprio insistete 0 OR 0=0 ..1 OR 0=1 e 1 OR 1=0)...e noi non lo possiamo permettere...conclusione non deve mai saltare...e per fare ci� basta guardare quando salta...

Allora NON salta mai se eax=zero...lo potete vedere agli indirizzi..67CE155F ,67CE1571 ,67CE157F e 67CE158D...come si f� a vederlo..?esistono le Xref...Osserviamo inoltre che sono tutti indirizzi preceduti da una call...bene ognuna di quelle call deve fare eax=zero..!Ora non resta che reversare le quattro call tenendo presente che alla loro uscita dovr� sempre essere eax=zero!

Inizio cagate:

--------------------------------------------------------------------------------------------------------------

Che pacchia la vita del reverser...!quasi quasi spengo nuovamente il cervello..che se no consumo troppi neuroni...si ma non fatelo che tra poco arriva il bello...e poi i neuroni sono fatti per essere bruciati ..come la vita � fatta per essere vissuta...e internet per essere navigato..ed io per essere fermato ..altrimenti continuo fino a domani!

Ma visto che ormai ho iniziato....troppo tardi!non siete riusciti a fermarmi...nel mezzo del cammin di nostra vita...mi ritrovai in una selva oscura...che la retta via era smarrita..ehy sono un poeta...:-D

Sto degenerando!

Una volta un mio amico,Asterix,si invent� una poesia...la dovrei dedicare ad una certa persona(cos� poi mi trovo scritto potere alle donne...) ma siccome si pu� usare qualunque nome o nick...Que per te:

Que mia amata,

il mio cuore batte all'impazzata...

Tu ragion della mia vita,

Dolcezza mia infinita.

Ok Fine cagate....cmq � bella!

In un modo o nell'altro dobbiamo anche divertirci...

--------------------------------------------------------------------------------------------------------------

Riprendiamo da dove eravamo rimasti

Andiamo ad analizzare la prima call..(ma poi perch� parlo con la prima persona plurale??che c'entra NOI???):

.text:67CE15A3 call sub_67D21F75 -->probabile che controlli se si � decriptato tutto correttamente
.text:67CE15A8 test eax, eax -->se eax=zero allora...
.text:67CE15AA jz short loc_67CE15B0-->salta..altrimenti
.text:67CE15AC or eax, 0FFFFFFFFh-->eax diverso da zero
.text:67CE15AF retn--> e poi esci...ma noi non vogliamo!

.text:67CE15B0 push esi --> salva esi=0
.text:67CE15B1 push 1 --> salva 1
.text:67CE15B3 call sub_67CE15CB
.text:67CE15B8 pop ecx --> recupera ecx
.text:67CE15B9 push 3Dh --> salva 3Dh
.text:67CE15BB pop esi --> recupera esi=3Dh
.text:67CE15BC push 0 -->salva 0 e inizio loop <--\
.text:67CE15BE call sub_67CE15CB                  |
.text:67CE15C3 dec esi --> decrementa esi         |
.text:67CE15C4 pop ecx -->recupera ecx            |
.text:67CE15C5 jnz short loc_67CE15BC-->�un loop!-/
.text:67CE15C7 xor eax, eax --> eax=zero
.text:67CE15C9 pop esi --> recupera esi
.text:67CE15CA retn -->qui ci va bene uscire...

Per prima cosa osserviamo le Xref...ce ne sono 3!La domanda giusta � perch� 3?Saranno mica 1 Check all'avvio,uno alla chiusura e il terzo?Dicevo il terzo magari quando clikkiamo su about??Come trovare la risposta a questo dubbio che mi attanaglia il cuore?Semplice mettiamo un bpx 67CE15A3 e vediamo quando sice poppa...per la chiusura del prog e per l'about non c'� problema...ma per l'avvio Aspack modifica i nostri bpx ricordate?allora lasciamo attiva la solita bpx sulla solita api oppure all'inizio abbiamo usato openfilea...scegliete voi...

Dopo queste righe inutili...tanto la risposta era scontata ed affermativa passiamo ad analizzare la call...

Troviamo subito una call...seguita da un test eax,eax e un jz...come al solito se eax=0 salta...e se salta evito un OR che mi farebbe eax diverso da zero...conclusione la call 67D21F75 dev fare eax=zero...ricordatelo per dopo quando andremo ad analizzarla...!

Per ora continuiamo..dicevamo se eax=zero allora salta(evita l'OR) e ci troviamo all'indirizzo 67CE15B0..

Salva esi nello stack,pusha 1 e chiama una funzione 67CE15CB...fa esi=3Dh...come?pusha 3Dh nello stack e poi mette questo valore in esi...ed inizia un loop...richiama la stessa funzione di prima 67CE15CB ma con parametro 0 stavolta e usa come variabile di controllo esi!lo decrementa ad ogni giro..e continua finch� non � esi=zero...quindi fa eax=zero ,recupera esi ed esce!Abbiamo incontrato 2 call nuove...che fanno?analizziamole partendo dalla seconda che mi � pi� simpatica...

.text:67CE15CB cmp [esp+arg_0], 0-->� chiamata con 0? 
.text:67CE15D0 mov ecx, 6572696Bh -->ecx=65726968
.text:67CE15D5 jnz short loc_67CE15DD-->allora NON salta
.text:67CE15D7 mov ecx, dword_67F126D0 -->ecx=67F126D0
.text:67CE15DD mov eax, ecx -->atterriamo qui dal salto
.text:67CE15DF lea edx, [ecx+ecx]
.text:67CE15E2 and al, 0FEh
.text:67CE15E4 xor eax, edx
.text:67CE15E6 mov edx, ecx
.text:67CE15E8 shl eax, 1
.text:67CE15EA and edx, 0FFFFFFFCh
.text:67CE15ED xor eax, edx
.text:67CE15EF mov edx, ecx
.text:67CE15F1 shl eax, 2
.text:67CE15F4 and edx, 0FFFFFFF0h
.text:67CE15F7 xor eax, edx
.text:67CE15F9 mov edx, ecx
.text:67CE15FB shl eax, 2
.text:67CE15FE and edx, 0FFFFFFC0h
.text:67CE1601 xor eax, edx
.text:67CE1603 mov edx, ecx
.text:67CE1605 shl eax, 19h
.text:67CE1608 and edx, 80000000h
.text:67CE160E xor eax, edx
.text:67CE1610 shr ecx, 1
.text:67CE1612 or eax, ecx
.text:67CE1614 mov dword_67F126D0, eax -->67F126D0=eax
.text:67CE1619 retn
In pratica controlla con che valore � stata chiamata...mette in ecx un indirizzo..poi se � stata chiamata con un valore 0 non salta e sovrascrive ecx con l'indirizzo 67F126D0 altrimenti salta questa istruzione...poi applica una particolare cura ad eax e salva il valore in 67F126D0..esatto lo stesso indirizzo...

In pratica la prima volta viene chiamata con 1...cos� mette in 67F126D0 un valore..giusto per inizializzare...poi dopo viene richiamata con parametro 0 e prende il valore in quell'indirizzo e vi applica la stessa "cura" e poi lo risalva....in pratica inizializza dei valori...

Passiamo all'altra..non ho voglia di scrivere tutto quindi beccatevi il riassunto..tanto il metodo per reversarla lo sapete deve fare eax=zero quindi non deve passare dall'OR...dicevo cosa fa?semplice fa un controllo per vedere se ha inizializzato delle arrays correttamente..come?controlla la loro lunghezza...ecco spiegato i vari strlen e strcmp...prende la lunghezza di un arrays e la v� a confrontare con un valore fisso...queste arrays sono molto importanti...interverranno dopo....

Fine prima Func1CheckCode...ricapitolando abbiamo eax=0 quindi non salta il jnz all'indirizzo 67CE15CF..e arriaviamo alla seconda Func2CheckCode...ma non potevo darci dei nomi pi� umani?tipo Func1 e cos� via?Si potevo ma poi era troppo facile...!

Per comodit� vi riporto un pezzetto di codice...

.text:67CE1561 push [ebp+mio_code] -->mio code...
.text:67CE1564 lea eax, [ebp+Var_Indirizzo] -->un addr
.text:67CE1567 push eax -->salva eax
.text:67CE1568 call Func2CheckCode -->che far� mai?
.text:67CE156D pop ecx --> recupera ecx
.text:67CE156E test eax, eax--> deve essere eax=zero
.text:67CE1570 pop ecx--> recupera ecx
.text:67CE1571 jnz short loc_67CE159E-->non deve saltare

Dunque salva nello stack il mio code,mette in eax un indirizzo(suppongo ci metter� qualcosa...)e poi lo salva nello stack...quindi chiama la Func2CheckCode...se esce con eax=zero allora non saltare e prosegui..altrimenti errore...

E cavoli � lunghetta...portate pazienza:

.text:67D2167D push ebp
.text:67D2167E mov ebp, esp
.text:67D21680 push ecx -->salva ecx...(=zero)
.text:67D21681 push ebx -->...ebx...(012F658)
.text:67D21682 push esi -->... ed esi(=zero)
.text:67D21683 mov esi, [ebp+TempCode]-->in esi mio code
.text:67D21686 mov al, 2Dh --> mette "-" in al
.text:67D21688 push edi -->salva edi(=1)
.text:67D21689 cmp [esi+1], al -->carattere 2 � = "-"?
.text:67D2168C jnz loc_67D21736 --> non deve saltare...
.text:67D21692 cmp [esi+7], al -->carattere 8 � = "-"?
.text:67D21695 jnz loc_67D21736 -->non deve saltare...
.text:67D2169B cmp [esi+0Dh], al-->carattere 14 � ="-"?
.text:67D2169E jnz loc_67D21736 -->non deve saltare...
.text:67D216A4 cmp [esi+13h], al-->carattere 20 � ="-"?
.text:67D216A7 jnz loc_67D21736 -->non deve saltare...
.text:67D216AD cmp [esi+19h], al-->carattere 26 � ="-"?
.text:67D216B0 jnz loc_67D21736 -->non deve saltare...
.text:67D216B6 push esi -->salva mio code...
.text:67D216B7 call _strlen -->quanto � lungo?
.text:67D216BC cmp eax, 1Fh -->� lunga 1fh=31d?se si oki
.text:67D216BF pop ecx-->prende dallo stack il mio code
.text:67D216C0 jnz short loc_67D21736-->non deve saltare
.text:67D216C2 mov eax, [ebp+indirizzo]-->eax=*indirizz
.text:67D216C5 mov cl, [esi]-->cl=val ascii della prima lettera del mio code
.text:67D216C7 and [ebp+var_4], 0-->inizialiazza var_4
.text:67D216CB lea edi, [esi+2] -->edi=esi+2
cio� il secondo gruppo del mio code in esi+1 c'� "-"

.text:67D216CE mov [eax], cl -->*eax=*esi
.text:67D216D0 add eax, 4 -->eax=eax+4
.text:67D216D3 mov [ebp+indirizzo],eax->eax in *indiriz

.text:67D21736 or eax, 0FFFFFFFFh-->se arriva qui eax non � zero.Voglio eax=zero quindi qui non deve arrivare
.text:67D2173D retn

Cosa fa?allora prende il mio code,mette in al il valore ascii di"-"(=2Dh) poi controlla se � presente alla posizione 1,7,D,13,19 altrimenti salta a 67D21736 e fa eax diverso da zero...e noi non vogliamo..conclusione deve esserci un "-" in quelle posizioni..i valori sono in esadecimale ovviamente!Poi arriva all'indirizzo 67D216B6 ..salva esi ..che per inciso contiene l'indirizzo del mio code e chiama strlen per vedere quanto � lungo...se � uguale a 1F allora non fare errore...siccome 1Fh=31d ho che la stringa del mio code deve essere lunga 31 caratteri ,con i trattini in posizioni specifiche..deve essere del tipo  1-66667-90123-56789-12345-78901..inutile che proviate tanto non funziona � solo un esempio...

Continuiamo ora siamo all'indirizzo 67D216C2:

Assegna eax come puntatore ad una variabile di indirizzo "indirizzo"(che fantasia che ho)..mette in questa variabile o se preferite nel contenuto di eax il valore ascii della prima lettera(o numero)del mio code..incrementa eax di 4..in pratica gli assegna un altro indirizzo e gi� che c'� inizializza una variabile...si st� preparando per un loop moolto importante...anzi a due loop molto importanti...:-D

li chiamer� piccolo loop e grande loop...

incontriamo prima il piccolo loop quindi..

.text:67D216D6 xor ebx, ebx-->inizio piccolo loop(ebx=0)
.text:67D216D8 mov [ebp+TempCode],1->metti 1 in tempcode
.text:67D216DF xor esi, esi -->esi=zero

-------------->>>INIZIO PICCOLO LOOP<<<----------------
.text:67D216E1 movsx eax, byte ptr [edi+esi]-->in edi c'� mio code e esi � un contatore incrementato ogni giro
.text:67D216E5 push eax -->pusha eax(contiene val ascii)
.text:67D216E6 push ds:off_67EBAEF0-->pusha questo addr
che contiene l'indirizzo di un arrays di lettere
.text:67D216EC call _strchr -->controlla se il codice
ascii in eax � nella tabella.serve per escludere valori
ascii nel gruppo non permessi,la tabella comprende valori da [a-z][A-Z][3-8] estremi compresi e la call ritorna l'indirizzo dove si trova quella lettera nella tabella

.text:67D216F1 pop ecx
.text:67D216F2 test eax, eax -->eax non deve essere zero

.text:67D216F4 pop ecx
.text:67D216F5 jz short loc_67D21736-->meglio non salti
.text:67D216F7 sub al, byte ptr ds:off_67EBAEF0-->in 67EBAEF0 c'� sempre lo stesso valore (74h)
.text:67D216FD movzx eax, al-->beh uccidi tutto sopra gli 8 bit
.text:67D21700 imul eax,[ebp+TempCode]->eax=eax*mio_code
.text:67D21704 add ebx, eax-->ebx=eax+ebx
.text:67D21706 mov eax, [ebp+TempCode]-->eax=mio_code
.text:67D21709 imul eax, 32h -->eax=eax*32h
.text:67D2170C inc esi -->incrementa esi
.text:67D2170D mov [ebp+TempCode], eax -->mio_code=eax
.text:67D21710 cmp esi, 5 --> esi<=5?
.text:67D21713 jl short loc_67D216E1-->se si rifai
loop 

---------------->>>FINE PICCOLO LOOP<<<----------------

Intanto cominciamo a dire che stante la struttura del code:1-66667-90123-56789-12345-78901 ecceto il primo numero(ripeto uso la parola cifra ,numero o lettera indifferentemente sarebbe meglio dire il carattere..se non fosse che mi � antipatico) che sono 5 gruppi di caratteri(non lo user� mai pi�) � ovvio aspettarsi un loop ripetuto per 5 volte...e la prima lettera del miocode...non viene controllata ..per ORA!

Cosa fa questo loop?Evito di scriverlo a parole e vi scrivo uno pseudo C:

code="1-........."

ebx=0

esi=0

temp_code=1

edi=code

for(esi=0;esi<5;esi++){

eax=*(esi+edi)

eax=strchr(eax,addr)

if eax==0 break

eax=eax-74

eax=eax AND FF

eax=eax*temp_code

ebx=ebx+eax

temp_code=temp_code *32

}

primo non ho messo i ";" non ne avevo voglia ,secondo manca la dicchiarazione delle variabile ..terzo mancano altre cose...

alla fine del loop deve essere ebx non deve avere il byte + grande settato o meglio deve essere qualcosa minore di 0FFFFFFFh=268435455d altrimenti codice sbagliato....

temp_code � un valore che viene moltiplicato per 32h ad ogni loop... quindi

vale 1   , 50   , 2500   , 125000   , 6250000  in decimale ovviamente!

quindi indicando con X Y Z T L i valori ascii in decimale delle lettere da cercare(alle quali abbiamo gi� sottratto 74 e fatto la cura di cercare nella tabella...cio� difatto sarebbero gli indirizzi della tabella - 74 e poi presi solo gli 8 bit minori..) si ha

X*1 + Y*50 + Z*2500 + T*125000 + L*6250000 <  268435455

L'idea � di  trovare gruppi di lettere che le soddisfino...

Intanto cominciamo col dire che valori ritorna la tabellina...

TABELLINA = "abcdefhijkmnprstuvwxyzABCDEFHJKLMNPQRSTUVWXY345678"

e di fatto viene ritornata la posizione... ad a viene associato 0..questo perch� dalla call strchr viene ritornato l'indirizzo del carattere trovato...e siccome la tabella parte dall'indirizzo pushato la posizione nella stringa � indirizzo della lettera - indirizzo inizio stringa.....OK � banale ma io l'ho detto lo stesso...

Facciamo un esempio se usiamo "aaaaa" quanto f�?f� 0 perch� ad "a" � associato un valore 0...siccome a "b" � asscoiato un valore 1 se scriviamo "bbbbb" cosa otteniamo?otteniamo 1*1+1*50+1*2500+1*125000+1*6250000=6377551d=61504Fh e possiamo verificarlo mettendo un bel bpx all'indirizzo 67D21715...

In pratica per semplificarvi le cose vi dico che vanno bene tutti i codici purch� l'ultima lettera sia nella tabellina minore di X compresa..insomma qualunque lettera (e non numero che venga nella tabellina prima di Y)...

Uno sproloquio per dire questa cagata...

Tanto per fare il punto della situazione quella specie di codice che ho scritto sopra e che disconosco non serve a nulla..basta richiedere che il gruppo di 5 lettere finisca con un a lettera minore di Y..

Ora arriva il secondo loop..quello grande!

.text:67D2171D mov eax, [ebp+indirizzo]-->eax=valore in indirizzo...
.text:67D21720 inc [ebp+var_4] -->incrementa la variabile...
.text:67D21723 add [ebp+indirizzo], 4--> *indirizzo = *indirizzo+4
.text:67D21727 add edi, 6 -->edi=edi+6 salta al prossimo gruppo di code
.text:67D2172A cmp [ebp+var_4], 5-->var � usato come controllo del secondo loop..se � maggiore di 5 smetti...
.text:67D2172E mov [eax], ebx --> *eax=ebx
.text:67D21730 jl short loc_67D216D6-->salta se var <=5
.text:67D21732 xor eax, eax -->figo fa eax=zero...e fine secondo loop quello che cambia gruppo
.text:67D21734 jmp short loc_67D21739-->salta alla fine

 

.text:67D21739 pop edi -->recupera edi...(=1)
.text:67D2173A pop esi -->...esi...(=zero)
.text:67D2173B pop ebx -->...ed ebx
.text:67D2173C leave -->manca ecx(=zero) ma lo recupera la call chiamante
.text:67D2173D retn -->ed esci...!

Siccome indirizzo contiene al suo interno un secondo indirizzo...eax diventa un puntatore al secondo indirizzo e alla fine del piccolo loop, il valore di ebx viene salvato nel contenuto di eax cio� nel contenuto del secondo indirizzo...poi questo secondo indirizzo viene incrementato(secondo_indirizzo = secondo_indirizzo +4) stiamo creando un array con i valori di ebx...in pratica se ebx vale rispettuvamente 1,2,3,4,5 (valori originakle eh?) e supponiamo che indirizzo valga F abbiamo *(F)=1...*(F+4)=2...*(F+8)=3...*(F+C)=4...*(F+10)=5

Scommettiamo che verranno usati  dopo..per qualche controllo aggiuntivo...?Sono Importantissimi...sono 5 numeri e vengono usati alla fine del tut...

Ehy abbiamo finito la Func2CheckCode ne abbiamo solo altre 2..accidenti a me e a quando faccio promesse senza senso...Ma ormai non ha senso piange sul latte versato..voce dal s� fuggita + richiamar non vale..non si trattien l'australe quando dall'arco usc�...

Per prima cosa che parametri passiamo a questa call?solo il solito indirizzo...andate su a rivederlo se volete..

.text:67CE161A push [esp+var_indirizzo]
.text:67CE161E call sub_67CE166C -->Call Procedure
.text:67CE1623 test eax, eax -->meglio eax=0
.text:67CE1625 pop ecx -->recupera ecx
.text:67CE1626 jnz short loc_67CE1636->non deve saltare.
.text:67CE1628 push [esp+var_indirizzo]->salva indirizzo
.text:67CE162C call sub_67CE163D--> Call Procedure
.text:67CE1631 test eax, eax -->meglio eax=0
.text:67CE1633 pop ecx -->recupera ecx
.text:67CE1634 jz short loc_67CE163A ->meglio saltare...
.text:67CE1636 or eax, 0FFFFFFFFh-->qui non deve arrivare...
.text:67CE1639 retn -->esci con dolore

.text:67CE163A xor eax, eax -->eax=0
.text:67CE163C retn -->esci con gloria

Solito sistema...voglio eax=zero...non devo passare da qualche parte...entrambe le call devono fare eax=zero..

E gi� che ci siamo ....ricevono entrambe come unico parametro il contenuto del solito indirizzo...

.text:67CE166C mov eax,[esp+var_indirizzo]->eax=indirizz
.text:67CE1670 push esi -->salva esi
.text:67CE1671 push 4 -->salva 4
.text:67CE1673 add eax, 4 -->eax=eax+4
.text:67CE1676 pop edx -->edx=4

.text:67CE1677 mov esi, [eax+4] -->esi=*(eax+4)
.text:67CE167A lea ecx, [eax+4] -->ecx=eax+4
.text:67CE167D xor [eax], esi --> *(eax)=*(eax) XOR esi
.text:67CE167F dec edx --> decrementa edx
.text:67CE1680 mov eax, ecx --> eax=ecx
.text:67CE1682 jnz short loc_67CE1677-->salta se edx non � zero,� un loop ed edx � usato come variabile di check
 

.text:67CE1684 xor eax, eax -->eax=0
.text:67CE1686 pop esi -->recupera esi
.text:67CE1687 retn -->esci

 

Che f�?ricordate quell'array che dicevo prima...bene prende il contenuto di ogni puntatore e lo xora con il contenuto del puntatore successivo e il risultato lo mette nel primo puntatore..ed esegue il loop 4 volte..

Alla uscita fa sempre eax=zero...quello che volevamo...

Beh ottiene dei valori...se serviranno ci ritorneremo dopo...(potete giurarci...)

La seconda call

.text:67CE163D push esi-->salva esi
.text:67CE163E push edi-->salva edi
.text:67CE163F xor edi, edi -->edi=0
 

.text:67CE1641 push 5 -->salva 5...e inizio loop
.text:67CE1643 mov eax, edi -->eax=edi al primo giro ho che eax=0
.text:67CE1645 xor edx, edx --> fai edx=0
.text:67CE1647 pop ecx --> ecx=5
.text:67CE1648 div ecx-->divisione di ecx
.text:67CE164A mov eax, [esp+var_indirizzo]->eax=indiriz
.text:67CE164E push 0 -->salva 0
.text:67CE1650 lea esi, [eax+edx*4+4]-->esi=eax+4+edx*4 siccome edx aumenta di 1 allora esi aumenter� di 4 per volta...
.text:67CE1654 call sub_67CE15CB -->la solita "cura"
.text:67CE1659 and eax, 0FFFFFFFh-->eax=eax AND 0FFFFFFF
.text:67CE165E pop ecx -->recupera ecx
.text:67CE165F xor [esi], eax-->xora eax col contenuto di esi
.text:67CE1661 inc edi --> incrementa edi
.text:67CE1662 cmp edi, 65h --> edi=65?
.text:67CE1665 jb short loc_67CE1641 -->se � minore allora salta e continua il loop
 

.text:67CE1667 pop edi -->recupera edi
.text:67CE1668 xor eax, eax -->eax=zero
.text:67CE166A pop esi --> recupera esi
.text:67CE166B retn --> esci

Per la solita cura si intende la funzione gi� analizzata che se richiamata con "0" faceva una cosa ..se richiamata con "1" ne faceva un altra...beh i commenti ci sono..sembrano anche chiari..sembrano!:-D

Il nocciolo del discorso (per ora) � che eax=zero comunque...!

Andiamo di volata alla Func4CheckCode..Finalmente alla fine....Si..tranquilli ancora 1000/2000 righe e abbiamo finito... :-p

Viene richiamata col solito indirizzo in eax e poi pushato nello stack..

.text:67D21885 push ebp
.text:67D21886 mov ebp, esp
.text:67D21888 sub esp, 1Ch -->fa posto a variabili
.text:67D2188B push [ebp+indirizzo]-->solito indirizzo ma questa volta c'� la prima lettera del mio code
.text:67D2188E lea eax, [ebp+var_1C]-->eax=var_1C
.text:67D21891 push eax -->contiene indirizzo di una tabella di lettere...
.text:67D21892 call sub_67D2173E -->prima funz da analizzare... modifica var_1C ed � importantissima
.text:67D21897 pop ecx
.text:67D21898 test eax, eax --> meglio sia zero
.text:67D2189A pop ecx
.text:67D2189B jnz short loc_67D218DD-->non deve saltare
.text:67D2189D lea eax, [ebp+indirizzo]-->eax=indirizzo
.text:67D218A0 push eax -->eax punta alla prima lettera del mio code
.text:67D218A1 lea eax, [ebp+var_1C]-->eax=var_1C punta alla tabellina...
.text:67D218A4 push eax -->salva var_1C
.text:67D218A5 call sub_67D217E0 -->seconda func da analizzare...
.text:67D218AA pop ecx -->recupera ecx..
.text:67D218AB test eax, eax-->meglio eax sia zero
.text:67D218AD pop ecx -->recupera ecx...
.text:67D218AE jnz short loc_67D218DD-->non deve saltare
.text:67D218B0 mov eax, [ebp+var_4] -->eax=var_4
.text:67D218B3 cmp eax, [ebp+indirizzo]-->meglio che siano uguali siccome il primo resta immodificato devo agire sul secondo...nella call precedente
.text:67D218B6 jnz short loc_67D218DD-->non deve saltare
.text:67D218B8 lea eax, [ebp+var_1C]-->eax=var_1C
.text:67D218BB push eax -->salva var_1C
.text:67D218BC call sub_67D218E6 -->terza func da analizzare
.text:67D218C1 test eax, eax -->meglio sia eax=zero..
.text:67D218C3 pop ecx
.text:67D218C4 jnz short loc_67D218DD-->non deve saltare
.text:67D218C6 cmp [ebp+var_1C], eax -->eax=0->var_1C=0 ma var_1C � uguale a *(solito indirizzo) quindi il contenuto di solito indirizzo deve essere nullo
.text:67D218C9 jnz short loc_67D218DD-->non deve saltare
.text:67D218CB cmp [ebp+var_18],3->*var_18 deve essere 3
.text:67D218CF jnz short loc_67D218DD-->non deve saltare
.text:67D218D1 cmp [ebp+var_14], 5-->*var_14 deve essere 5 o 2
.text:67D218D5 jz short loc_67D218E2->meglio saltare qui
.text:67D218D7 cmp [ebp+var_14], 2
.text:67D218DB jz short loc_67D218E2-->o qui...

.text:67D218DD or eax, 0FFFFFFFFh-->qui non devo passare
.text:67D218E0 leave
.text:67D218E1 retn -->esci senza onore

.text:67D218E2 xor eax, eax -->bello fa eax=zero..
.text:67D218E4 leave -->proprio come volevo
.text:67D218E5 retn -->ed esce con moolto onore!

Ahhhhhhhhhhhh.......ancora 3 Call da analizzare...basta.............Ahhhhhhhhhhhhhhh!!!!!!!!!!!!

Ok scusate lo sfogo...

Analizziamo con calma...beh almeno ci provo...inizio ad essere esausto..!!!

Per prima cosa fa posto alle variabili...salva 2 cose....un indirizzo che contiene la prima lettera del mio code...e un indirizzo di una tabella...se proprio volete lo potete vedere con Olly o Sice...Quindi la call 67D2173E prende questi due valori e fa qualcosa...poi modifica eax e se eax non � zero arriva in 67D218DD dove sicuramente eax non sar� mai zero...ed esce cos�...conclusione di qui non deve passare...e generalizzando...eax DEVE essere zero all'uscita di ognuna delle call qui dentro....arriviamo poi ai vari CMP...se vogliamo (E noi vogliamo) eax NON zero deve assolutamente saltare in uno dei due ultimi jz(Guardate i commenti...)..lo vediamo dopo cmq..!No aspetta decido che lo vediamo ora...supponiamo di essere all'indirizzo 67D218C1...abbiamo un test eax,eax e dopo un jnz che non deve essere eseguito..conclusione deve essere eax uguale a zero...poi subito dopo abbiamo un cmp tra eax ed *(ebp+var_1C) e dopo deve saltare...quindi *(var_1C) deve essere ZERO...ma var_1C � un puntatore al "solito indirizzo"...converr� ricordarlo...DEVE CONTENERE ZERO..

NOTA : "Al Solito Indirizzo" non � una pizzeria o roba simile...eh!Intesi?Ok..continuiamo...

Ora entriamo nella prima call...

Ricordate eax deve essere zero all'uscitita di ognuna delle 3 call...e poi FINE!

.text:67D2173E push ebp
.text:67D2173F mov ebp, esp
.text:67D21741 sub esp, 18h -->posto per le variabili
.text:67D21744 mov eax, [ebp+arg_0]-->eax=*arg_0 cio� eax punta alla solita tabella...
.text:67D21747 push esi-->salva esi
.text:67D21748 mov esi, [ebp+arg_4]-->esi=*arg_4 cio� prima lettera del mio code(qui arg_4 � il solito indirizzo)
.text:67D2174B push edi-->salva edi
.text:67D2174C mov edx, 0F0000000h-->edx=F0000000
.text:67D21751 mov ecx, [esi+8]-->ecx=*(esi+8)
.text:67D21754 mov [eax+0Ch], ecx-->trasferisci i dati
.text:67D21757 mov ecx, [esi+0Ch]->sono dati important
.text:67D2175A mov [eax+10h], ecx->verranno controllati
.text:67D2175D mov ecx, [esi+10h]
.text:67D21760 mov [eax+14h], ecx-->dopo...
.text:67D21763 mov ecx, [esi+14h]-->ma dove vengono
.text:67D21766 mov [eax+18h], ecx-->calcolati??
.text:67D21769 mov ecx, [esi+4]-->(esi+4)(=12F5FC) deve essere di soli 16 bit e tale che ecx AND 0F00h faccia 0F00h(vedi dopo)..sarebbe il solito indirizzo...e il perch� lo vediamo tra poco
.text:67D2176C shl ecx, 4
.text:67D2176F mov edi, ecx
.text:67D21771 and edi, edx
.text:67D21773 or [eax+0Ch], edi-->c'� un valore importante..per non farlo modificare voglio edi=0...ecx(shiftato di 4 a sinistra) AND 0F00h deve essere nullo..
.text:67D21776 shl ecx, 4
.text:67D21779 mov edi, ecx
.text:67D2177B and edi, edx
.text:67D2177D or [eax+10h], edi-->come prima solo che ecx viene shiftato di altri 4 a sinistra
.text:67D21780 shl ecx, 4
.text:67D21783 mov edi, ecx
.text:67D21785 and edi, edx
.text:67D21787 or [eax+14h], edi-->di nuovo?non ve lo spiego!!
.text:67D2178A shl ecx, 4
.text:67D2178D mov edi, ecx
.text:67D2178F and edi, edx
.text:67D21791 mov edx, 0F00h
.text:67D21796 or [eax+18h], edi
.text:67D21799 shr ecx, 10h->riporta ecx come era prima anzi se prima ecx = ilmnopqr ora diventa ecx = 0000opqr
.text:67D2179C mov edi, ecx->edi=ecx
.text:67D2179E and edi, edx->edi= edi AND edx=0F00h
.text:67D217A0 cmp edi, edx --> meglio siano uguali cio� deve essere edi=0F00h-> ecx tale che si abbia ... ecx AND 0F00h=0F00h..quindi ecx pu� essere ecx=xFyzh
.text:67D217A2 jnz short loc_67D217D2 --> cos� non salta
.text:67D217A4 mov edx, ecx --> edx=ecx
.text:67D217A6 and ecx, 1 -->ecx=ecx and 1
.text:67D217A9 shr edx, 1
.text:67D217AB push 6
.text:67D217AD and edx, 7Fh -->vorr� che sia 5 o 2
.text:67D217B0 mov [eax], ecx--> mette ecx nel contenuto di eax..siccome eax punta a var_1C... � come fare var_1C=ecx(per dopo ecx deve essere zero..il che implica che poco sopra esi deve essere di 16 bit e tale che con AND 1 faccia 0..)sovrascrive la tabella con il valore di ecx...RICORDIAMOCI la tabella non esiste +!!!
.text:67D217B2 pop ecx -->ecx=6
.text:67D217B3 lea edi, [ebp+var_18]
.text:67D217B6 mov [eax+8], edx -->sar� importante ma ve lo spiego alla fine del tut cmq dovr� essere 5 o 2..
.text:67D217B9 rep movsd
.text:67D217BB movzx edx, byte ptr [ebp+var_18]--> mette in edx la prima lettera o numero del mio code...
.text:67D217BF xor ecx, ecx --> ecx=zero
.text:67D217C1 movsx esi, ds:byte_67EBAEDC[ecx] --> mette in esi il valore ascii di lettere contenute nella nuova tabella(eh si � una nuova tabella)...edx cosa contiene?la prima lett o num del code
.text:67D217C8 cmp esi, edx -->devono essere uguali
.text:67D217CA jz short loc_67D217D7 -->cos� salta...
.text:67D217CC inc ecx -->incrementa ecx.. usa ecx come contatore per il loop
.text:67D217CD cmp ecx, 12h -->entro 18 giri di loop
.text:67D217D0 jle short loc_67D217C1--> altrimenti salta da qui e non � il caso
.text:67D217D2 or eax, 0FFFFFFFFh--> qui non deve arrivare
.text:67D217D5 jmp short loc_67D217DC -->salta ed esci..

.text:67D217D7 mov [eax+4], ecx -->*(eax+4)=ecx cio� la posizione nella tabella della prima lettera del code viene salvata in "solito indirizzo"+4...sar� importante nei check alla fine delle 3 call,dovr� essere 2=w o 5=v
.text:67D217DA xor eax, eax --> eax=zero...
.text:67D217DC pop edi
.text:67D217DD pop esi
.text:67D217DE leave
.text:67D217DF retn
 -->esci con gloria...

Nuova tabella ="emwWbvfpshatckyzdij"

E alcuni commenti li capirete quando arriverete alla fine del tut..cmq tanto per darvi le idee..copia dei valori da un array in un altra e li modifica facendo degli OR...ma alla fine di queste 3 call..si richieder� che siano uguali!Conclusioni l'OR non deve modificarli...cio� deve essere 0 il secondo membro...vedere fine tut

Bene Bene Bene...AIUTOOOO...per prima cosa osserviamo che arg_4 altro non � che il "solito indirizzo" quello usato nelle call precedenti per intenderci...che contiene un array...(vedi sopra...) vedremo tra poco...che esi+4 sar� molto importante perch� verr� fatto un check..e dovr� essere 0 perch� ci� avvenga *(esi+4) deve finire per 0....infatti quella serie di operazioni dopo servono tra le altre cose a shiftare a destra *(esi+4) di 4..uccidere il resto...e rishiftarlo nella posizione originale...poi un bel AND 7F e se zero sono moolto felice..

Ma la domanda �:cosa � stato messo nelle call precedenti in *(esi+4)?Uffa Un attimo di pazienza...ve lo spiego dopo aver finito di analizzare le ultime call..per ragioni di pura simpatia ed antipatia personali per alcune cose...

Ok mentre il loop che f�?controlla che la prima lettera del mio code sia contenuta entro il 18-esimo posto nella tabellina (scritta poco fa) ...p�o essere cio� solo uno di questi valori..."emwWbvfpshatckyzdij"...altrimenti errore...

e assegna la posizione nel "solito indirizzo"+4

nel contenuto del  "solito indirizzo" c'� una sfilza di 0 quindi -> solito indirizzo ha contenuto 00 00 00 00 yx

con yx posizione in esadecimale del primo carattere del mio code...

Bene siamo alla fine della prima call...Avanti alla seconda..!!!Con cosa viene richiamata?Con due parametri...il solito indirizzo che punta alla prima lettera del mio code...e il secondo che punta alla solita tabellina..ormai azzerata e vi preannucio che questa call � lunghetta...Ah qui var_1C non c'entra nulla con quello di prima...

.text:67D217E0 push ebp
.text:67D217E1 mov ebp, esp
.text:67D217E3 sub esp, 0Ch -->fa posto per le variabili
.text:67D217E6 mov ecx, [ebp+tabellina]
.text:67D217E9 push ebx -->ebx=indirizzo che contiene 0
.text:67D217EA push esi -->esi=zero
.text:67D217EB xor esi, esi --> azzera esi
.text:67D217ED mov eax, [ecx+4] -->eax=posizione della prima lettera del mio code nella tabella..ricordate prima nella call precedente?
.text:67D217F0 push edi -->salva edi
.text:67D217F1 inc eax -->incrementa eax
.text:67D217F2 mov [ebp+var_4], 73657879h-->creano strin
.text:67D217F9 mov [ebp+var_8], 62616265h-->sexybabe al contrario
.text:67D21800 mov [ebp+var_C], eax -->mette eax nel contenuto ebp+var_c..serve per salvare il valore...cio� salva il valore della posizione nella nuova tabellina + 1...
 

.text:67D21803 mov eax, esi-->inizio grande loop,eax=esi
(cio� eax=zero)

.text:67D21805 push 3 -->salva 3
.text:67D21807 cdq -->EAX -> EDX:EAX (lo ha messo IDA)
.text:67D21808 pop edi -->edi=3
.text:67D21809 idiv edi
.text:67D2180B inc esi -->incrementa esi
.text:67D2180C push 3 -->salva 3
.text:67D2180E mov eax, esi -->eax=esi
.text:67D21810 pop ebx --> ebx=3
.text:67D21811 mov edi, [ecx+edx*4+0Ch]-->edi=contenuto in indirizzo ecx+edx*4+Ch
.text:67D21815 cdq -->EAX -> EDX:EAX
.text:67D21816 idiv ebx
.text:67D21818 mov eax, [ebp+var_C] -->eax=var_C era il valore precedentemente salvato...posizione nella tab +1
.text:67D2181B test eax, eax -->eax=zero?
.text:67D2181D mov edx, [ecx+edx*4+0Ch]
.text:67D21821 jle short loc_67D2185A-->se eax � zero salta ,non dovrebbe mai saltare...
.text:67D21823 mov ebx, [ebp+var_4]
.text:67D21826 mov [ebp+tabellina], eax --> mette eax in arg_0 verr� usato come controllo per il loop
 

.text:67D21829 mov eax, ebx --> eax=ebx ,1 piccolo loop arg_0 � usato come controllo...il loop smette quando � zero..
.text:67D2182B imul eax, ebx -->eax=eax*ebx
.text:67D2182E xor eax, edi -->eax=eax xor edi
.text:67D21830 dec [ebp+tabellina]-->decrementa il contatore
.text:67D21833 mov ebx, eax -->ebx=eax
.text:67D21835 jnz short loc_67D21829-->se contatore � zero non saltare..non dovrebbe mai saltare...� come fare ebx = (ebx * ebx) XOR edi..e continua finch� *(tabellina) non � nullo...
 

.text:67D21837 mov [ebp+var_4], ebx-->salva ebx in var_4
.text:67D2183A mov eax, [ecx+8] -->ecx+8 � un valore costante..eax=5..settato nella call precedente..
.text:67D2183D add eax, 3 -->eax=8
.text:67D21840 test eax, eax -->� zero?
.text:67D21842 jle short loc_67D2185F --> se si salta...
.text:67D21844 mov [ebp+tabellina], eax
.text:67D21847 mov eax, [ebp+var_8]-->eax=*(var_8)
 


.text:67D2184A mov edi, eax->start 2piccolo loop,edi=eax
.text:67D2184C imul edi, eax -->edi=edi*eax
.text:67D2184F xor edi, edx -->edi=edi xor edx
.text:67D21851 dec [ebp+tabellina] -->decrementa arg_0
.text:67D21854 mov eax, edi -->eax=edi
.text:67D21856 jnz short loc_67D2184A -->continua loop finch� arg_0 non � nullo...questo piccolo loop � come fare eax = (eax*eax) XOR edx e lo ripete finch� [tabellina] non � zero...


.text:67D21858 jmp short loc_67D21864-->finito il loop arriva qui e salta...
.text:67D2185A mov ebx, [ebp+var_4]
.text:67D2185D jmp short loc_67D2183A
.text:67D2185F mov eax, [ebp+var_8]
.text:67D21862 jmp short loc_67D21867
.text:67D21864 mov [ebp+var_8], eax -->*var_8=eax...in parole povere proprio come prima salva il valore calcolato  dal 2loop nella variabile usata per chiamarlo
.text:67D21867 cmp esi, 1Fh -->grande loop smetti dopo 1Fh volte cio� dopo 31 volte
.text:67D2186A jl short loc_67D21803 -->finisce il grande loop dopo 31 volte...

.text:67D2186C and ebx, 0F0F0F0h
.text:67D21872 and eax, 0F0F0F0Fh
.text:67D21877 or ebx, eax-->ebx=eax OR ebx
.text:67D21879 mov eax, [ebp+Indirizzo]
.text:67D2187C pop edi
.text:67D2187D pop esi
.text:67D2187E mov [eax], ebx --> ecco qui mette in indirizzo il valore contenuto in ebx e siccome *(indirizzo) voglio sia zero..beh ebx deve essere nullo!
.text:67D21880 xor eax, eax -->fa eax=zero..SEMPRE
.text:67D21882 pop ebx-->recupera ebx...
.text:67D21883 leave
.text:67D21884 retn --> ritorna sempre eax=zero...ma allora perch� il controllo all'uscita??Forse � un check in pi�

Puntualizziamo subito una cosa...qui all'inizio abbiamo incontrato una cosa del tipo ecx=[tabellina+4] e poi eax=[ecx+4] e eax=[ecx+8]...bene ecx+4 � la posizione nella tabellina partendo dal valore 0....la cosa da notare � che ecx+4 � l'indirizzo ebp-18 fuori da questa call ...e ecx+8 � l'indirizzo ebp-14 sempre fuori da questa call e se guardate all'indirizzo 67D218CB vedrete che  debbono essere uguali rispettivamente a 3 e a 5...ecco perch� nel codice ho scritto che sono valori costanti...ovviamente si tratter� di andare a vedere dove e come vengono settati...ma questa � un altra storia e sar� l'ultima prima della  fine del tut...

Parliamo dei due piccoli loop..che fanno?...Beh applicano una cura ad un valore passato...e la cura � esattamente la stessa per entrambi..solo vengono richiamati con due parametri ciascuno..si ma diversi..

int loop(char a[],int edi,int c){

    int b=(int )a;

   while(c){

        a=a*a;   //costringe ad essere interi...

        a= a ^edi;

        c--;

    };

    return a;

};

   

In pratica vengono richiamati con due stringhe a[] diverse..una � yxes e l'altra � ebabyxes..poi edi viene preso dalla memoria(beh in un caso � edx ma a parte il nome ,il valore viene settato allo stesso modo) e il numero di loop � diverso..per il primo 5 e per il secondo 8...poi il valore che ritornano viene messo nella variabile con cui vengono chiamati...

static char var1[4]="sexy";

static char var2[8]="sexybabe";

 

chiamante(int maschera1,int maschera2){

    int numero1=5

    int numero2=8;

    (int) var1=loop(var1,maschera1,numero1);

    (int) var2=loop(var2,maschera2,numero2);

};

Ora il grande loop....che setter� i valori maschera1 e maschera2...viene ripetuto per 31 volte(31d=1Fh)

vi sono una serie di operazioni...che modificano edx poi settano edi..rimodificano edx..indicando edx1 ed edx2 il valore di edx prima e dopo la modifica di edi..si ha...edx1=0,1,2 ciclicamente ed edx2=1,2,0 anche qui ciclicamente...in pratica...

edx1 = 0   allora   edx2 = 1

edx1 = 1   allora   edx2 = 2

edx1 = 2   allora   edx2 = 0

Sembrava complicato eh?

poi:

maschera1 = *("solito indirizzo"+0Ch+edx1)

maschera2 = *("solito indirizzo"+0Ch+edx2)

In conclusione edi ed edx(che ho chiamato maschera1 e maschera2) assumono gli stessi valori....solo che a turni diversi...

Poi finito il grande loop che ripeto deve continuare per 1Fh volte...

for(int i;i<31;i++){

    maschera1 = *("solito indirizzo"+0Ch+edx1);

    maschera2 = *("solito indirizzo"+0Ch+edx2);

    chiamante(maschera1,maschera2);

};

Ovviamente mancano i valori di maschera1 e maschera2...e vederemo dopo quali sono...anche perch� vengono generati a partire dal mio code...

Come nel caso precedente disconosco quello che ho scritto...mi riferisco soprattutto a quello che dovrebbe essere C...non tanto perch� � sbagliato concettualmente quanto per il fatto che mi conosco e di errori..sono certo ve ne troverete....Cmq ripeto il keygen � compito per casa..e  soprattutto per chi legge...! :-p

poi alla fine della call..incontriamo

ebx = ebx AND 0F0F0F0h

eax = eax AND 0F0F0F0Fh

ebx = ebx OR eax

*(INDIRIZZO)=ebx...SICCOME ho gi� spiegato che lo voglio uguale a qualcosa di altro..(vedi indirizzo 67D218B3) deve essere un opportuno valore di ebx...

E anche L'ultima call..GRANDE SIAMO ALLA FINE..........viene richiamata con un solo valore...

.text:67D218E6 push esi
.text:67D218E7 mov esi, [esp+arg_0]
.text:67D218EB cmp dword ptr [esi+8],5->uguali?meglio si..e ci� accade nella prima call...
.text:67D218EF jnz short loc_67D21935-->non deve saltare
.text:67D218F1 mov eax, [esi+0Ch]
.text:67D218F4 lea ecx, [esi+0Ch]
.text:67D218F7 xor edx, edx-->edx=zero
.text:67D218F9 div ds:dword_67EBAED0
.text:67D218FF cmp eax, 3Ch -->eax<3C?meglio di no!
.text:67D21902 jb short loc_67D21935--> non deve saltare
.text:67D21904 mov eax, [esi+10h]
.text:67D21907 xor edx, edx -->edx=zero
.text:67D21909 div ds:dword_67EBAED4
.text:67D2190F cmp eax, 3Ch -->eax<3C?meglio di no!
.text:67D21912 jb short loc_67D21935-->non deve saltare
.text:67D21914 mov esi, offset dword_67EBAED0
 

.text:67D21919 mov eax, [ecx]-->inizio loop,eax=*(ecx)
.text:67D2191B xor edx, edx -->edx=zero
.text:67D2191D div dword ptr [esi]-->in esi ci sono gli indirizzi controllati prima..solo che ora richiede che edx sia zero...
.text:67D2191F test edx, edx -->edx=zero?
.text:67D21921 jnz short loc_67D21935-->se si non saltare..(sarebbe meglio che non saltasse..)
.text:67D21923 add esi, 4 -->esi=esi+4
.text:67D21926 add ecx, 4 -->ecx=ecx+4
.text:67D21929 cmp esi, offset byte_67EBAEDC-->uguali?
.text:67D2192F jl short loc_67D21919 -->� un loop


.text:67D21931 xor eax, eax -->bello eax=zero
.text:67D21933 pop esi -->recupera esi
.text:67D21934 retn

 
.text:67D21935 or eax, 0FFFFFFFFh -->non deve arrivare qui
.text:67D21938 pop esi
.text:67D21939 retn-->esci si ma senza gloria...

Che poi sta Gloria chi �?Mah sono impazzito...uhmm..lo sono sempre stato...

Questa call fa un po di controlli..alla fine spiegher� come me ne esco da questa call...

Ed ora gli ultimi cmp...che vi riporto perch� sono sadico...

.text:67D218C6 cmp [ebp+var_1C], eax -->uguali?meglio si
.text:67D218C9 jnz short loc_67D218DD-->non deve saltare
.text:67D218CB cmp [ebp+var_18], 3-->uguali?meglio si
.text:67D218CF jnz short loc_67D218DD-->non deve saltare
.text:67D218D1 cmp [ebp+var_14], 5-->uguali?meglio si
.text:67D218D5 jz short loc_67D218E2->meglio saltare qui
.text:67D218D7 cmp [ebp+var_14], 2-->se arrivo qui e voglio sempre far registrare il prog,devono essere ugual
.text:67D218DB jz short loc_67D218E2 --> cos� salta da qui e si registra..UFFA che fatica!

Eh cavolo ho appena scoperto che � uscita la nuova versione di Opera...Opera 8.0 pazienza la versione 7.54u � sempre disponibile sul sito se proprio la volete vedere...e cmq fa gli stessi controlli...ed � protetta allo stesso modo...e soprattutto si registra con lo stesso serial...quindi se ne trovate uno valido per la versione qui descritta ...vale anche per quella nuova...anzi se voi usate il sistema bpx openfile e arrivate al 67C38D1C e gli dite guarda che ti stai sbagliando ..devi saltare...il programma parte gi� registrato...hey � la prima volta che supero una protezione senza neanche aver visto cosa fa il programma protetto...

Restano degli indirizzi da sistemare...si proprio quelli che avevo promesso di spiegare alla fine del tut..eh SI!la fine del tut � quasi arrivata...e quindi vediamo cosa succede in quegli indirizzi noiosissimi...

Intanto cominciamo col partire dall'istruzione all'indirizzo 67D218D1  richiede che il suo contenuto sia uguale a 5 o a 2 !

Vediamo ..se guardiamo poche righe sopra...all'indirizzo 67D218C6 si richiede che il contenuto di var_1C sia zero..le ragioni ve le ho gi� spiegate (eax deve essere zero per prima...) e dove viene settato a zero?ma prima vi ho spiegato che var_1C  � un puntatore alla nuova tabella....vogliamo sia zero...ma dove viene modificato per l'ultima volta?se guardate su scoprite che f� ci� nella prima call ..ci sono i commenti..guardate all'indirizzo 67D217B0 ..e siccome non viene pi� modificato basta che venga messo in [eax]=ecx con ecx=0 gi� che ci siamo poche righe sotto viene fatto [eax+8]=edx....eax+8 sarebbe in questo caso var_14...e deve quindi essere settata a 5 o a 2...cio� edx=5 oppure edx =2...!

Bene la domanda ora �:come riesco a metterci i valori che voglio?

Intanto ci focalizziamo sulla prima delle tre call...visto che abbiamo capito che � l� il casino...

Ora Guardiamo all'indirizzo 67D218B3...c'� un cmp ..devono essere uguali...ma in quegli indirizzi cosa c'�?..ci sono dei numeri settati nella prima call e alla fine della seconda...vi ricordate quando ho detto che viene copiata un array in un altra e i valori vengono modificati?ecco ora sapete perch� non devono essere modificati ..e siccome vengono ORati(grande neologismo...) con qualcosa..beh quel qualcosa deve essere ZERO (vi prego accettatelo cos� perch� non ce la faccio pi� a spiegarlo,se proprio volete conferme usate il fido sice o Olly e guardate gli indirizzi...)...(insomma diciamo che a questi numeri poi verr� applicato qualche controllo nella 3 call e questi controlli vengono superati da tutti quei numeri che non vengono modificati qui...i controlli in questione saranno dei div e si richieder� che edx sia zero...e no non ve lo spiego il perch� i 3 numeri passano automaticamente il controllo se non vengono modificati...diciamo che vengono generati apposta cosi?e perch� non ve lo spiego??Perch� non lo so! :-p

Le richieste edx= 2 o 5 e cmp edi,edx (ad indirizzi diversi e quindi i valori non sono in relazione banale...) implicano ecx=0000xy0t (dove t pu� essere 2 o A se voglio che edx sia uguale a 2) e di qui segue che edi � zero...Uffa che fatica...

Traccia del perch�: (ecx<<1) AND F7  = 2 o 5 e  (ecx AND 1)= zero queste sono due condizioni che devono valere per lo stesso ecx..segue che ecx � della forma precedente e quindi edi sar� sempre zero...e quindi non modificher� i valori...beh almeno cos� credo...uso "F" per indicare qualunque valore...tanto se ci metto 0 sono gi� sicuro che funzioni..allora ragiono da pessimista e mi chiedo alla peggio che condizionio deve soddisfare...

ecx AND 1 = 0 implica che ecx=FFFFFFFx con x numero pari...0 2 4 6 8 A C E

(ecx << 1) AND 7F = 2 richiede che sia ecx = FFFFFF0A oppure FFFFFF02

quindi ecx = FFFFFF0A dove le "F" possono essere qualunque altro valore ...anche 0

ma richiedo inoltre che

ecx AND 0F00 = 0F00 questo � soddisfatto per ecx = FFFFFxFF con x = 1 3 5 7 9 B D F

se quardate nella prima call ho scritto anche che ecx -> cx ..gli vengono cancellati i 2 byte grandi

conclusione...ecx = 0x0A con x = 1 3 5 7 9 B D F ma ecx di partenza pu� essere del tipo ecx=FFFF0F0A

Ma voglio che i 3 numeri non vengano moficati dagli OR e l'unico modo � richiedere che ecx=00000F0A

Oh finalmente ne sono uscito da questo casino di numeri...compatisco chi sta leggendo in questo momento...

Se vi arrendete e non riuscite +  leggere cmq personalmente ed umanamente vi capisco...

Questo riguarda la prima parte del cmp...il secondo numero viene modificato dalla seconda call...nelle ultime istruzioni...

Gi� ma i numeri passati..dove vengono generati???..uhm..nella Func2CheckCode!!!vi ricordate piccolo loop...e grande loop?bene servono per scassare l'anima e anche per generare 5 numeri...si 5 di cui 4 li conoscete il 5 viene modificato nella func3Checkcode e diventa quel famoso ecx fatto 0F02 o 0F0A...

E questo dovrebbe sistemare quei jnz / jz che danno tantoo fasitidio...

Ehy alla fine ci siamo arrivati in fondo...

Ma riassumiamo i controlli...(evito volutamente di parlare di tutte le uscite sbagliate che hanno le call):

-Il mio code deve soddisfare il requisito di essere X-xxxxY-xxxxY-xxxxY-xxxxY-xxxxY dove Y pu� assumere solo valori nella tabella minori di ...e X deve appartenere alla nuova tabella....

-Preso il mio code...nella Func2CheckCode con i loop vengono generati 5 numeri...

-Nella Func3CheckCode i numeri generati vengono mastruzzati...

-Arriviamo nella Func4CheckCode e vengono applicate le due cure previste dalla prima call e dalla seconda.. e ovviamente devono essere uguali!..poi  i primi 3 numeri vengono sottoposti a controlli nella 3 call e se tutto � andato a buon fine allora si registra e

FINE controlli...

Tanta fatica per scrivere le 5 righe finali...

Keygenerator

Non vi preoccupate non ho intenzione di farlo...

Solo potreste tentare per forza bruta..il vantaggio sta che non avreste bisogno di fare altro..prendete le righe gi� pronte del disassemblato le ordinate per gruppi mettete qualche istruzione in c che le richiama (tipo "__asm__") e gli passate dei valori casuali come input...provare provare che prima o poi ci arrivate..!Magari mettendo delle limitazioni ai valori dei numeri..Es se ecx deve essere ...e viene generato solo a partire dal 2 al 6 numero del mio code...beh potete cercare dei valori tali che questo sia vero...Cmq visto che nessuno � tanto pazzo da leggere questo tutorial e anche da scrivere un keygenerator per questo programma...inutile sprecare il fiato :-p

Ed ora un bel Uninstall..tanto io uso Firefox...decisamente migliore...Free ma soprattutto OpenSource

Come dite?? Il compito 5 dov'�?beh � per casa naturalmente....

 
luca                                                                                         30/04/2005

Note finali

Bene Bene...

Inizia la parte dei saluti..

Per prima cosa ringrazio Que e tutto lo staff per il loro lavoro...senza voi sarebbe molto pi� difficile.

E mi raccomando non pensate che lo faccio se no,non mi pubblica il tut... :-p

Saluto come sempre Grappolo,Asterix,Diego e Corrado (beh anche Giulia)...e gi� che ci sono anche Paolo, Anna, Stefano,Guido,Alessandro e Aldo...

Stavolta aggiungo anche Vale e Nina...

E immancabilmente la signorina B.!(...e stavolta lei mi piace un p� meno di ieri... :-p)

Che saluti al femminile...

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 che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

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