Totoslim 3.0
(SoftSentry: code insertion)

Data

by "AndreaGeddon"

 

19/12/2000

UIC's Home Page

Published by Quequero


Ma il 2000 non doveva

Buone Feste :-)

Ma questa è recidività...Quanti anni sono????

Vabbè, devo ammettere che il tute è valido, un po' meno valido il saluto che ci hai fatto alla fine....Sai potremmo prenderla a male! :)) Ma sto tizio è lo stesso che ha fatto pure quel programma di totocalcio che ho crackato io ed il tute sta alla uic? Mi sa di si, si chiamava pure lui daniele.....Poverino :))

essere la fine del mondo?

....

Home page: www.andreageddon.8m.com   /  www.andreageddon.com
E-mail: [email protected]
IRC:  irc.azzurra.it / irc.tin.it      #crack-it

....

Difficoltà

( )NewBies (X)Intermedio (X)Avanzato ( )Master

 

Qui andrà un piccolo commento di 2-8 righe riguardante il progetto che stai per affrontare, tanto per far capire al lettore cosa si stà per fare.


TotoSlim 3.0
SoftSentry: code insertion

Written by  AndreaGeddon


Introduzione

Evvivaaa! Oggi ho fatto il parziale di algoritmi e strutture dati e ieri sera sono rimasto fino alle 2 a debuggare lo Strainer. Per svuotare il mio piccolo cervellino da pesanti nozioni sui BBAlberi, Heap, Grafi, Complessità asintotiche, Funzioni Hash con trabocco ... BANG! Beh non avevo voglia di incazzarmi sullo strainer che ti fa riavviare in continuazione, così mi è capitato sotto gli occhietti questo softsentry.

Tools usati

SoftIce
WDasm32 (ma poco poco)
-  Un hexedit
-  Opzionalmente qualche editor di PE/Risorse
-  Qualche biscottino (yum)

URL o FTP del programma

www.daniele.net  mi sembra fosse questo, non ricordo bene.

Notizie sul programma

Il prog permette di essere eseguito in modalità demo per 100 volte o 15 giorni, dopodichè non potete più usarlo. Se lo eseguiamo però abbiamo il modulo di registrazione (nag). Vediamo come farlo partire senza limitazioni e liberandoci della nag.

Essay

Se eseguiamo il programma ci appare il registration form che ci chiede se vogliamo eseguirlo in modalità demo oppure se vogliamo registrarci. Prima di tutto cerchiamo di capire cosa abbiamo davanti: diamo qualche occhiata con un hexeditor o con un editor di risorse/PE. In particolare con un editor del PE vediamo che una delle sezioni è insolita:

"20/20tm"

ed ha le caratteristiche di Esecuzione/Scrittura (60000020), e questo ci fa pensare a una protezione aggiuntiva (quindi non è il solito programmello scemo in cui basta invertire un jump).

In particolare notate che sotto questa sezione ci sono le sezioni _data, _rsrc, _idata etc... Quindi questo è un eseguibile "doppio": le prime sezioni sono quelle originali del programma, quelle da 20/20tm in poi sono quelle del programma aggiunto (con le relative sezioni di dati, risorse etc..).

Poi se prendiamo un editor di risorse (tipo ExeScope) vediamo che nella sezione Risorse/Dialog abbiamo il primo elemento che si chiama SENTRYABORTDIALOG. A questo punto è facile capire che ci troviamo davanti un SoftSentry. Sul ringzero ci sono 2 tutorial che trattano tale protezione, in particolare quello di Pusillus è molto dettagliato, quindi vi consiglio di leggerlo. Tale tutorial spiegava che SoftSentry in sè è abbastanza intricata da debuggare, ma che il suo punto debole è proprio l'interfaccia col programma originale: tutto il meccanismo infatti si basa su funzioni che restituiscono valori booleani, quindi noi possiamo benissimo basare il nostro attacco sul programma principale evitandoci di steppare il codice di softsentry; ci basterà stare in agguato ed esaminare tutti i return values delle funzioni di softsentry per modificarle a nostro piacimento. In particolare questo programma non si basa su una dll, ma sul programma aggiunto vero e proprio, quindi rimarremo sempre nello stesso processo. Per capire quando ci troviamo nel codice della protezione e quando no basta che guardiamo la taskbar del softice: quando ci sarà totoslim.20/20tm stiamo nella protezione, indi occhi aperti. Del resto anche gli indirizzi di memoria aiutano: la sezione 20/20tm si trova a partire dal VA 0010A000, per cui tutti gli indirizzi superiori a 0050A00 saranno quelli del codice della protezione. E guarda caso l'entry point si trova proprio a 0050CE90!

