Come fare un keygen ( scopo illustartivo)

« Older   Newer »
  Share  
Genesis 93
view post Posted on 2/9/2010, 12:45




Guida a sl scopo illustrativo,se lo volete fare,fate pure,io non tengo nessuna reponsabilità di che fate!

Introduction

In questo tutorial, andremo a creare una finestra avente forma e sfondo da noi deciso (cioè il cosiddetto "skinning" della finestra)

Prima di tutto creeremo una generifa finestra in Win32, poi ci staccheremo un attimo dalla programmazione dedicandoci alla grafica :P ed infine metteremo tutto insieme, aggiungendo anche qualche pulsantino per rendere la nostra finestra simile a quelle dei crackme/keygen delle varie crew in circolazione :D



Tools

Notepad++ o un qualcunque altro editor di testo

Ci servirà per scrivere il codice :P

FASM

L'assembler che uso e che consiglio. Naturalmente potete usarne altri, ma a quel punto la traduzione delle varie direttive spetta a voi.

Un programma per disegnare

QUi la scelta è ampia, dal paint di windows a Photoshop e derivati. Io uso di solito la suite di CorelDraw, ma come ho detto la scelta è soggettiva, ne va bene qualunque possa salvare in bitmap puro (.BMP)

Creatore Regioni

Un resource compiler

Ovvero il programmino che da resource script (.RC) ci dà la versione compilata e pronta al linking (.RES).

Potete scegliere quello che vi aggrada di più, se non sapete quale prendere, usate questo: GoRC

Guida API

Conoscienza dell'assembly (e del FASM magari)

Conoscienza della programmazione Win32


Essay


PARTE [1] -> Creazione della finestra generica


Bene Iniziamo:

Allora, apriamo il nostro editor di testo e iniziamo col creare una generica finestra in win32 (Nel sito ci sono tutorial a riguardo, altrimenti potete vedere anche il sito di Iczelion)

Quindi:
Format PE GUI 4.0
entry start

Con questo, indicheremo al linker interno del fasm il formato di file in output (Win32) e che l'EntryPoiny del programma sarà all'etichetta start
include "C:\FASM\INCLUDE\WIN32A.INC"

Includiamo il file win32a.inc che contiene alcune macro utili per velocizzare la scrittura del codice e per evitare di scriversi i descrittori dell'IT a mano (cosa che il fasm permette di fare ;) )
section "import" import data readable

library kernel32,"kernel32.dll",\
user32,"user32.dll",\
gdi32,"gdi32.dll"

include "C:\FASM\INCLUDE\API\kernel32.inc"
include "C:\FASM\INCLUDE\API\user32.inc"
include "C:\FASM\INCLUDE\API\gdi32.inc"

Ecco a voi la prima sezione che scriveremo: la cosiddetta sezione .idata (che per comodità ho chiamato "import"), alla quale ho attivato il flag di lettura

Per informazioni su l'uso di library e import vi rimando al sito del FASM.

Scriviamo ora una sezione per i dati:
section "dativari" data readable writeable

Classname db "SkinClass",0

wc WNDCLASSEX sizeof.WNDCLASSEX,\
CS_BYTEALIGNWINDOW + CS_BYTEALIGNCLIENT,\
WndProc,0,0,\
0,\
0,0,\
0,\
0,Classname,0
msg MSG

hInst dd 0
hwnd dd 0
himg dd 0

Come vedete, la sezione si chiama dativari, contiene dati generici e è leggibile e scrivibile.

Naturalmente c'è la struttura WNDCLASSEX inizializzata con i membri di cui abbiamo già il valore, una struttura MSG per la gestione dei messaggi e un pò di dword per handle vari.

Ora cominciamo a esaminare il codice della prima parte:
section "codice" code readable executable
start:
push 0
call [GetModuleHandle]

mov dword [hInst],eax
mov dword [wc.hInstance],eax

push IDC_CROSS
push 0
call [LoadCursor]
mov dword [wc.hCursor],eax

