WorldMap 3D v. 1.1
(Patch In Memoria)

Data

by "Pbdz"

 

13/09/2002

UIC's Home Page

Published by Quequero


Cane che abbaia..non dorme...

Come ti ho gia detto ieri, bravo il tute e' completo e utile :)

Lo so che quella frase fa schifo...ma è la prima che mi è venuta in mente! :)

....

Home page se presente: http://pbdz.cjb.net
E-mail:[email protected]
Pbdz, #asm server: irc.azzurra.org

....

Difficoltà

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

 

Salve a tutti! Oggi crackeremo un programma con la tecnica del Memory Patching


WorldMap 3D v. 1.1
(Patch in Memoria)
Written by Pbdz

Introduzione

Salve a tutti! Questo è il mio primo tutorial...spero che sia tutto comprensibile...dato che ho la febbre stanotte mentre dormivo mi sono detto: "Vorrei provare a fare una patch in memoria..non l'ho mai fatto!" Ma mi serviva un programma giusto per me…curiosando sull'HD mi ritrovo questo programma WorldMap 3D che non è altro che uno Screen Saver che raffigura la terra che gira...vi do un indizio...non mi è mai piaciuto il manual unpacking... ;-)

Tools usati

WinDasm

SoftIce

Masm o altro compilato

 

URL o FTP del programma

Scaricatelo http://digilander.libero.it/pbdz/wm3d1.rar

Notizie sul programma

Questo programma è uno Screen Saver che rappresenta il nostro pianeta che gira...con i vari fusi orari ed ha persino la funzione che consiste nel ricevere la posizione delle nuvole via internet...bello! Chiede un nome e un serial ma noi non ce ne preoccupiamo...i nostri scopi sono altri ;-) 

Essay

 

Il programma ci chiede nome e relativo seriale…proviamo a disassemblare con windasm e..azz è packato…mmm ecco l'occasione che cercavo…dato che odio fare il manual unpacking proviamo il la patch in memoria…praticamente la patch in memoria non è altro che la modifica dei byte del programma però non sul disco fisso (come si fa di solito) ma in memoria…

però noi qui siamo particolarmente fortunati perché il nostro crack dovrà essere eseguito una sola volta a differenza di altre occasioni in cui il crack deve essere sempre eseguito…nel nostro caso è semplice perché il programma dopo averci fatto tanti complimenti, non si preoccupa di controllare il codice di registrazione un'altra volta perciò rimane registrato senza problemi…per prima cosa con SICE cerchiamo il jump condizionale che decide se il serial è esatto oppure no...eccolo! E' all'indirizzo 00447C0Bh ! Come ho fatto a trovarlo dovete scoprirlo da soli, è questione di un minuto…proviamo ad invertire il salto con r fl z e…Registrato! Wow…però ora disinstalliamo il programma e reinstalliamolo…così torna come prima…
Ma come facciamo a patchare il programma? Semplice! Dobbiamo farci un piccolo programmino in preferibilmente assembler, c'è più gusto :-)
Ok, apriamo il QEditor del Masm…ma, cos'è? Ah si…sono le urla di Albe, Spider…insomma quasi tutti quelli di #asm che mi stanno maledicendo perché uso il masm! ;-) Lo so…c'è di meglio…ma a me piace scrivere invoke! :-) e vi dico un'altra cosa: mi piace il VB! :-) (Spider non rosicare…) vabè riprendiamo…il QEditor serve per scrivere i programmi per il masm, naturalmente non è altro che un notepad con qualke funzione in più, nulla vi vieta di scrivere tutto col notepad!
L'algoritmo per sommi capi del nostro programmino è questo:

Avvio il programma WorldMap 3D
|
V
Apro il suo processo
|
V
Modifico i bytes
|
V
Chiudo il mio programmino

Naturalmente ci sono delle funzioni in + che vi spiegerò…
Iniziamo a scrivere il nostro bel programma (ve lo faccio a pezzi per capire cosa facciamo…naturalmente alla fine metterò tutto il sorgente!)

