Offuscamento (software) - Obfuscation (software)

Nello sviluppo del software , l' offuscamento è l'atto deliberato di creare codice sorgente o macchina che è difficile da comprendere per gli esseri umani. Come l' offuscamento nel linguaggio naturale , può usare espressioni inutilmente indirette per comporre affermazioni. I programmatori possono offuscare deliberatamente il codice per nasconderne lo scopo ( sicurezza attraverso l'oscurità ) o la sua logica o i valori impliciti in esso incorporati, principalmente al fine di prevenire manomissioni, scoraggiare il reverse engineering o persino per creare un puzzle o una sfida ricreativa per qualcuno che legge la fonte codice. Questo può essere fatto manualmente o utilizzando uno strumento automatizzato, quest'ultimo è la tecnica preferita nell'industria.

Panoramica

L'architettura e le caratteristiche di alcuni linguaggi possono renderli più facili da offuscare rispetto ad altri. C , C++ e il linguaggio di programmazione Perl sono alcuni esempi di linguaggi facili da offuscare. Haskell (linguaggio di programmazione) è anche abbastanza offuscabile nonostante sia abbastanza diverso nella struttura.

Le proprietà che rendono offuscabile un linguaggio non sono immediatamente ovvie.

Offuscamento ricreativo

Scrivere e leggere codice sorgente offuscato può essere un rompicapo . Numerosi concorsi di programmazione premiano il codice più creativamente offuscato, come l' International Obfuscated C Code Contest e l' Obfuscated Perl Contest .

I tipi di offuscamento includono la semplice sostituzione di parole chiave, l'uso o il non utilizzo di spazi bianchi per creare effetti artistici e programmi autogeneranti o fortemente compressi.

Secondo Nick Montfort , le tecniche possono includere:

  1. naming offuscamento, che include nominare le variabili in modo insignificante o ingannevole;
  2. confusione di dati/codice/commenti, che include far sembrare del codice reale dei commenti o confondere la sintassi con i dati;
  3. doppia codifica, che può visualizzare il codice in forma di poesia o forme interessanti.

Brevi programmi Perl offuscati possono essere usati nelle firme dei programmatori Perl. Questi sono JAPH (" Solo un altro hacker Perl ").

Esempi

Questa è una voce vincente dell'International Obfuscated C Code Contest scritto da Ian Phillipps nel 1988 e successivamente decodificato da Thomas Ball.

/*
  LEAST LIKELY TO COMPILE SUCCESSFULLY:
  Ian Phillipps, Cambridge Consultants Ltd., Cambridge, England
*/

