»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
ª                                                                                            ª
ª                              [x] ringZ3r0  Proudly Presents [x]                            ª
ª                                                                                            ª
ª                 +-----------------------------------------------------------               ª
ª                                                                                            ª
                                 SoftSENTRY 2.1 DLL protection           

                                          by Pusillus

                                         13 luglio 1999




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 :((

Allegato