push IDI_APPLICATION
push 0
call [LoadIcon]
mov dword [wc.hIcon],eax
mov dword [wc.hIconSm],eax

mov dword [wc.hbrBackground],COLOR_WINDOW

push wc
call [RegisterClassEx]
or eax,eax
jz endofall

Dunque, con questo primo frammento, creiamo la sezione per il codice (chiamata appunto "codice") con permessi per la lettura ed esecuzione.

Nel codice vero e proprio, chiamiamo GetModuleHandle per ottenere l'instance handle del nostro programma e depositiamo tale valore sia nella variabile hInst che nella struttura WNDCLASSEX

Quindi, Riempiamo gli altri membri di WNDCLASSEX con LoadIcon, LoadCursor e sistemando temporaneamente (visto che successivamente lo cambieremo) il valore COLOR_WINDOW al membro hbrBackground

Riempita così la struttura WNDCLASSEX, la passiamo a RegisterClassEx controllando poi che sia tutto ok (risultato diverso da 0)

PS. Ricordatevi che il FASM, quando incontra il nome di un dato senza parentesi quadre o altre forme esplicite, intende l'indirizzo di quella variabile

Proseguiamo col codice:
push 0
push dword [hInst]
push 0
push 0
push 250
push 250
push 300
push 300
push WS_VISIBLE or WS_SYSMENU or WS_CAPTION or WS_BORDER
push Classname
push Classname
push 0
call [CreateWindowEx]

or eax,eax
jz endofall

mov dword [hwnd],eax

msgloop:
push 0
push 0
push 0
push msg
call [GetMessage]

or eax,eax
jz endofall

push msg
call [TranslateMessage]
push msg
call [DispatchMessage]
jmp msgloop

endofall:
push 0
call [ExitProcess]
nop

Avendo registrato la classe, adesso possiamo creare la finestra, e lo facciamo con CreateWindowEx e memorizzando l'handle dentro la variabile hwnd

Notate che come stile di finestra, per ora, abbiamo importato WS_VISIBLE or WS_SYSMENU or WS_CAPTION or WS_BORDER. Anche questo successivamente andrà cambiato

Dopo la creazione della finestra e la verifica di successo (or eax,eax è uno dei mille metodi per verificare se eax==0) scriviamo il generico ciclo di gestione di messaggi. (Se siete estranei a ciò, vi rimando ad altri tutorial :P)

Ora è tutto pronto per la WndProc. Eccola qui di seguito:
WndProc:
label .hwnd at ebp+8
label .msg at ebp+0Ch
label .wParam at ebp+10h
label .lParam at ebp+14h

enter 0,0

mov eax,dword [.msg]

cmp eax,WM_DESTROY
jnz @f
push 0
call [PostQuitMessage]
jmp .end
@@:
push dword [.lParam]
push dword [.wParam]
push dword [.msg]
push dword [.hwnd]
call [DefWindowProc]
leave
ret 10h

.end:
xor eax,eax
leave
ret 10h

A parte la dichiarazione delle label che è un mio tipico modo di fare (potete anche usare proc....endp per dichiarare funzioni e parametri), qui gestiamo il solo messaggio WM_DESTROY.

A questo punto la prima parte è finita. Assemblate il tutto, eseguite e avrete una piccola finestra semplicissima.


PARTE [2] -> Grafica!

Accantonate temporaneamente l'editor e prendete il vostro programma di grafica.

Quello che dobbiamo fare è creare un immagine bitmap delle dimenzioni della nostra finestra. La cosa importante è che L'immagine deve avere come sfondo un colore che differisca il più possibile dall'immagine stessa. Cioè se volessimo fare qualcosa sul verde-nero, consideriamo l'ipotesi di mettere come sfondo un colore quale il rosso o il magenta come sfondo.