#include <stdio.h>
main(t,_,a)
char
*
a;
{
	return!

0<t?
t<3?

main(-79,-13,a+
main(-87,1-_,
main(-86, 0, a+1 )

+a)):

1,
t<_?
main(t+1, _, a )
:3,

main ( -94, -27+t, a )
&&t == 2 ?_
<13 ?

main ( 2, _+1, "%s %d %d\n" )

:9:16:
t<0?
t<-72?
main( _, t,
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#;\
#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;\
q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; \
r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\
\
n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;\
{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\
#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
:
t<-50?
_==*a ?
putchar(31[a]):

main(-65,_,a+1)
:
main((*a == '/') + t, _, a + 1 ) 
:

0<t?

main ( 2, 2 , "%s")
:*a=='/'||

main(0,

main(-61,*a, "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry")

,a+1);}

È un programma C che una volta compilato ed eseguito genererà i 12 versi de I 12 giorni di Natale . Contiene tutte le stringhe richieste per la poesia in una forma codificata all'interno del codice.

Una voce non vincente dello stesso anno, questo prossimo esempio illustra l'uso creativo degli spazi bianchi; genera labirinti di lunghezza arbitraria:

char*M,A,Z,E=40,J[40],T[40];main(C){for(*J=A=scanf(M="%d",&C);
--            E;             J[              E]             =T
[E   ]=  E)   printf("._");  for(;(A-=Z=!Z)  ||  (printf("\n|"
)    ,   A    =              39              ,C             --
)    ;   Z    ||    printf   (M   ))M[Z]=Z[A-(E   =A[J-Z])&&!C
&    A   ==             T[                                  A]
|6<<27<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}

I compilatori C conformi ad ANSI non consentono la sovrascrittura di stringhe costanti, cosa che può essere evitata cambiando "*M" in "M[3]" e omettendo "M=".

Il seguente esempio di Óscar Toledo Gutiérrez, Best of Show entry nel 19° IOCCC , implementa un emulatore 8080 completo di terminale e controller del disco, in grado di avviare CP/M-80 ed eseguire applicazioni CP/M:

#include <stdio.h>
           #define n(o,p,e)=y=(z=a(e)%16 p x%16 p o,a(e)p x p o),h(
                                #define s 6[o]
             #define p z=l[d(9)]|l[d(9)+1]<<8,1<(9[o]+=2)||++8[o]
                                #define Q a(7)
           #define w 254>(9[o]-=2)||--8[o],l[d(9)]=z,l[1+d(9)]=z>>8
                               #define O )):((
                  #define b (y&1?~s:s)>>"\6\0\2\7"[y/2]&1?0:(
                               #define S )?(z-=
                    #define a(f)*((7&f)-6?&o[f&7]:&l[d(5)])
                               #define C S 5 S 3
                       #define D(E)x/8!=16+E&198+E*8!=x?
                             #define B(C)fclose((C))
                       #define q (c+=2,0[c-2]|1[c-2]<<8)
                          #define m x=64&x?*c++:a(x),
                         #define A(F)=fopen((F),"rb+")
                    unsigned char o[10],l[78114],*c=l,*k=l
                          #define d(e)o[e]+256*o[e-1]
#define h(l)s=l>>8&1|128&y|!(y&255)*64|16&z|2,y^=y>>4,y^=y<<2,y^=~y>>1,s|=y&4
+64506; e,V,v,u,x,y,z,Z; main(r,U)char**U;{

     { { { } } }       { { { } } }       { { { } } }       { { { } } }
    { { {   } } }     { { {   } } }     { { {   } } }     { { {   } } }
   { { {     } } }   { { {     } } }   { { {     } } }   { { {     } } }
   { { {     } } }   { { {     } } }   { { {     } } }   { { {     } } }
   { { {     } } }   { { {     } } }   { { {     } } }   { { {     } } }
    { { {   } } }    { { {     } } }    { { {   } } }    { { {     } } }
      { { ; } }      { { {     } } }      { { ; } }      { { {     } } }
    { { {   } } }    { { {     } } }    { { {   } } }    { { {     } } }
   { { {     } } }   { { {     } } }   { { {     } } }   { { {     } } }
   { { {     } } }   { { {     } } }   { { {     } } }   { { {     } } }
   { { {     } } }   { { {     } } }   { { {     } } }   { { {     } } }
    { { {   } } }     { { {   } } }     { { {   } } }     { { {   } } }
     { { { } } }       { { { } } }       { { { } } }       { { { } } }

                                   for(v A((u A((e A((r-2?0:(V A(1[U])),"C")
),system("stty raw -echo min 0"),fread(l,78114,1,e),B(e),"B")),"A")); 118-(x
=*c++); (y=x/8%8,z=(x&199)-4 S 1 S 1 S 186 S 2 S 2 S 3 S 0,r=(y>5)*2+y,z=(x&
207)-1 S 2 S 6 S 2 S 182 S 4)?D(0)D(1)D(2)D(3)D(4)D(5)D(6)D(7)(z=x-2 C C C C
C C C C+129 S 6 S 4 S 6 S 8 S 8 S 6 S 2 S 2 S 12)?x/64-1?((0 O a(y)=a(x) O 9
[o]=a(5),8[o]=a(4) O 237==*c++?((int (*)())(2-*c++?fwrite:fread))(l+*k+1[k]*
256,128,1,(fseek(y=5[k]-1?u:v,((3[k]|4[k]<<8)<<7|2[k])<<7,Q=0),y)):0 O y=a(5
),z=a(4),a(5)=a(3),a(4)=a(2),a(3)=y,a(2)=z O c=l+d(5) O y=l[x=d(9)],z=l[++x]
,x[l]=a(4),l[--x]=a(5),a(5)=y,a(4)=z O 2-*c?Z||read(0,&Z,1),1&*c++?Q=Z,Z=0:(
Q=!!Z):(c++,Q=r=V?fgetc(V):-1,s=s&~1|r<0) O++c,write(1,&7[o],1) O z=c+2-l,w,
c=l+q O p,c=l+z O c=l+q O s^=1 O Q=q[l] O s|=1 O q[l]=Q O Q=~Q O a(5)=l[x=q]
,a(4)=l[++x] O s|=s&16|9<Q%16?Q+=6,16:0,z=s|=1&s|Q>159?Q+=96,1:0,y=Q,h(s<<8)
O l[x=q]=a(5),l[++x]=a(4) O x=Q%2,Q=Q/2+s%2*128,s=s&~1|x O Q=l[d(3)]O x=Q  /
128,Q=Q*2+s%2,s=s&~1|x O l[d(3)]=Q O s=s&~1|1&Q,Q=Q/2|Q<<7 O Q=l[d(1)]O s=~1
&s|Q>>7,Q=Q*2|Q>>7 O l[d(1)]=Q O m y n(0,-,7)y) O m z=0,y=Q|=x,h(y) O m z=0,
y=Q^=x,h(y) O m z=Q*2|2*x,y=Q&=x,h(y) O m Q n(s%2,-,7)y) O m Q n(0,-,7)y)  O
m Q n(s%2,+,7)y) O m Q n(0,+,7)y) O z=r-8?d(r+1):s|Q<<8,w O p,r-8?o[r+1]=z,r
[o]=z>>8:(s=~40&z|2,Q=z>>8) O r[o]--||--o[r-1]O a(5)=z=a(5)+r[o],a(4)=z=a(4)
+o[r-1]+z/256,s=~1&s|z>>8 O ++o[r+1]||r[o]++O o[r+1]=*c++,r[o]=*c++O z=c-l,w
,c=y*8+l O x=q,b z=c-l,w,c=l+x) O x=q,b c=l+x) O b p,c=l+z) O a(y)=*c++O r=y
,x=0,a(r)n(1,-,y)s<<8) O r=y,x=0,a(r)n(1,+,y)s<<8))));
system("stty cooked echo"); B((B((V?B(V):0,u)),v)); }

