A TAXONOMY OF OBFUSCATING
TRASFORMATIONS
Funes Daniel 809619
Salvador Carlo 803776
Corso di Analisi e Verifica dei Programmi 2006/2007
INTRODUZIONE



Il software contiene informazioni riservate ed è una proprietà
intellettuale di chi lo produce:
 Codice
 Algoritmi
 Chiavi segrete
Attraverso le tecniche di analisi dei programmi (DataFlow
Analysis) è possibile analizzare il comportamento di un software
e rubarne i segreti.
Con abbastanza risorse in tempo e sforzo, un programmatore è
capace di fare il reverse engineering di una applicazione,
soprattutto se sviluppata in un linguaggio come Java, distribuita
in formato semplice da decompilare.
PROTEZIONE DEL SOFTWARE:
Scenario

Una volta creata l’applicazione deve essere distribuita in qualche
forma(codice nativo, bytecode).

Alice e Bob sono due sviluppatori software, Bob è
malintenzionato (algoritmi, strutture dati).

La protezione avviene attraverso mezzi legali o tecnici.

Le strategie tecniche sono:




vendere i servizi,
cifrare il codice,
compilatore just-in-time,
offuscamento del codice.
ALICE E BOB:
vendere i servizi
ALICE E BOB:
cifratura e compilatori just-in -time
ALICE E BOB:
offuscamento del codice


Alice da in input l’applicazione ad un offuscatore, con vantaggi e
svantaggi.
Il livello di sicurezza aggiunto da un’offuscatore ad
un’applicazione dipende da:


la potenza degli algoritmi di offuscamento,
la quantità di risorse (tempo e spazio) disponibili al
deoffuscatore.
TRASFORMAZIONI OFFUSCANTI:
classificazione

Le trasformazioni si classificano e si valutano rispetto alla loro:



potenza: grado di confusione causato nell’utente malizioso;
resilienza: quanto il codice offuscato è resistente ad un attacco
deoffuscante;
costo: quanto overhead è aggiunto all’applicazione originale.
TRASFORMAZIONI OFFUSCANTI:
definizione


Sia t:P  P’ una trasformazione di un programma sorgente P
in un altro programma P’.
t:P  P’ è una trasformazione offuscante se P e P’ hanno lo
stesso comportamento osservabile e più precisamente devono
essere mantenute le seguenti condizioni:

se P fallisce nel terminare o termina con una condizione di
errore allora P’ potrebbe terminare oppure no,

altrimenti, P’ deve terminare e produrre lo stesso output di
P.
VALUTAZIONE DELLLE TRASFORMAZIONI
OFFUSCANTI: metriche di complessità

E(X) è la complessità di un componente software X. F è una funzione
o metodo, C è una classe, e P è un programma.
μ1
Lunghezza del
programma
E(P) aumenta col numero di operatori e di
operandi in P
μ2
Cyclomatic
Complexity
E(F) aumenta col numero di predicati in F
μ3
Complessità
annidata
E(F) aumenta con il numero di livelli
annidati di predicati condizionali in F
μ4
Complessità del
flusso di dati
E(F) aumenta col numero di riferimenti a
basic block in F
μ5
Complessità fanin/out
E(F) aumenta col numero di parametri
formali di F, e con il numero di strutture
dati globali lette o aggiornate da F
VALUTAZIONE DELLLE TRASFORMAZIONI
OFFUSCANTI: metriche di complessità
μ6
Complessità delle E(P) aumenta con la complessità delle
strutture dati
strutture dati statiche dichiarate in P.
 La complessità di una variabile scalare è
costante;
 La complessità di un array aumenta col
numero di dimensioni e con la complessità del
tipo degli elementi;
 La complessità un record aumenta con il
numero e la complessità dei suoi campi.
VALUTAZIONE DELLLE TRASFORMAZIONI
OFFUSCANTI: metriche di complessità
μ7
Metrica 00
E(C) aumenta con:
 μ7a , il numero di metodi in C,
 μ7b , la profondità (la distanza dalla radice)
di C nell’albero di ereditarietà
 μ7c, il numero di sottoclassi dirette di C
 μ7d , il numero di altre classi alle quali C è
associata
 μ7e, il numero di metodi che possono