I controlli saranno molti, però basterà un pò di pazienza e di stepping per risolvere il tutto. Cominciamo. Per partire ho eseguito il prog, ho settato il solito break su GetWindowTextA e ho provato a registrarmi con un seriale a caso. Il codice di controllo del seriale è alquanto pesante e ingarbugliato da seguire, quindi perchè sprecare preziosi neuroni? Chiudiamo il tutto, carichiamoci il loader del softice, e avviamo la sessione di debugging del totoslim. Popperemo sull'entry point. L'idea è semplice: se il programma è registrato ci deve essere un punto in cui decide se deve eseguire il programma o se deve mandarci la finestra di registrazione. Quindi steppiamo dall'entry point e vediamo se cadiamo su qualche call che ci spara la nag, in tal caso cerchiamo di bypassarla (il che ci dovrebbe portare all'esecuzione del programma vero e proprio).

 


PARENTESI!!

Mentre provavo a modificare qualche jump, il programma mi ha sparato una messagebox di softsentry con un qualche errore idiota, dopodichè il programma si rifiutava di partire (fidiputt!). Cioè, partiva e terminava immediatamente senza neanche mostrare la nag. Evidentemente si accorge se lo vogliamo taroccare e si incazza. La soluzione a questo problema è semplice: per ricordarsi che lo volevamo taroccare dovrà salvare l'informazione nel registry o in un file. Con il filemon non ho trovato niente di sospetto, invece con il regmon qualche chiave che puzza c'è. In particolare questa:

HKEY_CLASSES_ROOT\{eQGJC1xeDg}\(Predefinito)

che contiene il valore:

NU!=-!!)!%Q!1!$I!#1!_!TEW/$EX!!!!!!#"?A%!>`]R-4-T.45X.TEZ!!!!N!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"!1%"!1%"N!1%"$Q"B!.!($!!#!"-!%!![!"5!.A(``Q)!!!!!!!!!!/08GQ""<G2S:7&(=:72E<WY!65F$!!!!!!!!!!!!!!!!!!!!!!!!!!!!

che sembra avere nessun senso, invece ogni tanto si intravede qualche faccina. Io ho semplicemente inserito una sfilza di "x" all'inizio di tale stringa, e il programma ora riparte senza problemi. Solo che adesso vi dà 0 giorni di utilizzo e 0 esecuzioni. Bah.

END PARENTESI

 


Detto questo iniziamo a steppare dall'entry point. Steppiamo sempre con F10, senza entrare nelle call. Dovremmo arrivare a questo punto:

 

:0050D05E    je 0050D07A       troviamo questo jump che non salta

:0050D064    mov ecx, dword ptr [ebp-50]

:0050D067    call 0050FCB0     questa ci chiama il Register Form

:0050D06C    mov dword ptr [ebp-50], eax

:0050D06F    mov ecx, dword ptr [ebp-50]

:0050D072    call 0050FD70

:0050D077    mov dword ptr [ebp-50], eax

 

è chiaro che subito subito manomettiamo il jump per fargli saltare sempre la call alla nag. Vediamo che però otteniamo solo la chiusura del programma. Deve quindi esserci un controllo dopo la nag. Andiamo quindi alla riga 0050D07A e continuiamo a steppare. Troverete alcuni jump, ma niente di importante fino alla riga:

 

