<?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>SAGES:: Blog &#187; buffer overflow</title>
	<atom:link href="http://blog.sages.com.pl/tag/buffer-overflow/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sages.com.pl</link>
	<description>Blog konsultantów firmy Sages - artykuły o technologiach Java EE i pokrewnych</description>
	<lastBuildDate>Mon, 13 Jun 2011 15:50:18 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Błąd Buffer Overflow&#8230; w szczegółach</title>
		<link>http://blog.sages.com.pl/2010/07/blad-buffer-overflow-w-szczegolach/</link>
		<comments>http://blog.sages.com.pl/2010/07/blad-buffer-overflow-w-szczegolach/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 12:52:58 +0000</pubDate>
		<dc:creator>Krzysztof Cabaj</dc:creator>
				<category><![CDATA[Problemy i rozwiązania]]></category>
		<category><![CDATA[bezpieczeństwo]]></category>
		<category><![CDATA[buffer overflow]]></category>

		<guid isPermaLink="false">http://blog.sages.com.pl/?p=68</guid>
		<description><![CDATA[Chyba każda osoba interesująca się sieciami komputerowymi i ich bezpieczeństwem zetknęła się z atakiem typu „Buffer overflow”. Idea działania większości też jest znana, jednak kojarzy się z jakimiś niesamowitymi sztuczkami. W tym artykule chcę przybliżyć jak w szczegółach wygląda podatny kod oraz jak trzeba spreparować specjalny ciąg wejściowy aby doprowadzić to ataku.
Rozpatrzmy prostą funkcję zaprezentowaną [...]]]></description>
			<content:encoded><![CDATA[<p>Chyba każda osoba interesująca się sieciami komputerowymi i ich bezpieczeństwem zetknęła się z atakiem typu „Buffer overflow”. Idea działania większości też jest znana, jednak kojarzy się z jakimiś niesamowitymi sztuczkami. W tym artykule chcę przybliżyć jak w szczegółach wygląda podatny kod oraz jak trzeba spreparować specjalny ciąg wejściowy aby doprowadzić to ataku.<span id="more-68"></span></p>
<p>Rozpatrzmy prostą funkcję zaprezentowaną poniżej:</p>
<pre>void VulnFunc(char *ptr)
{
  char buffer[32];
  int i;

  for(i=0;(*ptr)!='&amp;';i++)
    buffer[i]=*(ptr++);

  //dalsze instrukcje działające na buforze, nie zmieniające jego
  //zawartości, przykładowo liczące wartość skrótu MD5 z zawartości
  //bufora, nieistotne jeśli chodzi o atak buffer overflow
}
</pre>
<p>Możemy łatwo wyobrazić sobie i podać zadanie tej funkcji, która pobiera pewne dane, kopiuje je do bufora oraz wykonuje z jego pomocą pewne operacje. Łatwo możemy wskazać widoczny od razu błąd: dane kopiujemy do bufora bez sprawdzania czy go nie przepełnimy. Warunkiem zakończenia kopiowania jest natrafienie na znak &amp;. Właśnie taki błąd, o ile możemy podać dowolne dane wejściowe może zostać wykorzystany.</p>
<p>Nim przejdziemy do preparowania odpowiedniego ciągu znaków będących exploitem obejrzyjmy stos podczas normalnego wywołania funkcji, zaprezentowany na rysunku nr 1.</p>
<div id="attachment_77" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.sages.com.pl/wp-content/uploads/2010/07/rys1.png"><img class="size-medium wp-image-77" title="Stos podczas normalnego wywołania funkcji" src="http://blog.sages.com.pl/wp-content/uploads/2010/07/rys1-300x107.png" alt="Stos podczas normalnego wywołania funkcji" width="300" height="107" /></a><p class="wp-caption-text">Stos podczas normalnego wywołania funkcji</p></div>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } -->W lewej części rysunku przedstawiona jest zawartość pamięci wykorzystywanej na stos. Wyróżnione na czerwono obszary to zmienna i oraz bufor, z przepisaną zawartością, w tym przypadku tekstem „Ala”. Wyróżniony na niebiesko fragment to wskaźnik ptr przekazywany jako parametr. Wszystkie te informacje można skonfrontować z zawartością zmiennych podczas wykonania programu zaprezentowanych po prawej stronie rysunku.</p>
<p>Wróćmy na chwilę do wyróżnionego na niebiesko adresu, będącego parametrem. W takim przypadku nasze zainteresowanie powinny dotyczyć 32 bitowy adres znajdujący się bezpośrednio przed nim. Adres ten, jest adresem powrotu z funkcji. Jeśli uda nam się go zmienić, w momencie powrotu z funkcji … wykonamy inny kod, nieprzewidziany przez programistę.</p>
<p>Aby prześledzić taki przypadek rozpatrzmy sytuację, kiedy do funkcji zostanie podany ciąg znaków postaci (liczby hexadecymalne):</p>
<p><code><br />
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x83,0xec,0x80,0xbe,<br />
0xe6,0x10,0x41,0x00,0x68,0x41,0x6c,0x61,0x00,0x8b,0xdc,0x6a,0x40,0x53,<br />
0x53,0x33,0xc0,0x50,0xff,0xd6,0xff,0x15,0xe6,0x6c,0x41,0x00,0x68,<br />
0xfd,0x12,0x00,0x26</code></p>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } -->… i podobnie jak w poprzednim wywołaniu funkcji prześledźmy zawartość stosu.</p>
<div id="attachment_78" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.sages.com.pl/wp-content/uploads/2010/07/rys2.png"><img class="size-medium wp-image-78" title="Stos przy próbie ataku" src="http://blog.sages.com.pl/wp-content/uploads/2010/07/rys2-300x102.png" alt="Stos przy próbie ataku" width="300" height="102" /></a><p class="wp-caption-text">Stos przy próbie ataku</p></div>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } -->Na zaprezentowanym rysunku możemy zaobserwować, że do bufora zostało przepisane dużo więcej danych niż poprzednio. Dokładnie 44 bajty (wartość hexadecymalna 2c w obszarze pamięci zmiennej i). Wartość ta jest większa niż zadeklarowany na 32 bajty bufor. Jednak co najważniejsze, czy &#8211; powinniśmy powiedzieć &#8211; najgroźniejsze, został nadpisany adres powrotu z funkcji (fragment wyróżniony na niebiesko), gdzie teraz znajdują się instrukcje które zostaną wykonane przez program. Pamiętając iż zmienne na maszynach z procesorem Intel są przechowywane „od końca” możemy odkodować adres powrotu. Skok nastąpi do instrukcji znajdującej się pod adresem 0&#215;0012fd68. Jeśli przyjrzymy się dokładnie obszarowi pamięci stosu, możemy zauważyć, że skoczymy w zaprezentowany na rysunku obszar pamięci. Dokładniej wykonanie nowego kodu zaczniemy od instrukcji o kodzie 0&#215;90. Dalej możemy zaobserwować jeszcze kilka instrukcji o tym samym kodzie. Taka sekwencja jest często spotykana w exploitach. Kod 0&#215;90 ma instrukcja NOP – no operation. Instrukcja która nic nie robi, ale ma długość jednego bajta. Taka sekwencją zwana poduszeczką NOP ( jest przydatna, jeśli okazało by się, iż nie trafimy dokładnie w początek kodu exploita). Dalszą analizę tego kodu zostawmy na później … i zobaczmy co się stanie jak wykonamy ten kod. Wyniki przedstawia rysunek.</p>
<div id="attachment_79" class="wp-caption aligncenter" style="width: 310px"><a href="http://blog.sages.com.pl/wp-content/uploads/2010/07/rys3.png"><img class="size-medium wp-image-79" title="Wykonanie kodu" src="http://blog.sages.com.pl/wp-content/uploads/2010/07/rys3-300x154.png" alt="Wykonanie kodu" width="300" height="154" /></a><p class="wp-caption-text">Wykonanie kodu</p></div>
<h3>Co robi kod na stosie … trochę assemblera</h3>
<p>Znaczenie instrukcji o kodzie 0&#215;90 zostało już wyjaśnione wcześniej, teraz przyjrzyjmy się reszcie kodu.<br />
. . .</p>
<table>
<tbody>
<tr>
<td>0&#215;90</td>
<td>nop</td>
</tr>
<tr>
<td>0&#215;83,0xec, 0&#215;80,</td>
<td>sub esp,0&#215;80//zrobienie miejsca na stosie</td>
</tr>
<tr>
<td>0xbe,0xe6, 0&#215;10, 0&#215;41, 0&#215;00</td>
<td>mov esi, &lt;adres&gt;</td>
</tr>
<tr>
<td>0&#215;68,0&#215;41, 0&#215;6c, 0&#215;61, 0&#215;00</td>
<td>push &lt;dane&gt;</td>
</tr>
<tr>
<td>0&#215;8b,0xdc</td>
<td>mov ebx,esp</td>
</tr>
<tr>
<td>0&#215;6a,0&#215;40</td>
<td>push 0&#215;40</td>
</tr>
<tr>
<td>0&#215;53</td>
<td>push ebx</td>
</tr>
<tr>
<td>0&#215;53</td>
<td>push ebx</td>
</tr>
<tr>
<td>0&#215;33,0xc0</td>
<td>xor eax, eax</td>
</tr>
<tr>
<td>0&#215;50</td>
<td>push eax</td>
</tr>
<tr>
<td>0xff,0xd6</td>
<td>call esi</td>
</tr>
<tr>
<td>0xff,0&#215;15, 0xe6, 0&#215;6c, 0&#215;41, 0&#215;00</td>
<td>call &lt;adres&gt;</td>
</tr>
<tr>
<td>0&#215;68,0xfd, 0&#215;12,0&#215;00</td>
<td>adres nadpisujacy adres powrotu</td>
</tr>
<tr>
<td>0&#215;26</td>
<td>znak &amp;</td>
</tr>
</tbody>
</table>
<p>Co robi ten kod? Pierwsza instrukcja odejmuje 128 od rejestru esp – stack pointer, robiąc miejsce na stosie dla dalszego kodu. W dalszej części przypisujemy do rejestru esi adres funkcji MessageBox. Później odkładamy 5 wartości na stos, najpierw pewne dane, które już wcześniej widzieliśmy na stosie (co dokładnie … zostawiam czytelnikowi do zgadnięcia). Nim odłożymy kolejne 4 wartości zapamiętujemy zawartość rejestru esp w rejestrze ebx. Adres ten odpowiada początkowi stosu, czyli aktualnie danym załadowanym na stos przed chwila. W dalszej części odkładamy na stos liczbę 0&#215;40, dwa razy wskaźnik wskazujący na pewne dane znajdujące się na stosie oraz wartość 0. Potem dokonujemy wywołania funkcji MessageBoxA. Co robiliśmy wcześniej na stosie? – odkładaliśmy parametry – handle do okna (0 – NULL, czyli okno bez powiązania z innym oknem), dalej dwa razy wskaźnik na zawartość okna i jego tytuł (czy już wiadomo jakie dane były wkładane na stos? <img src='http://blog.sages.com.pl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ) i na końcu typ okna, w naszym przypadku okno informacyjne. Na uwagę zasługuje jeszcze ostatnia wartość – 0&#215;26 czyli w reprezentacji ASCII znak &amp; &#8211; warunek stopu pętli kopiującej dane do bufora.</p>
<p>Oczywiście zaprezentowany w tym przykładzie kod nie robi nic groźnego, jedynie wyświetla okienko. Jednak mając więcej miejsca na stosie można spreparować naprawdę groźną funkcję. Ale to już temat na kolejny wpis … <img src='http://blog.sages.com.pl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h3>Kilka wyjaśnień</h3>
<p>Wykorzystywane w przykładowym kodzie exploita adresy zostały wcześniej odkryte poprzez analizę kodu działającego programu za pomocą debuggera. Architektura systemu Windows (no może z wyjątkiem Visty i dalszych) powoduje, że w tym samym środowisku  (te same zainstalowane programy) wykonujący się program zawsze będzie posiadał te same adresy funkcji oraz stosu. Dzięki temu w środowisku testowym można je poznać … i wykorzystywać do ataku na inne identyczne lub podobne (patrz poduszeczkę NOP) systemy. Analogicznie ma się sprawa z adresem wykorzystywanej funkcji MessageBoxA.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.sages.com.pl/2010/07/blad-buffer-overflow-w-szczegolach/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