.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

Non vi spiego le prime 3 linee che ormai credo conosciate a cosa servono…
Dobbiamo importare le funzioni del kernel32.dll e user32.dll perché in questi 2 file c'è tutto quello che ci serve…

.data
NomeExe db "WorldMapC.exe",0
StartInfo STARTUPINFO <?>
ProcInfo PROCESS_INFORMATION <?>
class db "TfrmMain",0
handle dd 1 dup (?)
ProcessID dd 1 dup (?)
PrgHandle dd 1 dup (?)
ProcessHandle dd 1 dup (?)
ByteW dw 84h
Attenzione db "Attenzione - Errore!", 0
NotF db "Il programma WorldMapC.exe non è stato trovato!", 0dh,0ah
db "Assicurarsi di aver copiato questa patch nella cartella del programma!!",0
Fine db "Crackato!!" ,0
Istruzioni db "Bene!, ora premi il tasto Register," , 0dh,0ah
db "inserisci un Nome e Serial di fantasia e...REGISTERED!" ,0
Titolo db "Pbdz's patch for WorldMap 3D",0
Corpo db "Vuoi crackare il programma? (Dimmi di si :-P)",0
ComeNonDetto db "Ok, come non detto..sei onesto! :-P",0
Avvertenza db "Tanto la licenza devi COPRARLA lo stesso!", 0ah, 0dh
db "Questo crack è a scopo educativo..." ,0ah, 0dh
db "per farti capire che non è una bella cosa rubare!! CATTIVONE! :-)",0

Questa è la sezione .data qui ci sono le stringhe delle MsgBox, i puntatori alle strutture, dei buffer ecc...

Da ora in poi si inizia a fare sul serio:

.code
start:

invoke CreateProcess, Addr NomeExe , NULL, NULL, NULL, NULL, NULL, NULL, NULL, addr StartInfo, addr ProcInfo
cmp eax,1
jne nontrovato

Allora...qui usiamo la funzione CreateProcess, vediamo i parametri che dobbiamo passargli:

BOOL CreateProcess(

LPCTSTR lpApplicationName, // pointer to name of executable module
LPTSTR lpCommandLine, // pointer to command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // pointer to process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, // pointer to current directory name
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO
LPPROCESS_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION
);

Il primo parametro ci chiede il puntatore al nome del programma e noi mettiamo addr NomeExe, che se controllate anke nella sezione .data abbiamo:
NomeExe db "WorldMapC.exe",0
I prossimi 7 parametri possono essere NULL perciò non ce ne preoccupiamo...poi gli ultimi due devono essere i puntatori alle due strutture StartupInfo e Process_Information e potete vederli anche nella sezione .data...
Poi abbiamo:

cmp eax,1
jne nontrovato

Quando l'api CreateProcess funziona in eax viene riportato 1 perciò se eax non è 1 salta all'errore...
Ora provate a scrivere tutto quello fatto fino ad ora tranne il cmp eax,1 ecc...al loro posto mettete un invoke ExitProcess, NULL
Compilate il tutto copiate il nostro bel eseguibile nella cartella del programma, avviatelo et voilà WorldMap parte! Questo è il nostro primo passo!
Ora che facciamo? Beh possiamo usare WriteProcessMemory per scrivere i nostri byte in memoria anzi il nostro byte visto che ne è solo uno...eh si semplicissimo!
Allora analizziamo l'api WriteProcessMemory e vediamo cosa vuole:

BOOL WriteProcessMemory(

HANDLE hProcess, // handle of process whose memory is written to
LPVOID lpBaseAddress, // address to start writing to
LPVOID lpBuffer, // address of buffer to write data to
DWORD cbWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
);

Mmm…qui c'è qualcosa che non va…dove lo prendo l'handle del processo? Mi serve un'altra api per questo scopo!
Vediamo un po'… eccola OpenProcess! Ps. Per vedere di persona le api prendete il file Win32.hlp!!! Lo trovate dappertutto!