:0050D1CB   je 0050D2A3  questo ci fa saltare parecchio lontano

:0050D1D1    cmp dword ptr [ebp-50], 00000001

:0050D1D5    jne 0050D2A3  anche questo

:0050D1DB    xor eax, eax

:0050D1DD    mov ax, word ptr [005121B8]

:0050D1E3    test eax, eax

:0050D1E5    je 0050D2A3   ma che ce stai a caccià??

 

questo è il primo blocco che attira la nostra attenzione. Ci sono questi tre jump che ci fanno zompare a 0050D2A3, parecchio lontano da dove siamo ora. Se andiamo a vedere a 0050D2A3 ci troviamo qualche SendMessage e una bell' ExitProcess. Vedete che praticamente la caduta in ExitProcess non può essere evitata, il che ci fa pensare che nello spazio di codice che va da dove siamo noi ora all'ExitProcess ci sarà una chiamata alla giusta esecuzione del programma. Basta trovarla :-). Quindi facciamo in modo che i tre jump non ci facciano saltare (yeah! nop all!!), e continuiamo il nostro stepping. Di nuovo incontriamo qualcosa che attira la nostra attenzione (e che non è una gnocca :-) :

 

:0050D253    je 0050D281    eccoci qui. Se non saltiamo...

:0050D259    call 00510070

:0050D25E    mov dword ptr [ebp-50], eax

:0050D261    push 00000000

:0050D263    push 00000000

:0050D265    push 00000010

:0050D267    mov eax, dword ptr [00515B90]

:0050D26C    push eax

:0050D26D    call dword ptr [00516520]

:0050D273    mov word ptr [005121B8], 0000

:0050D27C    jmp 0050D2A3  ...arriviamo qui e veniamo buttati su ExitProcess!

 

di nuovo il programma cerca di buttarci fuori. Forziamo il primo jump per farci saltare e continuiamo la nostra corsa fino al prossimo blocco:

 

:0050D2CA    je 0050D318   no grazie, non accetto jump dagli sconosciuti

:0050D2D0    cmp dword ptr [ebp-50], 00000001

:0050D2D4    jne 0050D318  ehi, ho detto di no

:0050D2DA    xor eax, eax

:0050D2DC    mov ax, word ptr [005121B8]

:0050D2E2    test eax, eax

:0050D2E4    je 0050D318  miiiiiii lo vuoi capire che è no!?!?!?!

:0050D2EA    mov eax, dword ptr [ebp+08]

:0050D2ED    push eax

:0050D2EE    push 005121A8

:0050D2F3    call dword ptr [005164E0]

:0050D2F9    xor eax, eax

:0050D2FB    mov ax, word ptr [005121BC]

:0050D301    test eax, eax

:0050D303    je 0050D318  ancora?????? Ho detto di NO

:0050D309   mov eax, dword ptr [ebp-4C]

:0050D30C   push eax

:0050D30D   lea edx, dword ptr [ebp-54]

:0050D310   mov ecx, dword ptr [ebp-48]

:0050D313   call 0050D350 ormai questa call è l'ultima rimasta!!

 

uff... proprio non vuole farci continuare il maledetto bastardo! Sempre li a cercare di buttarci fuori! Strunz! Quei quattro salti ci fanno saltare la call a 0050D313 e ci mandano prematuramente a un ExitProcess. Noppiamoli tutti e quattro ed arriviamo quindi al momento della verità: è rimasta solo la call alla linea 0050D313, deve essere per forza questa quella che esegue il programma! Arriviamoci sopra, eseguiamola con F10 e... Doh! MessageBox di errore? Tutto lavoro da buttare? No per fortuna :-). Guardiamo la message box di errore:

SoftSentry

Failed to run!

come "failed to run"? Allora vuol dire che da qui si esegue il prog! Magari se ci scrivevano "memory allocation error" o qualcos'altro mi sarei spaventato. Dopo questo errore è probabile che il prog non parta più, quindi fate quello che ho scritto nella "parentesi" e risteppate fino alla call che ci ha appena dato errore. Quello che ci viene subito in mente di fare è di andare a cercare dentro questa call per cercare di vedere se possiamo evitare l'errore. Ci entriamo con F8 e troviamo:

 