//print("Hello world")

Un esempio di JAPH :

@P=split//,".URRUU\c8R";@d=split//,"\nrekcah xinU / lreP rehtona tsuJ";sub p{
@p{"r$p","u$p"}=(P,P);pipe"r$p","u$p";++$p;($q*=2)+=$f=!fork;map{$P=$P[$f^ord
($p{$_})&6];$p{$_}=/ ^$P/ix?$P:close$_}keys%p}p;p;p;p;p;map{$p{$_}=~/^[P.]/&&
close$_}%p;wait until$?;map{/^r/&&<$_>}%p;$_=$d[$q];sleep rand(2)if/\S/;print

Questo visualizza lentamente il testo "Solo un altro hacker Perl / Unix", più caratteri alla volta, con ritardi.

Alcuni esempi di Python possono essere trovati nelle FAQ ufficiali sulla programmazione Python e altrove.

Vantaggi dell'offuscamento

Tempo di caricamento più veloce

Gli script utilizzati dalle pagine Web devono essere inviati in rete all'agente utente che li eseguirà. Più piccoli sono, più veloce è il download. In tali casi d'uso, la minimizzazione (una forma relativamente banale di offuscamento) può produrre vantaggi reali.

Utilizzo ridotto della memoria

Negli antichi linguaggi interpretati a runtime (più comunemente noti come script ), come le versioni precedenti di BASIC, i programmi venivano eseguiti più velocemente e richiedevano meno RAM se utilizzavano nomi di variabili con una sola lettera, evitavano commenti e contenevano solo caratteri vuoti necessari (in breve, il più corto il più veloce).

Protezione per i segreti commerciali

Laddove il codice sorgente di un programma debba essere inviato all'utente, ad esempio JavaScript in una pagina Web, qualsiasi segreto commerciale, meccanismo di licenza o altra proprietà intellettuale contenuta nel programma è accessibile all'utente. L'offuscamento rende più difficile comprendere il codice e apportarvi modifiche.

I programmi desktop a volte includono funzionalità che aiutano a offuscare il loro codice. Alcuni programmi potrebbero non memorizzare l'intero codice su disco e potrebbero estrarre una parte del codice binario tramite il Web in fase di esecuzione. Possono anche utilizzare la compressione e/o la crittografia, aggiungendo ulteriori passaggi al processo di disassemblaggio.

Prevenzione dell'elusione

L'offuscamento del programma può, in tali casi, rendere più difficile per gli utenti eludere i meccanismi di licenza o ottenere informazioni che il fornitore del programma desiderava nascondere. Può anche essere usato per rendere più difficile l'hacking dei giochi multiplayer.