HANDLE OpenProcess(

DWORD fdwAccess, // access flag
BOOL fInherit, // handle inheritance flag
DWORD IDProcess // process identif
ier
);

Allora, il primo parametro è l'access flag…ce ne sono molte, ma noi usiamo PROCESS_ALL_ACCESS, il secondo parametro indica se l'handle può essere ereditato può assumere valore TRUE, FALSE, noi settiamo su FALSE, l'ultimo è il ProcessID e qui un altro guaio perché dobbiamo usare un'altra api per ricavarci questo valore…l'api che useremo è GetWindowTreadProcessId, eccolo:

DWORD GetWindowThreadProcessId(

HWND hWnd, // handle of window
LPDWORD lpdwProcessId // address of variable for process identifier
);

I parametri che richiede sono due: l'handle della finestra, che andremo a ricavarci con FindWindow e l'indirizzo dove andare a mettere il ProcessID
Allora, la sintassi di FindWindow è:

HWND FindWindow(

LPCTSTR lpClassName, // address of class name
LPCTSTR lpWindowName // address of window name
);

per usare FindWindow dobbiamo sapere la classe della finestra…questo lo possiamo scoprire con spy++ di microsoft…cmq nel nostro caso è TfrmMain, il secondo parametro è l'indirizzo del nome della finestra, ma questo può essere anke NULL e noi così lo lasciamo…
ora siamo pronti, aggiungiamo a quello che abbiamo scritto prima queste 2 righe:

invoke FindWindow, addr class, NULL
int 3

Compiliamo il tutto e settiamo un bpint 3 in SICE, allora, se FindWindow funziona in eax avrà il valore dell'handle della finestra, se è zero vuol dire che qualkosa è andato storto...proviamo...doh! tutto a zero! Come mai? Modifichiamo quell'int 3 che vediamo con un nop…scriviamo così in sice a, premiamo invio scriviamo nop e premiamo invio…ora uscite da SICE e vediamo che solo ora compare la finestra del nostro WorldMap…capito! FindWindow non trova niente perché quando viene eseguito la finestra ankora non è apparsa! Allora ovviamo con questa piccola routine:

Find: invoke FindWindow, addr class, NULL
cmp eax, 0 (oppure test eax, eax)
je Find
int 3

In sintesi esegue FindWindow finchè eax non conterrà un valore diverso da zero cioè l'handle...proviamo ora mettete il bpin 3 mi raccomando! Eccolo! Un bel numeretto in eax! Il secondo passo è fatto! Ritorniamo sul codice, ora chiamiamo l'api GetWindowTreadProcessId in questo modo…ricordate cosa ho scritto sopra…

invoke GetWindowThreadProcessId, eax, offset ProcessID

Usiamo il metodo dell'int 3 per verificare che tutto vada per il verso giusto, ok funziona!! Il ProcessID è nostro!! ;-)

Vai con la prossima, ovvero OpenProcess, dopo aver levato l'int 3 andiamo a scrivere

invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, dword ptr [ProcessID]

leggete la descrizione sopra se non ricordate che parametri ho pushato! Testiamo il tutto, bene funziona anke questo!!! Ora abbiamo il famoso Handle del Processo!
Di solito ora si fa un controllo dei byte che andremo a scrivere per verificare se sono effettivamente quelli…ma io mi rompo! Passiamo all'azione!! Se voi volete farlo provateci, l'api che si usa è ReadProcessMemory ed ha la sintassi identica a WriteProcessMemory!
Ecco qui la prossima istruzione e la + importante!

invoke WriteProcessMemory, eax, 00447C0Ch, offset ByteW, 1, NULL

Vabè sarò buono, vi descriverò tutti i parametri, ma solo per questa volta!

Allora, in
eax abbiamo l'handle del processo
0447C0Ch è l'indirizzo da cui inizieremo a patchare…vedete l'indirizzo dove c'era il nostro jnz all'inizio era 00447C0Bh ed i bytes erano 0F85xxxecc… ma a me interessa solo quell'85 che invertirà il salto infatti io lo sostituirò con 84 ma va bene anche con 90 perciò servendomi il secondo byte ho aumentato anche l'indirizzo! Spero sia chiaro…
ByteW è il buffer in cui abbiamo il byte da scrivere (84h, o 90h)
1 è il numero di byte che scriveremo…