In ogni caso, se volete un consiglio, per evitare di modificare l'immagine e ricompilare 500 volte, lo sfondo consiglio di farlo di colori come il bianco o il nero, cosicchè i bordi dell'imamgine, se sfumati, non presenteranno inesteticità evidenti....vi invito comunque a fare prove e vedere il colore più adatto per ogni situazione

Altra cosa che come detto, dobbiamo decidere, è la dimenzione. Io in questo tutorial utilizzerò le dimenzioni 600x600, ma potete scegliere qualunque dimenzione, l'importante è che utilizziate la stessa sia per la grandezza della finestra in CreateWindowEx sia per quanto riguarda l'immagine.

QUindi, ecco di seguito quello che ho fatto io, le dimenzioni sono come ho detto, 600 pixel per 600 pixel

Image:Skin k0h.jpg

Come vedere, lo sfondo è nero, mentre i colori usati nell'immagine spaziano dal bianco al blu.

Assicuratevi di aver salvato in bitmap, quidni prendete il Region Creator, caricate l'immagine e, scrivete nei campi Red, Green e Blue i valori RGB del colore usato come sfondo (in decimale). (Se non sapete dove prenderli, buttate questo tutorial e andate a funghi :D ...oppure studiatevi il vostro programma di grafica )

Se tutto vi è filato liscio a questo punto avremo il file .rgn (al quale farò riferimento col nome region).


Parte [3] -> File delle Risorse

Ebbene si, dobbiamo inserire nell'eseguibile sia il file bitmap che la region, e per farlo ci serviremo di un classico resource script (.rc)

Volendo potremo prendere qualche editor specifico per il lavoro che faremo tra poco, ma per 2 righe contante non vedo vantaggi :D

Dunque, create un nuovo file, dategli l'estenzione .rc e apritelo col vostro editor e scriviamo le seguenti righe: (sostituite i nomi dei file bitmap e region con i vostri)
401 BITMAP "skin.bmp"
REGION RGN "skin.rgn"

Se conoscete un minimo di script RC, come dovreste, potete modificarvelo a piacimento

Salvate il tutto e passatelo al resource compiler e otterrete così il file di risorse compilato e pronto all'uso. (.res)


Parte [4] -> Cambiamo Sfondo

Ed è arrivato il momento di far prendere forma al nostro progetto: cominciamo col sostituire allo sfondo della finestra, il file bitmap che abbiamo inserito nelle risorse

Riaprite il file .asm e aggiungiamo a fine file una sezione per le risorse
section "res" resource from "rsrc.res" data readable

Questa riga dice al FASM di utilizzare il file rsrc.res per le risorse. (Cambiate il nome del file col vostro se diverso)

Ora per sicurezza potete assemblare e verificare con ResHack o CFF se le risorse che abbiamo aggiunto ci sono effettivamente.

Prima di continuare, ecco praticamente quello che faremo:

Per impostare come sfondo la nostra bitmap, per prima cosa dichiariamo una nuova variabile per l'handle della bitmap:
hbmp dd 0

Dopodichè, carichiamo la bitmap in memoria con LoadBitmap:
push 401 ; lo stesso ID usato nel file rc
push dword [hInst]
call [LoadBitmap]
mov dword [hbmp],eax

Così facendo avremo in eax l'handle della bitmap.

Adesso dobbiamo far vedere la bitmap al programma come fosse il brush da usare per disegnare lo sfondo della finestra. A questo scopo usiamo CreatePatternBrush:
push eax
call [CreatePatternBrush]

Come risultato, in eax avremo l'handle del nuovo brush.

Quello che ci rimane da fare è quindi inserire l'handle ottenuto dentro il membro hbrBackground della struttura WNDCLASSEX, al posto di COLOR_WINDOW.

Ricapitolando, risaliamo nel codice scritto fino a questo punto:
push IDI_APPLICATION
push 0
call [LoadIcon]
mov dword [wc.hIcon],eax
mov dword [wc.hIconSm],eax

mov dword [wc.hbrBackground],COLOR_WINDOW

push wc
call [RegisterClassEx]
or eax,eax
jz endofall