:0050D350   push esi     dalla call arriviamo qui

:0050D351   push edi

:0050D352   mov esi, edx

:0050D354   mov edi, dword ptr [esp+0C]

:0050D358   mov edx, dword ptr [ecx+02]

:0050D35B   xor edx, dword ptr [ecx+06]

:0050D35E   xor edx, dword ptr [ecx+0A]

:0050D361   add edi, edx

:0050D363   xor edx, edx

:0050D365   mov eax, dword ptr [ecx+06]

:0050D368   inc edx

:0050D369   xor dword ptr [edi+4*edx-04], eax

:0050D36D   inc edx

:0050D36E   mov eax, dword ptr [ecx+0A]

:0050D371   xor dword ptr [edi+4*edx-04], eax

:0050D375   cmp edx, 00000014

:0050D378   jl 0050D365

:0050D37A   mov ecx, dword ptr [esi]

:0050D37C   call 005105E0

:0050D381   mov dword ptr [esi], 00000000

:0050D387   cmp word ptr [005121B8], 0000

:0050D38F   je 0050D39D      questo ci fa saltare alla messagebox

:0050D391   cmp word ptr [005121C0], 0000

:0050D399   je 0050D39D      anche questo

:0050D39B   call edi         entry point del programma originale!

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:

:0050D39D   push 00000000

:0050D39F   push 00512238

:0050D3A4   push 00512228

:0050D3A9   push 00000000

:0050D3AB   call dword ptr [00516510]  chiama la messagebox

:0050D3B1   pop edi

:0050D3B2   pop esi

:0050D3B3   ret 0004

 

Per evitare la messageBox di errore dobbiamo noppare i due jump che ci fanno saltare la call edi. edi contiene l'entry point del programma originale: 00472D60. A questo punto una lampadina si accende e l'idea ci folgora: se l'entry point attuale ci manda nella sezione 20/20tm (e quindi nel codice di softsentry), perchè non lo cambiamo con quello appena trovato? La sezione di codice del programma originale (la prima, .text) si estende da 00401000 a 004AD000, quindi l'entry point cade dentro questa sezione (ovviamente), allora se facciamo partire sin dall'inizio il programma originale non abbiamo problemi! Ho cambiato l'entry point, ma il programma va in gpf. Se lo caricate col loader del softice vedete che all'entry point del programma originale avete una serie di Invalid che non vi fanno steppare. Del resto se proviamo a modificare fisicamente tutti i jump visti, eseguendo il programma verranno lanciate 3 o 4 sessioni del programma stesso e avremo vari messaggi di gpf, il che ci costringerà prima a chiudere tutte le messagebox di errore e poi le sessioni in più del programma. A questo punto abbiamo il programma funzionante, ma ogni volta dobbiamo fare sto casino!

Ricapitolando, finora abbiamo provato due modifiche:

1 - Sostituiamo l'entry point attuale con quello originale

2 - Patchamo tutti i jump per arrivare all'esecuzione del programma

In entrambi i casi il risultato non è efficiente, quindi adesso possiamo seguire due strade: o scegliamo di riuscire a far partire il programma dall'original entry point, o cerchiamo di farlo partire patchato ma senza che vengano chiamate più sessioni del programma e errori vari.

PS: i jump che ho patchato io sono i seguenti: 0050D05E, 0050D1CB, 0050D1D5, 0050D1E5, 0050D253, 0050D2CA, 0050D2D4, 0050D2E4, 0050D2E4, 0050D303, 0050D38F, 0050D399. Non è escluso che patchando in modo diverso (ad esempio lasciando i jump che in realtà non ci fanno uscire dal programma) il programma si comporti in modo diverso. Io ho la mania di estirpare tutti i  jump che potrebbero creare problemi, quindi ora continuo col presupposto che siano stati patchati tutti i jump descritti.

 