Ok, la parte difficile è finita...anzi è finito tutto bisogna aggiungere qualke ritocchino tipo messaggi di avvertimento ecc…ora vi scrivo il sorgente intero…

.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data
NomeExe db "WorldMapC.exe",0
StartInfo STARTUPINFO <?>
ProcInfo PROCESS_INFORMATION <?>
class db "TfrmMain",0
handle dd 1 dup (?)
ProcessID dd 1 dup (?)
PrgHandle dd 1 dup (?)
ProcessHandle dd 1 dup (?)
ByteW dw 84h
Attenzione db "Attenzione - Errore!", 0
NotF db "Il programma WorldMapC.exe non è stato trovato!", 0dh,0ah
db "Assicurarsi di aver copiato questa patch nella cartella del programma!!",0
Fine db "Programma Crackato Correttamente!" ,0
Istruzioni db "Bene!, ora premi il tasto Register," , 0dh,0ah
db "inserisci un Nome e Serial di fantasia e...REGISTERED!" ,0
Titolo db "Pbdz's patch for WorldMap 3D",0
Corpo db "Vuoi crackare il programma? (Dimmi di si :-P)",0
ComeNonDetto db "Ok, come non detto..sei onesto! :-P",0
Avvertenza db "Tanto la licenza devi COPRARLA lo stesso!", 0ah, 0dh
db "Questo crack è a scopo educativo..." ,0ah, 0dh
db "per farti capire che non è una bella cosa rubare!! CATTIVONE! :-)",0

.code
start:
invoke MessageBox, NULL, addr Corpo, addr Titolo, MB_YESNO
cmp eax, 6
jne fine
invoke CreateProcess, Addr NomeExe , NULL, NULL, NULL, NULL, NULL, NULL, NULL, addr StartInfo, addr ProcInfo
cmp eax,1
jne nontrovato
find:
invoke FindWindow, addr class, NULL
test eax, eax
je find

invoke GetWindowThreadProcessId, eax, offset ProcessID
invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, dword ptr [ProcessID]
invoke WriteProcessMemory, eax, 00447C0Ch, offset ByteW, 1, NULL
cmp eax, 1
je AllOK
invoke ExitProcess, NULL
nontrovato:
invoke MessageBox, NULL, addr NotF, addr Attenzione, MB_ICONERROR
invoke ExitProcess,NULL
AllOK:
invoke MessageBox, NULL, addr Istruzioni, addr Fine, MB_OK
invoke ExitProcess,NULL
fine:
invoke MessageBox, NULL, addr Avvertenza, addr ComeNonDetto, MB_ICONINFORMATION
invoke ExitProcess,NULL
end start

Come potete vedere ho aggiunto una MsgBox iniziale che chiede se crackare o no il programma, una che avverte che non è stato trovato il file, un'altra che avverte che tutto ha funzionato, e una per chi non vuole crackare il programma! :-)

Siamo giunti alla conclusione! Spero abbiate imparato qualcosa di utile!

Pbdz

 

Note finali

Beh, volevo ringraziare per primo il Que che mi ha pubblicato questo tute! Poi naturalemente un saluto a tutti quelli di #asm, anche se in chat non parlo molto…ma io penso :-) e scusate se ho usato Masm! ;-) Non mi pare mica un crimine :) NdQue
Poi un grandissimo saluto agli amiconi di #rbnet sia della chat che del forum! Tra tutti IllusionTrip, ViRtUaL FoX, Capitano Nemo, JarreFan, macellaioTM, MarcoPon, SoloAMD (il cavaliere dell'h :-D) e gli altri che ora non ricordo, azz…un altro po' dimenticavo il supremo R(u)bnet! Poi un'ultimo saluto ad un amico acquisito da poco, Satlolo! Ciauz!!!

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 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.