Zoom Icon

Foxit Reader, come usare meglio i pdf protetti

From UIC

Foxit Reader, togliamo un po' di limitazioni.

Contents


Infos
Author: Gotterdamerung
Email: die.gotterdamerung@gmail.com
Website:
Date: 21/03/2007 (dd/mm/yyyy)
Level: Very Easy, if you can read this, you can do it
Language: Italian Image:Flag_Italian.gif
Comments:



Introduzione

Avete mai trovato in rete qualche file pdf che vi permette di essere letto, ma non stampato e salvato? Io personalmente li odio... ma come? Ti posso leggere, ma non ti posso stampare? Mi vuoi proprio distruggere gli occhi!! Beh, vediamo se ci si può fare qualcosa...


Tools

- OllyDBG
- per piazzare i breakpoint uso il plugin della command line di Quequero
- Regmon
- un file in pdf, protetto dalle modifiche


Link e Riferimenti

Foxit Reader è un carinissimo lettore di pdf, molto più veloce del reader di Acrobat.
La versione free (neanche troppo limitata) può essere scaricata dal sito del produttore, la versione a cui faccio riferimento in questo tutorial è la 2.0 build 1516.


Essay

Bene, cominciamo con le cose facili, scarichiamo il programmino, io preferisco la versione in formato .zip che contiene il solo eseguibile, quindi lo scompatto nella cartella C:\Programmi\Foxit Reader (che fantasia!).

A questo punto facciamo doppio click sull'eseguibile, in modo che si setti come lettore di pdf predefinito e crei le sue chiavi di registro.
Il nostro primo bersaglio saranno proprio queste ultime, partiamo!

Apriamo un pdf a caso e cominciamo a clickare qualche bottoncino, come minimo al terzo o quarto apparirà un popup che ci avverte che la feature che vogliamo utilizzare fa parte del PRO pack e che, anche se possiamo utilizzarla, il file salvato avrà delle informazioni aggiuntive.
Inseriamo ad esempio una nota e salviamo il file; a parte i due popup relativi, noterete che una antiestetica scritta compare sulla pagina del nostro pdf.

Andiamo con ordine:

I popup

Per fortuna qui le cose sono semplicissime, ogni popup che appare ha una casellina che si può spuntare e permette di non farlo più apparire.
Usando regmon mentre spuntiamo le suddette caselline possiamo accorgerci che le chiavi di registro che riguardano il programma sono in HKCU\Software\Foxit Software\Foxit Reader\.
Apriamo quindi il caro regedit di windows e visitiamo la chiave di cui sopra.
Tra le varie sottochiavi presenti ne troviamo una particolarmente interessante, ovvero MainFrame, che contiene al suo interno valori del calibro di CheckLicense, CheckRegister, altri check vari e alcuni ShowQualcosaAD_908.
Azzerando le chiavi giuste ci libereremo in un solo colpo dei popup e della pubblicità in alto a destra della finestra (non che sia così invadente, ma...)
A questo punto per velocizzare le cose possiamo crearci un file .reg e inserirci:

REGEDIT4

[HKEY_CURRENT_USER\Software\Foxit Software\Foxit Reader\MainFrame]
"CheckLicense"="0"
"CheckRegister"="0"
"CheckSnapShot"="0"
"CheckStandardFeature"="0"
"CheckStandardLimited"="0"
"CheckStandardSave"="0"
"ShowEditorAd_908"="0"
"ShowPOAd_908"="0"
"ShowReaderAd_908"="0"
"ShowSDKAd_908"="0"
"ShowTypewriterAd_908"="0"

questo infatti sarà molto comodo nel caso in cui abbiate più di un utente, in quanto la chiave HKCU (HKEY CURRENT USER) vale solo per l'utente attuale :)

Fin qui era decisamente banale, andiamo avanti!

Salvare il file senza fronzoli