RISOLVIAMO IL PROBLEMA DELLE SESSIONI MULTIPLE

Dopo aver patchato tutti jump per riuscire ad arrivare alla call che ci fa eseguire il programma originale si presenta questo problemino: vengono avviate più sessioni del programma e vengono generate decine di protection faults. Chiudendo tutte le finestrelle di notifica dei faults e chiudendo le sessioni in più del programma abbiamo comunque il nostro eseguibile funzionante. Ovviamente non vogliamo tutto questo casino ogni volta che avviamo il programma! La causa del problema è proprio la coesistenza dei due programmi in un unico file: i jump che abbiamo modificato si occupavano anche di decidere se il programma SoftSentry deve essere chiuso oppure no; lanciando il programma per primo viene eseguito il secondo pezzo, quello relativo a softsentry, quindi softsentry decide se eseguire o no il programma originale. Questo viene fatto attraverso un ciclo di questo tipo:

INIZIO

se non è registrato spara la nag

se il prog è registrato e se non è già aperta una sessione, esegui il programma originale

   altrimenti ExitProcess

ricomincia (se non è andato in exitprocess ovviamente)

FINE

tanto per rendere l'idea. Il programma SoftSentry termina se il programma originale è già in esecuzione ed è registrato. Con le nostre modifiche softsentry riconosce il programma originale sempre registrato ma mai in esecuzione, quindi lo lancia di continuo e dopo un pò va in fault, quindi lo terminiamo dal sistema (l'applicazione ha eseguito una operazione non valida bla bla chiudi). In questo modo chiudiamo il processo del SoftSentry, ma rimangono gli altri processi del Totoslim originale. Ora forse uno dei jump che abbiamo modificato doveva essere lasciato come stava, così alla seconda iterazione avrebbe riconosciuto il programma registrato ma già in esecuzione e sarebbe saltato a ExitProcess. Ho cercato se uno dei jump modificati cambiasse alla seconda iterazione, ma non ho trovato niente di utile. Quindi dovremo inserire noi del codice che discrimina la prima esecuzione. Per farlo dovremo cercare dello spazio disponibile nella sezione di codice 20/20tm, in particolare possiamo sfruttare il padding che viene inserito dal compilatore per rispettare gli allineamenti. Vediamo le caratteristiche della sezione:

 

Nome Virtual Size Virtual Offset Raw Size Raw Offset Characteristics
20/20tm 00007EA6 0010A000 00008000 00102A00 60000020
_data 00003C56 00112000 00000600 0010AA00 C0000040

la sezione 20/20tm ha un raw offset che va da 00102A00 a 0010AA00, quindi il raw size è 8000, però il Virtual Size lo abbiamo a 00007EA6, il che vuol dire che abbiamo 8000 - 7EA6 =

15A bytes disponibili per inserire il nostro codice di controllo (346 dec). Quindi l'indirizzo del primo byte disponibile è 102A00 + 7EA6 = 10A8A6. Se andiamo a vedere il file con un hex editor, vediamo che da 10A8A6 iniziano una sfilza di zeri fino a 10AA00. Questo è il padding, cioè tutti gli zeri che vengono inseriti per rispettare il file alignment che è di 200h.

NOTE SUL RAW OFFSET

Se dagli indirizzi di memoria (tipo 00505D5E) cercate di ricavarvi il raw offset dell'istruzione, in questo caso potreste avere problemi con il WinDasm: gli offset sulla status bar infatti sono errati. Ad esempio se vogliamo modificare il jump che si trova alla locazione 0050D05E, con WinDasm avete il seguente valore:

10C45E

invece il giusto valore è

105A5E

probabilmente l'errore è dovuto al fatto che la sezione di codice non è la prima. Cmq il mio FLC o quello integrato del PEditor funzioneranno benissimo (per non parlare di quello di Iczelion).

