Phoenix2
(Debugger/Loader/Patcher & Serial Fishing )

Data

by "x86"

 

20/03/2005
(eh cosa volete ... pensavo di non averlo salvato prima di un format e poi invece lo avevo tadà, così poi gli ho aggiunto qlcosina in più...)

UIC's Home Page

Published by Quequero

Come, Quando, Fiori, Piove

Grazie x86, ineccepibile come al solito!!!

Buio, Contro Buio

....

Home page (se presente): Non ho mai tempo per farla
E-mail: [email protected]
Nick: x86 canale IRC #crack-it

....

Difficoltà

( )NewBies (*)Intermedio ( )Avanzato ( )Master

 


Allegato

Introduzione

Dato che le Api-Debugger in questo periodo hanno riscosso molto successo, un pò vedi per le nuove tecniche di protezione di Armadillo e di conseguenza le nuove metodologie di cracking, dumping ecc. a riguardo, mentre stavo reversando questo crackme (tra l'altro molto interessante...) e stavo codando il KeyGen, (cosa abb. lunga dato la particolarità dell'algo di generazione del serial), ho pensato, perchè non provo a crearmi un loader-debugger, che mi aiuta, primo ad evitare tutta la parte di codice del loader (dato che è anke packato con Pex 0,99 - N.b. Si trova in giro anche l'unpacker), una volta in chiaro il codice del crackme ( non proprio così dato che il crackme stesso ha varie zone di codice smc che nascondono parti dell'algo della generazione del serial, ecc.), faccio settare dei breakpoint al mio loader in modo da arrivare alla zona in cui il crackme verifica la correttezza del serial (debolezza che secondo me, fa cadere l'intero castello posto a protezione di essa.....), la modifico e faccio mettere direttamente il seriale corretto in una zona di memoria in cui poi il mio loader lo andrà a leggere e a visualizzare! Ecco dopo questa premessa possiamo iniziare, ad addentrarci nel reversing e coding vero e proprio....

Tools usati

OllyDbg
Masm32

URL o FTP del programma

Nella sezione Crackme della U.I.C.

Essay

Faccio subito una premessa importante, questo tute risulterà abb. difficile a chi non ha ancora reversato il Phoenix2 e non ha compreso il suo funzionamento, anche perchè farò riferimento a precisi offset, che a me risultano familiari, in quanto identificano particolari zone di codice ... ( Lo so che avrei dovuto scrivere prima l'altro tute, nel quale spiegavo per filo e per segno tutto il codice che sta dietro a questo crackme, ( il KeyGen vero è proprio è già a metà ed il tute è in parte iniziato ... ) però per questioni di tempo, e anche perchè mi ero ingolosito delle Debug-Api... ho deciso di scrivere questo per primis ...

Sommario delle cose che dobbiamo fare:

  1. Gestire il primo exception trick Anti-Sice
  2. Gestire la seconda exception trick UD2
  3. Settare un hardware breakpoint sull'Api VirtualFree
  4. Settare un breakpoint all'Oep
  5. Settare un breakpoint all'indirizzo 401453h
  6. Settare un breakpoint all'indirizzo 401452h
  7. Verificare che effettivamente all'indirizzo 401455h i primi due byte siano stati decryptati (non si sa mai ....)
  8. Settare un breakpoint all'indirizzo 401455h
  9. Adesso che abbiamo tutta la routine di controllo del seriale decryptata possiamo modificarla a nostro piacimento
  10. Modifichiamo tramite WriteProcessMemory la nostra routine
  11. Settare un breakpoint all'indirizzo 401530h, in modo che il buffer sia stato riempito con il seriale corretto ( 15 char )
  12. Andare a leggere il buffer appena riempito, ma partendo dal secondo char in poi (questo perchè il primo char viene utilizzato per selezionare la call-algo, e verificare gli altri 15 char se sono corretti)
  13. Visualizzare tramite una Messagebox il seriale corretto

Dopo questa piccola premessa, iniziamo subito con caricare il Phoenix2 in Olly e andare a steppare il loader del Pex, dopo un pò che steppiamo arriviamo al seguente codice:

00416306 LEA EAX,DWORD PTR SS:[EBP+4023BD]
0041630C PUSH EAX
0041630D SUB EAX,EAX
0041630F PUSH DWORD PTR FS:[EAX] <-- Qui viene installata una seh, con il seh handler a 4161F1h
00416312 MOV DWORD PTR FS:[EAX],ESP
00416315 JMP SHORT Phoenix2.0041631A

Un'altra cosa da notare, della quale nn riporto il codice, dato che è una cosa semplicissima, in esi viene caricato il valore 4647h e in edi il valore 4A4Dh (chiamati anche Magic-Value), da questo si può intuire che subito dopo l'installazione della seh ci sarà un trick Anti-Sice, infatti dopo un step arriviamo alla seguente istruzione:

0041614C PUSH 9AE2FFCC <-- Pusha nello stack all'indirizzo 0012FF90 gli opcode delle istruzioni: INT3 e di seguito JMP EDX
00416151 JMP ESP <-- Dove Esp è = 0012FF90
 
N.B. se avete Sice caricato, l'int 3 nn genererà alcuna exception e quindi passerete alla istruzione JMP EDX che vi farà puntare alla chiamata ExitProcess

Se non avete capito perchè quando sice è caricato l'INT3 non genera alcuna Exception, basta che andiamo a vedere la lista di Ralf Brown, nella quale possiamo vedere che con i Magic Value caricati possiano utilizzare l'INT3 per fare varie cose (Soft-ICE - BACK DOOR COMMANDS), tipo visualizzare stringhe, ecc., è per questo che non genera alcuna exception perchè viene visto come un comando; Adesso dato che noi siamo con Olly l'INT3 genera un exception che verra trappata dalla seh e ci farà saltare all'indirizzo 4161F1h dove viene rimessa a posto la seh e si prosegue all'indirizzo 41615Bh, adesso dato che non ci interessa studiare il packer Pex, possiamo cliccare su F9 lasciarlo fare i suoi sporchi comodi e vedere dove si va a finire... tada.. ci blocchiamo su:

004161EE UD2 <-- Non fa altro che generare una exception e farci andare nuovamente all'indirizzo del Seh handler a 4161F1h

Riporto un pezzo di testo preso dal sito x86.org : ..... ( hihihi il mio omonimo :D )

UD2:
I found the following entry in a P6 document, somewhere: "UD2, an official, two byte long, undefined instruction is defined." This could mean one of two things.

There is a new exception called UD2, and a new opcode, which is guaranteed to generate the UD2 expection.
There is a reserved opcode called UD2, which will never be used by the processor. This new opcode, though undefined, will always generate an invalid opcode exception.
The latest revision of the Pentium manual (rev 004), defines UD2 as two opcodes. The following statement is quoted from the Pentium manual: "All banks in the opcode map are reserved and should not be used. Do not depend on the operation of unspecified opcodes. 0F0Bh or 0FB9h should be used when deliberately generating an illegal opcode exception." So there you have it. The definition of the UD2 opcodes

Il packer PeX 0.99 in tutto il suo loader ha solo due punti che utilizzano le seh, il primo con l'INT3 (Utilizzato anche come trick Anti-sice e quello appena descritto sopra con UD2), quindi la prima cosa nella nostra routine di debugger dobbiamo dirgli di far gestire queste eccezzioni direttamente dal loader di Phoenix2 e non dal nostro, iniziamo a vedere come si fa buttando giù un po di codice:

Tralascio sempre lo scheletro del file di masm32:

invoke CreateProcessA, offset nome_file, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+DEBUG_ONLY_THIS_PROCESS+CREATE_SUSPENDED, NULL, NULL, offset sinfo, offset pi

.while TRUE

invoke WaitForDebugEvent, addr debug_ev, INFINITE

.if debug_ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT

.break

.elseif debug_ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT

.if debug_ev.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, ...... (verifica degli address breakpoints)

jz

.elseif debug_ev.u.Exception.pExceptionRecord.ExceptionCode == 0C000001Dh

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, _address_004161EE ;Qui verifichiamo che siamo all'indirizzo corretto della istr. UD2 Trick seh PeX

jz

 

.endif

.endif

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLE

.endw

invoke ExitProcess, 0

end start

Questo è più o meno un pezzo dello scheletro del ciclo di loop del nostro debugger (ho tralasciato tutte le chiusure del while, e degli if, tanto è solo per far capire che una volta verificato le prime due exception (quelle del PeX), verificando anche gli indirizzi, così siamo più che sicuri che siano quelle e non altre, dobbiamo rispondere con un DBG_EXCEPTION_NOT_HANDLED, in modo da farle gestire direttamente dal suo loader e non dal nostro ciclo di debugger altrimenti uscirebbe un casino;A questo punto siamo quasi a posto, adesso per stepparci tutto il loader senza troppa fatica, saltando i vari controlli del byte CCh (quando nei debugger, come Olly e Sice si mette un BPX nome_api , si va a sostituire il primo byte originale con CCh, quello che poi andremo a fare anche noi con il nostro :) ) sugli indirizzi delle Api, possiamo tranquillamente mettere un hardware breakpoint sull'api VirtualFree ( questo lo so dato che ho già steppato tutto il loader, ed è secondo me la cosa più conveniente da fare...), quando viene eseguita questa Api, siamo sicuri che all'indirzzo del Oep, ci sia tutto il codice in chiaro, ( se pensate di dumpare e di avere l'exe pronto, ve lo potete scordare, dovete mettere a posto la IT), una volta brekkato su quell'api possiamo togliere l'hardware breakpoint e settare un BPX all'Oep, così siamo pronti per partire con il crackme vero e proprio. Al nostro debugger loop dobbiamo aggiungere alcune cose fondamentali, quando andremo ad inserire un hardware breakpoint dobbiamo verificare l'EXCEPTION_SINGLE_STEP, quindi avremo:

Tralascio sempre lo scheletro del file di masm32:

invoke CreateProcessA, offset nome_file, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+DEBUG_ONLY_THIS_PROCESS+CREATE_SUSPENDED, NULL, NULL, offset sinfo, offset pi

.while TRUE

invoke WaitForDebugEvent, addr debug_ev, INFINITE

.if debug_ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT

.break

.elseif debug_ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT

.if debug_ev.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, ......

jz

.elseif debug_ev.u.Exception.pExceptionRecord.ExceptionCode == 0C000001Dh

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, _address_004161EE ;Qui verifichiamo che siamo all'indirizzo corretto della istr. UD2 Trick seh PeX

jz

.break ;Se non è verificato usciamo da tutto

 

.elseif debug_ev.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, _address_virtualfree ;Qui verifichiamo che siamo all'indirizzo corretto della Api VirtualFree

jz

.break ;Se non è verificato usciamo da tutto

.endif

.endif

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLE

.endw

invoke ExitProcess, 0

end start

Ok, adesso lo scheletro del nostro debugger loop è quasi completo, dato che mancano solo alcune zone di codice, che ci consentiranno tramite dei breakpoint di far decryptare delle routine dell'algo di controllo e di creazione del seriale!, inoltre ci consentiranno di modificare il codice del crackme, in modo da avere il seriale corretto direttamente in un buffer di memoria, pronto per essere letto e visualizzato da una messagebox; Adesso siamo pronti e possiamo iniziare ad inseririre tutti passaggi:

Tralascio sempre lo scheletro del file di masm32:

invoke CreateProcessA, offset nome_file, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+DEBUG_ONLY_THIS_PROCESS+CREATE_SUSPENDED, NULL, NULL, offset sinfo, offset pi

.while TRUE

invoke WaitForDebugEvent, addr debug_ev, INFINITE

.if debug_ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT

.break

.elseif debug_ev.dwDebugEventCode == EXCEPTION_DEBUG_EVENT

.if debug_ev.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, _address_4017DF ; Quì si verifica che ci sia stato il Breakpoint all'Oep

jz ok_4017DF ; Se è avvenuto a quel indirizzo salta

cmp ecx, _address_401453 ;Qui si verifica che si stato il Breakpoint all'indirizzo 401453h

jz ok_401453 ; Se è avvenuto a quel indirizzo salta

cmp ecx, _address_401452 ;Qui si verifica che si stato il Breakpoint all'indirizzo 401452h

jz ok_401452 ; Se è avvenuto a quel indirizzo salta

cmp ecx, _address_401455 ;Qui si verifica che si stato il Breakpoint all'indirizzo 401455h

jz ok_401455 ; Se è avvenuto a quel indirizzo salta

cmp ecx, _address_401530 ;Qui si verifica che si stato il Breakpoint all'indirizzo 401530h

jz ok_401530 ; Se è avvenuto a quel indirizzo salta

cmp n_exception, 1 ; Check system breakpoint (alla prima esecuzione il valore di n_exception è 0, quindi siamo certi che per quel valore stiamo gestendo il system breakpoint, e quindi lo facciamo continuare con DBG_CONTINUE e incrementiamo la variabile n_exception a 1, in modo che al secondo exception breakpoint sappiamo per certi che è stato generato dal trick INT3 del loader del PeX che in questo caso dobbiamo farlo gestire direttamente dal suo loader e che quindi salterà a not_hanlde_cc dove nell'Api ContinueDebugEvent gli verrà passato il parametro DBG_EXCEPTION_NOT_HANDLE; (Punto 1)

jz not_hanlde_cc

inc n_exception


invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_CONTINUE
.continue

 

ok_4017DF:

invoke WriteProcessMemory, pi.hProcess, _address_4017DF, offset read_bytes_4017DF, 1h, NULL ;Rimettiamo a posto

mov contx.ContextFlags, CONTEXT_FULL

invoke GetThreadContext, pi.hThread , offset contx

dec contx.regEip ; Decrementiamo il registro Eip di uno in modo che continui l'esecuzione correttamente

invoke SetThreadContext, pi.hThread, offset contx ; Settiamo il context con i nuovi valori;

Quì settiamo il breakpoint all'inidirizzo 401453 (Punto 5)

invoke ReadProcessMemory, pi.hProcess, _address_401453, offset read_bytes_401453, 1h, NULL

invoke WriteProcessMemory, pi.hProcess, _address_401453, offset bpint3, 1h, NULL

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_CONTINUE
.continue

ok_401453:

invoke WriteProcessMemory, pi.hProcess, _address_401453, offset read_bytes_401453, 1h, NULL ; Rimettiamo a posto

mov contx.ContextFlags, CONTEXT_FULL

invoke GetThreadContext, pi.hThread , offset contx

dec contx.regEip ; Decrementiamo il registro Eip di uno in modo che continui l'esecuzione correttamente

invoke SetThreadContext, pi.hThread, offset contx ; Settiamo il context con i nuovi valori;

Quì settiamo il breakpoint all'inidirizzo 401452(Punto 6)

invoke ReadProcessMemory, pi.hProcess, _address_401452, offset read_bytes_401452, 1h, NULL

invoke WriteProcessMemory, pi.hProcess, _address_401452, offset bpint3, 1h, NULL

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_CONTINUE
.continue

ok_401452:

invoke WriteProcessMemory, pi.hProcess, _address_401452, offset read_bytes_401452, 1h, NULL ; Rimettiamo a posto

invoke ReadProcessMemory, pi.hProcess, _address_401455, offset read_bytes_401455, 1h, NULL

cmp word ptr read_bytes_401455, 6Ah ; Verifichiamo che i primi due byte siano stati decryptati correttamente e salviamo il primo (Punto 7)

jz ok_dec

.break

ok_dec:

mov contx.ContextFlags, CONTEXT_FULL

invoke GetThreadContext, pi.hThread , offset contx
dec contx.regEip ; Decrementiamo il registro Eip di uno in modo che continui l'esecuzione correttamente

invoke SetThreadContext, pi.hThread, offset contx ; Settiamo il context con i nuovi valori;

Quì settiamo il breakpoint all'inidirizzo 401455 (Punto 8)

invoke WriteProcessMemory, pi.hProcess, _address_401455, offset bpint3, 1h, NULL

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_CONTINUE

.continue

ok_401455:

;Adesso che abbiamo tutta la routine di controllo del seriale decryptata possiamo modificarla a nostro piacimento (Punto 9)

invoke WriteProcessMemory, pi.hProcess, _address_401455, offset read_bytes_401455, 1h, NULL

mov contx.ContextFlags, CONTEXT_FULL

invoke GetThreadContext, pi.hThread , offset contx

dec contx.regEip ; Decrementiamo il registro Eip di uno in modo che continui l'esecuzione correttamente

invoke SetThreadContext, pi.hThread, offset contx ; Settiamo il context con i nuovi valori;

Quì andiamo a modificare le istruzioni in modo che diventi così all'indirizzo (Punto 10); 401522 8807 --> 8807 --> mov byte ptr[edi], al; 401524 90 --> 90 --> nop; 401525 90 --> 90 --> nop; 401528 04 --> 01 --> add edi, 1; Possiamo scegliere di riscrivere tutto il codice con una solo WriteProcessMemory, oppure come ho fatto io; con tre chiamate di WriteProcessMemory, di andare a modificare solo i byte che ci interessano;------ Modifica delle istruzioni

invoke WriteProcessMemory, pi.hProcess, _address_401522, offset istr_1 , 2h, NULL

invoke WriteProcessMemory, pi.hProcess, _address_401524, offset istr_2 , 2h, NULL

invoke WriteProcessMemory, pi.hProcess, _address_401528, offset istr_3 , 1h, NULL

;Dopo aver modifato le istruzioni settiamo un breakpoint all'indirizzo 401530 (Punto 11)

invoke ReadProcessMemory, pi.hProcess, _address_401530, offset read_bytes_401530, 1h, NULL

* invoke WriteProcessMemory, pi.hProcess, _address_401530, offset bpint3 , 1h, NULL

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_CONTINUE
.continue

ok_401530:

; rimettimao a posto il byte sostituito all'indirizzo 401530 (anche se ormai non serve a nulla metterlo a posto)* invoke WriteProcessMemory, pi.hProcess, _address_401530, offset read_bytes_401530, 1h, NULL

; Andiamo a leggere all'indirizzo 404130 i 15 char del serial corretto appena caricato con le modifiche ai byte poco sopra (Punto 12)

* invoke ReadProcessMemory, pi.hProcess, _address_404130, offset read_bytes_zone_ser+1, 0Fh, NULL ; e li mettiamo saltando il primo byte del buffer_bytes_zone_ser, considerato che verrà caricato con il char del serial immesso all'inizio nel crackme

* mov byte ptr read_bytes_zone_ser+10h, 0 ; Questo zero lo solo messo per essere sicuro che la stringa contenuta in buffer_bytes_zone_ser, che andrò a visualizzare con un MessageBoxA sia terminata

* invoke ReadProcessMemory, pi.hProcess, _address_40416C, offset read_bytes_zone_ser, 1h, NULL ; Inseriamo adesso nel buffer il primo char del serial immesso nel crackme

* Convertiamo i byte nel loro corrispondente ASCII

xor ecx, ecx mov ecx, 1 ; Saltiamo il primo dato che avendolo letto direttamente dal buffer è già in ASCII

continua:

cmp ecx, 10h

jz finito

cmp byte ptr read_bytes_zone_ser[ecx], 0

jnge salta_a_lett

cmp byte ptr read_bytes_zone_ser[ecx], 9

jnbe salta_a_lett

add byte ptr read_bytes_zone_ser[ecx], 30h ;Se è compreso tra 0 e 9 sappiano che è un numero, altrimenti (anche considerando nella editbox,non si può immettere altro che da 0 - F) gli aggiungiamo 37h

jmp giu salta_a_lett:

add byte ptr read_bytes_zone_ser[ecx], 37h

giu:

inc ecx

jmp continua

finito:

; Andiamo a visualizzare il serial corretto (Punto 13)

* invoke MessageBoxA, NULL, addr read_bytes_zone_ser, addr cp_serial, MB_OK

; Terminiamo il tutto

* invoke GetExitCodeThread, pi.hThread, addr exitcode

xor eax, eax

* invoke TerminateProcess, pi.hProcess, exitcode


not_handle_cc:

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED
.continue

.elseif debug_ev.u.Exception.pExceptionRecord.ExceptionCode == 0C000001Dh

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, _address_004161EE ;Qui verifichiamo che siamo all'indirizzo corretto della istr. UD2 Trick seh PeX

jz not_handle_cd ; Dobbiamo far gestire l'execption direttamente dal loader del Phoenix2 (Punto 2)

.break ;Se non è verificato usciamo da tutto

not_hanldle_cd:

invoke GetModuleHandle, addr _kernel

invoke GetProcAddress, eax, addr _virtualfree

mov edi, eax ; Prendiamo l'indirizzo dell'Api VirtualFree per settare l'hardware breakpoint (Punto 3)

mov _address_virtualfree, eax ; Lo salviamo dato che ci servirà poi per verificare l'esattezza del breakpoint

mov contx.ContextFlags, CONTEXT_FULL OR CONTEXT_DEBUG_REGISTERS ; Settiamo i Flag, devono essere entrambi settati

invoke GetThreadContext, pi.hThread , offset contx

mov contx.iDr0, edi ; Mettiamo in Dr0 l'indirizzo dell'Api VirtualFree

mov contx.iDr7, 101h ; Settiamo Dr7 con il valore 101h, dato che corrisponde a un breakpoint in esecuzione settato all'indirizzo passato a Dr0;

N.B: se avete problemi a capire il perchè lookkatevi il manuale intel e così sarà tutto più chiaro.

mov contx.ContextFlags, CONTEXT_FULL OR CONTEXT_DEBUG_REGISTERS

invoke SetThreadContext, pi.hThread, offset contx ; Settiamo il context con i nostri nuovi valori


.elseif debug_ev.u.Exception.pExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP

mov ecx, debug_ev.u.Exception.pExceptionRecord.ExceptionAddress

cmp ecx, _address_virtualfree ;Qui verifichiamo che siamo all'indirizzo corretto della Api VirtualFree

jz ok_brkp_vf

.break ;Se non è verificato usciamo da tutto

ok_brkp_vf:

mov contx.ContextFlags, CONTEXT_FULL OR CONTEXT_DEBUG_REGISTERS

invoke GetThreadContext, pi.hThread , offset contx ; Prendiamo di nuovo il context

mov contx.iDr0, 0 ; Adesso azzeriamo il registro Dr0

mov contx.iDr7, 0 ; Adesso azzeriamo il registro Dr7, in modo da cancellare il Breakpoint sull'APi VirtualFree

mov contx.ContextFlags, CONTEXT_FULL OR CONTEXT_DEBUG_REGISTERS

invoke SetThreadContext, pi.hThread, offset contx ; Settiamo in context modificato;

Quì andiamo a settare un Breakpoint sull'Oep (Punto 4)

invoke ReadProcessMemory, pi.hProcess, _address_4017DF, offset read_bytes_4017DF, 1h, NULL ; Salviamo il byte

invoke WriteProcessMemory, pi.hProcess, _address_4017DF, offset bpint3, 1h, NULL; Settiamo il breakpoint

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_CONTINUE.continue

.endif

.endif

 

invoke ContinueDebugEvent, debug_ev.dwProcessId, debug_ev.dwThreadId, DBG_CONTINUE

.endw

invoke ExitProcess, 0

end start

Con questo è tutto, ad ogni modo allego al presente anche il loader già compilato e funzionante (testato su WinXp e vari Sp1 e Sp2 ..., su Win2K (testato su VM) il crackme deve avere qlc problema dato ke genera un errore quando si va ad inserire i valori del serial, altrimenti funzionerebbe anche su questo, mentre in Win9x, per delle limitazione del SO nn si possono settare hardware breakpoint sugli address delle Api... avrei dovuto aggirare il problema, cosa che per questioni di tempo nn ho fatto...), per farlo funzionare szippatelo in una cartella assieme al crackme Phoenix2 e lanciate il loader, inserite un nick (Chiaramente solo char composti da lettere!) e un serial di 16 char e cliccate su register, vi uscira una messagebox con il serial, adesso potete avviare un secondo Phoenix2 mettere il nick che avevate scelto prima e inserire il serial visualizzato nella MsgBox.

Byz x86

Note finali

Come al solito saluto in primis Adri e a seguire d31m0s, Que (che sarà ancora incazzato per la buca ke gli ho tirato in chat ... speriamo sia generoso, e che trovi ancora il tempo per discutere dello St.........) Il Q non si incazza mai tranquillo :) NdQue Yado, Andre e per finire come posso dimenticarmi di Paco.

Mandi Mandi biei..

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.