Prevenzione del rilevamento di virus

I programmi dannosi possono utilizzare l'offuscamento per mascherare ciò che stanno realmente facendo. La maggior parte degli utenti non legge nemmeno tali programmi; e quelli che in genere hanno accesso a strumenti software che possono aiutarli a eliminare l'offuscamento, quindi questa strategia è di efficacia limitata.

Svantaggi dell'offuscamento

  • Sebbene l'offuscamento possa rendere la lettura, la scrittura e il reverse engineering di un programma difficile e dispendioso in termini di tempo, non necessariamente lo renderà impossibile.
  • Aggiunge tempo e complessità al processo di compilazione per gli sviluppatori.
  • Può rendere estremamente difficili i problemi di debug dopo che il software è stato offuscato.
  • Una volta che il codice diventa abbandonato e non viene più mantenuto, gli hobbisti potrebbero voler mantenere il programma, aggiungere mod o capirlo meglio. L'offuscamento rende difficile per gli utenti finali fare cose utili con il codice.
  • Alcuni tipi di offuscamento (cioè codice che non è solo un binario locale e scarica mini binari da un server web quando necessario) può ridurre le prestazioni e/o richiedere Internet.

decompilatori

Un decompilatore può decodificare il codice sorgente da un eseguibile o da una libreria. La decompilazione è talvolta chiamata attacco man-at-the-end, basato sul tradizionale attacco crittografico noto come " man-in-the-middle ". Mette il codice sorgente nelle mani dell'utente, sebbene questo codice sorgente sia spesso difficile da leggere. È probabile che il codice sorgente abbia funzioni casuali e nomi di variabili, tipi di variabili errati e utilizzi una logica diversa rispetto al codice sorgente originale (a causa delle ottimizzazioni del compilatore).

Offuscamento crittografico

Recentemente, i crittografi hanno esplorato l'idea di offuscare il codice in modo che il reverse engineering del codice sia crittograficamente difficile. Ciò si formalizza nelle tante proposte per l' offuscamento dell'indistinguibilità , una primitiva crittografica che, se possibile costruire in modo sicuro, consentirebbe di costruire molti altri tipi di crittografia, compresi tipi completamente nuovi che nessuno sa fare. (Una nozione più forte, l' offuscamento della scatola nera , si è dimostrata impossibile nel 2001 quando i ricercatori hanno costruito programmi che non possono essere offuscati in questa nozione.)

Notifica agli utenti del codice offuscato

Alcuni software antivirus, come AVG AntiVirus , avviseranno anche i propri utenti quando arrivano su un sito Web con codice offuscato manualmente, poiché uno degli scopi dell'offuscamento può essere quello di nascondere il codice dannoso. Tuttavia, alcuni sviluppatori potrebbero utilizzare l'offuscamento del codice allo scopo di ridurre le dimensioni del file o aumentare la sicurezza. L'utente medio potrebbe non aspettarsi che il proprio software antivirus fornisca avvisi su un pezzo di codice altrimenti innocuo, in particolare da società fidate, quindi tale funzionalità potrebbe effettivamente dissuadere gli utenti dall'utilizzo di software legittimo.

Alcuni browser principali come Firefox e Chrome non consentono anche le estensioni del browser contenenti codice offuscato.

Software di offuscamento

Esiste una varietà di strumenti per eseguire o assistere con l'offuscamento del codice. Questi includono strumenti di ricerca sperimentale creati da accademici, strumenti per hobbisti, prodotti commerciali scritti da professionisti e software open source . Esistono anche strumenti di deoffuscamento che tentano di eseguire la trasformazione inversa.

Sebbene la maggior parte delle soluzioni di offuscamento commerciali funzionino trasformando il codice sorgente del programma o il bytecode indipendente dalla piattaforma utilizzato da Java e .NET, ce ne sono anche alcune che funzionano direttamente su binari compilati.

Licenze di offuscamento e copyleft

Si è discusso se sia illegale aggirare le licenze software copyleft rilasciando il codice sorgente in forma offuscata, come nei casi in cui l'autore è meno disposto a rendere disponibile il codice sorgente. Il problema è affrontato nella GNU General Public License richiedendo la messa a disposizione del "modulo preferito per apportare modifiche". Il sito web di GNU afferma che "il 'codice sorgente' offuscato non è un vero codice sorgente e non conta come codice sorgente".

Guarda anche

Appunti

Riferimenti

link esterno