ora che abbiamo trovato lo spazio dove andare a inserire il nostro pezzettino di programma, non ci rimane che scrivere il codice e poi modificare un jump di quelli patchati per redirigere il softsentry proprio al nostro codice: da qui sceglieremo se tornare al programma o se uscire da softsentry. Scriviamo   un semplicissimo pezzetto:

 

    pushad                salviamo tutti i registri

    cmp       flag_di_controllo, 01         il programma è già stato eseguito?

    jz          esci_programma                    se si, esci dal SoftSentry

    mov       flag_di_controllo, 01       altrimenti segna il codice di controllo con BA

    popad                                                ripristina tutti i registri dallo stack

   jmp        torna_al_programma            ritorna a softsentry per eseguire il programma originale

esci_programma:

    jmp       dove_ci_mandava_alla_uscita    torna a 0050D32A e da lì esci

 

ora dobbiamo compilarlo e mettere gli opcode al posto giusto. Inoltre dobbiamo scegliere in che punto SoftSentry chiamerà il nostro codice infiltrato. Io ho scelto la linea 0050D2CA, che ci mandava a 0050D318, il quale continuava per 0050D32A e usciva. Quindi l'idea è che il nostro pezzetto di codice ci fa tornare a 0050D2D0 (la riga successiva a 50D2CA) se è la prima iterazione che facciamo (prima esecuzione del programma), altrimeni ci rimanda a 0050D32A che ci fa uscire di colpo. Ora scriviamoci gli opcode:

 

10A8A5     60

10A8A7     803DxxXXxxXX01

10A8AE     74xx

10A8B0      C605xxXXxxXX01

10A8B7      61

10A8B8      E9xxXXxxXX

10A8BD     E9xxXXxxXX

 

