Claudio Brotto

gennaio 2007 - Posts

ASP.NET AJAX - Rilasciati i sorgenti

Lo annuncia direttamente Scott Guthrie.

Forte il commento: "Mi stavo così abituando a Reflector" :)

Posted: gen 31 2007, 07.26 by devlizard | with no comments
Filed under:
[APPTXT] Obfuscation: Considerazioni

Questo è di gran lunga l'argomento più gettonato tra i miei appunti.

E pensare che in *nessun caso* era a programma una discussione esplicita riguardo l'obfuscation degli assembly.

Le cose saltano fuori, per così dire, in maniera anche casuale e a volte ripetitiva: in *ogni caso* ho utilizzato almeno una volta Reflector, magari per illustrare concetti anche molto lontani tra loro.

Tempo massimo per la domanda direi 10 secondi: "Ma quindi stiamo guardando i sorgenti di .NET ?", così come "Ma allora i clienti vedono il nostro codice ?".

Qui scrivo le mie considerazioni su queste tematiche, anche se rimando comunque ad un paio di risorse (ce ne saranno migliaia) che possono affrontare il discorso in maniera più esaustiva.

Premessa (mooooolto breve e incompleta).

Il codice sorgente .NET (C#, VB.NET e *tutti* gli altri linguaggi .NET) all'atto della compilazione viene tradotto in un "componente" (d'ora in poi: assembly) che contiene fondamentalmente due cose: metadati e IL.

IL = Intermediate Language = il linguaggio della macchina virtuale .NET. Detta in altri termini, IL è il set di istruzioni che il Common Language Runtime comprende e traduce, in fase di esecuzione, in istruzioni native della piattaforma all'interno della quale l'applicazione gira.

I metadati descrivono l'assembly a cui si riferiscono in termini di tipi contenuti (campi, proprietà, metodi, ...) e di altri assembly ai quali questo fa riferimento. I metadati sono tutto tranne che opzionali ! Di conseguenza ogni assembly, ne possiamo essere certi, è auto-descrittivo.

Problema.

Il problema nasce nel momento in cui le informazioni di cui sopra (metadati e stream IL), oltre che dal CLR per l'esecuzione del componente, vengono utilizzate da qualche strumento per l'indagine del contenuto del componente.

Quale tool ?

Ne indico un paio, con questa considerazione: la class library del .NET Framework espone funzionalità di ispezione degli assembly tramite Reflection, che già potrebbe essere sufficiente per scrivere un tool del genere. Se le funzionalità sono troppo limitate e ci vogliamo divertire, possiamo utilizzare le interfacce unmanaged, che consentono un livello di esame più basso (quindi più complesso e più potente).

I tool in questione sono ILDASM e Reflector.

ILDASM (IL Disassembler) è uno strumento scritto da Microsoft e parte del .NETFX, funzionante sia a linea di comando che con interfaccia grafica, che dà accesso in lettura alle informazioni sui metadati (anche in forma "grezza" a livello di struttura interna degli stessi) e al codice IL, che viene disassemblato e visualizzato come file di testo.

Reflector, il miglior amico di molti sviluppatori .NET, è un eccellente tool scritto da Lutz Roeder, disponibile gratuitamente e aggiornato di frequente. Oltre ad essere più ... carino dal punto di vista grafico, ha "un po'" di funzionalità aggiuntive niente male. Una su tutte la decompilazione del codice IL in un linguaggio di alto livello ... a scelta (meccanismo aumentabile tramite plugin) ! 

Non mi dilungo. Provare per credere !

Il falso problema.

Torno quindi alle domande.

E metto subito in chiaro il punto che a mio giudizio è fondamentale.

Se distribuiamo un assembly .NET, *non distribuiamo i sorgenti*. Punto.

Non facciamo nulla di differente rispetto a prima: diamo ai nostri clienti del codice "eseguibile". Perchè lo devono eseguire e non "leggere".

Se prendiamo un eseguibile Win32, al di là delle questioni legali che non sono il tema di questo post, nulla ci vieta di aprirlo con un editor binario e "leggere" il codice macchina. Così come nulla ci vieta di utilizzare qualche disassemblatore per codice x86. Invece di una serie apparentemente incomprensibile di zeri e uno (rappresentati magari in base esadecimale o con i corrispondenti caratteri ASCII, ma poco cambia) abbiamo la traduzione di quelle istruzioni in assembler.

E poi ... e poi ci fermiamo perchè ...

Perchè è troppo difficile !

Non impossibile. Solo molto difficile. Tanto per noi uomini, quanto per le macchine e i decompilatori.

Tutto qui: il nodo della questione è la complessità del codice che andiamo a leggere.

Complessità che, di per sè, non è un problema, e lo diventa ovviamente quando la variabile tempo viene presa in considerazione. Se abbiamo 2000 anni a disposizione, siamo in gamba (molto) e ci facciamo dare una mano da qualche strumento, il codice sorgente di, che so, Word forse possiamo anche riuscire a dedurlo (non uguale, simile !).

Se l'applicazione è scritta in .NET il tutto diventa, obiettivamente, molto più agevole.

I tempi si riducono, le competenze richieste anche, la cosa diventa ... facile (in proporzione, si intende) !

Un rimedio al problema ?

Vista in questa ottica, se la pensiamo in termini di protezione della nostra proprietà intellettuale (ho scritto un algoritmo segretissimo e ultraottimizzato e il mio concorrente non lo deve avere) la strada che dobbiamo seguire è indicata: aumentare la complessità.

Aumentare la complessità, in ultima analisi, può anche voler dire rinunciare alla piattaforma ed adottarne una che sia intrinsecamente più complessa (da questo punto di vista). Insomma, back to C++.

Ma siamo proprio sicuri che quello che otteniamo, in termini di "protezione", sia realmente un motivo per rinunciare a quel centinaio di migliaia di milioni di triliardilioni di vantaggi che ci sono nell'adottare .NET come piattaforma di sviluppo ?

Mmhhhh ... forse ho un po' condizionato la risposta, vero ?

Obfuscation.

Ed eccoci quindi al punto.

Possiamo rendere più complessa la decifrazione dei nostri segreti, pur mantenendo la piattaforma che abbiamo scelto ?

Quando ho parlato di obfuscation ho sempre visto espressioni del tipo "ah sì, ne ho sentito parlare". E in effetti se ne parla dagli albori della piattaforma .NET (evidentemente il problema alla radice era, ed è, ben chiaro e molto sentito).

Trovo molto bella la definizione di obfuscation su Wikipedia:

  1. The concept of concealing the meaning of communication by making it more confusing and harder to interpret.
  2. ...
  3. (computing) The option to alter computer code, preserving its behavior but concealing its structure and intent.

Nascondere il significato. Mantenere il funzionamento.

Nella pratica esistono diverse tecniche, anche complementari, di obfuscation di assembly .NET.

Comunemente, vengono modificati i nomi (di classi, metodi, ...) nei metadati, in modo da renderli meno chiari.

La classe AuthenticationManager esponde un metodo VerifyCredentials ? Bene, offusco il codice. La classe h8hsaqisqw1uhsshasa espone un metodo ijsdsc9mx4312co2c2 !

In realtà molto spesso vengono usati nomi del tutto simili l'uno all'altro (per esempio differenti per un carattere), in modo tale che per un uomo la lettura diventi quantomeno scomoda !

Addirittura, è molto comune dare lo stesso nome a membri logicamente disgiunti: viene sfruttata la funzionalità di overloading e si parla in questo caso di "overload induction". Provate ad aprire con Reflector un assembly offuscato e vi ritroverete, nella maggior parte dei casi, di fronte ad un insieme di metodi, costanti, proprietà che si chiamano tutti "a".

In questo caso il funzionamento (funzionalità ma anche prestazioni) non viene minimamente alterato (potrebbe teoricamente anche esserci un miglioramento delle prestazioni, discorso per un altro post). D'altra parte il contenuto dei metodi rimane tale e quale a prima.

Altro livello di obfuscation è quello, più invasivo, in cui vengono generati flussi di codice IL intricati e "inconcludenti". E qui ci si capisce sempre meno, cambia il contenuto dei metodi, a volte cambiano anche le prestazioni.

Questa tecnica peraltro è un buon metodo per ingannare i decompilatori.

Ad esempio: i cicli sono costrutti sintattici non presenti in IL (in fin dei conti, è sempre intermediate !) e i compilatori generalmente emettono sequenze di istruzioni IL piuttosto standard per implementarli. Se la sequenza non è più standard per via di codice iniettato o modificato da un obfuscator è probabile che il decompilatore non riesca a tradurre in maniera corretta.

Conclusioni e Riferimenti.

Questo (lungo) APPTXT numero 1 non voleva essere (e vi assicuro che non è) una guida di riferimento alle tecniche di Obfuscation.

Esprimere un giudizio ... beh quello forse era il mio intento, sì.

Il mio punto di vista personale, come probabilmente avrete avuto modo di intuire se siete riusciti ad arrivare fino qui, è questo.

Fatto saldo che la facilità di reverse engineering su codice .NET *non è* un difetto della piattaforma ma una sua caratteristica intrinseca, e che esistono comunque tecniche per ridurre tale "facilità", nella realtà credo che il problema sia molto sopravvalutato e, talvolta, utilizzato come "capro espiatorio".

Addurre la semplicità di decompilazione come fattore determinante nella scelta di NON passare a .NET è, a mio parere, decisamente sbagliato. Ne ho sentiti diversi, di discorsi del genere, e in quei casi la paura di effettuare un upgrade della tecnologia (con tutte le problematiche di gestione che ne derivano) era semplicemente ...

... offuscata dietro all'obfuscation !!!

Se vi interessano questi argomenti, comunque, vi posso consigliare:

Posted: gen 28 2007, 05.08 by devlizard | with 1 comment(s)
Filed under: ,
C# 3.0 Changes: Collection Initializers

Da alcuni giorni è stata rilasciata una nuova CTP di Orcas (Visual Studio 200*).

Segnalo questo post di Charlie Calvert, che elenca alcune "breaking changes" rispetto alla CTP di Maggio relative a C#, LINQ ecc ...

Al di là della rinominazione dei namespace e di numerosi tipi (e giù di Find&Replace ...) risalta la modifica ai collection initializers.

In breve, questo codice:

Book[] books = new Book[] 
{
  {Title="CLR via C#", Author="Richter"},
  {Title="Professional C#", Author="Duffy"}
};

 diventa:

Book[] books = new Book[] 
{ 
  new Book {Title="CLR via C#", Author="Richter"}, 
  new Book {Title="Professional C#", Author="Duffy"} 
};

con l'invocazione esplicita del costruttore di ogni elemento.

Buuuuhhhh :(

In realtà alcuni, (cito Alex Thiessen qui) propongono una possibile motivazione: con l'indicazione esplicita del costruttore è possibile utilizzare come elementi della collezione oggetti di tipo differente (purchè, ovviamente, compatibili, il che significa nel nostro esempio oggetti di tipo Book o derivati).

Benissimo ...

Ma cosa vietava di lasciare *anche* la possibilità di utilizzare la sintassi compatta ? Semplicemente facendo, in quel caso, inference del tipo di item dal tipo di collezione ?

Evidentemente nulla ... se non fosse che la sintassi compatta diventa problematica se si vogliono utilizzare gli inizializzatori per collezioni che non implementano ICollection<T> (con relativo metodo Add(T item)):

The collection initializer has been generalized to allow initialization of collection that do not explicitly implement ICollection<T>, but do have Add() methods.  The nested brace syntax is now reserved to mean the equivalent of an argument list for a call to Add().  If your collection has an Add() method will multiple arguments, or multiple Add() methods, the new interpretation allows you to get access to them.

For example, now you can use the collection initializer to construct a dictionary.

Dictionary<int, string> d = new Dictionary<int, string> {{0, "zero"}, {1, "one"}, {2, "two"}};

(Matt Warren)

E tutto si riduce a definire cos'è una collezione :) Nello specifico, un collection initializer cosa intende per collection ?

Interessante questo post a riguardo di Bill Wagner.

Posted: gen 27 2007, 02.18 by devlizard | with no comments
Filed under:
[APPTXT] Appunti.txt Reloaded - Numero 0

Nel mio post di inizio anno, il proposito numero 5 recitava "scrivere con costanza su questo blog".

Detto ... non fatto ...

Per una volta cercherò di rimediare, allora, e già che ci sono vediamo di mettere in pratica un'idea che mi gira per la testa da un po'.

La cosa nasce da una serie di considerazioni, che riassunte all'osso sono:

  • Ricevo diverse eMail in cui mi chiedono suggerimenti, delucidazioni o semplici risposte a problematiche tecniche, il tutto relativo agli argomenti che tratto durante i corsi di formazione.
  • Ho sempre detto a *tutti* i partecipanti dei corsi che tengo di scrivermi tranquillamente per qualsiasi cosa ... e lo stanno facendo !
  • Rispondere singolarmente è difficile perchè col tempo aumenta anche il numero di "ex-alunni" (sorry per la definizione molto scolastica)
  • Rispondere singolarmente *non va bene*. Cito volentieri la frase che Romeo ha scritto come descrizione del suo blog: "Knowledge has to be managed and shared". E di shared, in questo caso, c'è ben poco !

La mia collezione di Appunti.txt sta crescendo. La mia inbox anche.

Ed entrambe sono risorse che reputo veramente preziose, per il mio lavoro e non solo per quello.

Sono preziose per gli spunti che danno. E perchè, per quanto parziale, sono il mio piccolo spaccato della realtà sui cui il mio lavoro si fonda.

Ecco da dove viene l'idea. Tutto qui.

Ooops ... sì, l'idea, dimenticavo !

L'idea è semplicemente quella di ... organizzare e condividere (Romeo, ti devo una quota per il copyright ?).

Da alcuni giorni sto dando una forma informaticamente migliore ai miei Appunti.txt e alla mia Inbox. Categorizzando gli argomenti e assegnando un minimo di priorità a ciascuno di essi. (N.B. L'algoritmo per il calcolo della priorità *non* dipende esclusivamente dal numero di richieste).

Fatta l'organizzazione, via con la condivisione allora !

Inauguro con questo "numero 0" una serie di post, taggati con [APPTXT].

In cui proverò a rispondere ai quesiti in maniera un po' più organica.

Lo faccio su questo blog perchè credo che il blog sia un mezzo di condivisione delle informazioni molto efficace, se sfruttato in maniera adeguata.

Senza togliere lo spazio o il ruolo ai forum e ai newsgroup. Anzi, 99 su 100 troverete qui rimandi a discussioni che nei forum e nei ng hanno la forma d'essere più consona !

Semplicemente, nel blog ho modo di dare la "mia" visione delle cose. Che va presa in quanto tale, quindi assolutamente fallibile e perfettibile.

Da questa ultima considerazione deriva la conclusione di questo numerozero nonchè il "disclaimer".

Gli argomenti di cui, da quello che vedo ora con i miei appunti.txt sotto mano, andrò a discutere non necessariamente hanno *LA* soluzione.

Semplicemente perchè *LA* soluzione non sempre esiste.

Un conto è chiedere "Come si fa a convertire una stringa in maiuscolo da codice .NET ?", un conto è chiedere "Dove è giusto che io apra la connessione al db ?".

Nel primo caso, beh ... occhei, diciamo che c'è meno spazio per le opinioni ... e molto spazio per un link all'MSDN !

Nel secondo ... vabbè dai, questo è il numero zero, mi sembra un po' prematuro iniziare a parlare di problematiche di accesso ai dati !

Voila, c'est tout.

Ovviamente sono ben accetti i suggerimenti di *tutti*, sia sul contenuto che sulla forma che ... insomma, basta che non siano insulti e va tutto bene.

E ovviamente stay tuned.

New Look, New Feel

Thank you guys

Hooked On Linq
Cito, bookmarko e ... LinQo :)

Troy Magennis has started a community resource web site about LINQ: Hooked on LINQ.

"I've uploaded and started to prime content on what I hope will become the community repository for all things LINQ related. My motivation is simple; I want one place that I can go to get my hands on official and community based LINQ resources."


The site already has some content and pointers to LINQ resources from everywhere. It's a wiki so you'll be able to participate and publish content as well. Go there and contribute.

Oh, and don't forget to visit Troy's blog. It also has very interesting content about LINQ.

Link: HookedOnLinq

Fonte: Fabrice Marguerie's Blog
Posted: gen 06 2007, 07.05 by devlizard | with no comments
Filed under:
Qui si parla tanto di sicurezza ...
... e poi si scoprono cose piuttosto carine :-(

L'altro giorno ho telefonato al numero di assistenza di un (forse il principale) ISP italiano per chiedere alcune informazioni su un router dato in comodato d'uso.

Le informazioni le ho avute (dopo 20 minuti di attesa, ma questo temo sia lo standard in molti casi ...), in compenso ho saputo che:

1) Hanno installato e configurato il router lasciando l'accesso HTTP remoto aperto.

2) Hanno lasciato invariata la password di amministratore impostata dalla fabbrica.

3) Password che, per inciso, non è propriamente "strong" ...