essere eseguiti in risposta all’invio di un
messaggio ad un oggetto di C
 μ7f, il grado di quali metodi di C non fanno
riferimenti allo stesso insieme di variabili
d’istanza.
TRASFORMAZIONI OFFUSCANTI:
potenza della trasformazione

Sia T una trasformazione che conserva il comportamento | t:
P P’ cioè che trasforma un P sorgente in un P’. Sia E(P) la
complessità di P.

Tpot(P), la potenza di T rispetto al P, è la misura di quanto T
cambia la complessità di P.

Tpot(P)=E(P’)/E(P)-1.

T è una trasformazione offuscante potente se: Tpot(P)>0.

Si misura in (low, medium, high).
TRASFORMAZIONI OFFUSCANTI:
resilienza della trasformazione

Data T





locale se ha effetto su un singolo basic block di un grafo del
flusso di controllo (CFG),
globale se ha effetto sull’intero CFG,
interprocedurale se ha effetto sul flusso di informazioni tra le
procedure,
interprocesso se ha effetto sulle interazioni tra thread di controllo
in esecuzione indipendente .
Si misura su una scala che va da “trivial” a “one-way”.
TRASFORMAZIONI OFFUSCANTI:
resilienza della trasformazione





Sia T una trasformazione che
conserva il comportamento | t :
PP’ .
Tres(P) è la resilienza di T rispetto
al programma P.
Tres(P) è one-way se
l’informazione è rimossa da P in
modo che P non possa più essere
ricostruito da P’.
Altrimenti Tres=resilienza(Tsforzo D,
Tsforzo P).
La resilienza è la f definita dalla
matrice seguente:
TRASFORMAZIONI OFFUSCANTI:
costo della trasformazione



E’ l’overhead di tempo/spazio che una trasformazione
aggiunge ad un’applicazione.
E’ classificato su una scala a 4 punti (free, cheap, costly, dear).
Tcost(P) è l’overhead in termini di tempo/spazio in P’ rispetto a P
e può essere:





dear, se P’ richiede una quantità esponenziale di risorse rispetto a
P.
costly, se P’ richiede più di O(n^p ), p>1, risorse rispetto a P.
cheap, se P’ richiede più di O( n ) risorse rispetto a P.
free, se P’ richiede più di O(1) risorse rispetto a P.
Tqual(P), la qualità di una trasformazione T è definita come:
Tqual(P)=(Tpot(P),Tres(P),Tcost(P)).
TRASFORMAZIONI DEL CONTROLLO

Le TRASFORMAZIONI DEL CONTROLLO tentano di oscurare
il flusso di controllo dell’applicazione sorgente:
 Aggregazione : spezzano le computazioni logicamente
affini oppure fonde computazioni non logicamente affini;


Ordine di controllo : randomizza l’ordine con cui le
computazioni sono eseguite;
Computazioni del flusso di controllo : inseriscono nuovo
codice (creano molto overhead).
TRASFORMAZIONI DEL CONTROLLO:
predicati opachi



Una variabile V è opaca nel punto p di un programma, se V ha
una proprietà q in p che è conosciuta al momento
dell’offuscamento. Indicheremo ciò con Vp^q o con V^q se p è
libero dal contesto.
Un predicato P è opaco nel punto p di un programma, se il suo
esito è conosciuto al momento dell’offuscamento. Indicheremo
con Pp^F o con Pp^T.
Misura del costo aggiunto di un costrutto opaco : free, …, dear.
TRASFORMAZIONI DEL CONTROLLO:
costrutti opachi

trivial



rotto solo attraverso un’analisi locale statica.
un’analisi locale è ristretta ad un singolo basic block del CFG.
weak


rotto solo attraverso un’analisi globale statica.
Un’analisi globale è ristretta ad un singolo CFG.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni computazionali



Inseriamo codice morto o irrilevante;
Aumentando le metriche μ2 e μ3;
Inseriamo codice morto o irrilevante;
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni computazionali

Estendere le condizioni dei cicli:

il predicato usato x^2(x+1)^2=0(mod 4) è sempre valutato true.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni computazionali


Convertire un grafo di flusso riducibile ad uno non riducibile.
Trasformazioni language-breaking:
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni computazionali

