Totoslim 3.0 |
||
Data |
by "AndreaGeddon" |
|
19/12/2000 |
Published by Quequero |
|
|
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? |
.... |
|
.... |
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 |
Tools usati |
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 |
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).
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: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.