4) Alla perplessità sui "piccoli" problemi di sicurezza che questa politica può comportare, il tecnico (gentilissimo, peraltro) sostiene che "al limite può cambiare la password, ma non glielo consiglio comunque perchè se poi se la dimentica il router non è resettabile via hardware e quindi lo deve riportare da noi per un ripristino delle impostazioni originali".

Da ridere o da piangere ?
Posted: gen 04 2007, 01.30 by devlizard | with no comments
Filed under:
Debug.Assert(_YearEnumerator.Current is FantasticYear)
Ed ecco i miei propositi e le mie speranze.
Non OT, questa volta, perchè ... beh ... molti progetti sono legati alla mia attività professionale.
Ieri sera ho conosciuto diverse persone, alcune delle quali mi hanno chiesto: "Che lavoro fai ?"
Come mai è così difficile per noi informatici rispondere ?
E' la solita storia dei cappellini, mi direte.
I "dev" ...
Siamo tutti un po' sviluppatori, tester, architetti, perfino analisti, dove tutti questi termini hanno la loro collocazione precisa ma spesso si fondono ed è difficile, a quel punto, stabilire i confini.
Ammesso che sia possibile e ammesso che sia giusto.
Beh, no, giusto lo è secondo me, però ...
Sto già andando fuori tema, ritorno al dunque.
I miei propositi ?
Li scrivo così avrò qualcosa da rileggere fra 364 giorni, ridendo di me stesso e della mia capacità di programmazione.