Rimuovere le chiamate a libreria e gli idiomi della
programmazione;



Molti programmi scritti in Java si basano sulle chiamate alle librerie
standard e sui clichè (o pattern).
Aggiungere operatori ridondanti
P e Q possono assumere tutti i valori il cui quoziente sia 2 ogni
volta che l’espressione (2') è raggiunta.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni computazionali

Parallelizzazione del codice


Si possono creare due processi fantoccio che non eseguono nessun
compito utile.
Possiamo spezzare una sezione sequenziale dell’applicazione in
sezioni multiple eseguite in parallelo.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni per aggregazione

Chi programma usa l’astrazione procedurale per vincere alcune
difficoltà.

Queste astrazioni vengono rimosse utilizzando:





Inlining,
Outlining,
Interleaving,
Clonazione.
Si procede nel modo seguente:


Il codice che il programmatore ha allegato insieme in un metodo
deve essere sparpagliato nel programma.
Il codice che sembra non essere logicamente connesso deve essere
aggregato in un metodo.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni per aggregazione


Metodi Inline e Outline
Inline: si rimpiazza una chiamata a procedura con il corpo della
procedura chiamata e si rimuove la procedura:



altamente resiliente (generalmente one-way);
non c’è più traccia dell’astrazione.
Outlining: si trasforma una sequenza di espressioni in una
subroutine
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni per aggregazione




Metodi Inline e Outline.
Nei linguaggi object oriented come Java, l’inlining può non
sempre essere una trasformazione totalmente one-way.
L’attuale procedura chiamata dipenderà dal tipo di m
determinato a run-time.
Occorre applicare l’inlining a tutti i possibili metodi e ramificare
su m.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni per aggregazione



Metodi interleave.
La scoperta del codice interfogliato è un difficile compito di
reverse engineering.
L’idea:


fondere i corpi e la lista dei parametri dei due metodi;
aggiungere un parametro extra (o parametro globale) per
discriminare tra le chiamate ai metodi individuali.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni per aggregazione



Metodi di clonazione.
Per capire il comportamento di una subroutine sono importanti
anche i differenti ambienti in cui è stata chiamata.
Idea : offuscare il punto di una chiamata ad un metodo per far
sembrare che differenti routine sono state chiamate.
TRASFORMAZIONI DEL CONTROLLO:
trasformazioni per aggregazione
TRASFORMAZIONI DEI DATI:
Storage e Encoding


Trasformazioni che oscurano le strutture dati usate
nell’applicazione sorgente.
Le trasformazioni storage tentano di scegliere una classe di
immagazzinamento non naturale sia per i dati dinamici che per
quelli statici


Es. storage int i; a[i]=3;
le trasformazioni encoding tentano di scegliere codifiche non
naturali per i comuni tipi di dati

Es. encoding 0000000000001100 sarà interpretato come 12.
TRASFORMAZIONI DI STORAGE E ENCODING:
Cambiare la codifica


Viene sostituito i con i’=c1*i + c2.
c1 e c2 sono costanti.
Introduce overhead in termini di tempo d’esecuzione ma
può essere deoffuscato usando le comuni tecniche di
analisi dei compilatori.
TRASFORMAZIONI DI STORAGE E ENCODING:
Promozione di variabili


Promuovere le variabili da una classe di memorizzazione ad una
più generale.
Bassa potenza e resilienza, ma usate in modo congiunto con
altre trasformazioni sono molto efficienti.
Promozione di una varibile da
integer ad un oggetto integer
Promozione di una varibile
da locale a globale, questa
trasformazione incrementa
la metrica μ5.
TRASFORMAZIONI DI STORAGE E ENCODING:
Splitting delle varibili (1)




Variabili di tipo Boolean o con raggio d’azione ridotto posso
essere spezzate in più variabili.
V=[p1,..,pk] ( V di tipo T, pi di tipo U).
La potenza, la resilienza, e il costo di questa trasformazione
crescono con l’aumentare di k, ma di solito k<= 3 a causa del
costo della trasformazione troppo elevato.
Per spezzare una variabile V in due variabili p e q è necessario
fornire:



Una funzione f(p,q)=V,
Una funzione g(V),
Nuove operazioni che possano essere effettuate su p e q.
TRASFORMAZIONI DI STORAGE E ENCODING:
Splitting delle varibili (2)
TRASFORMAZIONI PER AGGREGAZIONE:
Fusione di variabili scalari


In un programma object oriented il controllo è organizzato
attorno alle strutture dati, che un reverse engineering prova a
ricostruire. Quindi è importante per un offuscatore provare a
nasconderle.
Due o più variabili scalari V1,…, Vk posso essere fuse in un’unica
variabile Vm:


L’aritmetica sulle variabili individuali deve essere trasformata in
un’aritmetica su Vm,
Fusione di due variabili integer a 32 bit X e Y in una a 64 bit Z,
usando la funzione Z(X,Y) =232 * Y + X .
TRASFORMAZIONI PER AGGREGAZIONE:
Ristrutturare array

Operazioni su array : splitting(1-2), merging(3-5) ,folding(6-7) ,flatting(8-9)
TRASFORMAZIONI PER AGGREGAZIONE:
Modificare le relazioni di ereditarietà



Si dice che la classe C2 eredita dalla classe C1 e
indichiamo ciò con (C2  C1  C2 ).
la complessità di una classe cresce con la sua
ampiezza (gerarchia di ereditarietà).
Idea : aumentiamo l’ampiezza della gerarchia (μ7)




Fattorizzazione,
Inserimento di classi fantoccio
 Variante : falsa rifattorizzazione.
Problema : bassa resilienza.
Soluzione : usate in modo combinato.
VALORI E PREDICATI OPACHI:
uso di alias



L’analisi statica
interprocedurale è
significativamente
complicata ogni volta che
c’è possibilità d’aliasing.
Infatti, differenti versioni
di precise analisi statiche
sugli alias hanno
dimostrato che questo è
un problema NP-hard.
L’idea di base è di
costruire una struttura
dinamica complessa e
mantenere un insieme di
puntatori in questa
struttura.
VALORI E PREDICATI OPACHI:
uso di thread



I programmi paralleli sono molto più difficili da
analizzare rispetto alla loro controparte
sequenziale.
La ragione di ciò è la loro semantica
interfogliante: n espressioni in una regione
parallela.
Idea base analoga a quella che usa gli alias


Vantaggi



struttura dati globale aggiornato da thread
i predicati opachi richiedano nel caso peggiore
tempo esponenziale per essere rotti
grado molto alto di resilienza
Si combinano gli effetti di interfogliamento e
aliasing.
DEOFFUSCAMENTO E TRASFORMAZIONI
PREVENTIVE
Architettura di un tool di
deoffuscazione Java.
L'input principale del
tool è un'applicazione
costituita da un insieme
di file class Java
offuscati.
L'output del tool è un
insieme di file class
deoffuscati che
possono essere
convertiti in sorgenti
Java da un
decompilatore.
DEOFFUSCAMENTO E TRASFORMAZIONI
PREVENTIVE

Trasformazioni preventive innerenti:


Rendono le tecniche di deoffuscamento più difficili,
Poca potenze, molta resilienza.
 Trasformazioni preventive mirate:
 esplorare i problemi conosciuti nei correnti deoffuscatori o nei
decompilatori,
 Es. il decompilatore Mocha.
IDENTIFICARE E VALUTARE I COSTRUTTI
OPACHI

La parte più difficile del deoffuscamento è identificare e valutare i
costrutti opachi :



Locali,
Globali,
Interprocedurali.
locale
globale
if ( x * x  (7* y * y  1) F )...
R  x * x;
...
S  7 * y * y  1;
...
if ( R  S F )....
IDENTIFICARE E VALUTARE I COSTRUTTI OPACHI:
Pattern Matching




Un deoffuscatore può usare la conoscenza delle strategie
impiegate dagli offuscatori conosciuti per identificare i predicati
opachi.
regole di pattern-matching che possano identificare i
predicati opachi comunemente usati.
L’offuscatore dovrebbe evitare di usare un numero limitato di
predicati opachi;
Utilizzo di costrutti opachi sintatticamente simili ai costrutti usati
nell’applicazione reale.
IDENTIFICARE E VALUTARE I COSTRUTTI OPACHI:
slicing del programma



Uno slice di un programma P rispetto ad un punto p e ad una
variabile v, consiste di tutte le espressioni di P che possono aver
contribuito al valore di v nel punto p.
Il deoffuscatore creerà quindi degli slice per ogni variabile da
esaminare, al fine di eliminare falso codice e unire pezzi di
codice logicamente legati.
L’offuscatore deve rendere difficile lo slicing


Aggiungendo parametri alias,
Aggiungendo dipendenze alle variabili.
IDENTIFICARE E VALUTARE I COSTRUTTI OPACHI:
Analisi Statistica(1)


Un deoffuscatore può sfruttare un programma offuscato per
analizzare il risultato di tutti i predicati e avvisare il reverse engineer
di qualunque predicato che restituisce sempre lo stesso valore di
verità.
Predicati che si verificano in casi eccezzionali.
IDENTIFICARE E VALUTARE I COSTRUTTI OPACHI:
Analisi Statistica(2)


?
L’offuscatore dovrebbe quindi favorire i predicati p
Predicati opachi con side-effect.
ARCHITETTURA DI UN TIPICO
OFFUSCATORE JAVA
 Permette di inserire
dei profili per evitare
che trasformazioni
troppo costose siano
applicate a parti del
codice usate molto
frequentemente.
 Contiene un gran
numero di
trasformazioni.
ALGORITMI D’OFFUSCAMENTO:
ciclo principale




SelectCode restituisce il prossimo codice oggetto sorgente che
deve essere offuscato.
SelectTransform restituisce la trasformazione che dovrebbe
essere usata per offuscare il particolare codice oggetto
sorgente.
Apply applica le trasformazioni al codice oggetto sorgente e di
conseguenza aggiorna l’applicazione.
Done determina quando il livello d’offuscamento richiesto è
stato ottenuto.
ALGORITMI D’OFFUSCAMENTO:
strutture dati

Per ogni codice oggetto sorgente S e per ogni routine M:




Ps(S) l’insieme dei costrutti del linguaggio che il programmatore
ha usato in S.
A(S) ={T1V1, … , TnVn} è un mapping tra le trasformazioni
Ti e i valori Vi.
I(S) è la priorità d’offuscamento di S.
R per ogni routine M, R(M) è il rango del tempo d’esecuzione di
M.
ALGORITMI D’OFFUSCAMENTO:
funzioni di qualità

Restituiscono informazioni di tipo numerico riguardanti ogni
trasformazione:




Tres(S) - restituisce una misura della resilienza della trasformazione
T quando è applicata al codice oggetto sorgente S.
Tpot(S) - restituisce una misura della potenza della trasformazione T
quando è applicata al codice oggetto sorgente S.
Tcost(S) - restituisce una misura del tempo d’esecuzione e
dell’overhead di spazio aggiunto da T a S.
Pt - mappa ogni trasformazione T nell’insieme dei costrutti del
linguaggi che T aggiungerà all’applicazione.
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 1 (offuscamento del codice)
Caricare l’applicazione C1,C2,… da offuscare
1.
a.
b.
Caricare il codice contenuto nei file delle librerie L1,L2,..
Costruire una rappresentazione interna dell’applicazione
2.
3.
a.
b.
c.
4.
Codice sorgente oppure
Codice oggetto
Un grafo di controllo del flusso per ogni routine di A
Un call-graph per le routine in A
Un grafo di ereditarietà per le classi di A.
Costruire R(M) e Ps(S) usando l’algoritmo 5, I(S) usando
l’algoritmo 6 e A(S) usando l’algoritmo 7.
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 1 (offuscamento del codice)
5.
Applicare le Trasformazioni offuscanti all’applicazione
REPEAT
S:=SelectCode(I);
T:=SelectTrasformation(S,A);
Applica T ad S ed aggiorna le strutture dati rilevanti del
punto 3
UNTIL Done(ReqObf,AcceptCost,S,T,I)
6.
Ricostruisci il codice oggetto sorgente offuscato in una nuova
applicazione offuscata X.
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 2(SelectCode)

Input



Il mapping della priorità di offuscamento I come computato
dall’algoritmo 6
Output: un codice oggetto sorgente S.
I mappa ogni codice oggetto sorgente S in I(S).


Trattiamo I come una coda a priorità
Selezioniamo S in modo da massimizzare I(S)
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 3 (Select Transform)

Input




Un codice oggetto sorgente S.
La mappa di appropriatezza computata dall’Algoritmo 7
Output: Una trasformazione T
Due aspetti importanti da considerare

T deve essere inglobata in modo naturale con il resto del codice S


Alto livello di appropiatezza in A(S)
T deve rendere alti livelli di offuscamento con bassi costi di
overhead
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 3 (Select Transform)

Restituisci una trasformazione T tale che:
Dove ω1,ω2,ω3 sono costanti definite dall’implementazione
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 4 (Done)

Svolge vari compiti

Aggiorna la coda a priorità I



La riduzione è basata su una combinazione resilienza/potenza
Aggiorna anche ReqObf e AcceptCost
Determina se la condizione di terminazione è stata raggiunta.
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 5 (informazioni pragmatiche)

Input




Un’applicazione A
I = {I1,I2,..}
Output: R(M), Ps(S)
Si computano le informazioni pragmatiche

Dinamiche



Uso di profiler su I
Calcolare R(M) per ogni routine/basic block
Statiche

Calcolare Ps(S)
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 5 (informazioni pragmatiche)
FOR S:=ogni codice oggetto sorgente in A DO
O := l’insieme di operatori che S usa;
C := l’insieme dei costrutti del linguaggio ad alto livello
(WHILE,eccezzioni,threads,etc.) che S usa;
L := l’insieme di classi/routine di libreria che S referenzia;
Ps(S) := O U C U L;
END FOR
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 6 (priorità dell’offuscamento)

Input




un’applicazione A
R(M)
Output: I(S)
Possibili euristiche per I(S) possono essere


Se molto tempo è speso ad eseguire una routine M, allora M è
probabilmente una procedura importante che dovrebbe essere
pesantemente offuscata
Il codice complesso è più probabile che contenga importanti segreti
commerciali che semplice codice
ALGORITMI D’OFFUSCAMENTO:
ALGORITMO 7(appropiatezza dell’offuscamento)

Input



Un’applicazione A costituita dai file C1,C2,…
Pt,Ps(S),A(S)
Output: A(S)
FOR S := ogni codice oggetto sorgente in A DO
FOR T := ogni trasformazione DO
V := grado di somiglianza tra e Pt(T) e Ps(S);
A(S) := A(S) U {TV};
END FOR
END FOR
CONCLUSIONI (1)

Metodo migliore di offuscamento è quello che ha il miglior
rapporto costo,resilienza,potenza:





Gli offuscatori commerciali usano una combinazione di
trasformazioni: Package/Class/Method/Field renaming , Control
Flow Obfuscation , String Encryption.
In oltre attuano una ottimizzazione del codice per incrementare al
massimo le performance.
Trade-off tra protezione e prestazione.
Protegge solo parti del codice.
Usare gli offuscatori come ottimizzatori di codice, per ridurre le
dimensioni delle applicazioni e renderle più performanti.
CONCLUSIONI (2)



Reverse Engeneering sempre possibile, si deve avere un costo
elevato per effettuarla.
Offuscamento può introdurre bug nel codice.
Difficoltà nel debug del codice


Lo sviluppatore a volte dovrà mantenere 2 versioni
dell’applicazione.
Uno sguardo avanti:


Obsfucation tool sempre più presenti nel processo di creazione del
software, inclusi in strumenti di sviluppo come visual studio 2005.
Interessi commerciali che portano a investimenti per la protezione
del software.
BIBLIOGRAFIA




Software protection and Application Security: Understanding the
Battleground (A. Main and P.C. van
Oorschot), LNCS 2003
A Taxonomy of Obfuscating Transformation (C. Collberg, C.
Thomborson and D. Low), TR 1998
Wikipedia, the free encyclopedia. (2002), “Obfuscated code”,
http://www.wikipedia.com/wiki/obfuscated+code
Metrics for Measuring The Effectiveness of Obfuscators
(N.Naeem, M.Batchelder, L.Hendren), Sable, 2006.