Your SlideShare is downloading. ×
0
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Attacchi alle applicazioni basati su buffer overflow
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Attacchi alle applicazioni basati su buffer overflow

679

Published on

Slides about attacks based on buffer overflows and defence techniques (IN ITALIAN)

Slides about attacks based on buffer overflows and defence techniques (IN ITALIAN)

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
679
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
10
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Università Degli Studi Di Catania Facoltà di Ingegneria Corso di Laurea di 2° Livello in Ingegneria InformaticaCorso di Sicurezza nei Sistemi InformativiGiacomo Antonino Fazio
  • 2. Cos’è il Buffer Overflow Il buffer overflow (spesso abbreviato in BOF) è una delletecniche più avanzate di hacking del software. Spesso si sente parlare di “exploit”, ossia metodi ad hoc cheutilizzano le vulnerabilità scoperte in questo o in quel software eche permettono all’utilizzatore di acquisire privilegi che non glispettano (ad esempio i tanto agognati privilegi di root) o diportare al “denial of service” del computer attaccato. Molti diquesti exploit utilizzano per i loro scopi buffer overflow. Il buffer overflow consiste nel fornire ad un programma più datidi quanti lo spazio di memoria ad essi assegnato ne possacontenere, facendo in modo che una parte di questi dati vadascritta in zone di memoria dove ci sono, o dovrebbero esserci,altri dati (da ciò il nome, che letteralmente significa “Traboccodell’area di memoria”).
  • 3. Cos’è il Buffer OverflowAd esempio, un programma definisce due variabili:una stringa A di 8 byte e un intero B di 2 byte. A è inizializzata con soli caratteri ‘0’ (ognuno deiquali occupa 1 byte, dunque sono 8 caratteri). B contiene il numero 3.
  • 4. Cos’è il Buffer Overflow Adesso supponiamo che sia previsto un inserimento della stringa A daparte dell’utente, ma che non si effettui un controllo sulla lunghezzadell’input inserito. Proviamo ad inserire una stringa più lunga di 8caratteri, ad esempio inseriamo “excessive”, che occuperà 9 caratteripiù il carattere di fine stringa. La porzione di memoria successiva, che era occupata da B, verràirrimediabilmente sovrascritta. Se si prova a leggere l’intero che ci dovrebbe essere in B, un sistemabig-endian che utilizza l’ASCII, leggerà ‘e’ seguita dallo ‘0’ come 25856. Se invece proviamo a scrivere una stringa ancora più lunga, essainvadere anche l’area di memoria che si trova dopo di B. Risultato:segmentation fault!!!
  • 5. Cos’è il Buffer OverflowUn programma è esposto a Buffer Overflow ealle conseguenze che esso può causare se:  prevede linput di dati di lunghezza variabile e non nota a priori;  li immagazzina entro buffer allocati nel suo spazio di memoria dati vicino ad altre strutture dati vitali per il programma stesso;  il programmatore non ha implementato alcun mezzo di controllo della correttezza dellinput inserito.
  • 6. Tipi di Buffer OverflowEsistono diversi modi per portare avanti unBOF. Tra i più importanti: Arithmetic overflow: si ha quando ilrisultato prodotto da un calcolo è più grandedelle spazio che dovrebbe contenerlo. Buffer Overflow basati sulla memoria:vengono distinti in base all’area di memoriache vanno a interessare. Quelli più diffusisono i buffer overflow “di heap” e “di stack”.
  • 7. Arithmetic Overflow Avviamo la calcolatrice di Windows scegliendo la modalitàscientifica dal menu, scriviamo ‘-1’ e premiamo su ‘Hex’.Vedremo così il valore esadecimale di -1, che è‘FFFFFFFFFFFFFFFF’. Adesso premiamo ‘Dec’. Ci aspetteremmo di rivedere il nostro ‘-1’, ma inveceotteniamo il valore ‘18446744073709551615’ e ciò è dovutoal fatto che la calcolatrice ha cambiato il valore da “signed” a“unsigned”.
  • 8. Struttura della memoria di un processoQuando eseguiamo un programma, esso verrà caricato inmemoria in maniera ben strutturata creando diverse zone:  .TEXT, che contiene il codice del programma in esecuzione ed è di sola lettura, infatti se si tentasse di scriverci sopra si incorrerebbe in un errore di Segmentation Fault;  zona dati, che contiene le variabili globali, sia inizializzate (contenute in una regione detta .DATA) che non inizializzate (contenute in una regione detta .BSS);  HEAP, generalmente posto dopo la zona dati, in cui vengono memorizzate le variabili allocate dinamicamente;  STACK, che contiene le variabili locali, gli argomenti delle funzioni, le informazioni di stato del chiamante (ad esempio il contenuto di alcuni registri della CPU), l’indirizzo di ritorno necessario per poter ritornare dalla funzione corrente e altre
  • 9. Struttura della memoria di un processo  Come si può vedere dalla figura, lo heap e lo stack crescono in maniera diversa: il primo cresce verso l’alto, il secondo verso il basso.  Lo stack è organizzato a pila, nel senso che l’ultimo dato inserito è il primo ad essere letto (LIFO, Last In First Out);  In Assembly esistono dei comandi (push e pop) che permettono rispettivamente di inserire e di prelevare valori in cima allo stack.  Man mano che i dati vengono scritti nello stack, esso cresce verso il basso, quindi va da indirizzi di memoria alti ad indirizzi di memoria bassi.
  • 10. E il processore?Anche il processore è interessato dall’esecuzione delprogramma, in particolare lo sono alcuni suoi registri,strettamente legati alla situazione della memoriadurante l’esecuzione:  EBP, che è il puntatore alla base dello stack e, nel caso stiamo eseguendo una funzione, punta alla base della porzione di stack utilizzata da essa;  ESP, tramite il quale possiamo scorrere tutto lo stack per inserire o prelevare dati da un punto ben preciso di esso;  EIP, che punta alla prossima istruzione che la CPU dovrà eseguire dopo quella corrente.
  • 11. Programma esemplificativoUna parte del programma disassemblato
  • 12. Programma esemplificativo Le prime tre istruzioni sono tre operazioni di push, che inserisconoi valori 2, 1 e 0 nello stack (in ordine inverso). Successivamente si ha una CALL, utilizzata per chiamare lafunzione example, infatti si salta all’indirizzo 00401234. Da notareche, ogni qualvolta bisogna fare una CALL, il processore salva ilvalore attuale di EIP nello stack e poi lo modifica per effettuare unsalto incondizionato alla funzione, in modo da poterlo ripristinare altermine di essa, per poter riprendere l’esecuzione dall’istruzionesuccessiva alla chiamata. All’interno della funzione, per prima cosa EBP viene salvato sullostack, in EBP viene memorizzato il valore di ESP (cioè l’inizio dellostack per la funzione) e poi viene sottratto a ESP lo spazionecessario per le variabili con una operazione di SUB. Le istruzionisuccessive riguardano l’allocazione e l’assegnazione delle variabili ie buffer, inserite nello stack seguendo come sempre la modalitàLIFO. Alla fine, mediante l’istruzione LEAVE, i registri EBP e ESPriacquisiscono i valori che avevano prima di chiamare la CALL e,mediante l’istruzione RET, si ritorna alla funzione principaleutilizzando l’indirizzo di ritorno presente nello stack.
  • 13. Buffer Overflow di StackQuesto tipo di BOF è quello in assoluto più diffuso einteressa lo stack. È necessario: Fare in modo che il codice sia nell’addressspace del programma . Si distinguono due casi:  Inserirlo manualmente (Code injection): il programma chiede in input una stringa, che verrà inserita dall’attaccante in modo da contenere il codice di attacco, sotto forma di istruzioni per la CPU.  Il codice si trova già lì: il codice che ci serve è già presente, bisogna solo parametrizzarlo a dovere.
  • 14. Buffer Overflow di Stack Fare in modo che il programma salti al codice di attacco e lo esegua :  Activation Records: si utilizza all’interno di una funzione e consiste nell’effettuare l’overflow di un buffer, con lo scopo di arrivare a sovrascrivere l’EIP con l’indirizzo del codice di attacco.  Puntatori a funzioni: si effettua l’overflow di un buffer vicino ad un puntatore, in modo da corrompere quest’ultimo e da farlo puntare alla locazione del codice di attacco.  Longjmp buffers: sfrutta un meccanismo presente in C che consente di salvare lo stato di un buffer mediante il comando setjmp(buffer) e di ripristinarlo in seguito mediante il comando longjmp(buffer). Se abbiamo un buffer adiacente di cui è possibile effettuare l’overflow, potremmo corrompere anche lo stato del buffer di checkpoint in modo che, non appena viene chiamato il comando longjmp, si salta alla locazione del codice di attacco. Spesso l’inserimento del codice di attacco e la sua esecuzione sono effettuati in unavolta sola, ma non necessariamente. Lo shellcode è un pezzo di codice macchina eseguito per sfruttare una vulnerabilità.Deve essere altamente specifico e verificato nei minimi dettagli.
  • 15. Esempio 1 di BOF di Stack Il programma non fa altro che chiamare la funzione example(), la quale alloca la variabile command con valore calc, che rappresenta il comando che vogliamo eseguire (la semplice calcolatrice di Windows). Successivamente viene allocata la variabile name, in cui vogliamo inserire un nome da dare allo script, cosa che viene fatta richiamando la funzione gets(). La restante parte serve per farci capire cosa sta succedendo in memoria, infatti ci mostra un’istantanea dello stack.
  • 16. Esempio 1 di BOF di StackSe come nome dello script inseriamo “hello”: Tutto ok Abbiamo inserito “hello” nella variabile name e poi abbiamo eseguito il contenuto di command, cioè “calc”.
  • 17. Esempio 1 di BOF di StackSe come nome dello script inseriamo “xxxxxxxxxxxxxxxxcmd ”: Buffer overflow e shell in locale!!! Abbiamo scritto al di là della variabile name, sovrascrivendo anche command che adesso contiene “cmd”
  • 18. Esempio 2 di BOF di Stack  Il programma prende una stringa in ingresso e la inserisce all’interno della variabile var, utilizzando la funzione strcpy(). La funzione function() non viene mai chiamata dal programma. Il nostro obiettivo sarà quello di causare un buffer overflow, inserendo in ingresso una stringa più lunga dei 10 caratteri a disposizione e di sostituire l’indirizzo di ritorno di main() con quello della funzione function(), in modo che essa venga eseguita.  Facendo un po’ di prove, ci accorgiamo che il programma va in segmentation fault non appena inseriamo 14 caratteri.  Se diamo in input 14 caratteri e l’indirizzo della funzione function() (che possiamo trovare disassemblando il codice)… il gioco è fatto!
  • 19. Esempio 2 di BOF di Stack Come fare a passargli l’indirizzo? Esso infatti è scritto in caratteri esadecimali e non ASCII. Scriviamo un piccolo exploit, che si occupa di convertire in ASCII e di passare al programma l’indirizzo da noi inserito in esadecimale.
  • 20. Buffer Overflow di HeapQuesto tipo di BOF è noto e sfruttato da molto tempo, ma se ne parlasempre meno di quello di stack, soprattutto perché è in genere più difficileda sfruttare rispetto a quest’ultimo. Esistono diverse tecniche per portarloavanti: Attacchi basati su malloc() e funzioni simili: per ogni variabile allocatadinamicamente, viene allocato uno spazio di lunghezza prestabilita ma senon ci sono controlli, è molto semplice scrivere oltre esso, sovrascrivendol’area adiacente occupata possibilmente da un’altra variabile. Attacchi basati sulla sovrascrittura di puntatori: si effettua l’overflow diun buffer adiacente ad un puntatore in modo da corrompere quest’ultimoe farlo puntare alla locazione del codice di attacco. Attacchi basati su puntatori a funzioni: si effettua l’overflow di un buffervicino ad un puntatore a funzione, in modo da corrompere quest’ultimo efarlo puntare alla funzione di attacco.
  • 21. Esempio di BOF di HeapIl programma appartiene all’utente root ma è impostato il bit SUID, checonsente a chiunque di eseguirlo con privilegi di root.In particolare, il programma alloca una parte di memoria nello heap e vi copiadentro lo shellcode. Subito dopo l’indirizzo di ritorno del main è sovrascrittodall’indirizzo dello shellcode, in modo che quando il main ritorna, fornisce unashell.
  • 22. Alla ricerca di Buffer Overflow Gli esempi finora visti sono scritti per puro scopo didattico,in quanto non troveremo in giro programmi così, pronti peressere sfruttati per accedere al sistema di turno. Chi attacca generalmente non prova a casaccio, analizza ilcodice del programma alla ricerca di vulnerabilità dasfruttare, o aspetta che sia qualcun altro a farlo. Quando si sa che la versione x del programma y è affettada una certa vulnerabilità, allora è il momento di crearel’exploit che permetta di utilizzarla. L’analisi del codice può essere fatta a diversi livelli:lessicale, semantico, basato su tecniche di intelligenzaartificiale, a runtime, reverse engineering, ricerca di bugspecifici, ecc.
  • 23. Blaster: un worm costruito su un BOF Rilevato l’11 Agosto 2003 sui primi computer, si diffuse amacchia d’olio nel giro di appena 2 giorni Infetta i computer con SO Microsoft Windows XP o 2000 L’obiettivo finale era colpire Microsoft, mediante un attaccoDDoS al sito di Windows Update. L’avversione nei confronti di Microsoft è dimostrata anchedalla stringa trovata nel codice del worm: “billy gates why doyou make this possible ? Stop making money and fix yoursoftware!!” Effetti: danni in tutto il mondo per oltre 3 milioni di dollari Colpevole: un ragazzo di 18 anni del Minnesota (USA)
  • 24. Blaster: un worm costruito su un BOF Blaster si sviluppa su una vulnerabilità descritta daMicrosoft stessa nel Microsoft Security Bulletin MS03-026.Si tratta di una falla nell’interfaccia RPC (RemoteProcedure Call) di un oggetto DCOM (DistributedComponent Object Model). DCOM: tecnologia che abilita componenti software chenon si trovano sulla stessa macchina a comunicaredirettamente utilizzando una rete; RPC: protocollo usato per la comunicazione e larichiesta di servizi tra le due parti di software, permettendoad un programma che gira su un certo computer dieseguire codice su un sistema remoto.
  • 25. Blaster: un worm costruito su un BOF Se la richiesta di comunicazione viene postaall’interfaccia RPC in modo errato, ci possono essereproblemi perché essa non controlla opportunamente ledimensioni dei messaggi ricevuti in input. Un malintenzionato potrebbe scrivere un exploit cheinvia all’oggetto DCOM un messaggio non corretto ecostruito in modo da causare un buffer overflow, che glipermetterebbe di avere il controllo completo sullamacchina. Per poter fare ciò, il malintenzionato deveutilizzare una tra le porte aperte per RPC, tra cui 135,139, 445 e 593. Blaster fa proprio questo!!!
  • 26. Blaster: un worm costruito su un BOFSupponiamo di avere un computer infetto. Il tutto si svolge in diverse fasi:  Attesa: A deve prima controllare di essere connesso ad Internet, mediante la funzione InternetGetConnectedState(). Se l’esito è positivo, si va alla fase 2  Generazione indirizzi IP: il programma genera gli indirizzi IP dei computer a cui lanciare il contagio. Effettua uno scan di essi alla ricerca di computer vulnerabili, tra cui supponiamo ci sia un ipotetico B.  Attacco al RPC: utilizzando la porta TCP 135, A invia pacchetti formulati in modo errato (ma costruiti ad hoc per ottenere l’effetto nefasto) al servizio RPC/DCOM di B che, essendo affetto dalla falla, non effettua controlli sulla lunghezza di essi. Risultato: buffer overflow!!!  Controllo del contagio: attraverso la porta 135, A controlla se B è già infetto e in caso affermativo termina; in caso negativo, invece, attiva i socket per comunicare con B.  La shell CMD.EXE: A questo punto, A lancia su B la shell tramite il comando cmd.exe, necessaria ad A per far eseguire a B dei comandi.  Download del worm: tramite la shell, B richiede ad A l’eseguibile msblast.exe, che scarica nella cartella %systemroot%/system32 (cartella di sistema). Il file appena scaricato viene lanciato.  Aggiornamento delle Registry Keys: utilizzando la shell lanciata nella fase 5, A apporta delle modifiche ad alcune Registry Keys di B, in modo che il worm venga eseguito ad ogni avvio del pc.
  • 27. Blaster: un worm costruito su un BOF Il worm è stato progettato affinchè i computer infettieffettuino un attacco DDoS in momenti ben precisi: ognigiorno (nel caso di mesi compresi tra Settembre eDicembre) e dal 16 del mese in poi per gli altri mesi. I sintomi che permettono di accorgersi della presenza diBlaster sul proprio sistema sono: prestazioni ridotte,continui riavvii, traffico irregolare sulle porte TCP 135 e4444 e UDP 69. Presenza di tool per l’eliminazione automatica del worm Rilevate ad oggi 4 varianti: Lovesan A, Lovesan B,Lovesan C e Lovesan F.
  • 28. Difesa contro i BOF e… nuovi attacchiDiverse tecniche sono state inventate per cercare di frenare il più possibile i bufferoverflow e nuovi attacchi sono stati messi a punto per bypassare esse. Difesa - scelta del linguaggio di programmazione: C e C++ nonforniscono la giusta protezione contro l’accesso e la sovrascrittura dei dati inmemoria (attraverso i puntatori è possibile praticamente spostarsi e scrivere inmemoria pressoché dovunque) e contro la scrittura in un array al di fuori dei suoiconfini (è il problema principale che causa il buffer overflow). Altri linguaggieffettuano controlli (es. Java, Python, Ada, Lisp). Difesa - Scrivere codice corretto: utopia! Per quanto si possa controllare ilproprio codice, i bug potrebbero risiedere nelle funzioni delle librerie utilizzate. Difesa – Attenzione ai programmi SUID: programmi che vanno inesecuzione con privilegi di root, chiunque sia ad eseguirli. Alcuni di essi sononecessari per effettuare operazioni comuni, altri non lo sono affatto o non vengonomai usati, ma possono rappresentare un problema, dato che possono esseresfruttati da un malintenzionato attraverso un buffer overflow, al termine del qualesi troverà con privilegi di root e quindi avrà il controllo della macchina.
  • 29. Difesa contro i BOF e… nuovi attacchi Difesa - uso di librerie “safe”: sostituiscono le funzioni “incriminate” di LibC(es. gets(), scanf(), printf(), ecc.) con versioni “safe” (in teoria) offrendo in alcunicasi una completa nuova implementazione delle stringhe. Es.: Libsafe The Better String Library Arri Buffer API Vstr Funzione strlcpy() Difesa – Protezione contro lo “stack smashing”: viene scritto nello stackun “canary”, cioè un valore noto sistemato tra un buffer e i dati di controllo. In caso dibuffer overflow, il canary viene sovrascritto, dunque al ritorno dalla funzione ci siaccorge dell’avvenuta manipolazione dello stack ed è possibile correre ai ripari. 3 tipi dicanaries: Terminator, Random e Random XOR canaries. Esempio di programmi cheimplementano questo tipo di protezione:  ProPolice  StackGuard  StackGhost
  • 30. Difesa contro i BOF e… nuovi attacchi Difesa – Protezione dello spazio eseguibile: protezioneimplementata sia a livello hardware che software. L’idea è quella di rendereparte della memoria non scrivibile o non eseguibile, in modo da evitare lamaggior parte dei BOF, ad esempio quelli basati sulla “code injection” (se lamemoria non è eseguibile, inserisco il codice di attacco ma non possoeseguirlo).  Soluzione hardware: NX bit  Soluzione software: DEP (Windows), W^X (OpenBSD), PaX (Linux), Exec Shield (Linux). Nuovo attacco – Gli attacchi “return-to-libc”: Lo scopo è quello disovrascrivere l’indirizzo di ritorno di una funzione non con quello dellalocazione di memoria dove si trova lo shellcode, bensì con quello di unafunzione di libC, spesso system(), magari passandogli come argomentoqualcosa come /bin/sh (che ci dà una shell in locale). In questo modo non ènecessario eseguire codice che si trova nello stack o nello heap, aggirandoquindi l’ostacolo rappresentato dalla protezione dello spazio eseguibile.
  • 31. Difesa contro i BOF e… nuovi attacchi Difesa – Address Space Layout Randomization (ASLR):l’idea di base è quella di organizzare alcune parti chiave dellamemoria di un processo (ad esempio stack, heap, librerie e partieseguibili) in maniera casuale nell’address space di un processo. Ciòrende difficili alcuni tipi di attacco, in particolare gli activation recordse i return-to-libc, a causa della difficoltà di trovare l’indirizzo del codiceda eseguire. Implementata anche in PaX e Exec Shield. Difesa – Deep Packet Inspection (DPI): consente diesaminare i pacchetti che transitano in una rete, confrontandoli con leinformazioni a disposizione presenti in un database e riguardantiattacchi conosciuti. Ciò permette di trovare gli eventuali pacchetti cheportano le tracce di un buffer overflow o di un altro tipo di attacco e dievitare che passino. Utile ma spesso poco efficace: previene solo gliattacchi conosciuti.
  • 32. Difesa contro i BOF e… nuovi attacchiDifesa – Intrusion Detection Systems (IDS): riconoscono i pacchetti chetransitano in rete e che mirano ad effettuare manipolazioni sui sistemi o attacchi controservizi vulnerabili e applicazioni. Sono composti da diverse parti:  Sensori: osservano gli eventi che avvengono sul sistema;  Analizzatori: analizzano gli eventi passati loro dai sensori;  Gestore: riceve gli eventi degni di nota dagli analizzatori e prende provvedimenti sia passivi che attivi. Nuovo attacco – Shellcode alfanumerici, polimorfici, metamorfici eautomodificanti: utilizzano tecniche spesso messe in pratica dai worm per non farsiscovare. In particolare:  Shellcode polimorfici: variano continuamente, lasciando immutato l’algoritmo originale. Spesso per ottenere ciò utilizzano la crittografia, lasciando però una parte non criptata che contiene le informazioni per decriptare il resto. Gli IDS mirano a riconoscere proprio questa parte, attraverso una scansione basata su pattern.  Shellcode metamorfici: ancora peggio di quelli polimorfici, con l’obiettivo di vanificare le scansioni degli IDS basate su pattern.
  • 33. Difesa contro i BOF e… nuovi attacchiConclusioni: La soluzione non esiste!!! Scrivere codice corretto è un’utopia, perché è facilesbagliare o commettere una leggerezza o utilizzare codicedi terzi che involontariamente contiene dei bug. È possibile comunque affrontare il problema, siautilizzando il buon senso, che mediante svariate tecnicheche si possono spesso combinare tra loro. Ricordare che se qualcuno lavora per produrre armi chepossano competere con le armi del nemico, il nemico nonsta con le mani in mano e nello stesso tempo lavora permigliorare le sue.

×