Applicando quello che ho detto sopra, diventerà:
push IDI_APPLICATION
push 0
call [LoadIcon]
mov dword [wc.hIcon],eax
mov dword [wc.hIconSm],eax

;------------da qui

push 401
push dword [hInst]
call [LoadBitmap]

mov dword [hbmp],eax

push eax
call [CreatePatternBrush]

mov dword [wc.hbrBackground],eax

;-------------a qui

push wc
call [RegisterClassEx]
or eax,eax
jz endofall

Altra cosa da aggiungere è la distruzione della bitmap quando chiudiamo il programma. La cosa più normale da fare risulta chiamare DeleteObject' in risposta a WM_DESTROY, poco prima della chiamata a PostQuitMessage. Il codice quindi prenderà questo aspetto:
cmp eax,WM_DESTROY
jnz @f
push dword [hbmp]
call [DeleteObject]

push 0
call [PostQuitMessage]
jmp .end

Salvate, compilare e avrete la vostra finestra che come sfondo ha la vostra bitmap :D


Parte [5] -> Skinniamo!

Ora il succo del discorso: lo skinning vero e proprio.

Quello che faremo è scrivere è scrivere una funzione chiamata SkinWindow che caricherà la region, contenuta nelle risorse, in memoria e l'adatterà e applicherà alla finestra.

Per iniziare, aggiungiamo le seguenti variabili:
restype db "RGN",0
resname db "REGION",0

hrgn dd 0

La prima non è altro che il tipo di risorsa (vedere il file rc), la seconda è il nome che abbiamo dato alla region (ancora, vedere il file rc), mentre la terza è una varibabile (globale) che useremo per memorizzare l'handle della regione una volta che sarà pronta all'uso.

Poi, andiamo alla chiamata di CreateWindowEx e cambiamo lo stile in WM_POPUP, ovvero:
push 0
push dword [hInst]
push 0
push 0
push 600
push 600
push 0
push 0
push WS_VISIBLE or WS_POPUP ;cioè una finestra visibile e senza bordature varie
push Classname
push Classname
push 0
call [CreateWindowEx]

Ricordiamoci che avendo applicato lo stile WM_POPUP non avremo pulsanti di chiusura: dovremo chiudere la finestra con ALT+F4 !!

Ora, andiamo nel codice appena dopo la WndProc e cominciamo a scrivere:
SkinWindow:

label hres1 at ebp-4
label hres2 at ebp-8
label ressize at ebp-0Ch

enter 0Ch,0

push restype
push resname
push 0
call [FindResource]
mov dword [hres1],eax

Iniziamo a commentare: prima di tutto, ci sistemiamo le label per 3 dword che ci serviranno come variabili locali.

l'istruzione enter ci eviterà di scrivere quello che normalmente andrebbe scritto come:
push ebp
mov ebp,esp
sub esp, 0Ch

La prima chiamata a funzione che facciamo è FindResource, che ci permette a partire da un tipo di risorsa e un nome, di ottenere un identificatore per la risorsa cercata. (Lo 0 indica che la risorsa è nel modulo usato per creare il processo, cioè alla fine dei conti, il nostro file .exe)

Memorizziamo il valore che ci viene restituito nella variabile locale hres1

Poi,
;in eax c'è il risultato di FindResource
push eax ;attenzione, questo è il secondo parametro di LoadResource!

push eax
push 0
call [SizeofResource]
mov dword [ressize],eax

push 0
call [LoadResource]
mov dword [hres2],eax

push eax
call [LockResource]

push eax
push dword [ressize]
push 0
call [ExtCreateRegion]
mov dword [hrgn],eax

Chiamiamo in seguenza SizeofResource per ottenere la grandezza in bytes del file region, LoadResource per caricare tutto in memoria, LockResource per ottenere il puntatore alla region in memoria e ExtCreateRegion per adattare i dati della region ai nostri usi (Date uno sguardo alla guida API per maggiori informazioni)

