Zoom Icon

Phoenix2 - Debugger, Loader, Patcher e Serial Fishing

From UIC

Phoenix2 (Debugger/Loader/Patcher & Serial Fishing)

Contents


Infos
Author: x86
Email: x86_cmp_x86@hotmail.com
Website:
Date: 20/03/2005 (dd/mm/yyyy)
Level: Some skills are required
Language: Italian Image:Flag_Italian.gif
Comments: Que: Grazie x86, ineccepibile come al solito!!!


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


Link e Riferimenti

Questo è il Crackme n° 79 disponibile alla pagina Crackme 76 - 100.


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</comment
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:
;Rimettiamo a posto
invoke WriteProcessMemory, pi.hProcess, _address_4017DF, offset read_bytes_4017DF, 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ì 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:
; Rimettiamo a posto
invoke WriteProcessMemory, pi.hProcess, _address_401453, offset read_bytes_401453, 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ì 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:
; Rimettiamo a posto
invoke WriteProcessMemory, pi.hProcess, _address_401452, offset read_bytes_401452, 1h, NULL
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 modificato 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)

 ; 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

* invoke ReadProcessMemory, pi.hProcess, _address_404130, offset read_bytes_zone_ser+1, 0Fh, NULL
* mov byte ptr read_bytes_zone_ser+10h, 0 ; Questo zero l'ho solo messo per essere sicuro che la
 ; stringa contenuta in buffer_bytes_zone_ser, che andrò a visualizzare con un MessageBoxA sia
 ; terminata

; Inseriamo adesso nel buffer il primo char del serial immesso nel crackme
* invoke ReadProcessMemory, pi.hProcess, _address_40416C, offset read_bytes_zone_ser, 1h, NULL
; 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

; Settiamo i Flag, devono essere entrambi settati
mov contx.ContextFlags, CONTEXT_FULL OR CONTEXT_DEBUG_REGISTERS
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)
; Salviamo il byte
invoke ReadProcessMemory, pi.hProcess, _address_4017DF, offset read_bytes_4017DF, 1h, NULL
; Settiamo il breakpoint
invoke WriteProcessMemory, pi.hProcess, _address_4017DF, offset bpint3, 1h, NULL
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

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.