OK, adesso dobbiamo occuparci della brutta scritta che compare quando salviamo un file dopo averlo modificato.
Apriamo Olly e carichiamo il nostro Foxit Reader.
Come prima cosa (+Mala docet) cerchiamo qualche stringa, quindi avviamo il plugin Ultra String Reference e cerchiamo stringhe ASCII.
Cosa viene scritto quando salviamo il file? "Edited by Foxit Reader, Copyright(C) by Foxit Software Company,2005-2006, For Evaluation Only.", perfetto, ^F (ctrl+F serve a fare ricerche all'interno della finestra di Ultra String Reference) e cerchiamo, ad esempio, la stringa 'Edited by'.
BUM.
Tra tutte le stringhe del prog questa compare solo due volte, e guarda caso è proprio la stringa che cerchiamo noi!
Doppio click sulla stringa e ci ritroviamo nel codice:

...
00420460 |CALL 00623A41
00420465 |MOV EAX,SS:[ESP+18]
00420469 |MOV BYTE PTR SS:[ESP+64],2
0042046E |CMP DS:[EAX-8],EBP
00420471 |JE 0042056B
00420477 |PUSH 006E1C24 ; ASCII "Edited by Foxit ... la nostra stringa
0042047C |LEA ECX,SS:[ESP+18]
00420480 |CALL 00623A41
00420485 |MOV BYTE PTR SS:[ESP+64],3
0042048A |XOR ESI,ESI
0042048C |/PUSH ESI
0042048D ||PUSH 0A
0042048F ||LEA ECX,SS:[ESP+1C]
00420493 ||CALL 00623EA8
00420498 ||MOV EDI,EAX
0042049A ||CMP EDI,-1
0042049D ||JNZ SHORT 004204A8
0042049F ||MOV ECX,SS:[ESP+14]
...

questa parte mi è risultata un po' strana...
come si vede, subito prima della stringa che abbiamo cercato c'è un JE, allora ho messo un breakpoint su quella locazione e ho fatto un po' di prove, modificando e salvando il file... ma sembra che quella stringa non venga mai toccata, così sono passato a quella dopo:

...
00420876 JNZ SHORT 0042087C
00420878 TEST EBX,EBX
0042087A JE SHORT 004208CE
0042087C TEST EBP,EBP
0042087E JNZ SHORT 004208CE
00420880 PUSH 0FF
00420885 PUSH ECX
00420886 MOV ECX,ESP
00420888 MOV SS:[ESP+20],ESP
0042088C PUSH -1
0042088E PUSH 006E1C24 ; ASCII "Edited by Foxit... la solita stringa
00420893 CALL 00498990
00420898 PUSH 41300000
0042089D PUSH ECX
0042089E MOV ECX,ESP
004208A0 MOV SS:[ESP+2C],ESP
004208A4 PUSH -1
004208A6 PUSH ; ASCII "Helvetica"
004208AB MOV SS:[ESP+58],EBP
004208AF CALL 00498990
004208B4 MOV ECX,SS:[ESP+34] ; |
004208B8 MOV EDX,SS:[ESP+30] ; |
004208BC PUSH ECX ; |Arg3
004208BD PUSH EDX ; |Arg2
004208BE PUSH ESI ; |Arg1
004208BF MOV ECX,EDI ; |
004208C1 MOV DWORD PTR SS:[ESP+5C],-1 ; |
004208C9 CALL 00420D60 ; \Foxit_Re.00420D60
...

mettendo invece un breakpoint sul JNZ prima di questa stringa e facendo qualche prova finalmente si vede che questa è proprio la parte di codice che ci interessa!
Viene caricata la stringa e passato il font con cui scriverla, inoltre il test in 42087E viene eseguito diverse volte (una volta per ogni pagina) e solo nelle pagine modificate viene scritto il testo caricato in memoria.
Per aggirare questo controllo sarà sufficiente sostituire il JNZ con un JMP in modo che ogni controllo semplicemente salti la procedura di scrittura del testo.

Veniamo al bello, stampare i pdf protetti

Eccoci quindi al succo del tutorial, ovvero il motvo per il quale mi sono dato al reversing di questo bel programmino: i pdf che si possono aprire, ma non salvare/stampare.

Attenzione, non sto parlando dei pdf protetti da password! Solo dei pdf con protezione da modifiche e stampe!

Bene, apriamo quindi un pdf protetto e proviamo a clickare sul tasto di stampa: verrà fuori di nuovo una bella messagebox che ci avverte che il file è protetto (ma va?).
Proviamo il solito approccio, ci segnamo la stringa e proviamo a cercare qualcosa in Olly, ad esempio la parola 'printing'.
Azz questa volta non ci è andata bene! La stringa printing non compare MAI tra le stringhe del programma... come facciamo ora?
Poco male, proviamo a mettere un bpx MessageBoxA e a riprovare a stampare.
Ok, Olly ferma l'esecuzione e ci troviamo nel modulo USER32, mentre la prima riga dello stack (la parte in basso a destra della finestra principale di Olly) ci dice:

0012DCE0 0062BEBF /CALL to MessageBoxA from Foxit_Re.0062BEB9

Questo ci indica la riga successiva a quella da dove è stata chiamata la MessageBox, per tornare in quella parte di codice basta farci click con il mouse e pigiare invio.
Ci troveremo in questo blocco:

0062BE07 PUSH EBP
0062BE08 MOV EBP,ESP
0062BE0A SUB ESP,114
0062BE10 PUSH EBX
0062BE11 PUSH ESI
0062BE12 PUSH EDI
0062BE13 XOR EBX,EBX
0062BE15 MOV EDI,ECX
0062BE17 PUSH EBX
0062BE18 MOV [LOCAL.4],EDI
0062BE1B CALL 0062BDD9
0062BE20 LEA EAX,[LOCAL.1]
0062BE23 PUSH EAX
0062BE24 PUSH EBX
0062BE25 CALL 0062BF7F
0062BE2A XOR ESI,ESI
0062BE2C CMP EAX,EBX
0062BE2E MOV [LOCAL.3],EAX
0062BE31 JE SHORT 0062BE4B
0062BE33 PUSH EBX ; /lParam
0062BE34 PUSH EBX ; |wParam
0062BE35 PUSH 376 ; |Message = MSG(376)
0062BE3A PUSH [LOCAL.1] ; |hWnd
0062BE3D CALL DS:[<&USER32.SendMessageA>] ; \SendMessageA
0062BE43 CMP EAX,EBX
0062BE45 JE SHORT 0062BE4B
0062BE47 MOV ESI,EAX
0062BE49 JMP SHORT 0062BE55
0062BE4B CMP EDI,EBX
0062BE4D JE SHORT 0062BE55
0062BE4F LEA ESI,DS:[EDI+9C]
0062BE55 CMP ESI,EBX
0062BE57 MOV [LOCAL.2],EBX
0062BE5A JE SHORT 0062BE6F
0062BE5C MOV EAX,DS:[ESI]
0062BE5E MOV [LOCAL.2],EAX
0062BE61 MOV EAX,[ARG.3]
0062BE64 CMP EAX,EBX
0062BE66 JE SHORT 0062BE6F
0062BE68 ADD EAX,30000
0062BE6D MOV DS:[ESI],EAX
0062BE6F MOV EBX,[ARG.2]
0062BE72 TEST BL,0F0
0062BE75 JNZ SHORT 0062BE8E
0062BE77 MOV EAX,EBX
0062BE79 AND EAX,0F
0062BE7C CMP EAX,1
0062BE7F JBE SHORT 0062BE8B
0062BE81 CMP EAX,2
0062BE84 JBE SHORT 0062BE8E
0062BE86 CMP EAX,4
0062BE89 JA SHORT 0062BE8E
0062BE8B OR EBX,30
0062BE8E TEST EDI,EDI
0062BE90 JE SHORT 0062BE97
0062BE92 MOV EDI,DS:[EDI+78]
0062BE95 JMP SHORT 0062BEB1
0062BE97 LEA EAX,[LOCAL.69]
0062BE9D PUSH 104 ; /BufSize = 104 (260.)
0062BEA2 PUSH EAX ; |PathBuffer
0062BEA3 PUSH 0 ; |hModule = NULL
0062BEA5 LEA EDI,[LOCAL.69] ; |
0062BEAB CALL DS:[<&KERNEL32.GetModuleFileNameA>] ; \GetModuleFileNameA
0062BEB1 PUSH EBX ; /Style
0062BEB2 PUSH EDI ; |Title
0062BEB3 PUSH [ARG.1] ; |Text
0062BEB6 PUSH [LOCAL.3] ; |hOwner
0062BEB9 CALL DS:[<&USER32.MessageBoxA>] ; \MessageBoxA
0062BEBF TEST ESI,ESI <- Esattamente ci troveremo qui
0062BEC1 MOV EDI,EAX
...

Questo codice è piuttosto pieno di test e salti relativi, ma NESSUNO di questi ci permetterà di saltare oltre la call incriminata!
Ciò ci fa capire che non è in questo blocco che viene controllato se il file è protetto o meno, ma nel codice precedente.
Come fare però a capire da dove veniamo esattamente? Prima di questo blocco c'è un RETURN e quindi sicuramente non veniamo da lì.
Beh, allora useremo esattamente lo stesso metodo che abbiamo usato ora, ovvero piazzeremo un breakpoint sulla prima riga di questo blocco (all'indirizzo 62BE07, subito dopo il RETN) e riproveremo a stampare. Quando Olly bloccherà l'esecuzione perché siamo passati sul breakpoint potremo guardare lo stack e vedere da dove siamo arrivati (e quindi dove dobbiamo andare).
Dovremo fare questa procedura un po' di volte prima di arrivare al punto in cui viene fatto il vero controllo; per ogni livello che risaliamo possiamo accorgerci che non è quello giusto semplicemente guardando i test e i jump, nessuno infatti ci permetterà di evitare il punto da cui siamo venuti (che è in realtà la direzione in cui va il programma, stiamo andando al contrario OK?), fino a che non arriveremo in questo punto:

00425600 PUSH -1
00425602 MOV EAX,FS:[0]
00425608 PUSH 006506B6
0042560D PUSH EAX
0042560E MOV EAX,158C
00425613 MOV FS:[0],ESP
0042561A CALL 00466CB0
0042561F PUSH EBX
00425620 MOV EBX,ECX
00425622 PUSH EBP
00425623 PUSH ESI
00425624 MOV EAX,DS:[EBX+3C]
00425627 PUSH EDI
00425628 LEA ECX,DS:[EAX+E8]
0042562E CALL 0042E630
00425633 TEST EAX,EAX
00425635 JNZ SHORT 00425649 <- questo JNZ ci può far saltare la nostra CALL!
00425637 PUSH -1
00425639 PUSH EAX
0042563A PUSH 7F5
0042563F CALL 0062BF26 <- noi veniamo da qui
00425644 JMP 00425778
00425649 CALL 00448B80 <- se il test in 425633 fallisce arriviamo qui
0042564E TEST EAX,EAX
...

Oltre al fatto che questo sia l'unico jump che ci fa evitare la CALL, risalendo ulteriormente andremmo a finire nel ciclo principale dell'applicazione, dove evidentemente non si può trovare il check, in quanto questo avviene dopo aver pigiato il bottone di stampa.
Bene, anche in questo caso quindi sarà sufficiente trasformare il JNZ in JMP per permetterci di stampare addiritto tutte le pagine del documento (toner/cartucce permettendo).

Ultimo appunto, salvare i pdf protetti

OK, ora il gioco si fa più difficile.
Il pulsante di save è disabilitato, ma curiosando nel menù vediamo che possiamo ancora 'salvare con nome'... ma che gentili alla Foxit :)
Certo, provando a salvare anche con un altro nome verremo avvisati che, per via dei soliti motivi di protezione, potremo salvare solo una copia dell'originale, che quindi non conterrà alcuna modifica.
Come abbiamo fatto per la stampa allora mettiamo un bel bpx MessageBoxA e salviamo il nostro documento con ctrl+shift+S e il nostro Olly ci porterà nel modulo USER32.
Di nuovo click sulla prima riga dello stack e invio per tornare al nostro programma, come la volta precedente risaliamo in cima a questa call e mettiamo un altro breakpoint all'inizio, ripetendo la procedura 3 - 4 volte, fino a che, come per la volta precedente, non arriveremo alla parte di codice subito dopo il ciclo principale, ovvero qui:

004252A0 MOV EAX,DS:[73D8E0]
004252A5 PUSH ESI
004252A6 TEST EAX,EAX
004252A8 MOV ESI,ECX
004252AA JE SHORT 004252B3
004252AC CALL 00423150
004252B1 POP ESI
004252B2 RETN
004252B3 MOV EAX,DS:[ESI+3C]
004252B6 LEA ECX,DS:[EAX+E8]
004252BC CALL 0042E5C0
004252C1 TEST EAX,EAX
004252C3 JNZ SHORT 004252DB <- questo salto ci permetterebbe di non prendere la call
004252C5 PUSH -1
004252C7 PUSH EAX
004252C8 PUSH 7F7
004252CD CALL 0062BF26 <- questa è la call da cui veniamo
004252D2 MOV ECX,ESI
004252D4 CALL 00423150
004252D9 POP ESI
004252DA RETN
004252DB MOV ECX,ESI <- e invece finiremmo qui...
004252DD CALL 00422C00
004252E2 POP ESI
004252E3 RETN

Ottimo, direte voi, l'abbiamo già fatto due volte finora... si cambia il JNZ in JMP ed è fatta!
E invece NO!
Se forzate il jump infatti, non succederà assolutamente niente... niente finestre, niente messaggi, niente di niente.
Allora proviamo a fare una cosa... prendiamo un normale pdf (non protetto) e apriamolo, lasciando un breakpoint in cima a questa call, proviamo a salvarlo CON NOME e vediamo come si comporta il programma:

004252A0 MOV EAX,DS:[73D8E0]
004252A5 PUSH ESI
004252A6 TEST EAX,EAX
004252A8 MOV ESI,ECX
004252AA JE SHORT 004252B3 <- qui SALTA sia con il file protetto che col normale
004252AC CALL 00423150
004252B1 POP ESI
004252B2 RETN
004252B3 MOV EAX,DS:[ESI+3C]
004252B6 LEA ECX,DS:[EAX+E8]
004252BC CALL 0042E5C0
004252C1 TEST EAX,EAX
004252C3 JNZ SHORT 004252DB <- questo invece con il file non protetto SALTA,
mentre con il protetto NON SALTA

004252C5 PUSH -1
004252C7 PUSH EAX
004252C8 PUSH 7F7
004252CD CALL 0062BF26
004252D2 MOV ECX,ESI
004252D4 CALL 00423150
004252D9 POP ESI
004252DA RETN
004252DB MOV ECX,ESI
004252DD CALL 00422C00
004252E2 POP ESI
004252E3 RETN

Bene, ma allora perché se io lo forzo a saltare non riesco a salvare?
Segnamoci l'indirizzo a cui va la call (42E5C0) prima del salto ed esaminiamo invece la call successiva, che incontreremmo se avessimo fatto il salto, ovvero la call in 4252DD, in quanto all'interno di questa call ci deve essere qualche altro controllo sui diritti del file (sennò salverebbe lo stesso, no?).
Piazziamo quindi un breakpoint sul JNZ incriminato, salviamo con nome il nostro file protetto, quando Olly ci porterà su questo punto cambiamo il flag Z (alla destra del codice, nella finestrella Registers (FPU)) facendoci doppio click, in modo da farlo diventare 0.
A questo punto steppiamo con F8 fino a che non ci ritroveremo sulla call in 4252DD ed entrimoci dentro con F7, ci ritroveremo qui:

00422C00 /$ MOV EAX,FS:[0]
00422C06 |. PUSH -1
00422C08 |. PUSH 00650494
00422C0D |. PUSH EAX
00422C0E |. MOV FS:[0],ESP
00422C15 |. SUB ESP,750
00422C1B |. PUSH EBX
00422C1C |. MOV EBX,ECX
00422C1E |. PUSH EBP
00422C1F |. PUSH ESI
00422C20 |. MOV EAX,DS:[EBX+3C]
00422C23 |. PUSH EDI
00422C24 |. LEA ECX,DS:[EAX+E8]
00422C2A |. CALL 0042E5C0 <- NOTARE QUESTA CALL
00422C2F |. TEST EAX,EAX
00422C31 |. JE 00423132
00422C37 |. MOV EAX,DS:[73DAC8]
00422C3C |. TEST EAX,EAX
00422C3E |. JNZ SHORT 00422C88
00422C40 |. MOV EAX,DS:[73D910]
00422C45 |. TEST EAX,EAX
00422C47 |. JE SHORT 00422C88
00422C49 |. MOV ECX,DS:[EBX+3C]
00422C4C |. CALL 00420900
00422C51 |. TEST EAX,EAX
00422C53 |. JE SHORT 00422C88
00422C55 |. PUSH 0
00422C57 |. LEA ECX,SS:[ESP+74]
00422C5B |. CALL 004518C0
00422C60 |. LEA ECX,SS:[ESP+70]
00422C64 |. MOV DWORD PTR SS:[ESP+768],0
00422C6F |. CALL 00625D9C
00422C74 |. LEA ECX,SS:[ESP+70]
00422C78 |. MOV DWORD PTR SS:[ESP+768],-1
00422C83 |. CALL 00625962
00422C88 |> MOV EBP,DS:[EBX+3C]
00422C8B |. MOV ECX,EBX
00422C8D |. CALL 00422500
00422C92 |. MOV ECX,EBX
00422C94 |. MOV ESI,EAX
00422C96 |. CALL 004224D0
00422C9B |. MOV EDX,DS:[EBX+44]
00422C9E |. MOV EAX,SS:[EBP+4B0]
00422CA4 |. MOV ECX,SS:[EBP+498]
...

Ma guarda, in questa call troviamo una chiamata a qualcosa che abbiamo già visto, ricordate?
La call è la stessa del blocco precedente; quello che ci faceva o meno saltare a questa call che stiamo esaminando!
Da notare che anche il costrutto è lo stesso, la call a 42E5C0, un test sul valore di EAX e poi un jump.
Ne potremmo dedurre che la call restituisce un certo valore di EAX, se questo è 0 allora il file è protetto, altrimenti no...
Controlliamo allora (siamo alla fine) cosa succede all'indirizzo 42E5C0:

0042E5C0 /$ PUSH EBX
0042E5C1 |. PUSH EBP
0042E5C2 |. PUSH ESI
0042E5C3 |. MOV ESI,ECX
0042E5C5 |. PUSH EDI
0042E5C6 |. MOV ECX,DS:[ESI+3B0]
0042E5CC |. CALL 004A1E70 controlla 'qualcosa'
0042E5D1 |. MOV ECX,DS:[ESI+3B0]
0042E5D7 |. MOV EDI,EAX e lo piazza in EDI
0042E5D9 |. AND EDI,4 facendoci qualche operazione
0042E5DC |. CALL 004A1E70 controlla altro...
0042E5E1 |. MOV ECX,DS:[ESI+3B0]
0042E5E7 |. MOV EBX,EAX e lo mette in EBX
0042E5E9 |. AND EBX,20 con qualche altra operazione
0042E5EC |. CALL 004A1E70 ancora...
0042E5F1 |. MOV ECX,DS:[ESI+3B0]
0042E5F7 |. MOV EBP,EAX e lo infila in EBP
0042E5F9 |. AND EBP,40 modificandolo anche questo
0042E5FC |. CALL 004A1E70 e ancora
0042E601 |. AND EAX,80 e lo tiene in EAX con qualche modifica
0042E606 |. TEST EDI,EDI a questo punto controlla il primo valore ottenuto
0042E608 |. JNZ SHORT 0042E61B
0042E60A |. TEST EBX,EBX il secondo
0042E60C |. JNZ SHORT 0042E61B
0042E60E |. TEST EBP,EBP il terzo
0042E610 |. JNZ SHORT 0042E61B
0042E612 |. TEST EAX,EAX e l'ultimo
0042E614 |. JNZ SHORT 0042E61B
0042E616 |. POP EDI se tutti i test hanno dato 0
0042E617 |. POP ESI si prende i valori
0042E618 |. POP EBP che ha controllato
0042E619 |. POP EBX
0042E61A |. RETN e ritorna indietro
0042E61B |> POP EDI se invece qualche controllo
0042E61C |. POP ESI è venuto DIVERSO da 0
0042E61D |. POP EBP prende i soliti dati
0042E61E |. MOV EAX,1 e mette 1 in EAX!!
0042E623 |. POP EBX
0042E624 \. RETN e poi torna alla call

OK, non è difficile; basta ricordare che dopo la call viene controllato il valore di EAX e se questo è 0 il TEST EAX, EAX risulterà 0, mentre se è 1 il test risulterà 1 (TEST alla fine altro non è che un AND logico).
Se volete potete provare a vedere cosa succede all'interno di questa call con un pdf protetto e con uno non protetto, in pratica con quello protetto torneremo al primo RETN, mentre con i pdf non protetti i test falliranno e usciremo con EAX uguale a 1.
Ottimo, finalmente abbiamo la soluzione corretta! Per poter salvare basta forzare uno dei jump che fanno saltare il primo RETN e otterremo un EAX uguale a 1 che praticamente dirà al programma che il pdf non è protetto.

Un'ultima piccolissima (giuro) osservazione; se clickate con il mouse ad evidenziare la riga 42E5C0 in Olly, ovvero la prima riga di questa call, potrete vedere nel piccolo riquadro sotto il codice che questa call viene richiamata in ben cinque punti diversi del codice!
Questo ci potrebbe confermare che questa call è proprio usata per controllare i diritti sul file e viene chiamata ogni volta che c'è da attivare/disattivare una funzione!
Infatti questa call viene usata anche per disattivare il bottone di save! Modificando il jump e riaprendo il documento, il pdf verrà riconosciuto come non protetto e da ora potrete anche salvare tramite il comodo tastino sulla barra, anziché dal menù.

Ho finito sul serio! Ciauz a tutti!


Note Finali

Tutto ciò è nato solo dalla poca voglia di leggermi 5000 pagine sullo schermo del PC rischiando di perdere 5000 diottrie... e poi a me piace leggere a letto, non posso mica portarmi lo schermo a letto, no?

I ringraziamenti per avermi reso possibile tutto ciò sono prima di tutto per il Que, il Geddon e +Mala, poi ovviamente a tutti i ragazzi (e non) che contribuiscono alla UIC.

Chiedo scusa al Que per il tute non finito che ho lascito sul sito... pensavo di avere un po' più di tempo a disposizione :(

E infine... martedì prossimo ho l'esame di Gestione delle Reti e sono qui a scrivere tutorial... quando metterò la testa a posto??? :)


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.