Oliver's first crackme |
||
Data |
by "Pincopall " |
|
10/01/2001 |
Published by Quequero |
|
|
Anche questo tutorial vi propone una via per trasformare un programma in un autokeygenerator, l'altro lo trovate alla uic, e lo scrissi io su come trasformare il 3DMark99, questo tutorial è completo e spiega chiaramente tutta la procedura necessaria, bravo pinco :) |
...arriva dopo ;-)) |
|
||
Difficoltà |
(X)NewBies (X)Intermedio ( )Avanzato ( )Master |
Prima troveremo il giusto seriale per il nostro nome e poi faremo anke in modo ke sia il crackme stesso a dircelo una volta inseritone uno sbagliato :-)
Introduzione |
Tools usati |
URL o FTP del programma |
Notizie sul programma |
Essay |
Allora, allacciate le cinture e pronti a partire,
lanciamo il file ocrackme.exe e vediamo ke si tratta di una semplice finestrella :) con
due box, uno per il nome ed uno per il serial, ed il bottone "Check".
Ok, infiliamo il nostro nome "Pincopall", la nostra password
"11224433" ad cazzum, e premiamo "Check" e TADAA, non succede niente,
nemmeno una Beggar Off con scritto qualcosa, niente, mmmm vabbè, proviamo ad aprire
SoftIce (Ctrl+D) e mettiamo un bpx, già ma...su ke? Bhè io ho deciso di metterlo il più
generale possibile, visto ke i vari bpx GetDlgItemTexta , GetWindowTexta, MessageBox et
similia non davano frutti, ho dunque messo un bel bpx hmemcpy.
Usciamo dal SIce (F5) e clikkiamo su "Check" e SoftIce poppa, premiamo 7 volte
F12 e ci troveremo nel codice di ocrackme.exe, cominciamo dunque a steppare con F 10
eseguendo ogni ret, e dopo un po' ci ritroveremo qui:
:00430CB2 lea edx, dword ptr
[ebp-08] ---- arriviamo qui
:00430CB5 mov eax, dword ptr
[esi+000001E0]
:00430CBB call 0041AC18
Ok, steppiamo kon F10, arriviamo sopra la call, ankora F10 e questa ci risbatte nel Kernel, vabbè, ancora 7 volte F12 e ritorniamo in ocrackme.exe stavolta per restarci, una altra serie di ret, e alla fine dei ret arriviamo qui :
:00430CC0 mov eax,
dword ptr [ebp-04] --- arriviamo qui dove mette il nostro nome in
eax
:00430CC3 call 00403938
:00430CC8 cmp eax, 00000006 --- si accerta ke il seriale sia almeno di 6
caratteri
:00430CCB jge
00430CDC --- se lo è si và avanti
:00430CCD mov eax, 00430EF4
:00430CD2 call 0042EB3C
:00430CD7 jmp
00430EC4 --- sennò....Bambino Cattivo
Referenced by Jump at Address:
|:00430CCB(C)
|
:00430CDC cmp dword ptr [ebp-08],
00000000 --- controlla ke il
codice abbia almeno
una cifra
:00430CE0 jne 00430D16 --- e se la ha , tutto bene, sennò ...
:00430CE2 mov eax, 00430F24
:00430CE7 call 0042EB3C
:00430CEC jmp 00430EC4 --- ...Bambino Cattivo
Dunque il nostro nome deve essere di
almeno 6 caratteri ed il nostro seriale deve quantomeno esistere :)
Allora, vediamo un po', il nostro
nome, 6 caratteri li ha, il nostro seriale esiste, il salto a 00430CE0 salta e ci porta al
primo dei loop ke modificheranno il nostro nome ovvero qui :
:00430CF1 mov eax, dword ptr [ebp-04] --- inizio loop dove rimette in eax il nostro
nome
:00430CF4 call
00403938 --- Controlla ke eax
non sia vuota e se non lo è ci mette il
numero di caratteri del nome
:00430CF9 sub
eax, ebx --- Sottrae a eax il
numero di caratteri già modificati
:00430CFB mov
edx, dword ptr [ebp-04] ---
Muove in edx il nostro nome
:00430CFE mov
dl, byte ptr [edx+eax-01] ---
Muove in dl il carattere da modificare,
partendo dall'ultimo
:00430D02 lea
eax, dword ptr [ebp-1C]
:00430D05 call
00403860 --- Questa e quella qui
sotto sono due call ke modificano
ankora il nostro nome, ma ankora non abbiamo il
seriale completo
:00430D0A mov
edx, dword ptr [ebp-1C]
:00430D0D lea
eax, dword ptr [ebp-0C]
:00430D10 call
00403940
:00430D15 inc
ebx --- incrementa il numero di
caratteri modificati
* Referenced by Jump at
Address:
|:00430CE0(C)
|
:00430D16 mov
eax, dword ptr [ebp-04] ---
arriviamo qui dove mette in eax il nostro
nome
:00430D19 call
00403938 --- Qui controlla ke
eax non sia zero e se non lo è ci mette
il numero di caratteri del nome
:00430D1E cmp
ebx, eax --- il loop continua
finkè eax=ebx, ovvero finkè non ha
ritoccato tutti i caratteri del nome
:00430D20 jl
00430CF1 --- se non li ha
ankora finiti di modificare tutti, il loop
riparte
:00430D22 mov
ebx, 00000001
:00430D27 jmp
00430D5F --- Questo salto ci
porta al secondo loop
Dunque vediamo qui il primo loop ke verrà scorso 9 volte ( Pincopall è di 9 caratteri ) e poi passerà alla istruzione successiva, per non sorbirci tutte le volte il loop, in SIce clikkiamo sulla riga all'offset 00430D22 in modo da metterci un bp, usciamo da SIce e questo subito ricompare dopo aver finito il loop; eseguiamo dunque il salto all'offset 00430D27 e arriviamo al secondo loop di modifica :
:00430D29 push
[ebp-14] --- viene
pushato ogni volta il nome modificato
:00430D2C lea eax,
dword ptr [ebp-1C]
:00430D2F mov edx,
dword ptr [ebp-04] ---
viene mosso in edx il nostro nome
:00430D32 mov dl,
byte ptr [edx+ebx-01] --- viene
messo in dl il carattere da modificare
:00430D36 call
00403860
:00430D3B push
[ebp-1C]
:00430D3E lea edx,
dword ptr [ebp-20]
:00430D41 mov eax,
dword ptr [ebp-0C] --- viene messo in eax il nome al contrario
:00430D44 movzx eax,
byte ptr [eax+ebx-01] --- viene
messo in eax il primo carattere
del nome al contrario
:00430D49 call
00406778
:00430D4E push
[ebp-20]
:00430D51 lea eax,
dword ptr [ebp-14]
:00430D54 mov edx,
00000003
:00430D59 call
004039F8
:00430D5E inc ebx --- incrementa il numero dei caratteri
esaminati
* Referenced by a (U)nconditional or
(C)onditional Jump at Address:
|:00430D27(U)
|
:00430D5F mov
eax, dword ptr [ebp-04] --- il
salto ci porta qui dove viene messo in eax
il nostro nome
:00430D62 call
00403938 --- Questa call l'abbiamo già vista in
precedenza
:00430D67 cmp
ebx, eax --- Guarda se ha modificato tutti i caratteri
:00430D69 jl
00430D29
--- se no ricomincia il loop
:00430D6B mov
ebx, 00000001 --- se si muovi in ebx, 1
:00430D70 lea
eax, dword ptr [ebp-0C]
Come vedete il secondo loop è molto
simile al primo, ed alla fine, in ebp-14 troveremo il nostro nome modificateo, ad
esempio da "Pincopall" si arriva a "P108i108n97c112o111p99a110l105" e
come vedete manca un carattere, infatti se ho un nome di X caratteri, il loop ne
modificherà X-1, continuiamo , una volta finito il loop a steppare, finkè non ci
ritroviamo nel terzo :
|
:00430DC7 mov eax, dword
ptr [ebp-14] --- qui ci porta il
salto all'offset 430DC7 e
mette in eax il nome ottenuto dai primi 2
loop
:00430DCA call 00403938 --- solita call
:00430DCF dec
eax --- decrementa eax
:00430DD0 cmp ebx,
eax --- e lo confronta con
ebx ke viene incrementato all'offset
430DC6
:00430DD2 jl
00430D7A --- se ebx
è minore allora si riinizia il loop
Nel mio caso eax è uguale a 1E, infatti è trenta caratteri e quando ebx è 1D il salto non salta, a quel punto il codice finirà in un salto ke ci porterà al 4° loop, ovvero qui :
:00430DFE inc ebx
* Referenced by a (U)nconditional or
(C)onditional Jump at Address:
|:00430DE1(U)
|
:00430DFF mov
eax, dword ptr [ebp-0C]
:00430E02 call
00403938
:00430E07 cmp
ebx, eax
:00430E09 jl
00430DE3
:00430E0B mov
ebx, 00000003
:00430E10 lea
eax, dword ptr [ebp-0C]
:00430E13 call
004036BC
:00430E18 cmp
ebx, 00000030
:00430E1B jge
00430E3F ---questo salto NON
salta
Di questo loop vi riporto solo la fine, come farò degli altri in quanto lo scopo di questo tutorial non voleva essere lo spiegarvi la routine di creazione del seriale ke potrete facilmente studiarvi da soli, sennò ke gusto c'è ? :) ma voleva essere il far diventare il programma un autokeygenerator. Quindi , finito il loop qui sopra, un jmp ci porta al loop ke ha inizio all'offset 00430E1D e da quì si arriva alla fine del :
:00430E2C mov edx,
dword ptr [ebp-1C]
:00430E2F lea eax,
dword ptr [ebp-0C]
:00430E32 call
00403940
:00430E37 add ebx,
00000003
:00430E3A cmp ebx,
00000030
:00430E3D jl 00430E1D
E da qui si arriva finalmente all'ultimo loop ke inizia all'offset 00430E46 e termina qui :
:00430EA0 inc ebx
* Referenced by a Jump at Address:
|:00430E44(U)
|
:00430EA1 mov eax, dword ptr
[ebp-0C]
:00430EA4 call 00403938
:00430EA9 cmp ebx, eax
:00430EAB jle
00430E46 --- finito il loop
:00430EAD mov eax, dword ptr
[ebp-0C] --- viene messo in eax
il serial giusto
:00430EB0 mov edx, dword ptr
[ebp-08] --- ed in edx quello da
noi immesso
:00430EB3 call 00403A48 --- in questa call vengono confrontati i
serial
:00430EB8 jne 00430EC4 --- se non sono uguali non appare la
MessageBox di complimenti
:00430EBA mov
eax, 00430F40 --- viene messa in
eax la stringa di congratulazioni
Vediamo dentro la call ke confronta i seriali :
:00403A48 push ebx
:00403A49 push esi
:00403A4A push edi
:00403A4B mov esi, eax
:00403A4D mov edi, edx
:00403A4F cmp eax, edx --- qui c'è il confronto fra seriali
:00403A51 je
00403AE6 --- e se
sono uguali si va alle congratulazoni
:00403A57 test esi, esi --- sennò guarda se il codice generato non
esiste
:00403A59 je
00403AC3 --- e se lo
è : errore
:00403A5B test edi, edi --- e se non lo è guarda se nullo è il
serial da noi immesso
:00403A5D je
00403ACA --- e se lo
è : errore
:00403A5F mov eax, dword ptr
[esi-04] --- sennò fà andare
avanti il prog ke però non
fà apparire niente
:00403A62 mov edx, dword ptr
[edi-04]
:00403A65 sub eax, edx
Bene, ovviamente basta fare quando si è terminato il loop un "d eax" per trovare il serial, ke per la cronaca, per Pincopall è "431114434654410".
Bene, abbiamo finito il serial fishing, e credo abbiate notato ke è stato abbastanza
facile, e ora arriviamo al vero scopo del nostro cercare il seriale, non è infatti,
almeno per me , essere registrati, ma trasformare il crackMe in un generatore di kiavi,
bene, mettiamoci all'opera.
Noi vogliamo ke, se il seriale inserito fosse sbagliato, il programma ci mostri una
MessageBox con il codice da mettere in base al nostro nome, la nostra MessageBox sarà
inoltre il più semplice possibile, con solo il pulsante di Ok, vi riporto sotto la
sintassi dell'API MessageBox :
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
Dunque, vediamo ke ci dobbiamo mettere dentro e, una volta pronta vediamo kome
inserirla nel codice del programma:
intanto noi vogliamo una Messagebox kon il pulsante ok, e come ci dice la guida alle API
il flag da mettere è 0, il primo push sarà quindi un push 00, perkè i parametri vanno
pushati nel senso opposto in cui vengono passati, quaesto per la proprietà LIFO (Last In
First Out ) ke ha lo stack; poi possiamo subito impostare l'handle of owner window ke
sarà ank'esso zero, ed ancora, sin da subito sappiamo quale sarà l'indirizzo cui far
andare la call, se infatti vediamo fra le Imported Functions del programma troviamo una
MessageBox, clikkiamoci sopra, e vediamo ke c'è una call 004057F4, bene, questa sarà
anke la call ke dovremo usare noi.
Abbiamo dunque per ora un:
push 00
push address of title of message box
push address of text in message box
push 00
Call 004057F4
Ci sono però ankora da pushare il titolo della
MessageBox nonkè il suo contenuto, e mentre il titolo sarà il nostro nome, il contenuto
sarà il seriale esatto.
Bene, il nostro seriale giusto è contenuto in ebp-0C , mentre il nostro nome iniziale è
in 00BA1720. Vediamo intanto ke tale MessageBox dovrà apparire al salot di quel jne
all'offset 00430EB8 ke andrà quindi reindirizzato.E vediamo inoltre ke dopo tale salto
eax viene rimodificato poikè vi viene inserita la stringa di congratulazioni, dunque
possiamo usare eax per i nostri scopi facendo diventare il nostro codice:
push 00
mov eax, 00BA1720
push eax
mov eax, [ebp-0C]
push eax
push 00
Call 004057F4
Ok, la nostra MessageBox è pronta, ora c'è solo da decidere dove infilarla nel programma. Bene, apriamo WDasm ed andiamo a vedere le sezioni :
Object01:
CODE RVA: 00001000 Offset: 00000400 Size: 00030200 Flags: 60000020
Object02: DATA
RVA: 00032000 Offset: 00030600 Size: 00000C00 Flags: C0000040
Object03:
BSS RVA: 00033000 Offset: 00031200 Size: 00000000 Flags:
C0000000
Object04: .idata RVA: 00034000
Offset: 00031200 Size: 00001E00 Flags: C0000040
Object05: .tls
RVA: 00036000 Offset: 00033000 Size: 00000000 Flags: C0000000
Object06: .rdata RVA: 00037000
Offset: 00033000 Size: 00000200 Flags: 50000040
Object07: .reloc RVA: 00038000
Offset: 00033200 Size: 00003600 Flags: 50000040
Object08: .rsrc RVA:
0003C000 Offset: 00036800 Size: 00004600 Flags: 50000040
Come vedete la sezione CODE ha una dimensione di 30200
bytes a partire dall'offset 400, mentre la sezione DATA, ke la segue comincia all'offset
30600, andiamo dunque a vedere kosa c'è prima di quel 30600 con il nostro editor
esadecimale, e troviamo un sacco di byte 00 da modificare a nostro piacimento in cui
possiamo quindi mettere gli opcode della nostra MessageBox, stando però attenti a non
toccare il primo di questi byte perkè potrebbe sempre essere un terminatore di stringa.
Attenzione però, perkè ai byte corrispondenti alle istruzioni della nostra messagebox,
ci vanno messi anke quelli corrispondeti ad un jmp incondizionato ke c riporti alla
normale esecuzione del programma come se il codice fosse stato errato , ovvero un jmp
00430EC4 ke nel nostro codice andrà messo subito dopo la call 004057F4.
Ma vediamo, prima di mettere i relativi opcode, a ke indirizzo poi mi risulteranno nel
disassemblato, ebbene, se provate ad andare alla fine del disassemblato troverete una
serie di
:004310D6 00000000000000000000 BYTE 10 DUP(0)
E se guardate in basso a destra troverete a ke offset
andarlo a trovare nell'editor esadecimale, per esempio in questo sopra è 00304D6h, bene
dunque, possiamo per esempio mettere proprio qui la nostra messagebox.
Ordunque vediamo ke opcode mettere, allora per i push 00 si mette un 6A00, per i mov eax,
00BA1720 e [ebp-0C] si mette rispettivamente B82017BA00 e B845F4, per i push
eax un 50 , già ma per il jmp? e per la call? bhè, per il jmp si mette E9 e ,
ribaltato, la differenza fra l'indirizzo di destinazione e l'indirizzo della istruzione
successiva a quella di partenza, e stesso dicasi per la call, solo ke al posto dell'E9 c
andrà un E8, ma vediamo ora il risultato finale :
:004310E0
6A00
push 00000000
:004310E2
B82017BA00
mov eax, 00BA1720
:004310E7
50
push eax
:004310E8
8B45F4
mov eax, dword ptr [ebp-0C]
:004310EB
50
push eax
:004310EC
6A00
push 00000000
* Reference To: user32.MessageBoxA, Ord:0000h
|
:004310EE
E80147FDFF
Call 004057F4
:004310F3
E9CCFDFFFF
jmp 00430EC4
Non resta ora ke kambiare quel jnz all'offset 00430EB8,
ke era il salta ke c portava all'errore kon un bel jmp 004310E0, bene, per vedere l'opcode
da dare a quest'ultimo basta andare in SoftIce, entrare come prima in ocrackme.exe e
mettere un bpx 00430EB8, ora usciamo da e lui subito si rifà vivo posizionato sulla riga
ke c serve, digitiamo " a eip" e scriviamo accanto a quell'offset : jmp
004310E0, ma , sfiga, è un salto lungo , ke non vuole + 2 bytes, bensì 5, e ke per
questo mi và a cancellare la fondamentale stringa all'offset 00430EBA. Ma allora come
fare? Bene, ecco cosa si deve fare, si deve prendere quel mov eax,00430F40 e metterlo alla
fine del nostro codice, dopo il salto condizionato all'offset 4310F3, e dopo questo mov
dobbiamo inserire un jmp ke ci riporterà a 00430EBF, inoltre, prima del nostro codice
dobbiamo inserire un je ke ci porterà direttamente a quel mov, e quindi a quel secondo
salto incondizionato, nel caso ke il codice da noi immesso vada bene.
MA vediamo ke opcode mettere per questi due nuovi salti, mentre ovviamente per il mov
metteremo quello ke già ha, ovvero
B8400F4300; dunque, per il jmp usiamo la formula sopra citata e troviamo ke l'opcode ad
esso relativo è E9BDFDFFFF, mentre troviamo ke per il je 004310F8 , ke andrà posizionato
subito sopra il primo deo nostri push 00, ovvero all' offset 004310DE, l'opcode sarà 7418
; questo sarà alla fine il nostro codice con i relativi opcode:
:004310DE
7418
je 004310F8
:004310E0
6A00
push 00000000
:004310E2
B82017BA00
mov eax, 00BA1720
:004310E7
50
push eax
:004310E8
8B45F4
mov eax, dword ptr [ebp-0C]
:004310EB
50
push eax
:004310EC
6A00
push 00000000
* Reference To: user32.MessageBoxA, Ord:0000h
|
:004310EE
E80147FDFF
Call 004057F4
:004310F3
E9CCFDFFFF
jmp 00430EC4
* Referenced by a Jump at Address:
|:004310DE(C)
|
:004310F8
B8400F4300
mov eax, 00430F40
:004310FD
E9BDFDFFFF
jmp 00430EBF
C'è inoltre ora da considerare ke il salto all'offset 00430EB8 non c dovrà più portare a 4310E0 ma bensì a 004310DE, andiamo dunque a vedere kome apparirà il codice all'indirizzo 430EB8:
:00430EB8
E921020000
jmp 004310DE
:00430EBD
90
nop
:00430EBE
90
nop
Andiamo dunque ad inserire quei byte al posto di quelli
del jne 00430EC4 e del mov eax, 00430F40 e salviamo.
Dunque abbiamo finito, proviamo, facciamo partire il prog, mettiamo "Pincopall"
, "Dummy_serial" e lui TADAA fà apparire la message Box con titolo
"Pincopall" e argomento "431114434654410", alèèè funzia, è
diventato un keygenerator !
That's the End
ByeZ
Note finali |
Un saluto ed un ringraziamento in primis a +Malattia perkè è un grande, poi a Tutti i membri della UIC, ed in particolare a Il_Bieco ke se ne partirà a giorni per gli USA con con biglietto per New York e ke, una volta là, aperta la valigia mi ci troverà dentro :) eheheh CIAO BIECONE FATTE SENTIIII'.
And last but not least, come ogni mio tute, un salutoz a Ra1n (ke è Nio col nick nuovo :-), B3bos, GiPOCO, C1CC10 e tutti quelli di #hackit99
Disclaimer |
Vorrei ricordare che questo software non può essere nè comprato nè rubato, per cui ke volete da me?! 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.