Primo, fondamentale, irrinunciabile: continuare sempre e comunque a studiare. Sempre e Comunque.
Anche perchè direi che ce n'è d'avanzo di materiale.
LINQ. LINQ, le ragioni e le tecnologie che ci stanno dietro.
Perchè guardi il passato e vedi nascere progetti come F#, C-omega, Boo. E allora scavi e scopri un mondo che hai sempre considerato "accademia" e invece prepotentemente diventa la nuova "tendenza".
Linguaggi imperativi si avvicinano al paradigma funzionale, linguaggi funzionali, magari "spuri", ma che girano (e bene) su una piattaforma nata per esigenze ben differenti.
Ne salta fuori un riesame profondo del concetto di "linguaggio di programmazione" con il quale ho vissuto sino a pochi mesi fa.

Ecco, quindi, il mio secondo proposito.
Integrare le mie conoscenze, colmare le lacune per poter avere un'ottica diversa con la quale guardare questa parte della tecnologia.
Che mi affascina e mi stimola come poche altre cose hanno fatto negli ultimi anni.

Il proposito numero tre (non vado per ordine di importanza) è di orientare la mia carriera sempre più verso la formazione.
Termine molto generale che include tanto le docenze in corsi in aula quanto la scrittura di materiale tecnico.
Il 2006 ha avuto un colpo di coda per me fondamentale in questa direzione.
Questo è quello che lo rende, professionalmente parlando, un anno magnifico.