Ecco il finale della funzione:
push 1 ;ridisegnare tutto? yes
push eax ;risultato di ExtCreateRegion
push dword [hwnd]
call [SetWindowRgn]

push dword [hres1] ;chiudiamo tutti gli handle rimasti aperti
call [CloseHandle]

push dword [hres2]
call [CloseHandle]

push dword [hrgn]
call [CloseHandle]

leave
ret

Tutto viene infine applicato con una chiamata a SetWindowRgn

Quello che ci rimane da fare per completare questo passo è di far fare al programma una chiamata a questa funzione. Una buona idea è quella di metterla appena dopo creata la finestra cioè:
or eax,eax
jz endofall

mov dword [hwnd],eax

call SkinWindow ;->>>>>>>>>>> QUI !

msgloop:
push 0
push 0
push 0
push msg
call [GetMessage]

Ora salvate assemblate e godetevi il risultato....ma sappiate che ancora non è finita :P


PARTE [6] -> Muovimi!


...Non è finita perchè infatti abbiamo una finestra, ma non ha pulsanti di chiusura, ne possibilità di muoverla.

In questa parte ci occuperemo del movimento della finestra.

Il concetto che useremo sarà il seguente: faremo in modo che, ogni volta che "trascineremo" dentro la finestra, essa pensi che il puntatore del muose sia in realtà sulla caption della finestra (cioè sulla barra del titolo), cosicchè windows la muova a nostro piacimento :D

Per fare questo, dovremo tornare nella WndProc e far gestire 'WM_LBUTTONDOWN:

(per semplificare, eccovi tutta la WndProc)
WndProc:
label .hwnd at ebp+8
label .msg at ebp+0Ch
label .wParam at ebp+10h
label .lParam at ebp+14h

enter 0,0

mov eax,dword [.msg]

cmp eax,WM_DESTROY
jnz @f
push dword [hbmp]
call [DeleteObject]

push 0
call [PostQuitMessage]
jmp .end
@@:
cmp eax,WM_LBUTTONDOWN
jnz @f
push dword [.lParam]
push 2
push WM_NCLBUTTONDOWN
push dword [.hwnd]
call [SendMessage]
jmp .end
@@:
push dword [.lParam]
push dword [.wParam]
push dword [.msg]
push dword [.hwnd]
call [DefWindowProc]
leave
ret 10h

Come potete vedere, appena ci arriva un messaggio di tipo WM_LBUTTONDOWN, noi ne rispediamo un altro con SendMessage, più precisamente, mandiamo un WM_NCLBUTTONDOWN (per esteso, Non Client Left Button Down). A questo messaggio mandiamo ome wParam il valore HTCAPTION (che è uguale a 2) e come lParam la struttura POINT che indica la posizione del mouse e che già abbiamo dentro lParam stesso.

Salvate, assemblare e provate a trascinare :D


Parte [7] -> E chiudiamola!

Certo, chiudere la finestra con ALT+F4 non è che sia proprio eccezionale come cosa...per questo aggiungeremo un piccolo pulsantino che ci permetterà di chiudere tutto

Dobbiamo prima aggiungere 3 variabili:
btnclass db "Button",0
btntitle db "[X]",0
hXbtn dd 0

La prima è la il nome della classe standard per i pulsanti, la seconda è il testo che metteremo nel pulsante (originale eh?) e la terza è dove andremo a depositare l'handle del pulsante

Per comodità, aggiungiamo una nuova funzione, che chiamerò CreaControlli, nella quale creeremo tutti i controlli di cui abbiamo bisogno (per ora è solo un pulsante ma lascio a voi la fantasia :P)

