<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mind Unpacked &#187; Informatica</title>
	<atom:link href="http://mindunpacked.com/category/informatica/feed/" rel="self" type="application/rss+xml" />
	<link>http://mindunpacked.com</link>
	<description>informatica.elettronica.chimica.new stuff</description>
	<lastBuildDate>Tue, 22 Dec 2009 17:35:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<image>
<link>http://mindunpacked.com</link>
<url>http://mindunpacked.com/wp-content/plugins/maxblogpress-favicon/icons/favicon-2.ico</url>
<title>Mind Unpacked</title>
</image>
		<item>
		<title>Crittografia asimmetrica e algoritmo RSA. Parte II</title>
		<link>http://mindunpacked.com/2009/crittografia-asimmetrica-e-algoritmo-rsa-parte-ii/</link>
		<comments>http://mindunpacked.com/2009/crittografia-asimmetrica-e-algoritmo-rsa-parte-ii/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 17:33:29 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[chiave pubblica]]></category>
		<category><![CDATA[crittografia]]></category>
		<category><![CDATA[crittografia asimmetrica]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[RSA]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=468</guid>
		<description><![CDATA[In questa seconda parte dell&#8217;articolo vedremo come implementare l&#8217;algoritmo RSA di cui si era precedentemente discusso in quest&#8217;altro articolo solamente in linea teorica. Il linguaggio di programmazione usato sara&#8217; Java, poiche&#8217; fornisce nativamente una classe BigInteger per il supporto di numeri interi di   dimensione arbitraria, che useremo per manipolare gli enormi numeri primi [...]]]></description>
			<content:encoded><![CDATA[<p>In questa seconda parte dell&#8217;articolo vedremo come implementare l&#8217;<strong>algoritmo RSA</strong> di cui si era precedentemente discusso in <a href="http://mindunpacked.com/2009/crittografia-asimmetrica-e-algoritmo-rsa-parte-i/">quest&#8217;altro articolo</a> solamente in linea teorica. Il linguaggio di programmazione usato sara&#8217; <strong>Java</strong>, poiche&#8217; fornisce nativamente una classe BigInteger per il supporto di numeri interi di   dimensione arbitraria, che useremo per manipolare gli enormi numeri primi necessari alla generazione delle chiavi, impossibili da gestire con tipi di dati   primitivi. Non mi soffermero&#8217;, ovviamente, su questioni sintattiche relative al linguaggio; inoltre non commentero&#8217; tutto il codice ma solo le parti piu&#8217;   importanti, mentre potrete leggere il resto scaricando l&#8217;archivio in fondo all&#8217;articolo.  La prima funzione necessaria al funzionamento della classe e&#8217; quella relativa alla generazione delle chiavi. Come avevamo visto nel precedente articolo, per   generare le chiavi si segue una procedura standard che e&#8217; facilmente implementabile usando la classe BigInteger di Java.<br />
<span id="more-468"></span></p>
<pre class="brush: java;">
		BigInteger p = BigInteger.probablePrime(keyLength/2, new SecureRandom()); // Generiamo un numero &quot;probabilmente&quot; primo, p
		BigInteger q = BigInteger.probablePrime(keyLength/2, new SecureRandom()); // Generiamo un numero &quot;probabilmente&quot; primo, q

		// Calcoliamo n e phi
		BigInteger n = p.multiply(q);
		BigInteger phi = p.subtract(new BigInteger(&quot;1&quot;)).multiply(q.subtract(new BigInteger(&quot;1&quot;)));

		// publicKey conterra' l'esponente pubblico e,
		// scegliendo e come il primo numero primo successivo a
		// p, esso sara' anche coprimo con phi (come richiesto nell'algoritmo)
		this.publicKey = p.nextProbablePrime();
		this.privateKey = publicKey.modInverse(phi);
		this.n = n;
	}
</pre>
<p>Una precisazione sulla funzione probablePrime() e nextProbablePrime(): esse restituiscono un numero che <strong>probabilmente</strong> e&#8217; primo, utilizzando dei test di   probabilita&#8217; probabilistici. Il margine di errore e&#8217; molto basso: per essere precisi, la probabilita&#8217; che un numero restituito da queste due funzioni sia   composto e&#8217; sempre minore di 2^-100 e la velocita&#8217; dell&#8217;algoritmo lo rende preferibile ad uno deterministico nella generazione delle chiavi. Una volta generate le chiavi, si possono gia&#8217; creare le due funzioni di base per criptare/decriptare un numero intero. Ecco il codice:</p>
<pre class="brush: java;">
	public BigInteger encrypt(BigInteger m) {
		return m.modPow(publicKey, n); // (m^publicKey) % n
	}
	public BigInteger decrypt(BigInteger m) {
		return m.modPow(privateKey, n); // (m^privateKey) % n
	}
</pre>
<p>Dovrebbe essere abbastanza chiaro. La funzione modPow(e, n) restituisce semplicemente this ^ e % n e ci risparmia un po di calcoli. Con queste due semplici funzioni possiamo pero&#8217; criptare unicamente numeri interi; per poter usare l&#8217;algoritmo su un testo piu&#8217; o meno lungo dobbiamo creare   altre due funzioni che processano il testo in maniera tale da essere compatibile con l&#8217;algoritmo, i passi principali saranno questi:</p>
<ol>
<li> aggiungere del padding (casuale) al testo in modo da renderlo divisibile in blocchi di uguali dimensioni. la dimensione di ogni blocco sara&#8217; la   lunghezza della chiave.</li>
<li>processare ogni blocco, convertire il testo in un intero e cifrarlo</li>
</ol>
<p>Per il processo inverso, invece:</p>
<ol>
<li> dividere il testo nel numero di blocchi in base alla chiave.</li>
<li> decriptare ogni blocco e convertire gli interi nel testo corrispondente</li>
<li> rimuovere il padding.</li>
</ol>
<p>Ecco il codice con alcuni commenti esplicativi:</p>
<pre class="brush: java;">
	public String encrypt(String m) {
		/* Per comodita' (piu' sotto si vedra' perche') convertiamo i
		 * caratteri del messaggio nel loro codice ASCII (esadecimale)
		 */
		String mHex = &quot;&quot;;
		for (int i = 0; i &lt; m.length(); i++) {
			mHex += Integer.toHexString(m.charAt(i));
		}

		/* Calcoliamo quanto padding e' necessario, chiamiamolo N, e poi concateniamo al messaggio
		 * N-1 bytes di padding casuale. L'ultimo non deve essere casuale ma deve contenere appunto
		 * il numero N, cosi' da poter poi rimuovere la giusta quantita di padding nella funzione decrypt().
		 */
		int padding = blockSize - (mHex.length()/2)%blockSize;
		for (int i = 0; i &lt; padding-1; i++) { // Prima generiamo N-1 byte casuali
			int randomPadding = (int)(10*Math.random());
			mHex += randomPadding &lt; 10 ? &quot;0&quot; + Integer.toHexString(randomPadding) : Integer.toHexString(randomPadding);
		}
		// Ultimo byte di padding
		mHex += padding &lt; 10 ? &quot;0&quot; + Integer.toHexString(padding) : Integer.toHexString(padding);

		int numBlocks = (mHex.length()/2)/blockSize; // Numero di blocchi in cui dividere il messaggio

		String result = &quot;&quot;, currentBlock = &quot;&quot;;
		for (int b = 0; b &lt; numBlocks; b++) {
			currentBlock = mHex.substring(b*blockSize*2, (b+1)*blockSize*2);

			/* Il blocco corrente, essendo una stringa in formato esadecimale,
			 * quindi un numero, puo' essere criptato con le due funzioni che abbiamo gia'
			 * creato precedentemente che accettano come argomento un BigInteger.
			 */
			// Questo costruttore accetta una stringa, e la base come secondo argomento
			BigInteger r = encrypt(new BigInteger(currentBlock, 16)); 

			/* Puo' accadere che la string che otteniamo come risultato abbia un byte in meno,
			 * in questo caso, per non avere problemi nel decriptare il messaggio, aggiungiamo
			 * uno zero iniziale che non cambia niente, ma la rende della dimensione corretta.
			 */
			if (r.toString(16).length() == blockSize*4) {
				result += r.toString(16);
			} else {
				result += (&quot;0&quot; + r.toString(16));
			}
		}
		return result;
	}

	public String decrypt(String m) {
		int numBlocks = (m.length()/2)/(blockSize*2);

		String temp = &quot;&quot;, currentBlock = &quot;&quot;;
		/* Questo ciclo, quasi uguale a quello della funzione encrypt(), scorre ogni
		 * blocco, lo decripta e concatena il risultato in una nuova stringa.
		 */
		for (int b = 0; b &lt; numBlocks; b++) {
			currentBlock = m.substring(b*blockSize*4, (b+1)*blockSize*4);
			BigInteger r = decrypt(new BigInteger(currentBlock, 16));
			temp += r.toString(16);
		}

		/* Il padding e' uguale all'ultimo byte della
		 * stringa, come avevamo precedentemente impostato.
		 */
		int padding = Integer.parseInt(temp.substring(temp.length()-2), 16);
		int actualLength = temp.length() - padding*2;

		// Rimuove il padding
		temp = temp.substring(0, actualLength);

		String result = &quot;&quot;;
		// Riconverte la stringa da esadecimale a testo
		for (int i = 0; i &lt; temp.length(); i+=2) {
			result += (char)Integer.parseInt(temp.substring(i,i+2), 16);
		}
		return result;
	}
</pre>
<p>Tutto il codice e&#8217; contenuto in <a href="http://www.mindunpacked.com/risorse/RSA.zip">questo archivio</a> disponibile per il download.</p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2009/crittografia-asimmetrica-e-algoritmo-rsa-parte-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Crittografia asimmetrica e algoritmo RSA. Parte I</title>
		<link>http://mindunpacked.com/2009/crittografia-asimmetrica-e-algoritmo-rsa-parte-i/</link>
		<comments>http://mindunpacked.com/2009/crittografia-asimmetrica-e-algoritmo-rsa-parte-i/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 14:47:42 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[chiave pubblica]]></category>
		<category><![CDATA[crittografia]]></category>
		<category><![CDATA[crittografia asimmetrica]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[RSA]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=451</guid>
		<description><![CDATA[La crittografia asimmetrica, o crittografia a chiave pubblica, e&#8217; un particolare tipo di crittografia nel quale vengono utilizzate, al posto della singola chiave privata utilizzata nella crittografia simmetrica, una coppia di chiavi di cui una pubblica (per cifrare il messaggio) ed una privata (per decifrarlo).

Uno dei problemi principali da risolvere quando si utilizza la crittografia [...]]]></description>
			<content:encoded><![CDATA[<p>La <strong>crittografia asimmetrica</strong>, o crittografia <strong>a chiave pubblica</strong>, e&#8217; un particolare tipo di crittografia nel quale vengono utilizzate, al posto della singola chiave privata utilizzata nella crittografia simmetrica, una coppia di chiavi di cui una pubblica (per cifrare il messaggio) ed una privata (per decifrarlo).<br />
<span id="more-451"></span><br />
Uno dei problemi principali da risolvere quando si utilizza la crittografia simmetrica e&#8217; infatti quello dello <strong>scambio della chiave</strong>: utilizzando la stessa chiave per cifrare e decifrare il messaggio, le parti comunicanti devono in qualche modo entrare in contatto prima di scambiarsi il messaggio proprio per scambiare la chiave con cui, successivamente, operare. In pratica, bisogna trovare un canale sicuro per comunicarsi la chiave, altrimenti esiste sempre il rischio che essa possa essere carpita dall&#8217;esterno.</p>
<p>L&#8217;idea di base della <strong>crittografia a chiave pubblica</strong> serve proprio a porre fine a questo inconveniente e a rendere non piu&#8217; necessaria una comunicazione preliminare (e sicura) tra le parti per scambiarsi una chiave. In un algoritmo a chiave asimmetrica vengono infatti create due chiavi anziche&#8217; una: quella pubblica verra&#8217; usata da chi vuole cifrare un messaggio da inviare al possessore di quella chiave, quella privata verra&#8217; utilizzata dallo stesso per decifrare il messaggio ricevuto. La chiave pubblica di ognuno viene, insomma, resa disponibile a chiunque voglia inviargli un messaggio, che sara&#8217; poi decifrabile solamente usando la chiave privata, tenuta segreta.</p>
<p>Chiaramente le due chiavi devono essere correlate in qualche modo per avere la proprieta&#8217; sopra descritta, e cioe&#8217; che si possa crittografare un testo con una chiave (quella pubblica) e decriptarlo con un&#8217;altra (quella privata) ottenendo lo stesso testo di partenza. In particolare, esistendo questa relazione tra le chiavi bisogna evitare che dalla chiave pubblica, che tutti possono leggere, si possa risalire a quella privata. Bisogna cioe&#8217; trovare un modo per generarla che sia facile da percorrere in un verso (cioe&#8217; generare la chiave), ma che sia quasi impossibile da percorrere nell&#8217;altro, cioe&#8217; trovare i dati usati per generarla partendo dalla chiave pubblica (altrimenti, una volta ottenuti i dati, si potrebbe generare la chiave privata ad essa associata).</p>
<p>I primi ad inventare un tale sistema furono W. <strong>Diffie</strong> e M. <strong>Hellman</strong> nel 1976, ma fu nel &#8216;77 che Rivest, Shamir e Adleman, tutti studenti del MIT, realizzarono uno degli algoritmi a chiave pubblica piu&#8217; utilizzato al giorno d&#8217;oggi e che prende il nome di RSA. La sicurezza dell&#8217;<strong>algoritmo RSA</strong> si basa sulla difficolta&#8217; di fattorizzare in tempi accettabili il prodotto di due grandi numeri primi: infatti, mentre e&#8217; facilissimo calcolare il prodotto di questi due numeri, non esiste un algoritmo che possa fattorizzarlo velocemente. Nel resto di questo articolo vedremo a grandi linee come opera l&#8217;algoritmo RSA mentre nella seconda parte vedremo un&#8217;implementazione in Java.</p>
<p>In linea generale possiamo distinguere tre &#8220;fasi&#8221; dell&#8217;algoritmo: generazione delle chiavi, criptaggio, decriptaggio (si, lo so che suonano malissimo).</p>
<p><strong>Generazione delle chiavi</strong></p>
<ol>
<li>Si generano due grandi numeri primi <em>p</em>, <em>q</em> tali che il loro prodotto <em>n = pq</em> ha la lunghezza in bit che desideriamo.</li>
<li>Si calcola <em>n = pq</em>, e <em>phi = (p-1)(q-1)</em></li>
<li>Si sceglie un intero positvo <em>e</em> &lt; <em>phi</em> e coprimo con phi (cioe&#8217; MCD(e, phi) = 1)</li>
<li>Si calcola un intero positivo <em>d &lt; phi</em> tale che<span> <em>ed</em> <em>≡ 1 (mod phi)</em></span></li>
<li><span>La coppia (n, e) forma la chiave pubblica, la coppia (n, d) quella privata.</span></li>
</ol>
<p><strong>Criptaggio</strong><br />
Per criptare un messaggio si ottiene la chiave pubblica del destinatario e, dopo aver trasformato il messaggio di testo in un numero intero, si utilizza la formula <em>c = m<sup>e</sup> mod n</em>, dove m e&#8217; il messaggio.</p>
<p><strong>Decriptaggio</strong><br />
Partendo dal testo criptato si usa la formula <em>m = c<sup>d</sup> mod n, </em>dove c e&#8217; il testo cifrato.</p>
<p>L&#8217;unico modo per decriptare un messaggio, come e&#8217; evidente dall&#8217;algoritmo, e&#8217; quello di essere a conoscenza dell&#8217;esponente segreto <em>d</em> e del modulo, <em>n. </em>Mentre l&#8217;esponente e&#8217; segreto, il modulo e&#8217; pubblico poiche&#8217; e&#8217; utilizzato anche per criptare il messaggio:<em> </em>ad ogni modo, per risalire a <em>d</em>, che permetterebbe di accedere al contenuto del messaggio, abbiamo bisogno non di <em>n</em>, ma di <em>p</em> e <em>q</em>, i due grandi numeri primi usati per generarlo. Se i numeri primi sono abbastanza grandi, e&#8217; impossibile fattorizzare <em>n</em> in tempi accettabili con gli algoritmi attuali.</p>
<p>In questo articolo non abbiamo visto una prova teorica del funzionamento dell&#8217;RSA e cioe&#8217; una prova del fatto che criptando un messaggio con la chiave pubblica e decriptandolo con la chiave privata si ottiene sempre di nuovo il messaggio in chiaro, ma potete trovare una dimostrazione (in inglese) a questo link: <a title="RSA Proof" href="http://www.di-mgt.com.au/rsa_theory.pdf" target="_blank">http://www.di-mgt.com.au/rsa_theory.pdf</a>. Per comprenderla sono necessarie nozioni (non troppo avanzate) di teoria dei numeri.</p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2009/crittografia-asimmetrica-e-algoritmo-rsa-parte-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DeCSS e i numeri primi illegali</title>
		<link>http://mindunpacked.com/2009/decss-e-i-numeri-primi-illegali/</link>
		<comments>http://mindunpacked.com/2009/decss-e-i-numeri-primi-illegali/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 14:57:14 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[decss]]></category>
		<category><![CDATA[numeri primi]]></category>
		<category><![CDATA[numeri primi illegali]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=407</guid>
		<description><![CDATA[Che un numero primo (ma anche un numero e basta) possa essere considerato illegale e&#8217; assurdo, ed effettivamente non esiste nessuna norma che miri a rendere illegale il possesso di alcuni numeri. Qualche anno fa si e&#8217; pero&#8217; verificata una curiosa coincidenza (intenzionale) quando un matematico di nome Phil Carmody scopri&#8217; un numero primo che [...]]]></description>
			<content:encoded><![CDATA[<p>Che un <strong>numero primo</strong> (ma anche un numero e basta) possa essere considerato <strong>illegale</strong> e&#8217; assurdo, ed effettivamente non esiste nessuna norma che miri a rendere illegale il possesso di alcuni numeri. Qualche anno fa si e&#8217; pero&#8217; verificata una curiosa coincidenza (intenzionale) quando un matematico di nome Phil Carmody scopri&#8217; un numero primo che rappresentava la versione compressa con gzip di un noto programma usato per bypassare il sistema di protezione CSS dei DVD, DeCSS. Ma partiamo dall&#8217;inizio&#8230;<br />
<span id="more-407"></span><br />
<strong>DeCSS</strong> e&#8217; un programma rilasciato nell&#8217;Ottobre 1999 da un gruppo di tre persone di cui due rimangono ancora anonime. John Lec Johansen, che si era occupato della creazione dell&#8217;interfaccia grafica, e&#8217; l&#8217;unico membro noto di questo gruppo, ed ovviamente e&#8217; stato anche l&#8217;unico a subire le conseguenze legali della pubblicazione su internet di DeCSS. Dopo vari processi iniziati nel 2000, nel 2004 Joahansen viene assolto a il suo caso viene chiuso. Tra il 2000 e il 2004 per protestare contro le leggi che impedivano la pubblicazione di codice sorgente di programmi come DeCSS, nacquero nuovi metodi piu&#8217; o meno originali per diffonderne il codice sorgente, attraverso immagini steganografate, <a title="DeCSS Haiku" href="http://www-2.cs.cmu.edu/~dst/DeCSS/Gallery/decss-haiku.txt">poemi haiku</a>, codice stampato sulle magliette o&#8230; numeri primi illegali.<br />
<center><script type="text/javascript">
heyos_ad_user = 11334;
heyos_ad_type = "G";
heyos_ad_format = "1";
heyos_color_border = "23292b";
heyos_color_bg = "23292b";
heyos_color_link = "FFFFFF";
heyos_color_text = "21b8ca";
heyos_color_url = "21b8ca";
</script>
<script type="text/javascript" src="http://admaster.heyos.com/core/bnr.js"></script></center></p>
<p>Per <strong>Phil Carmody</strong> l&#8217;idea che del codice sorgente potesse essere intrinsecamente illegale era assolutamente bizarra, e cosi&#8217; si mise a cercare un modo di rappresentare il codice di <strong>DeCSS</strong> che non potesse essere in alcun modo considerato illegale. Il sito che attualmente si trova a <a title="Prime Numbers Archive" href="http://primes.utm.edu/">questo indirizzo</a> archiviava, e archivia ancora, i numeri primi che hanno particolari proprieta&#8217;. Cosi&#8217;, armatosi di molta pazienza e di vari tool per lavorare sui numeri primi (come test di primalita&#8217; probabilistici o deterministici), riusci&#8217; a trovare un <strong>numero primo</strong> abbastanza lungo (1901 cifre) da meritare di essere archiviato sul sito, anche perche&#8217; rientrava nella top 20 dei numeri primi testati con l&#8217;algoritmo ECPP. Tra l&#8217;altro, visto che gzip ignora i caratteri dopo uno zero binario alla fine di un file compresso, dovrebbero in realta&#8217; esistere infiniti numeri primi che rappresentano la stessa cosa, cioe&#8217; il codice compresso di DeCSS.</p>
<p>Dopo qualche mese, Phil Carmody e&#8217; anche riuscito a trovare un numero primo che rappresenta un eseguibile valido in ambiente Linux e che offre le stesse funzionalita di DeCSS. Se volete qualche dettaglio piu&#8217; tecnico sulla ricerca di questi due numeri primi potete visitare <a title="Illegal prime 1" href="http://www.asdf.org/~fatphil/maths/illegal1.html" target="_blank">questa</a> e <a title="Illegal prime 2" href="http://www.asdf.org/~fatphil/maths/illegal.html" target="_blank">questa pagina</a>. Se non vi fidate sul fatto che quel numero primo corrisponda esattamente ad un archivio che genera il codice di DeCSS vi lascio questo programma in Perl (non scritto da me, ma opera di un certo Jamie McCarthy) che prende il numero primo da una pagina web, crea un archivio gzip ed estrae il codice:</p>
<pre class="brush: perl;">
#!/usr/bin/perl
use LWP::Simple;
use Math::BigInt;
my $html = get(&quot;http://www.utm.edu/research/primes/curios/48565...29443.html&quot;);
my($prime) = $html =~ m{&lt;blockquote&gt;([^&lt;]+)&lt;/blockquote&gt;};
$prime =~ s{\D+}{};
$prime = Math::BigInt-&gt;;new($prime);
my $binary = '';
while ($prime &gt; 0) {
$binary = pack(&quot;N&quot;, ($prime % 2**32)) . $binary;
$prime /= 2**32;
}
$binary =~ s{^\0+}{};
open(my $fh, &quot;| gunzip -c 2&gt;/dev/null&quot;) or die &quot;cannot gunzip, $!&quot;;
print $fh $binary;
close $fh;
</pre>
<p>Sulla pagina inglese di Wikipedia dedicata ai <a href="http://en.wikipedia.org/wiki/Illegal_prime">numeri primi illegali</a> trovate anche i due numeri (quello del file gzip e quello del file eseguibile) che ho omesso in questo articolo. Alla prossima.</p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2009/decss-e-i-numeri-primi-illegali/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Robocode: guerre tra robot in Java</title>
		<link>http://mindunpacked.com/2009/robocode-guerre-tra-robot-in-java/</link>
		<comments>http://mindunpacked.com/2009/robocode-guerre-tra-robot-in-java/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 19:48:56 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[crobots]]></category>
		<category><![CDATA[Intelligenza artificiale]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[robocode]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=378</guid>
		<description><![CDATA[Molti di voi probabilmente conosceranno o avranno sentito parlare di CRobots, il gioco di programmazione in cui gli sfidanti devono creare, usando un sottoinsieme delle istruzioni del linguaggio C, un robot che distrugga tutti gli altri robot (creati da altri programmatori) presenti nell&#8217;arena. Bene, Robocode e&#8217; un gioco molto simile ma con alcune differenze: i [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Molti di voi probabilmente conosceranno o avranno sentito parlare di <strong>CRobots</strong>, il gioco di programmazione in cui gli sfidanti devono creare, usando un sottoinsieme delle istruzioni del linguaggio C, un robot che distrugga tutti gli altri robot (creati da altri programmatori) presenti nell&#8217;arena. Bene, <strong>Robocode</strong> e&#8217; un gioco molto simile ma con alcune differenze: i robot si scrivono in Java e non ci sono limiti alla fantasia del programmatore come avveniva in CRobots (perche&#8217; usava solo un set limitato di istruzioni) rendendo possibile creare anche robot dalla complessa intelligenza artificiale!<br />
<span id="more-378"></span><br />
Sul <a href="http://robocode.sourceforge.net">sito ufficiale</a> di <strong>Robocode</strong> trovate molte info e l&#8217;installer in Java. Vediamo subito come creare il nostro primo robot dopo aver effettuato l&#8217;installazione. Subito dopo aver aperto Robocode, aprite il menu Robot e cliccate su Editor; si aprira&#8217; una nuova finestra, cioe&#8217; l&#8217;editor tramite il quale possiamo programmare i nostri robot. Cliccate su File-&gt;New-&gt;Robot. Battezzate la vostra creature e scegliete un nome o una sigla caratteristica per tutti i vostri robot (il programma crea una cartella contenente tutti i robot che creerete usando come nome la seconda sigla che inserite).</p>
<p style="text-align: justify;">Quello che vedete ora nell&#8217;editor e&#8217; il codice di base per un robot molto semplice che non fa altro che muoversi avanti e indietro e girare il suo cannone di 360 gradi, sparando quando vede un nemico. Ma analizziamo piu&#8217; da vicino il codice:</p>
<pre class="brush: java;">
public class MURobot extends Robot {
</pre>
<p>Creiamo una classe che eredita tutti gli attributi e i metodi dalla classe di base Robot.</p>
<pre class="brush: java;">
	/* Qui possiamo dichiarare tutte le variabili utilizzate dal nostro robot,
	 * in questo caso non ne abbiamo.
	 */
	public void run() {
		while(true) {
			ahead(100);
			turnGunRight(360);
			back(100);
			turnGunRight(360);
		}
	}
</pre>
<p style="text-align: justify;">Dopo aver dichiarato le eventuali variabili utilizzate all&#8217;interno della classe, vediamo il metodo run(). Questo metodo viene chiamato ogni qualvolta inizia la battaglia. All&#8217;interno di run() si trova quasi sempre un ciclo infinito: se l&#8217;esecuzione di run() termina, infatti, il nostro robot non fara&#8217; altro che stare fermo e sparare ai robot che rientrano nel suo campo visivo. Se dobbiamo svolgere delle azioni particolari, come il posizionamento in una particolare zona della mappa, conviene inserirle prima di entrare nel ciclo infinito.<br />
All&#8217;interno del ciclo il robot si muove in avanti (ahead(100)) fa un giro completo del cannone, torna indietro, fa lo stesso giro e cosi&#8217; finche&#8217; non viene distrutto o distrugge tutti i robot nell&#8217;arena.</p>
<p style="text-align: justify;">
<pre class="brush: java;">
	public void onScannedRobot(ScannedRobotEvent e) {
		fire(1);
	}
</pre>
<p><center><script type="text/javascript">
heyos_ad_user = 11334;
heyos_ad_type = "G";
heyos_ad_format = "1";
heyos_color_border = "23292b";
heyos_color_bg = "23292b";
heyos_color_link = "FFFFFF";
heyos_color_text = "21b8ca";
heyos_color_url = "21b8ca";
</script>
<script type="text/javascript" src="http://admaster.heyos.com/core/bnr.js"></script></center><br />
Il metodo onScannedRobot() e&#8217; uno dei tanti metodi per gestire gli eventi forniti di default. Questo metodo viene automaticamente eseguito quando un robot nemico rientra nel campo visivo del nostro: in questo caso l&#8217;azione e&#8217; di sparare. L&#8217;oggetto e (sta per event) passato come argomento contiene informazioni utili come la direzione del proiettile, la distanza da noi, etc&#8230; non utilizzate nel nostro caso. Potete consultare la documentazione sulle API di Robocode che e&#8217; molto esaustiva a riguardo.</p>
<pre class="brush: java;">
	public void onHitByBullet(HitByBulletEvent e) {
		turnLeft(90 - e.getBearing());
	}
}
</pre>
<p style="text-align: justify;">L&#8217;ultimo metodo viene chiamato quando il nostro robot viene colpito da un proiettile: per evitare di essere colpiti di nuovo il robot si gira nella direzione perpendicolare al proiettile e quindi si sposta grazie alle istruzioni all&#8217;interno del metodo run(). Il metodo getBearing() restituisce l&#8217;angolo tra la direzione in cui ci stiamo muovendo e la direzione del proiettile ed e&#8217; sempre compreso tra -180 e 180, ed e&#8217; uno dei tanti metodi di cui vi parlavo in precedenza.</p>
<p style="text-align: justify;">Se provate a iniziare una battaglia tra questo robot e altri leggermente piu&#8217; avanzati presenti gia&#8217; di default, vi accorgerete che le sue prestazioni non sono proprio ottimali, di fatto perdera&#8217; la maggior parte delle battaglie se non tutte (ovviamente dipende contro chi lo fate combattere), ma e&#8217; comunque un inizio. Il metodo migliore per realizzare robot sempre piu&#8217; avanzati e&#8217; cominciare da subito a crearne: ricordate anche che avendo abbastanza padronanza con Java non ci sono limiti a quello che si puo&#8217; realizzare!</p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2009/robocode-guerre-tra-robot-in-java/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Matrici e filtri di convoluzione</title>
		<link>http://mindunpacked.com/2009/matrici-e-filtri-di-convoluzione/</link>
		<comments>http://mindunpacked.com/2009/matrici-e-filtri-di-convoluzione/#comments</comments>
		<pubDate>Sat, 10 Jan 2009 17:23:34 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[filtri convoluzione]]></category>
		<category><![CDATA[image processing]]></category>
		<category><![CDATA[matrici convoluzione]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=310</guid>
		<description><![CDATA[Per matrice di convoluzione si intende una matrice che viene applicata ad un&#8217;immagine per ottenere una seconda immagine con caratteristiche particolari. I filtri di convoluzione sono appunto quei filtri, presenti in quasi tutti i programmi di grafica, che modificano l&#8217;immagine imprimendogli alcuni effetti come per esempio la sfocatura (blur), una maggiore definizione (sharpen), etc&#8230; quasi [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Per <strong>matrice di convoluzion</strong>e si intende una matrice che viene applicata ad un&#8217;immagine per ottenere una seconda immagine con caratteristiche particolari. I <strong>filtri di convoluzione</strong> sono appunto quei filtri, presenti in quasi tutti i programmi di grafica, che modificano l&#8217;immagine imprimendogli alcuni effetti come per esempio la sfocatura (blur), una maggiore definizione (sharpen), etc&#8230; quasi tutti questi filtri fanno uso di matrici di convoluzione, e vedremo come creare un semplice programma in C++ che, data un&#8217;immagine in input ed una matrice di convoluzione produca l&#8217;immagine di output.</p>
<p style="text-align: justify"><span id="more-310"></span> Sebbene le matrici di convoluzione, chiamate anche &#8220;<strong>kerne</strong><strong>l</strong>&#8220;, possano essere di qualsiasi dimensione, le piu&#8217; usate sono quelle 5&#215;5 e <strong>3x</strong><strong>3</strong>. In questo articolo prenderemo in considerazione solo le seconde, che sono sufficienti a creare una grande varieta&#8217; di effetti. La matrice va applicata separatamente ad ogni canale dell&#8217;immagine (R, G, B) nel seguente modo. Supponiamo di operare esclusivamente sul canale R, visto che le operazioni sono analoghe agli altri canali, e di avere pixel con i valori indicati nella matrice a sinistra a cui vogliamo applicare la matrice di convoluzione presente a destra:</p>
<table style="text-align: center;" border="0">
<tbody>
<tr>
<td>
<table style="text-align: center;" border="0">
<tbody>
<tr>
<td>255</td>
<td>180</td>
<td>100</td>
</tr>
<tr>
<td>125</td>
<td><span style="color: #ff0000;">175</span></td>
<td>150</td>
</tr>
<tr>
<td>0</td>
<td>123</td>
<td>20</td>
</tr>
</tbody>
</table>
</td>
<td>
<table border="0">
<tbody>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>Il pixel evidenziato in rosso e&#8217; quello su cui stiamo lavorando in questo momento, mentre la matrice a destra e&#8217; il nostro kernel. Per applicare il filtro di convoluzione sul pixel dobbiamo immaginare di sovrapporre l&#8217;elemento centrale della matrice kernel con il pixel che stiamo considerando e di fare la somma di tutti i prodotti degli elementi sovrapposti. In poche parole dobbiamo moltiplicare gli elementi corrispondenti tra le due matrici e sommare tutti i risultati. Notate che non stiamo effettuando una normale moltiplicazione tra matrici (cioe&#8217; un prodotto riga per colonna)!</p>
<p style="text-align: justify">Nel nostro caso il calcolo e&#8217;:</p>
<p style="text-align: justify">255*0 + 180*0 + 100*0 + 125*0 + 175*1 + 150*0 + 0*0 + 123*0 + 20*0 == 175</p>
<p style="text-align: justify">La matrice di convoluzione che abbiamo scelto, potrebbe essere paragonata alla matrice identita&#8217; nel caso di un prodotto tra matrici. Come la matrice identita&#8217; non cambia il risultato, cosi&#8217; questa matrice  fornisce come risultato lo stesso pixel e quindi l&#8217;immagine di output rimane invariata. Ovviamente questo e&#8217; un caso particolare, e alla fine dell&#8217;articolo vedremo alcuni degli effetti prodotti da altre matrici particolari.</p>
<p style="text-align: justify">Comunque, quando la matrice di convoluzione viene applicata a tutti i pixel dell&#8217;immagine il lavoro e&#8217; terminato ed abbiamo ottenuto la nostra immagine modificata. Vediamo alcune parti del codice in C++ che trovate allegato alla fine dell&#8217;articolo. Ah, il codice fa uso, come al solito, delle librerie EasyBMP per la gestione delle BMP.</p>
<pre class="brush: cpp;">int mat[DIM][DIM];

typedef struct pixel {
	int red, green, blue;
};
</pre>
<p><!--adsense--></p>
<p style="text-align: justify">Creiamo una matrice DIMxDIM (dove DIM = 3 nel nostro caso), che sara&#8217; la nostra matrice di convoluzione, e creiamo un nostro tipo per descrivere i pixels. Dopo aver fatto inserire all&#8217;utente i 9 valori degli elementi della matrice, possiamo iniziare i calcoli. Nelle righe 38-56 (non le scrivo qua perche&#8217; vengono formattate male) svolgiamo i calcoli veri e propri. Gli indici i e j sono le coordinate x e y del pixel che stiamo esaminando; notate che escludiamo i pixel appartenenti al bordo esterno dell&#8217;immagine semplicemente perche&#8217; non hanno 8 pixel confinanti come tutti gli altri, e quindi verrebbe piu&#8217; difficile applicare la matrice perche&#8217; dovremmo escludere alcuni pixel dal conteggio; il risultato non cambia di molto.</p>
<p style="text-align: justify">I nuovi valori dei pixel vengono salvati in un array di oggetti pixel (il typedef che abbiamo definito poco piu&#8217; su). Quello che ci manca è riportare questi valori in un intervallo 0&#8230;255. Sappiamo infatti che 255 e&#8217; il valore massimo per ogni componente di un pixel, ma dall&#8217;applicazione del nostro filtro, potremmo avere (e&#8217; spesso e&#8217; cosi&#8217;) valori che superano questa soglia. Per fare cio&#8217; calcoliamo la somma di tutti gli elementi della matrice di convoluzione e dividiamo tutti i valori di output per questa somma. Se dopo questa operazione ci saranno ulteriori valori &gt; 255, li imposteremo uguali a 255, cosi&#8217; come imposteremo a 0 quelli &lt; 0.</p>
<p style="text-align: justify">Vediamo un esempio:</p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.mindunpacked.com/risorse/2.bmp"><img class="alignnone" title="Immagine originale" src="http://www.mindunpacked.com/risorse/2_th.bmp" alt="" width="200" height="183" /></a></td>
<td>
<p style="text-align: center">MATRICE DI CONVOLUZIONE</p>
<p style="text-align: center">0 -1  0</p>
<p style="text-align: center">-1  4  -1</p>
<p style="text-align: center">0  -1  0</p>
</td>
<td><a href="http://www.mindunpacked.com/risorse/out.bmp"><img class="alignnone" title="Risultato" src="http://www.mindunpacked.com/risorse/out_th.bmp" alt="" width="200" height="183" /></a></td>
</tr>
</tbody>
</table>
<p style="text-align: justify">In questo esempio, e&#8217; stata applicata all&#8217;immagine una matrice per individuare i bordi (edge detection). Le immagini sono piuttosto pesanti essendo BMP e quindi non compresse.</p>
<p style="text-align: justify">Su Internet si trovano facilmente altre matrici di convoluzione associate a risultati particolari. Ecco il <a title="Codice C++ matrici di convoluzione" href="http://www.mindunpacked.com/risorse/matrix.zip" target="_self">codice del programma</a>. Alla prossima.</p>
<p style="text-align: justify">
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2009/matrici-e-filtri-di-convoluzione/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Buffer overflow: Windows</title>
		<link>http://mindunpacked.com/2009/buffer-overflow-windows/</link>
		<comments>http://mindunpacked.com/2009/buffer-overflow-windows/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 14:16:01 +0000</pubDate>
		<dc:creator>Marco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[arwin]]></category>
		<category><![CDATA[Buffer overflow]]></category>
		<category><![CDATA[exploit]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=352</guid>
		<description><![CDATA[Nella parte introduttiva sull&#8217;overflow mi sembra di aver spiegato abbastanza chiaramente i fondamenti di questo tipo di errore, quasi un incubo per i programmatori. In questo articolo vedremo come sfruttare la suddetta vulnerabilità in ambiente Windows.
Il primo overflow
Passo subito alla pratica, proprio perché nel precedente articolo ho già trattato la parte teorica. Vediamo quindi un [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Nella <a href="http://mindunpacked.com/2008/il-buffer-overflow-introduzione/">parte introduttiva sull&#8217;overflow</a> mi sembra di aver spiegato abbastanza chiaramente i fondamenti di questo tipo di errore, quasi un incubo per i programmatori. In questo articolo vedremo come sfruttare la suddetta vulnerabilità in ambiente Windows.<span id="more-352"></span></p>
<p><strong>Il primo overflow</strong></p>
<p style="text-align: justify;">Passo subito alla pratica, proprio perché nel precedente articolo ho già trattato la parte teorica. Vediamo quindi un semplice programma vulnerabile all&#8217;overflow dello stack:</p>
<pre class="brush: cpp;">
#include
int main(int argc, char **argv) {
char buf[20];  //inizializzo un buffer di 20 bytes
FILE* f=NULL;
int i=0;
printf(&quot;\nTest BOF&quot;);
f=fopen(&quot;input.txt&quot;,&quot;rb&quot;); //apro il file...

while(!feof(f)) { //...e comincio a leggerne il contenuto
buf[i]=fgetc(f); //salvo i byte nel buffer
i++;
}
fclose(f); //chiudo il file
}
</pre>
<p style="text-align: justify;">Si tratta di un esempio tipico di buffer overflow, dovuto all&#8217;uso incauto di un buffer nella lettura da file. Se infatti il file contiene dati per più di 20 bytes il programma andrà in crash, visualizzando il classico avviso di Windows.</p>
<p><a href="http://mindunpacked.com/wp-content/uploads/2009/01/avviso.gif"><img class="aligncenter size-medium wp-image-353" title="Crash del programma" src="http://mindunpacked.com/wp-content/uploads/2009/01/avviso.gif" alt="Crash del programma" width="454" height="229" /></a></p>
<p style="text-align: justify;">Il codice, infatti, non fa altro che leggere un carattere alla volta dal file input.txt fino alla fine per poi copiarlo nella variabile buf. Naturalmente, poiché non c&#8217;è nessun controllo sulla dimensione del file, basta superare il limite del buffer per provocare la condizione di overflow. Nell&#8217;esempio, per far crashare il programma, ho inserito di proposito una stringa di 28 bytes (AAAABBBBCCCCDDDDEEEEFFFFGGGG) dove “FFFFGGGG” sono i byte eccedenti. Ma dove finiscono questi dati? Come detto la scorsa volta i dati che causano il traboccamento del buffer vanno a sovrascrivere lo stack della memoria. In questo caso, se si usa un debugger per visionare lo stato della memoria al momento dell&#8217;overflow, si noterà che il registro EIP ha assunto il valore 0&#215;47474747 e quello EBP il valore 0&#215;46464646, che rispettivamente equivalgono – in esadecimale – ai caratteri GGGG e FFFF.</p>
<p><!--adsense--></p>
<p><strong>Primi passi verso l&#8217;exploit</strong></p>
<p style="text-align: justify;">Modificare il registro EIP significa, in parole povere, riuscire a modificare l&#8217;esecuzione del programma, dirigendolo in una qualsiasi zona a nostro piacere. Una volta chiarito questo punto possiamo iniziare a progettare un exploit in grado di sfruttare l&#8217;overflow individuato per prendere il controllo del programma. Si procede studiando l&#8217;esecuzione del programma fino alla condizione di overflow, passo dopo passo, grazie ad un debugger. Vediamo ora la prima parte del programma. Dovete comunque tenere conto che se disassemblate un eseguibile da voi compilato l&#8217;output potrebbe differire dal mio, ciò è dovuto dalla differenza del compilatore, od anche da una versione diversa dello stesso:</p>
<pre class="brush: cpp;">
00401000 push ebp //salva EBP nello stack
00401001 mov ebp,esp
00401003 sub esp,1Ch //riserva spazio per buffer
00401006 mov dword ptr [ebp-18h],0 //variabile FILE* f
0040100D mov dword ptr [ebp-1Ch],0 //variabile int i
</pre>
<p style="margin-bottom: 0cm; text-align: justify;">Questa parte iniziale di codice viene generata dal compilatore e si “preoccupa” di riservare spazio nello stack utile per allocare buf (0&#215;1C byte) e le altre variabili. Sono riportati i valori dei registri dello stack ESP e EPB prima e dopo l&#8217;esecuzione delle istruzioni. Successivamente il programma esegue la stampa a video con printf() della stringa “Test BOF”. In linguaggio assembly i prametri di una funzione vengono passati mediante salvataggio nello stack: prima della chiamata a printf() troviamo infatti un&#8217;istruzione PUSH che memorizza nello stack l&#8217;offset della stringa di testo.</p>
<pre class="brush: cpp;">
00401014 push 407030h //offset stringa  “\nTest”
00401019 call 00401114 //printf()
0040101E add esp,4
...
</pre>
<p style="margin-bottom: 0cm;">Analizziamo ora il ciclo while che legge fino alla fine del file i byte memorizzandoli nella variabile buf:</p>
<pre class="brush: cpp;">
00401033 mov dword ptr [ebp-18h], eax
00401036 mov eax, dword ptr [ebp-18h]
00401039 mov eax, dword ptr [eax-0Ch]
0040103C and ecx,10h
0040103F test ecx,ecx //test di fine file (EOF)
00401041 jne 00401061
00401043 mov edx, dword ptr [ebp-18h]
00401046 push edx
00401047 call 004010C7 //lettura da file fgetc()
0040104C add esp,4
0040104F mov ecx, dword ptr [ebp-1Ch]
00401052 mov byte ptr [ebp+ecx-14h],al //memorizza il byte in buf
00401056 mov edx, dword ptr [ebp-1Ch]
00401059 add edx,1 //incremento variabile i (i++)
0040105C mov dword ptr [ebp-1Ch],edx
0040105F jmp 00401036
</pre>
<p style="margin-bottom: 0cm;">
<p style="margin-bottom: 0cm; text-align: justify;">l&#8217;istruzione alla riga 12 è quella che scrive nel buffer il dato letto da file mediante fget(). L&#8217;indirizzo del buffer è dato da [EBP+ECX-14h]; il valore vinere incrementato ad ogni iterazione grazie al registro ECX. E&#8217; tuttavia la parte finale del programma, quella che segue immediatamente all&#8217;istruzione fclose(), la più interessante: viene ripristinato il valore del registro EBP e per chiudere la procedura si esegue un&#8217;istruzione di ritorno RET. Tale istruzione ha l&#8217;effetto di estrarre una word (32 bit) dallo stack e di memorizzare in eip, modificando l&#8217;indirizzo dell&#8217;istruzione corrente e spostando così il flusso di esecuzione del programma. E&#8217; in questo momento che emergono i problemi dell&#8217;overflow e il programma raggiunge una condizione indefinita. Il ciclo while infatti, non si accorge di scrivere nel buffer più dati di quelli previsti (28 contro 20) e di conseguenza inizia a scrivere sopra lo stack alterando i valori in esso memorizzati.</p>
<pre class="brush: cpp;">
00401061 mov eax, dword ptr [ebp-18h]
00401064 push eax
00401065 call 00401071
0040106A add esp,4
0040106D mov esp,ebp
0040106F pop ebp //ripristina EBP
00401070 ret //istruzione di ritorno
</pre>
<p style="margin-bottom: 0cm; text-align: justify;">Tutto ciò si traduce con un errore che scatta nel momento in cui si eseguono le istruzioni POP e RET: i valori estratti dallo stack non sono quelli corretti, ma sono diventati parte dei dati letti da input; infatti, nel momento in cui si verifica il crash, ci si accorge che i registri EBP e EIP contengono i valori 0&#215;46464646 e 0&#215;47474747, che corrispondono proprio ai caratteri in eccedenza nel file input.txt (rispettivamente le stringe “FFFF” e “GGGG”).<br />
Vediamo ora com&#8217;è possibile creare un exploit capace di sfruttare l&#8217;overflow del programma di esempio. Si è visto come sia possibile controllare l&#8217;andamento del programma fornendo input in eccedenza, ma è possibile andare oltre: se nell&#8217;input invece di fornire stringhe di testo, memorizziamo istruzioni assembly a nostro piacimento, possiamo iniettare il nostro codice direttamente nello stack affidato al programma e quindi modificare l&#8217;andamento del flusso d&#8217;esecuzione, dirottando il registro EIP nel punto in cui si trova il codice iniettato. L&#8217;unica difficoltà di questa fase è il calcolo degli indirizzi e degli offset di allineamento, che dovranno combaciare perfettamente per far sì che il programma ad un certo punto esegua le nostre istruzioni; analizzando la stringa di overflow ci si accorge che il valore GGGG pilota il registro EIP. La struttura dell&#8217;exploit prevede, quindi, un input di questa forma: in testa possiamo sfruttare i primi 20 byte del buffer per memorizzare il codice che vogliamo far eseguire, aiutandoci con eventuali istruzioni NOP (istruzione assembly che corrisponde a no-operation, quindi ininfluente) per allineare il codice esattamente alla dimensione di 20 byte. Seguono due word da 32 bit che corrispondono ai valori scritti dall&#8217;overflow nei registri EBP e EIP; infine, poiché per questo exploit ho pensto di visualizzare una semplice stringa di testo, memorizzeremo nella parte finale dell&#8217;input quest&#8217;ultima, terminata da 0.</p>
<table border="1" cellspacing="0" cellpadding="4" width="100%" bordercolor="#000000">
<col width="60"></col>
<col width="38"></col>
<col width="51"></col>
<col width="51"></col>
<col width="57"></col>
<tbody>
<tr valign="top">
<td width="23%">
<p align="center"><strong>Codice 			iniettato</strong></p>
</td>
<td width="15%">
<p align="center"><strong>NOP 			(0&#215;90)</strong></p>
</td>
<td width="20%">
<p align="center"><strong>EBP</strong></p>
</td>
<td width="20%">
<p align="center"><strong>EIP</strong></p>
</td>
<td width="22%">
<p align="center"><strong>String\0</strong></p>
</td>
</tr>
<tr valign="top">
<td width="23%">0&#8230;</td>
<td width="15%">
<p align="right">&#8230;20</p>
</td>
<td width="20%">
<p align="center">1 			word (4byte)</p>
</td>
<td width="20%">1 			word (4byte)</td>
<td width="22%">“Exploit 			works”</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 0cm; text-align: justify;">Il registro EIP servirà per dirottare il flusso del programma verso l&#8217;inizio del codice da noi iniettato. Analizzando col debugger l&#8217;esecuzione del programma, si nota che il valore di EBP prima dell&#8217;overflow è 0&#215;0012FF80, mentre lo stack usato per memorizzare i dati inizia all&#8217;offset 0&#215;0012FF6C, che sarà proprio il punto in cui partirà il codice iniettato. Conosciamo quindi i valori delle word di EBP e di EIP, non resta che scrivere il codice da ineittare.<br />
Come ho accennato prima, descriverò un exploit di esempio che non frà altro che stampare a schermo una stringa di testo. E&#8217; ovvio che ci si può spingere oltre e creare i cosiddetti shellcode, ovvero del codice assembly in grado di aprire una shell sul sistema vittima, solitamente con privilegi da amministratore. Alla fine di questo articolo accennerò alla costruzione di uno shellcode, ma un argomento del genere andrebbe approfondito non poco, e richiederebbe un articolo a parte.</p>
<p style="margin-bottom: 0cm; text-align: justify;">Ritornando all&#8217;exploit, per stampare del testo abbiamo bisogno di conoscere l&#8217;offset in cui risiede la stringa e l&#8217;indirizzo  di printf(), che come si è visto prima, è localizzata a 0&#215;00401114. Il codice assembly da iniettare sarà il seguente, per un totale di 3+5+5=13 byte.</p>
<p style="margin-bottom: 0cm;">
<table border="1" cellspacing="0" cellpadding="4" width="408" bordercolor="#000000">
<col width="188"></col>
<col width="202"></col>
<tbody>
<tr valign="top">
<td width="188"><strong><span style="font-family: Courier New;">OPCODES</span></strong></td>
<td width="202"><strong><span style="font-family: Courier New;">ISTRUZIONE</span></strong></td>
</tr>
<tr valign="top">
<td width="188"><span style="font-family: Courier New;">83 EC 20</span></td>
<td width="202"><span style="font-family: Courier New;">SUB ESP, 0&#215;20</span></td>
</tr>
<tr valign="top">
<td width="188"><span style="font-family: Courier New;">68 x1 x2 x3 x4</span></td>
<td width="202"><span style="font-family: Courier New;">PUSH offset(stringa)</span></td>
</tr>
<tr valign="top">
<td width="188"><span style="font-family: Courier New;">E8 y1 y2 y3 y4</span></td>
<td width="202"><span style="font-family: Courier New;">CALL printf()</span></td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 0cm;">
<p style="text-align: justify;">Per raggiungere  i 20 bytes richiesti dall&#8217;overflow, si aggiungono 7 istruzioni NOP alla fine del codice. Gli opcodes sono i codici esadecimali che corrispondono univocamente alle istruzioni assembly; ad esempio 83 EC identifica l&#8217;istruzione SUB ESP, che seguita dal valore 0&#215;20, sottrae 20 byte dal registro EBP. Non rimane che calcolare i valori “x1 x2 x3 x4” e “y1 y2 y3 y4” della PUSH e della CALL. L&#8217;offset della stringa di testo si calcola partendo dall&#8217;indirizzo iniziale del nostro buffer (dove inizia il codice, 0&#215;0012FF6C) a cui si aggiungono i 28 byte del buffer, ottenendo 0&#215;0012FF88. Per calcolare il valore di  y1 y2 y3 y4 occorre invece partire dall&#8217;indirizzo della funzione printf() 0&#215;00401114 a cui bisogna sottrarre l&#8217;offset in cui si trova l&#8217;istruzione CALL, che è dato da 0&#215;0012FF6C+3+5+5 = 0&#215;0012FF79. Quindi otteniamo il valore di 0&#215;002D119B. In definitiva:</p>
<table border="1" cellspacing="0" cellpadding="4" width="455" bordercolor="#000000">
<col width="220"></col>
<col width="217"></col>
<tbody>
<tr valign="top">
<td width="220"><strong><span style="font-family: Courier New;"><span style="font-size: small;">OPCODES</span></span></strong></td>
<td width="217"><strong><span style="font-family: Courier New;"><span style="font-size: small;">S</span></span><span style="font-family: Courier New;"><span style="font-size: small;">I</span></span><span style="font-family: Courier New;"><span style="font-size: small;">TRUZIONE</span></span></strong></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">83 EC 20</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">SUB ESP, 0&#215;20</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">68 88 FF 12 00</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">PUSH 0&#215;0012FF88</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">E8 9B 11 2D 00</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">CALL 0&#215;002D119B</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">90</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">NOP</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">90</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">NOP</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">90</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">NOP</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">90</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">NOP</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">90</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">NOP</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">90</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">NOP</span></span></td>
</tr>
<tr valign="top">
<td width="220"><span style="font-family: Courier New;"><span style="font-size: small;">90</span></span></td>
<td width="217"><span style="font-family: Courier New;"><span style="font-size: small;">NOP</span></span></td>
</tr>
</tbody>
</table>
<p style="text-align: justify;">Va specificato che gli indirizzi e gli offset delle istruzioni assembly vanno scritti al contrario, cioè leggendoli da destra verso sinistra. Per creare un file di input di fatto in questo modo basta ricorrere ad un <a href="http://mindunpacked.com/risorse/file_gen.cpp">semplice programma in c++</a> che unisca vari pezzi dell&#8217;exploit scrivendoli su di un unico file “input.txt”. Usando il file così generato come input per il programma mostrato ad inizio articolo, l&#8217;exploit prenderà il controllo del programma visualizzando la stringa “Exploit works”. In ogni caso, al termine della funzione printf() il programma si trova in un punto indefinito, e quindi andrà in crash comunque. Ciò si può evitare aggiungendo una chiamata ad una funzione come exit().</p>
<p><strong>Windows Shellcoding</strong></p>
<p style="text-align: justify;">Non approfondirò questo argomento, sarebbe troppo lungo e andrebbe aldilà dello scopo di questi articoli. Scrivere degli shellcode è complesso, e non cambia solo da sistema a sistema ma addirittura a seconda delle diverse versioni dello stesso. In generale uno shellcode dovrebbe aprire una shell sul sistema vittima, ma può essere usato per richiamare qualsiasi funzione di sistema approfittando dei privilegi del programma vulnerabile al buffer overflow. La difficoltà di scrivere shellcode universali è appunto dovuto al fatto che gli indirizzi delle varie funzioni cambiano a seconda del sistema. In windows è possibile risalire a tali indirizzi con un <a href="http://mindunpacked.com/risorse/arwin.c">comodo programma di nome arwin</a>. Esso permette di estrapolare l&#8217;indirizzo di una funzione presente in una determinata libreria di sistema (DLL).</p>
<p>C:\&gt;arwin kernel32.dll GetProcAddressarwin<br />
- win32 address resolution program &#8211; by steve hanna &#8211; v.01<br />
GetProcAddress is located at <strong>0&#215;77e7b332</strong> in kernel32.dll</p>
<p style="text-align: justify;">In questo caso siamo riusciti a capire l&#8217;indirizzo della funzione GetProcAddres, che fra l&#8217;altro è molto utile per risalire a qualsiasi altra API di sistema. Il codice da iniettare dovrà essere scritto usando gli indirizzi così ricavati, avrete quindi capito che  con uno shellcode si può fare qualsiasi cosa, capacità di programmazione assembly permettendo. <img src='http://mindunpacked.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2009/buffer-overflow-windows/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Reti neurali attraverso algoritmi genetici in C++. Parte VI</title>
		<link>http://mindunpacked.com/2008/reti-neurali-attraverso-algoritmi-genetici-in-c-parte-vi-ultima/</link>
		<comments>http://mindunpacked.com/2008/reti-neurali-attraverso-algoritmi-genetici-in-c-parte-vi-ultima/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 17:57:53 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Intelligenza artificiale]]></category>
		<category><![CDATA[Reti neurali]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=345</guid>
		<description><![CDATA[Applicazioni.
Le reti neurali hanno diverse applicazioni e spaziano in diversi campi. In questo paragrafo elencherò alcune applicazioni interessanti che ho trovato sulla rete e poi mostrerò come è possibile creare un molto rudimentale sistema di riconoscimento dii  immagini, capace di riconoscere i numeri da 0 a 9.

Alcune applicazioni sono:
Vita artificiale: la vita artificiale tenta [...]]]></description>
			<content:encoded><![CDATA[<p align="center"><strong>Applicazioni.</strong></p>
<p align="justify">Le reti neurali hanno diverse applicazioni e spaziano in diversi campi. In questo paragrafo elencherò alcune applicazioni interessanti che ho trovato sulla rete e poi mostrerò come è possibile creare un molto rudimentale sistema di riconoscimento dii  immagini, capace di riconoscere i numeri da 0 a 9.</p>
<p><span id="more-345"></span></p>
<p align="justify">Alcune applicazioni sono:</p>
<p align="justify">Vita artificiale: la vita artificiale tenta di simulare l&#8217;evoluzione di organismi viventi tramite computer. Spesso gli organismi sono dotati di reti neurali per svolgere i loro compiti come trovare fonti di cibo, muoversi, etc&#8230;</p>
<p align="justify">Finanza: prevedere l&#8217;andamento dei mercati.</p>
<p align="justify">Riconoscimento di forme, immagini, facce, etc&#8230;</p>
<p align="justify">Quello che noi creeremo è un sistema molto rudimentale di riconoscimento delle immagini, di fatto potra riconoscere solo quelle immagini che gli abbiamo presentato nel training set e non sarà probabilmente in grado di riconoscerle se gli è stato modificato anche solamente qualche pixel. E&#8217; solo un esempio di base per mostrare cosa si può fare, ed anche in maniera abbastanza semplice. Le immagini che la nostra rete neurale sarà capace di riconoscere avranno dimensioni fisse (5&#215;7 pixels) e saranno simili a questa:</p>
<div id="attachment_346" class="wp-caption aligncenter" style="width: 108px"><a href="http://mindunpacked.com/wp-content/uploads/2008/12/1.png"><img class="size-medium wp-image-346" title="1" src="http://mindunpacked.com/wp-content/uploads/2008/12/1.png" alt="Immagine di esempio" width="98" height="138" /></a><p class="wp-caption-text">Immagine di esempio</p></div>
<p align="justify">
<p align="justify">
<p align="justify">
<p align="justify">I quadratini con il bordo nero sono semplicemente i pixel dell&#8217;immagine. Avendo questa immagine 7&#215;5 = 35 pixel in totale, la nostra rete neurale dovrà avere 35 neuroni di input, uno per ogni pixel. Per semplicità l&#8217;input potrà essere o 1 o 0, dove 1 simboleggia il colore rosso della precedente immagine e 0 lo sfondo. Così facendo si ottiene una matrice che rappresenta l&#8217;immagine, che nel caso di quella appena vista sarebbe questa:</p>
<p align="justify">
<p align="center">0 0 1 0 0</p>
<p align="center">0 1 1 0 0</p>
<p align="center">0 0 1 0 0</p>
<p align="center">0 0 1 0 0</p>
<p align="center">0 0 1 0 0</p>
<p align="center">0 0 1 0 0</p>
<p align="center">0 1 1 1 0</p>
<p align="center">
<p align="justify">Nell&#8217;allenamento della nostra rete, noi daremo un solo esempio per ogni numero, ma volendo potremmo dare più esempi diversi che rappresentano diversi modi di scrivere il numero 1 e così la nostra rete avrebbe una capacità più alta di riconoscere caratteri diversi (chiaramente l&#8217;allenamento sarà più lungo).</p>
<p align="justify">Per la nostra rete neurale creeremo noi il training set direttamente su un file di testo o altrimenti, essendo la rete neurale capace di riceve in input solo dei numeri, dovremmo creare un programma che data in input un&#8217;immagine crei la matrice numerica associata ad essa, ma siccome il nostro training set sarà molto piccolo le creeremo manualmente. Ogni riga dovrà contenere la rappresentazione di un numero, di conseguenza non avremo matrici nel file di input ma le righe saranno affiancate. Il file di input risulta così:</p>
<p align="justify">
<p style="text-align: center;">0 0 1 0 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 0 0</p>
<p style="text-align: center;">0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 1 0</p>
<p style="text-align: center;">0 0 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 1 1 1 1</p>
<p style="text-align: center;">0 0 1 1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 1 0 0 1 0 0 1 1 0</p>
<p style="text-align: center;">0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 1 0 1 1 1 1 1 0 0 0 1 0 0 0 0 1 0</p>
<p style="text-align: center;">0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0</p>
<p style="text-align: center;">0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 1 1 0 0 0 1 0 1 1 1 0</p>
<p style="text-align: center;">0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 0 0</p>
<p style="text-align: center;">0 1 1 1 0 1 0 0 0 1 1 0 0 0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 0 1 0 1 1 1 0</p>
<p style="text-align: center;">0 1 1 1 0 1 0 0 0 1 1 0 0 0 1 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0</p>
<p style="text-align: center;">
<p align="justify">Se spezzate ogni riga in parti composte da 5 elementi riottenete la matrice che rapresenta il numero.</p>
<p align="justify">Il file di output avrà tante righe quante quelle del file di input e sarà il seguente:</p>
<p align="justify">
<p style="text-align: center;">1 0 0 0 0 0 0 0 0 0</p>
<p style="text-align: center;">0 1 0 0 0 0 0 0 0 0</p>
<p style="text-align: center;">0 0 1 0 0 0 0 0 0 0</p>
<p style="text-align: center;">0 0 0 1 0 0 0 0 0 0</p>
<p style="text-align: center;">0 0 0 0 1 0 0 0 0 0</p>
<p style="text-align: center;">0 0 0 0 0 1 0 0 0 0</p>
<p style="text-align: center;">0 0 0 0 0 0 1 0 0 0</p>
<p style="text-align: center;">0 0 0 0 0 0 0 1 0 0</p>
<p style="text-align: center;">0 0 0 0 0 0 0 0 1 0</p>
<p style="text-align: center;">0 0 0 0 0 0 0 0 0 1</p>
<p><!--adsense--></p>
<p align="justify">I neuroni di output saranno 10 ed ognuno è associato ad un numero. Con il numero 0 il primo neurone emette un segnale mentre gli altri no, con il numero 1 il secondo neurone emette un segnale mentre gli altri no, etc&#8230; di conseguenza ci aspettiamo che dopo l&#8217;addestramento, quando passiamo in input, per esempio il numero 9 soltanto l&#8217;ultimo neurone si attiverà. Il codice è il seguente:</p>
<pre class="brush: cpp;">
#include &lt;iostream&gt;
#include &lt;fstream&gt;
#include &lt;sstream&gt;
#include &lt;vector&gt;
#include &lt;ctime&gt;
#include &lt;cmath&gt;

using namespace std;

#include &quot;Misc.hpp
#include &quot;GenAlg.hpp&quot;
#include &quot;NeuralNet.hpp&quot;
#include &quot;NNController.hpp&quot;

int main() {
NNController NC(35, 10, 1, 10);
NC.loadTrainingSet(&quot;input&quot;, &quot;output&quot;);
NC.train();
NC.saveWeights(&quot;img.txt&quot;);
cout &lt;&lt; &quot;*** La rete e' allenata ***&quot; &lt;&lt; endl;
}
</pre>
<p align="justify">Come vedete, abbiamo creato 35 neuroni di input, 10 di output ed un livello nacosto con 10 neuroni.</p>
<p align="center"><strong>LINKS</strong></p>
<p align="justify"><a href="http://www.ai-junkie.com/ann/evolved/nnt1.html">http://www.ai-junkie.com/ann/evolved/nnt1.html</a> &#8211; Questo tutorial in Inglese sulle reti neurali è uno dei migliori che abbia mai letto, tant&#8217;è che ne ho preso spunto per scrivere questo. Vengono usati anche lì gli algoritmi genetici per aggiornare la rete e troverete delle somiglianze anche nelle classi del codice (però vi assicuro che il codice per questo tutorial l&#8217;ho scritto da zero <img src='http://mindunpacked.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://www.ai-junkie.com/ga/intro/gat1.html">http://www.ai-junkie.com/ga/intro/gat1.html</a> &#8211; Tutorial sugli algoritmi genetici, sempre in Inglese.</p>
<p><a href="http://blacklight.gotdns.org/wiki/index.php/Introduzione_ai_sistemi_fuzzy_e_alle_reti_neurali">http://blacklight.gotdns.org/wiki/index.php/Introduzione_ai_sistemi_fuzzy_e_alle_reti_neurali</a> &#8211; Implementazione di una rete neurale error back propagation in C, tutorial in Italiano.</p>
<p align="justify"><a href="http://www.aitalk.net/">http://www.aitalk.net</a> &#8211; Forum sull&#8217;intelligenza artificiale in lingua Inglese. Contiene anche una piccola sezione in lingua Italiana.</p>
<p>Ho anche realizzato la stessa guida in formato PDF: trovate <a href="http://www.mindunpacked.com/risorse/TutorialRetiNeurali.tar.gz">QUI</a> un archivio contenente tutti i file sorgente di cui abbiamo parlato e la guida in formato PDF (un po meglio impaginata e con qualche illustrazione in piu&#8217;).<br />
Alla prossi</p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2008/reti-neurali-attraverso-algoritmi-genetici-in-c-parte-vi-ultima/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Steganografia in C++</title>
		<link>http://mindunpacked.com/2008/steganografia-in-c/</link>
		<comments>http://mindunpacked.com/2008/steganografia-in-c/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 19:13:21 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[LSB]]></category>
		<category><![CDATA[Steganografia]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=321</guid>
		<description><![CDATA[Su Mind Unpacked abbiamo gia&#8217; parlato di steganografia digitale in due precedenti articoli (Introduzione alla steganografia digitale e Algoritmi steganografici), oggi percio&#8217; discuteremo di un&#8217;implementazione in C++ dell&#8217;algoritmo LSB. L&#8217;algoritmo e&#8217; gia&#8217; stato trattato dal punto di vista teorico nei precedenti articoli, quindi non mi soffermero&#8217; piu&#8217; di tanto su di esso e passero&#8217; quasi [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify">Su Mind Unpacked abbiamo gia&#8217; parlato di <strong>steganografia</strong> digitale in due precedenti articoli (<a title="Introduzione alla steganografia digitale" href="http://mindunpacked.com/2008/introduzione-alla-steganografia-digitale/" target="_blank">Introduzione alla steganografia digitale</a> e <a title="Algoritmi steganografici" href="http://mindunpacked.com/2008/algoritmi-steganografici/" target="_blank">Algoritmi steganografici</a>), oggi percio&#8217; discuteremo di un&#8217;<strong>implementazione in C++ dell&#8217;algoritmo LSB</strong>. L&#8217;algoritmo e&#8217; gia&#8217; stato trattato dal punto di vista teorico nei precedenti articoli, quindi non mi soffermero&#8217; piu&#8217; di tanto su di esso e passero&#8217; quasi subito alla spiegazione del codice.</p>
<p><span id="more-321"></span></p>
<p style="text-align: justify">L&#8217;algoritmo <strong>LSB</strong> (least significat bit) mira a nascondere un messaggio in un contenitore (immagine, file audiom file video) modificando i bit meno significativi. Nel nostro caso creeremo un programma per <strong>nascondere file di testo all&#8217;interno di immagin</strong><strong>i</strong> bitmap. Ogni pixel della nostra immagine e&#8217; rappresentato da una terna di numeri che indicano le tre componenti RGB. Modificheremo il bit meno significativo di ogni componente di ogni pixel e lo adatteremo ai bit del nostro messaggio di testo. Il cambiamento che otteremo modificando solo il bit meno significativo sara&#8217; al massimo di una unita&#8217; e, di conseguenza, produrra&#8217; immagini all&#8217;apparenza identiche, poiche&#8217; un tale cambiamento non e&#8217; percepibile ad occhio nudo.</p>
<p style="text-align: justify">Il nostro programma e&#8217; sostanzialmente diviso in due parti: quella per nascondere il testo nell&#8217;immagine e quella per recuperarlo.</p>
<p style="text-align: justify"><strong>Steganografare un testo</strong></p>
<p style="text-align: justify">La prima parte del programma si occupera&#8217; di fare le seguenti operazioni:</p>
<ol>
<li style="text-align: justify">Leggere il messaggio da un file di testo</li>
<li>Calcolare il numero di pixels necessari ad occultare il messaggio nell&#8217;immagine ed accertarsi che l&#8217;immagine sia abbastanza grande da poterlo fare. Salvare in forma binaria il valore di ogni componente di questi pixels.</li>
<li>Modificare i bit meno significativi per adattarli a quelli del messaggio</li>
<li>Scrivere i nuovi bit su una nuova immagine apparentemente uguale alla prima, ma contenente il testo.</li>
</ol>
<p>Saltando il passo 1 (che spero chiunque sia capace di fare), passiamo al due:</p>
<pre class="brush: cpp;">
numbits = message.size()*8;  // La stringa message contiene il messaggio letto dal file
numpixels = (numbits%3 == 0 ? numbits/3 : (int)numbits/3 + 1);
numrows = (int)numpixels/img.TellWidth() + 1;
if (numrows &gt; img.TellHeight()) {
	cout &lt;&lt; &quot;Errore: il messaggio e' troppo lungo per essere contenuto in questa immagine.&quot; &lt;&lt; endl;
	exit(0);
}
for (int i = 0; i &lt; numrows; i++) {
	for (int j = 0; j &lt; img.TellWidth(); j++) {
		bits.push_back(bitset&lt;8&gt;((int)img(j, i)-&gt;Red));
		bits.push_back(bitset&lt;8&gt;((int)img(j, i)-&gt;Green));
		bits.push_back(bitset&lt;8&gt;((int)img(j, i)-&gt;Blue));
	}
}
</pre>
<p><!--adsense--></p>
<p>Il programma calcola il numero di bit e il numero di pixel necessari in base alla lunghezza del messaggio. Visto che ogni pixel puo&#8217; nascondere 3 bit, il numero di pixel viene calcolato semplicemente dividendo il numero di bit per 3 e arrotondando per eccesso nel caso di resto. numrows contiene invece il numero di righe dell&#8217;immagine che bisogna copiare in memoria. Se il numero di righe e&#8217; maggiore dell&#8217;altezza del&#8217;immagine il programma genera un errore poiche&#8217; l&#8217;immagine e&#8217; troppo piccola per contenere il messaggio. Dopo aver fatto cio&#8217;, salviamo i tutti i valori RGB dei pixel che ci servono in un array di bitset. bits e&#8217; un vettore (classe vector delle STL) di oggetti bitset, una classe della STL creata appositamente per gestire dati in forma binaria. La notazione bitset&lt;8&gt;(&#8230;) crea un oggetto bitset con 8 bit che assumono il valore dell&#8217;argomento che gli si passa tra parentesi. Visto che i valori RGB di un&#8217;immagine sono compresi tra 0 e 255 8 bit sono sufficienti.</p>
<pre class="brush: cpp;">
count = 0;
for (int i = 0; i &lt; message.size(); i++) {
	bitset&lt;8&gt; temp = bitset&lt;8&gt;(message[i]);
	for (int b = 7; b &gt;= 0; b--) {
		bits[count].set(0, temp[b]); // 0 e' l'indice del bit meno significativo; 		temp[b] e' il b-esimo bit della lettera che stiamo esaminando
		count++;
	}
}
</pre>
<p>Dopo aver salvato i valori in memoria, dobbiamo modificare il bit meno significativo di ogni elemento salvato per renderlo uguale a quello del nostro messaggio. Il codice qui sopra svolge questo compito: scorre ogni lettera del messaggio e crea un oggetto bitset contenente il valore di quella lettera in binario. Il ciclo innestato scorre tutti i bit della lettera e modifica i bit meno significativi dell&#8217;immagine in modo appropriato.</p>
<pre class="brush: cpp;">
for (int i = 0; i &lt; numrows; i++) {
	for (int j = 0; j &lt; img.TellWidth(); j++) {
		imgout(j, i)-&gt;Red = (int)bits[count++].to_ulong();
		imgout(j, i)-&gt;Green = (int)bits[count++].to_ulong();
		imgout(j, i)-&gt;Blue = (int)bits[count++].to_ulong();
	}
}
for (int i = numrows; i &lt; img.TellHeight(); i++) {
	for (int j = 0; j &lt; img.TellWidth(); j++) {
		imgout(j, i)-&gt;Red = img(j, i)-&gt;Red;
		imgout(j, i)-&gt;Green = img(j, i)-&gt;Green;
		imgout(j, i)-&gt;Blue = img(j, i)-&gt;Blue;
	}
}
imgout.WriteToFile(&quot;out.bmp&quot;);
</pre>
<p><!--adsense--></p>
<p>Una volta che i bit sono stati modificati in maniera corretta, dobbiamo solo riscriverli su una nuova immagine. Il primo ciclo scrive i bit contenenti il messaggio (la funzione to_ulong() converte un bitset nel suo valore decimale), mentre il secondo riscrive semplicemente i valori dei pixel che non sono stati modificati riprendendoli dall&#8217;immagine originale.</p>
<p><strong>Recuperare il testo steganografato</strong></p>
<p>La seconda parte del programma e&#8217; quella che, data in input un&#8217;immagine recupera il testo contenuto in essa. Un difetto del programma e&#8217; quello di richiedere la lunghezza del messaggio per poterlo estrarre: in realta&#8217; si potrebbe ovviare a questo problema in maniera piuttosto semplice (dopo vedremo come) ma per ora, bisognera&#8217; accontentarsi di andare a tentativi se non si conosce la lunghezza del messaggio completo.</p>
<p>La struttura di questa seconda parte ricalca quella della prima: dopo aver preso in input la lunghezza del messaggio ed aver calcolato in base ad essa il numero di pixel che sono stati modificati, il programma prende dall&#8217;immagine i valori delle componenti di questi pixel e li mette in un array di bitset. Un secondo ciclo:</p>
<pre class="brush: cpp;">
for (int i = 1; i &lt; numbits; i++) {
	temp.set(count, bits[i-1][0]);
	count--;
	if (count == -1) {
		count = 7;
		cout &lt;&lt; (char)temp.to_ulong();
	}
}
</pre>
<p>si occupa di prendere i bit meno significativi a gruppi di 8 e di stampare il corrispondente valore alfanumerico.</p>
<p><strong>Possibili miglioramenti</strong></p>
<p>Il programma in questa maniera e&#8217; piuttosto rudimentale, ecco alcuni possibili miglioramenti che potreste allenarvi a mettere in pratica:</p>
<ol>
<li>Evitare di dover richiedere la lunghezza quando bisogna estrarre un messaggio. Una possibilita&#8217; potrebbe essere quella di conservare i primi N bit meno significativi dell&#8217;immagine per salvare la lunghezza del messaggio e per estrarla al volo senza doverla richiedere all&#8217;utente. 10 bit permetterebbero, per esempio, di salvare un numero fino a 2<sup>10</sup> = 1024.</li>
<li>Introdurre la possibilita&#8217; di inserire una chiave. Una chiave potrebbe essere un numero intero N che indicherebbe al programma di modificare non tutti i pixel uno per uno ma di prendere 1 pixel ogni N. Questo ridurrebbe la capacita&#8217; dell&#8217;immagine di contenere messaggi ma renderebbe piu&#8217; difficile un&#8217;eventuale individuazione del messaggio.</li>
<li>Introdurre la possibilita&#8217; di crittografare un messaggio prima di steganografarlo per una maggiore sicurezza.</li>
</ol>
<p>Ecco il codice del programma: <a href="../../risorse/Stego.zip">Steganografia in C++</a>. Fa uso delle librerie EasyBMP per la gestione delle immagini presenti nell&#8217;archivio stesso.</p>
<p>Ciao!</p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2008/steganografia-in-c/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Animare il Buddhabrot</title>
		<link>http://mindunpacked.com/2008/animare-il-buddhabrot/</link>
		<comments>http://mindunpacked.com/2008/animare-il-buddhabrot/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 16:55:53 +0000</pubDate>
		<dc:creator>Francesco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[Buddhabrot]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Frattali]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=244</guid>
		<description><![CDATA[In un precedente articolo abbiamo visto come sia possibile renderizzare immagini dell&#8217;insieme di Mandelbrot ottenendo il cosiddetto Buddhabrot. Oggi mostrerò come si possano renderizzare, invece, delle animazioni del Buddhabrot sfruttando il fatto che questo frattale puo&#8217; essere &#8220;interpretato&#8221; come un oggetto in quattro dimensioni. Spiegare cio&#8217; non e&#8217; molto facile, per il semplice motivo che [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">In un <a title="Renderizzare il Buddhabrot" href="http://mindunpacked.com/2008/un-nuovo-metodo-per-visualizzare-linsieme-di-mandelbrot-il-buddhabrot/" target="_self">precedente articolo</a> abbiamo visto come sia possibile renderizzare immagini dell&#8217;insieme di Mandelbrot ottenendo il cosiddetto <strong>Buddhabrot</strong>. Oggi mostrerò come si possano renderizzare, invece, delle <strong>animazioni del Buddhabrot</strong> sfruttando il fatto che questo frattale puo&#8217; essere &#8220;interpretato&#8221; come un oggetto in quattro dimensioni. Spiegare cio&#8217; non e&#8217; molto facile, per il semplice motivo che non ci e&#8217; possibile visualizzare un oggetto in 4 dimensioni e che dobbiamo accontentarci di una approssimazione creata dalla nostra immaginazione, ma faro&#8217; del mio meglio per rendere l&#8217;articolo il piu&#8217; chiaro possibile.<br />
<span id="more-244"></span><br />
Il concetto di base e&#8217; questo: quando utilizziamo la formula di Mandelbrot e cioe&#8217; Z<sub>n+1</sub>=Z<sub>n</sub><sup>2</sup> + C i valori che entrano in gioco sono 4 e sono le parti reali di Z e C e le loro parti immaginarie (d&#8217;ora in poi saranno indicate con Z.r, C.r, Z.i, C.i); per ogni possibile combinazione di questi quattro valori avremo un solo valore in uscita, diverso per ogni combinazione. Visto pero&#8217;, che non possiamo visualizzare un oggetto in quattro dimensioni, l&#8217;unica cosa che possiamo fare e&#8217; visualizzare una sezione bidimensionale dell&#8217;oggetto, ed e&#8217; questo quello che accade quando poniamo Z=0 nel renderizzare l&#8217;insieme di Mandelbrot. Gli insieme di Julia non sono altro che sezioni dello stesso oggetto ma su piani diversi (che corrispondono ad una diversa scelta del valore iniziale di Z).</p>
<p style="text-align: justify;">In un ambiente tridimensionale abbiamo 3 piani perpendicolari tra di loro; in <strong>4 dimensioni</strong> invece, questi piani diventano 6 e sono rappresentati appunto dalle varie coppie possibili dei 4 valori in entrata: [Z.r, Z.i], [Z.r, C.r], [Z.r, C.i], [Z.i, C.r], [Z.i, C.i], [C.r, C.i]. Questi piani sono tutti perpendicolari tra di loro e sono i piani che si riconoscono a prima vista, ma ovviamente il numero di piani su cui potremmo effettuare delle sezioni da visualizzare e&#8217; infinito. Questo e&#8217; il punto che ci permette di renderizzare delle vere e proprie animazioni che includono delle <strong>rotazioni del Buddhabrot</strong>. Prima di parlare di questo, pero&#8217;, vediamo quali sono le modifiche da effettuare al file sorgente che ho distribuito nel precedente articolo per renderizzare sezioni di piani diverse.</p>
<p style="text-align: justify;">In realta&#8217;, la modifica da fare e&#8217; una sola ed e&#8217; questa: nella funzione escape() si trova questa parte:</p>
<pre class="brush: cpp;">
zz[(int)N].r = ZOOM*(Z.r+OFFSET_X)*(WIDTH/2);
zz[(int)N].i = ZOOM*(Z.i)*(HEIGHT/2) + HEIGHT/2;
</pre>
<p style="text-align: justify;">Come vedete, le coordinate che prendiamo in considerazione sono Z.r e Z.i. Basta cambiare questi valori per renderizzare un&#8217;altra sezione del frattale. Se al posto di Z.i mettiamo, per esempio, C.r, visualizzeremo l&#8217;oggetto visto dal piano [Z.r, C.r].</p>
<p style="text-align: justify;">Vediamo ora come realizzare una rotazione del frattale. Quello che vogliamo fare e&#8217;, in poche parole, passare gradualmente dall&#8217;immagine di un piano, diciamo [Z.r, Z.i] a quella di un&#8217;altro, per esempio, [Z.i, C.r]. Per fare cio&#8217; dobbiamo modificare sempre la formula precedente, nella seguente maniera:</p>
<pre class="brush: cpp;">
zz[(int)N].r = ZOOM*(rot*Z.r+Z.i*(1-rot)+OFFSET_X)*(WIDTH/2);
zz[(int)N].i = ZOOM*(rot*Z.i+C.r*(1-rot))*(HEIGHT/2) + HEIGHT/2;
</pre>
<p><!--adsense--></p>
<p style="text-align: justify">E&#8217; apparso un nuovo coefficiente, rot. Questo, come potete immaginare, e&#8217; un coefficiente che rappresenta, se vogliamo, l&#8217;angolo di rotazione. Per un valore di rot pari a 1, verra&#8217; renderizzato il piano [Z.r, Z.i] poiche&#8217; 1-rot = 0 e quindi le parti Z.i e C.r si annullano. Per rot = 0, avverra&#8217; il contrario. Ovviamente per valori di rot che variano tra 0 e 1 otteremo immagini diverse, per esempio, visto che la rotazione complessiva e&#8217; di 90° (da rot = 0 a rot = 1), rot=0.5 dovrebbe corrispondere ad una rotazione di 45°. Se si renderizzano varie immagini per valori di rot che aumentano progressivamente da 0 a 1, si otterra&#8217; una vera e propria animazione del Buddhabrot rotante.</p>
<p style="text-align: justify">Ora, se non volete mettervi a modificare manualmente ogni volta il valore di rot, vi conviene aggiungere un paio di cicli for al codice e fare in modo che, ad ogni ciclo, il valore di rot venga modificato per renderizzare un&#8217;immagine diversa. Ecco un esempio di &#8220;rotazione&#8221;, anche se non appare affatto come tale:</p>
<p style="text-align: center"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/NcyQHsuv-1o&amp;hl=it&amp;fs=1" /><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/NcyQHsuv-1o&amp;hl=it&amp;fs=1" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p style="text-align: justify">Vi lascio un ultimo link alla pagina originale creata da chi ha scoperto questa tecnica (e&#8217; in inglese): <a title="Buddhabrot Hologram" href="http://www.superliminal.com/fractals/bgram/ZrZiOut.htm" target="_blank">http://www.superliminal.com/fractals/bgram/ZrZiOut.htm</a></p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2008/animare-il-buddhabrot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Il buffer overflow: introduzione</title>
		<link>http://mindunpacked.com/2008/il-buffer-overflow-introduzione/</link>
		<comments>http://mindunpacked.com/2008/il-buffer-overflow-introduzione/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 22:05:15 +0000</pubDate>
		<dc:creator>Marco</dc:creator>
				<category><![CDATA[Informatica]]></category>
		<category><![CDATA[Buffer overflow]]></category>
		<category><![CDATA[c/c++]]></category>
		<category><![CDATA[shellcode]]></category>
		<category><![CDATA[stack]]></category>

		<guid isPermaLink="false">http://mindunpacked.com/?p=267</guid>
		<description><![CDATA[Questo è il primo di tre articoli in cui cercherò di trattare una delle vulnerabilità più gravi che affliggono il software: il buffer overflow. In questo primo articolo spiegherò più o meno approfonditamente cos&#8217;è il buffer, lo stack, il bound checking eccetera, ed i principi base che permettono di sfruttare un buffer overflow a vantaggio [...]]]></description>
			<content:encoded><![CDATA[<p style="margin-bottom: 0cm; text-align: justify;">Questo è il primo di tre articoli in cui cercherò di trattare una delle vulnerabilità più gravi che affliggono il software: il <strong>buffer overflow</strong>. In questo primo articolo spiegherò più o meno approfonditamente cos&#8217;è il buffer, lo stack, il bound checking eccetera, ed i principi base che permettono di sfruttare un buffer overflow a vantaggio di un eventuale attaccante.</p>
<p><span id="more-267"></span></p>
<p style="margin-bottom: 0cm;"><strong>Introduzione</strong></p>
<p style="margin-bottom: 0cm; text-align: justify;">Va anticipato che uno dei linguaggi di programmazione più predisposti al buffer overflow (d&#8217;ora in poi BOF) è senza dubbio il C/C++. Infatti a differenza di altri linguaggi permette al programmatore un controllo quasi completo sulla memoria &#8211; quasi quanto un linguaggio assembly – ma non sempre fa gli opportuni controlli, a scapito dei programmatori alle prime armi. Linguaggi come il Java, ad esempio, hanno una gestione molto sofisticata della memoria, ricorrendo ad algoritmi di de-allocazione e a sistemi come il <strong>Garbage Collector</strong>, quindi i rischi di BOF sono molto rari.<br />
Vediamo innanzi tutto cos&#8217;è il buffer. Nella sua accezione più generale un buffer è un&#8217;area di memoria contigua, con una dimensione prefissata, utilizzata per memorizzare dati omogenei. Nel linguaggio C un buffer è rappresentato dal puntatore all&#8217;indirizzo iniziale dell&#8217;area di memoria corrispondente. Alcune funzioni della libreria standard del C (strcpy(), strcat(), gets() e la famosa scanf()) operano su buffer di caratteri senza effettuare nessun controllo sulla dimensione del buffer di destinazione (bound checking): semplicemente arrestano la loro scrittura quando non hanno più caratteri disponibili. È evidente che in questi casi è abbastanza facile incorrere in un buffer overflow. Nel caso in cui il buffer mal gestito sia una variabile automatica, sia cioè allocato sullo stack, la situazione può venire sfruttata da un attaccante per sovrascrivere l&#8217;indirizzo di ritorno di una chiamata da funzione e forzare così l&#8217;esecuzione di codice malevolo, che può essere posizionato sia nel buffer stesso che in una variabile d&#8217;ambiente.<br />
In sintesi un buffer overflow avviene quando in un programma, al tempo di esecuzione, una certa istruzione tenta di scrivere dentro ad un buffer più informazioni di quante esso ne possa contenere.<br />
<!--adsense--></p>
<p style="margin-bottom: 0cm;"><strong>Organizzazione della memoria</strong></p>
<p style="margin-bottom: 0cm;">È possibile suddividere la memoria allocata ad un processo in tre zone, ognuna specializzata per una determinata funzione: un&#8217;area text, un&#8217;area dati statica ed un&#8217;area dati dinamica:</p>
<ul>
<li>
<p style="margin-bottom: 0cm; text-align: justify;">L&#8217;area text è un&#8217;area di sola 	lettura, collocata nella parte più bassa dello spazio di 	indirizzamento di un processo, in cui vengono memorizzate le 	istruzioni del programma ed è condivisa da tutti i processi che 	eseguono lo stesso codice; un tentativo di scrittura in quest&#8217;area 	dà origine ad un errore.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">L&#8217;area dati statica è a sua volta 	suddivisa in due regioni (data e bss), una per i dati inizializzati 	ed un&#8217;altra per i dati inizializzati; le variabili statiche trovano 	posto in quest&#8217;area.</p>
</li>
<li>
<p style="margin-bottom: 0cm; text-align: justify;">L&#8217;area dati dinamica è divisa a 	sua volta in due parti: lo stack e  lo heap. Quest&#8217;ultima è un&#8217;area 	dati dinamica che viene allocata a run time attraverso le funzioni 	del C come malloc() e calloc(), e cresce verso gli indirizzi alti. 	Viene usato per gestire variabili dinamiche e puntatori. Andrò ora 	a descrivere un po&#8217; più nel dettaglio lo stack.</p>
</li>
</ul>
<p style="margin-bottom: 0cm;">
<p style="margin-bottom: 0cm;"><strong>Lo stack e sua gestione</strong></p>
<p style="margin-bottom: 0cm; text-align: justify;">Lo stack è quell&#8217;area di memoria che si trova sul fondo della memoria e che viene utilizzata durante le chiamate alle funzioni per salvare lo stato corrente dell&#8217;esecuzione e per passare i parametri per argomento. Viene gestito con la politica LIFO (Last In, First Out) e mediante due istruzioni fondamentali del linguaggio assembly: PUSH e POP. La prima memorizza un dato, la seconda lo estrae seguendo il modello LIFO, l&#8217;ultimo ad entrare è il primo ad uscire. La memorizzazione dei dati nello stack segue un ordine inverso, cioè parte dal fondo e man mano che le informazioni vengono memorizzate, sale verso la cima della memoria.<br />
La gestione dello stack è affidata a due registri a 32-bit molto importanti, chiamati EBP e ESP (base pointer e stack pointer), usati – rispettivamente – per delimitare la cima e il fondo dello stack; quando si esegue una PUSH, il registro ESP viene decrementato di un numero di byte pari alla dimensione del dato memorizzato, quando si esegue una POP il registro ESP viene invece incrementato. Le variazioni di ESP e EBP possono inoltre essere fatte anche direttamente, tramite operazioni di somma e sottrazione (ADD e SUB): ad esempio l&#8217;istruzione SUB ESP,5 riserva cinque byte nello stack. Questo tipo di struttura si rivela efficiente e utile nella gestione della gestione delle chiamate di funzioni e procedure in un programma, costituendo quello che è il meccanismo della “call chain”: una funzione può infatti richiamare un&#8217;altra funzione che a sua volta può chiamarne un&#8217;altra ancora e così via. Il sistema operativo deve poter tener traccia di tutte le chiamate innestate fra loro ed essere in grado di tornare a punti prestabiliti del programma dove richiesto. Ogni chiamata ad una funzione viene tradotta in una istruzione di tipo CALL, che ha l&#8217;effetto di congelare l&#8217;esecuzione del codice fino a quel punto, passando poi il controllo alla funzione chiamata, dopo aver salvato lo stato corrente e l&#8217;indirizzo di ritorno (return address), che servirà per riportare l&#8217;esecuzione nel punto in cui si era interrotta (il registro EIP è quello che punta sempre all&#8217;istruzione corrente). Da questo meccanismo si evince una prima considerazione importante: poiché l&#8217;indirizzo di ritorno viene salvato nello stack, una eventuale corruzione di tale area dati impedirà ad un qualsiasi programma di ritornare in uno stato consistente, con conseguente crash dell&#8217;esecuzione.<br />
Per approfondimenti riguardo allo stack si veda il seguente link: <a href="http://blacklight.gotdns.org/wiki/index.php/Stack">Stack on Hacknowledge</a></p>
<p style="margin-bottom: 0cm;">
<p style="margin-bottom: 0cm; text-decoration: none;"><strong>Usi malevoli del buffer overflow</strong></p>
<p style="margin-bottom: 0cm; text-decoration: none; text-align: justify;">Come ho detto ad inizio articolo abbiamo a che fare con un errore particolarmente grave, che permetterebbe ad un hacker di ottenere una shell (anche root in certi casi) sulla macchina vittima.<br />
Detto sinteticamente – comunque nei prossimi articoli vedremo il tutto più nel dettaglio – è possibile far eseguire del codice macchina semplicemente sovrascrivendo l&#8217;indirizzo di ritorno e facendolo puntare ad uno shellcode. Quest&#8217;ultimo è un “programma” in grado di sfruttare un buffer overflow, e solitamente provoca l&#8217;apertura di una shell &#8211; per questo shellcode &#8211; sulla macchina vittima. Uno shellcode viene solitamente scritto tramite codici esadecimali che identificano le varie istruzioni assembly da eseguire, successivamente questo codice viene iniettato nel buffer e fatto eseguire modificando l&#8217;indirizzo di ritorno della funzione vulnerabile. I rischi di un errore del genere in alcuni casi possono essere gravissimi, ad esempio un login che va in buffer overflow se il nome utente è troppo lungo&#8230;<br />
Ecco un&#8217;immagine che forse vi faciliterà la comprensione di quanto detto:</p>
<p style="margin-bottom: 0cm; text-decoration: none;">
<p style="text-align: center;"><img class="size-full wp-image-268 aligncenter" title="stack" src="http://mindunpacked.com/wp-content/uploads/2008/12/stack.gif" alt="" width="460" height="279" /></p>
<p style="margin-bottom: 0cm; text-decoration: none; text-align: justify;">In ogni caso questo è un overflow dello stack – uno dei più comuni – ma ne esistono anche altri meno conosciuti, ed anche più difficili da sfruttare: heap overflow, frame pointer exception e l&#8217;adjacent memory overflow.<br />
L&#8217;overflow dello stack rimane il più facile da sfruttare, poiché permette di maneggiare in maniera efficace i registri EBP, ESP e EIP, fondamentali per poter eseguire del codice</p>
<p style="margin-bottom: 0cm; text-decoration: none;">Ma vediamo ora com&#8217;è possibile prevenire un BOF:</p>
<ul>
<li>
<p style="margin-bottom: 0cm; text-decoration: none;"><strong>Non 	Executable Stack</strong>: questa è la soluzione più radicale. Modificando 	il kernel del sistema si può rendere il segmento che contiene i 	dati dello stack non-eseguibile, in modo che se accidentalmente o 	volutamente un programma dovesse finire in quellaa zona di memoria 	verrebbe generato un cosiddetto protection fault, terminando il 	processo.</p>
</li>
<li>
<p style="margin-bottom: 0cm; text-decoration: none;"><strong>Random 	Stack Address</strong>: Per poter pilotare il flusso di esecuzione, un 	exploit deve disporre di indirizzi affidabili e validi da assegnare 	ai registri EIP e ESP. Utilizzando uno stack con modalità di 	indirizzamento casuale, si potrebbe complicare la vita ad un 	eventuale attaccante nella realizzazione di exploit a compatibilità 	universale, che cioè funzionino in qualsiasi sistema in cui sia 	presente il programma vulnerabile.</p>
</li>
<li>
<p style="margin-bottom: 0cm; text-decoration: none;"><strong>Bound 	Checking</strong>: Il problema degli overflow nasce principalmente da 	disattenzioni da parte del programmatore e del compilatore, che non 	controlla in anticipo se una variabile è soggetta a “traboccare”. 	Comunque anche nel C/C++ sono presenti alcuni accorgimenti da 	rispettare, e perfino delle funzioni safe, che appunto effettuano 	dei controlli sull&#8217;input in modo che non superi la grandezza del 	buffer a cui è destinato. Di seguito degli esempi:</p>
</li>
</ul>
<pre class="brush: cpp;">
strcpy(buf, ptr); //insicuro
strncpy(buf, sizebuf(buf), ptr); //sicuro
</pre>
<p>oppure con il classico scanf():</p>
<pre class="brush: cpp;">

char buf[10];
scanf(&quot;%s&quot;, buf); //insicuro
scanf(&quot;%10s&quot;, buf); //sicuro
</pre>
<p style="margin-bottom: 0cm; text-decoration: none; text-align: justify;">Nei prossimi due articoli tratterò appunto questo tipo di buffer overflow, applicandolo ai due sistemi operativi più famosi, ovvero Windows e Linux.</p>
]]></content:encoded>
			<wfw:commentRss>http://mindunpacked.com/2008/il-buffer-overflow-introduzione/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!-- www.000webhost.com Analytics Code -->
<script type="text/javascript" src="http://analytics.hosting24.com/count.php"></script>
<noscript><a href="http://www.hosting24.com/"><img src="http://analytics.hosting24.com/count.php" alt="web hosting" /></a></noscript>
<!-- End Of Analytics Code -->