Il proposito numero 4 è molto specifico.
Vorrei scrivere un libro.
E visto che con le poesie non me la cavo ... pensavo un libro di informatica :)
Idee e bozze ci sono, spero di avere il tempo per provarci e le capacità per riuscirci.

Infine il proposito numero 5. Questo blog.
Un blog che ho iniziato un paio di anni fa, in cui ho scritto con un'incostanza spaventosa.
In cui (rileggendo un po' di cose ... nostalgia maledetta) ho scritto di argomenti tecnici, di stupidaggini e ogni tanto delle "grandi regole" che governano il mio mondo professionale.
Nel 2007 vorrei avere quella costanza che mi è mancata sinora.
Beh, per ora inizio bene, è il mio secondo post nelle prime 12 ore dell'anno !!

Coi propositi direi che ci siamo.
Con le speranze ?
Facile !
Vorrei vedere realizzati tutti i miei propositi.

E questo auguro a voi.

Stay Tuned ...
[OT] _YearEnumerator.Next()
Anno nuovo.
Si sa, tempo di bilanci, di prospettive e di ringraziamenti.
Arrivo in ritardo con questo post, ancora un po' offuscato dalla nottata.
Spero di essere chiaro nelle mie parole.
Partiamo dall nottata, appunto. Una serata che doveva essere, non è stata, e alla fine è stata comunque. Grazie a chi l'ha resa possibile.
Il 2006 è stato un anno densissimo di eventi, per me, sia sul piano umano e personale che su quello professionale.
E in entrambi ci sono state persone che mi hanno promesso, persone che mi hanno deluso, persone che mi hanno accolto, persone che mi hanno respinto, persone che mi hanno (ancora) entusiasmato.
Sta suonando "Verso Oriente" dei timoria sul player accanto a me. Un brano che mi è entrato dentro come un missile ad implosione. Una banale impersonificazione del mio stato.
"Vado via ... ".
Eccolo in una frase il mio anno vecchio.
Abbandonare. Ricostruire. Sbagliare. Demolire. Dimenticare. Ripartire e Ricordare.
Trovare una strada, 8 corsie spianate senza limite di velocità e con un traffico da metropoli.
E correre. Correre !
Rischiare incidenti ad ogni manovra, e continuare a correre.
E non trovare più un posto da chiamare casa.
O forse scoprire che la casa non è un posto e non è fatta di muri.
Ho vissuto in albergo.
Ma le persone importanti sono state, sono e saranno sempre presenti perchè le sento senza vederle.
Queste persone sono la ragione della mia sopravvivenza, perchè esistono e mi rendono un viaggiatore conscio.
Sono la mia forza di gravità perchè mi tengono dentro in curva anche quando le leggi del mondo mi vogliono stampato sul muro.
Altrimenti è facile diventare una pallina che scorre regolata solo dai vincoli, senza capacità di impartire una direzione diversa da quella che il lanciatore ha impresso.
Grazie.
A tutti, senza specificare chi siete perchè presi singolarmente meritereste un post kilometrico.
Ma presi insieme siete ... me !