ci mancano solo gli operandi delle istruzioni (xx). Per primo devo inserire il puntatore al flag di controllo. O uso una locazione di memoria (ma non so se poi questa loc mi rimarrà intatta), oopure sotto suggerimento del grande GioCrack uso un byte della sezione di codice come flag (è sicuro che non verrà sovrascritto!). Attenzione però che per fare questa operazione dobbiamo settare le caratteristiche di 20/20tm da 60000020 a E0000020 (da exe/read a exe/read/write) altrimenti andremo in crash. Quindi per il nostro flag di controllo useremo il primo byte disponibile dopo il nostro codice. Il nostro codice occupa 28byte (1Ch), quindi 10A8A6 + 1C = 10A8C2 che in VA sarebbe 00511EC2. E questo sarà l'indirizzo del nostro flag. Ora ci manca da determinare gli argomenti dei jump. Il primo è un jump near (74xx), e come argomento prende i byte da sommare per arrivare all'istruzione a cui jumpiamo. Quindi: 0010A8BD - 0010A8AE - 2 = D (2 sono i bytes dell'opcode del jump). Allo stesso modo ci calcoliamo i jump far, i due E9:

 

10A8B7 - 105CCA - 2 = 4BEC

10A8BD - 105D2A - 3 = 4B97

 

li complemento perchè stiamo saltando all'indietro, e ottengo:

FFFFB413 e FFFFB468

e quindi direi che ci siamo. Ecco il nostro completo opcode:

 

10A8A6     60

10A8A7     80 3D C2 1E 51 00 01     <- byte invertiti (notazione intel)

10A8AE     74 0D

10A8B0     C6 05 C2 1E 51 00 01

10A8B7      61

10A8B8      E9 13 B4 FF FF

10A8BD     E9 68 B4 FF FF

 

l'ultimo passo è solo quello di modificare il jump alla riga 0050D2CA per redirigerlo al nostro codice iniettato. Analogamente a prima calcoliamo la differenza:

00511EA6 - 0050D2CA - 6 = 4BD6

quindi l'opcode cercato è  0F 84 D6 4B 00 00. Bene, ora che abbiamo cambiato tutti gli opcode eseguiamo il programma e... DOH! Come prima! Come mai? Carichiamo il programma con il loader, steppiamo fino al codice inserito da noi e settiamo un break. La prima esecuzione va bene, nel senso che softsentry trova 00 ed esegue il programma originale, la seconda volta trova ancora 00? Bene, facciamogli scrivere 01 e riproviamo. La terza volta: ancora 00! Cavolo, evidentemente questo processo viene controllato da un altro processo ancora, infatti se vediamo la lista dei task abbiamo 3 processi del nostro totoslim. Quindi ogni volta il processo viene chiuso e riaperto, per cui si cancellano gli eventuali dati che abbiamo salvato (lo 01). E non possiamo neanche usare la ram per mantenere il flag (con la chiusura del processo verrebbe perso lo stesso). Allora che famo? Innanzitutto facciamo una prova: settiamo un break sul codice inserito da noi e eseguiamo il programma: la prima volta gli facciamo eseguire il programma originale, tutte le altre volte eseguiamo il jump e andiamo alla chiusura. Come vedrete il softice poppà parecchie volte, alla fine però se noi terminiamo sempre il softsentry i controlli finiscono e rimane solo una sessione del totoslim senza errori. Quindi l'idea era giusta, ma la realizzazione pratica è sbagliata. Se il processo viene ogni volta riavviato e quindi la sua memoria cancellata, allora dobbiamo cercare un pezzo di memoria che non venga influenzato dalla chiusura del processo. La prima cosa che mi viene in mente è di andare a cercare nello spazio di memoria che va da 80000000 a BFFFFFFF. Questo spazio è una porzione di memoria condivisa da tutti i processi (prima di 80000000 abbiamo lo spazio di memoria occupato dalle applicazioni e dopo BFFFFFFF abbiamo lo spazio di memoria in cui risiede il winskif). Se è una memoria condivisa non verrà deallocata quando chiuderemo il nostro processo, quindi perchè non usare questa memory? Non è una buona regola giocare così con la memoria, ma a noi ce ne serve solo un byte! Tanto per dare una occhiata in giro possiamo andare in softice, e quando ci troviamo in una applicazione a 32bit (cs : 32bit) allora guardiamo la memoria da 80000000: ci troveremo un bel pò di punti interrogativi, il che vuol dire che quello spazio per noi è morto. Proseguiamo un pò e a 80001000 inzia una bella sfilza di byte (i primi sono tutti zeri). Quindi invece di usare una locazione del programma stesso (00511EC2), ora usiamo la locazione 80001000. I relativi opcode cambiano quindi in:

10A8A7     80 3D 00 10 00 80 01

e

10A8B0     C6 05 00 10 00 80 01

 

salviamo le modifiche, rieseguiamo il programma et... voilà! Ora parte senza errori e senza sessioni aggiuntive! Ora si palesa un altro problema: la locazione a 80001000 è inizialmente 0, quindi quando eseguiamo il programma la mettiamo a 1 e tutto funziona. La prossima volta che eseguiamo il programma però, la locazione sarà ancora ad 1, e quindi il programma non si eseguirà. Quindi allo stesso modo possiamo installare un nostro codice di controllo alla fine del programma, in modo da ripristinare il valore 0 alla locazione 80001000, in modo che la prossima volta il programma si ritroverà nelle stesse condizioni! Stavolta non vi spaventate, è tutto più facile! Basta che intercettiamo la messagebox di uscita (che io elimirei, mi da solo fastidio), quindi non dobbiamo cercare neanche uno spazietto libero: avviamo il programma, settiamo un break su MessageBoxA e arriveremo nel seguente punto:

 

00492F5F     FF742414                  push

00492F63     57                               push

00492F64     FF742414                  push

00492F68     51                               push

00492F69      FF15145D4D00        push

 

abbiamo 16 bei byte da noppare e da riusare a piacimento. Per i nostri scopi bastano e avanzano. Quello che dobbiamo fare è inserire l'istruzione:

mov     byte ptr [80001000] , 00

per ripistinare il byte originale. Tutto qui. Ricicliamo l'opcode di prima, quindi adesso a 00492F5F avremo:

90 90 90 90 90 90 90

C6 05 00 10 00 80 00

90 90

ovviamente potete disporre i nop a piacimento. Prima di inserire il nuovo codice, notate che la messagebox di uscita deve valutare la pressione del pulsante "si" o "no", quindi se volete che poi il programma esca realmente dopo la messagebox seguite il ret e arrivate al primo jump a 00402A3F: questo lo dovete trasformare in NOP, così ogni volta che che andremo a chiudere il programma la messagebox non verrà eseguita, cmq il programma crederà che è stato premuto "si" e quindi terminerà. Finalmente possiamo chiudere questo paragrafo!

 

SI PUO' FARLO PARTIRE ESTIRPANDO TUTTE LE SEZIONI DI SOFTSENTRY?

Come accennato i metodi di procedere eranno due. Il primo, quello del patching, lo abbiamo appena concluso. Il secondo è quello di far partire il programma direttamente estirpando il programma aggiunnto SoftSentry. L'entry point attuale è quello che sta nella sezione di codice di SoftSetry, quindi prima noi steppando avevamo trovato un JUMP EDI dove in edi c'era l'entry point originale del programma 00472D60. Se adesso nel file exe originale di totoslim (quello non patchato) cambiamo semplicemente l'entry point otterremo solo che il programma andrà in page fault. Carichiamo il programma con il loader del softice, e questo ci farà breakare all'entry point. Come vedete ci sono solo parecchi INVALID e non possiamo steppare nè fare niente. Che sia un problema di paginazione? Possiamo provare a inserire a manno le pagine del codice in cui ci troviamo "invalidati", ma la soluzione più semplice è un'altra: patchandolo in memoria arriviamo alla esecuzione del programma vero e proprio (ormai sappiamo come si fa!). Una volta che il programma è in esecuzione bello tranquillo, allora prendiamo il PEDitor (o unn qualsiasi tool per dumpare), e facciamo il Dump Full del processo di totoslim. Adesso abbiamo dumpato il programma con i giusti attributi di pagia e tutto il resto, quindi proviamo ora a cambiare l'entry e aggiustiamolo a 00472D60. Che succede? Andiamo sempre inn page fault. Possibilè che non è cambiato nulla? Carichiamo il totoslim con il loader, e arriveremo all'entry point. Ora vediamo che possiamo steppare e che il codice è presente! Iniziamo a steppare dopo un pò finiremo in page fault. Ho steppato di volta in volta sulla call che mi mandava in gpf, e sono arrivato ad un punto in cui abbiamo:

...

jz  QUI

InizializeCriticalSection

QUI

EnterCriticalSection

...

quello che succede è che il programma salta l'api InizializeCriticalSection, ma poi arriva in EnterCriticalSection e questo causa il crash. Giustamente forziamo il jump per eseguire IizializeCriticalSection, e vediamo che se arriviamo a EnterCriticalSection ora non andiamo più in crash. Cmq questo pezzo di codice viene iterato parecchie volte, ed inoltre ho subito altri crash in altri punti del programma. Tutto questo procedimento è stato condito però da diversi riavvi! Siccome che mi sono rotto le scatole dei programmi che ti piantano il piccì ho lasciato stare questo approccio, visto che tanto già col patching siamo arrivati ad ua versione funzionante e pulita del programma. Sono convinto che comunque il programma possa essere eseguito anche senza le sezioni di softsentry, e che non dovrebbe essere difficile risolvere il problema dei crash. Quindi se volete risolverlo in quest'altro modo, accomodatevi: io ne ho abbastanza di questo prog. Bai bai.

 

AndreaGeddon

 

Note finali

Un saluto agli HackManiaci per OndaQuadra che è stupenda (merito del mio aritcle :-P). Le feste arrivano, auguri a tutti!!!!!!!! Un gran vaff... a Que e Olga e il loro maledetto strainer che si blocca sempre (ma questo non ci fermerà :-PP). Byex.

Disclaimer

Qui inserirete con questo carattere il vostro piccolo disclaimer, non è obbligatorio però è meglio per voi se c'è. Dovete scrivere qualcosa di simile a: 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.