La funzione non contiene altro che chiamate a CreateWindowEx, eccovela:
CreaControlli:
push 0
push dword [hInst]
push 1 ; essendo un controllo, al posto di hmenù va messo l'ID che vogliamo per il controllo
push dword [hwnd] ;qui va l'handle del parent, cioè la finestra principale in questo caso
push 18 ;altezza
push 22 ;larghezza
push 10 ;coordinata y
push 500 ;coordinata x
push WS_VISIBLE or BS_FLAT or WS_CHILD ;attenzione! deve avere lo stile WS_CHILD!!
push btntitle ;testo
push btnclass ;classe
push 0
call [CreateWindowEx]
mov dword [hXbtn],eax ;memorizziamo dentro la variabile hXbtn
ret

Dopo creato, il pulsante va fatto funzionare (comunque prima di ciò, vi invito a assemblare e eseguire per vedere se il pulsante viene creato). Per far ciò è inutile dire che aggiungeremo la gestione del messaggio WM_COMMAND nella WndProc:

(la rimetto tutta di nuovo)
WndProc:
label .hwnd at ebp+8
label .msg at ebp+0Ch
label .wParam at ebp+10h
label .lParam at ebp+14h

enter 0,0

mov eax,dword [.msg]

cmp eax,WM_DESTROY
jnz @f
push dword [hbmp]
call [DeleteObject]

push 0
call [PostQuitMessage]
jmp .end
@@:
cmp eax,WM_LBUTTONDOWN
jnz @f
push dword [.lParam]
push 2
push WM_NCLBUTTONDOWN
push dword [.hwnd]
call [SendMessage]
jmp .end
@@:
cmp eax, WM_COMMAND
jnz @f
mov eax,dword [.lParam]
cmp eax,dword [hXbtn]
jnz .end

push 0
push 0
push WM_DESTROY
push dword [.hwnd]
call [SendMessage]

jmp .end
@@:
push dword [.lParam]
push dword [.wParam]
push dword [.msg]
push dword [.hwnd]
call [DefWindowProc]
leave
ret 10h

.end:
xor eax,eax
leave
ret 10h

Appena riceviamo il WM_COMMAND, verifichiamo che l'handle del controllo (che ci arriva da lParam) sia quello del nostro pulsante. Se è il nostro pulsantino, mandiamo con SendMessage un bel WM_DESTROY alla finestra :D

Attenzione: se volete fare le cose bene, verificate anche che la word alta di wParam sia uguale a BN_CLICKED prima di chiamare SendMessage

Salvate, assemblate e godetevi la vostra finestra....per ora :P


Parte [8] -> Alla moda!

Ebbene si, la trasparenza delle finestre è alla moda...o così dicono :P

Mettiamola anche noi nella nostra finesta, è semplicissimo.

Per prima cosa, cambiate gli Exstyle della finestra (primo parametro) in WS_EX_LAYERED, poi chiamiamo SetLayeredWindowAttributes per impostare la trasparenza:
push 0
push dword [hInst]
push 0
push 0
push 600
push 600
push 0
push 0
push WS_VISIBLE or WS_POPUP
push Classname
push Classname
push WS_EX_LAYERED
call [CreateWindowEx]

or eax,eax
jz endofall

mov dword [hwnd],eax

push LWA_ALPHA ; ci basiamo sul canale alpha (da 0 a 255)
push 7Fh ; indovinate qual'è la metà di 255 ;P
push 0 ; il nero come base va sempre benissimo
push eax ; handle della finestra
call [SetLayeredWindowAttributes]

Fatto, salvate, compilate et voilà!

Ora potete anche cambiare il valore 7Fh in qualcos'altro per regolare la trasparenza, o magari aggiungere una scrollbar o un paio di pulsanti per farla cambiare a runtime!

Guida by nick40
 
Top
Desert90
view post Posted on 2/9/2010, 21:58




wow grandissimo
 
Top
MASAI
view post Posted on 5/9/2010, 18:07




wooooooooooowww o.O
 
Top
Desert90
view post Posted on 5/9/2010, 18:17




masai ti sei presentato??
 
Top
Paky1
view post Posted on 4/8/2014, 13:42




Ecco un semplice Tutoria che spiega tutte le istruzioni


CITAZIONE
 
Top
4 replies since 2/9/2010, 12:45   923 views
  Share