SoftSENTRY 2.1 DLL protection
Qualche giorno fa mi è capitato di avere a che fare con una di quelle protezioni "ready made" ed in particolare con "softSENTRY". Nel mio caso non si trattava della protezione applicata direttamente all'eseguibile il cui schema è spiegato nelle "notes" di Tornado, ma di una dll, in piu la dll era ben nascosta e non è stato molto facile andare a pescare il punto in cui entrava in azione perchè l'eseguibile era di 5 Mega!
In questo tute cercherò di spiegare come la dll lavora, e a tal scopo ho realizzato un programmino che fa uso della protezione in questione.
La prima cosa che si dovrebbe fare quando si studia una protezione commerciale è andare sul sito della casa che lo produce (http://www.twenty.com) e cercare di reperire più informazioni possibili al riguardo. In questo caso era disponibile addirittura una Trial di 30 giorni e quindi me la sono scaricata ed installata.
La protezione tramite dll, piuttosto che quella che encripta l'exe, viene usata quando si vogliono disabilitare delle funzioni, quando il metodo che agisce sull'exe non funziona o si vuole che la protezione parta in un punto particolare dell'eseguile.
Con questo tool di protezione è possibile creare delle TRIAL, proteggere tramite password il programma e mixare queste funzioni, quindi è possibile creare una trial che alla sua scadenza necessita di una password per essere registrata ecc ecc.
Naturalmente le funzioni della dll devono comunicare in qualche maniera con il programma principale perchè a seconda di certe condizioni (scaduto, non scaduto, passw errata, ecc), questo si dovra comportare in un certo modo.
Per sapere come la dll interagisce con il programma principale basta leggersi le istruzioni!: riassumendo la dll restituisce TRUE (1) o FALSE (0) se il programma è in trial o scaduto, se invece ci sono di mezzo le password il valore TRUE sara incrementato di 1 a seconda della password inserita (possono essere max 10 pwd). Nelle istruzioni c'è anche scritto che è possibile specificare quale deve essere il valore di partenza di TRUE, ma non mi pare di aver trovato nulla del genere sull'interfaccia del progz.
Per utilizzare la protezione è necessario caricare la dll con un "LoadLibrary" e lanciare la funzione softSENTRY(). in alternativa si possono utilizzare altre funzioni per rendere meno facile il tracciamento del programma, i parametri saranno ignorati:
Init - initiates softSENTRY function
DWORD CALLBACK Init()
Open - initiates softSENTRY function
DWORD CALLBACK Open(LPSTR)
InitDriver - initiates softSENTRY function
DWORD CALLBACK InitDriver(int)
Load - initiates softSENTRY function
DWORD CALLBACK Load (LPSTR)
InitSystem - initiates softSENTRY function
DWORD CALLBACK InitSystem()
come al solito il punto debole della protezione è il programma, nel senso che le protezioni ready made sono ben fatte ed è difficile entrare nei meandri della protezione stessa ma quando si tratta di leggere da parte del programma protetto i valori che la protezione restituisce allora le cose cambiano e la protezione va a farsi friggere se il programmatore di turno non la nasconde efficacemente.
In questo caso il programmatore ero io :) anche se non sono molto bravo ho cercato di celare il parametro della loadlibrary e la funzione di libreria che viene lanciata. Se provate a disassemblare loadlibrary.exe noterete che non c'e' nessuna stringa che si riferisce alla dll di protezione e alla funzione lanciata. Il mio programmino è molto piccolo e rintracciare la funzione non è difficle, ma immaginate di avere a che fare con un eseguibile bello grosso allora le cose cambiano, quindi non rimane che affidarsi al softice.
Con questa macro sarà possibile ispezionare il contenuto dello stack e verificare il nome della libreria caricata:
bpx LoadLibraryA do "p ret; d *(esp-4)"
al primo break sul data display ci sara CRTDLL.DLL, ma non è la dll che ci interessa, quindi andiamo avanti con "x (invio)", al secondo break sul data display comparira il nome della dll incriminata e come noterete non corrisponde a sentr.dll che sembrava l'evenienza più plausibile ;)
:004015E0 E891FFFFFF call 00401576
:004015E5 6818214000 push 00402118 < --- nome libreria lpLibFileName
* Reference To: KERNEL32.LoadLibraryA, Ord:0191h
|
:004015EA E84D010000 Call 0040173C
:004015EF A328214000 mov dword ptr [00402128], eax < --- Hinstance della dll
:004015F4 E8FDFDFFFF call 004013F6
:004015F9 83F800 cmp eax, 00000000
la funzione LoadLibrary necessita del parametro lpLibFileName che abbiamo scovato tramite la macro e come valore di ritorno ci da Hinstance in EAX. Prendiamo nota di questo valore, nel mio caso corrispondeva a "10000000".
HINSTANCE LoadLibrary(
LPCTSTR lpLibFileName // address of filename of executable module
);
Ora il programma dovra' lanciare una di quelle funzioni di libreria di cui abbiamo parlato prima e per farlo dovra prima ricavare l'indirizzo in cui è memorizzata nella dll con la funzione GetProcAddress:
FARPROC GetProcAddress(
HMODULE hModule, // handle to DLL module
LPCSTR lpProcName // name of function
);
come parametri abbiamo il nome della funzione (lpProcName), e l'handle della dll (hModule). Noi sappiamo quale è l'handle della nostra dll, è quel valore di EAX di cui abbiamo preso nota (10000000). bastera impostare con il softice un break condizionale nel caso in cui la call GetProcaddress sia con la handle della dll che ci interessa:
bpx GetProcAddressA if ((esp->4)==10000000) do "p ret; d *(esp-4)"
come potrete constatare il softice dopo aver eseguito il break ci mostrera nella finestra dati il nome della funzione di protezione.
:00401638 E878FDFFFF call 004013B5
:0040163D 83C40C add esp, 0000000C
:00401640 6808214000 push 00402108 < --- Nome della funzione di protezione
:00401645 FF3528214000 push dword ptr [00402128] < --- Handle della DLL (hModule)
* Reference To: KERNEL32.GetProcAddress, Ord:0117h
|
:0040164B E8E0000000 Call 00401730
:00401650 A32C214000 mov dword ptr [0040212C], eax < --- memorizzazione del'indirizzo della funzione
:00401655 FF152C214000 call dword ptr [0040212C] < --- chiamata della funzione di protezione
:0040165B A320214000 mov dword ptr [00402120], eax < --- memorizzazione del risultato
:00401660 FF3528214000 push dword ptr [00402128]
* Reference To: KERNEL32.FreeLibrary, Ord:0099h
|
:00401666 E8A1000000 Call 0040170C
:0040166B 833D2021400000 cmp dword ptr [00402120], 00000000
:00401672 7504 jne 00401678
Il valore di ritorno della GetProcAddress è l'indirizzo della procedura e questo valore è memorizzato in EAX. Alla riga successiva viene invocata la funzione di protezione, e verra mostrata la splash screen. Il valore di ritorno, che come abbiamo detto è 1 per trial, 0 per scaduto, è memorizzato alla locazione 00402120. A questo punto non sara difficile fare una patch per ingannare la protezione.
Colgo l'occasione per salutare tutti i membri di RingZer0 visto che è un bel po di tempo che non sento nessuno, a parte +Malattia. Purtroppo il tempo non basta mai :((