Přetečení paměti

 

C je vysokoúrovňový jazyk, který ale stále ponechává odpovědnost za datovou integritu na programátorovi. Kdyby se o ni staral kompilátor, výsledné binární kódy by byly znatelně větší a pomalejší, protože by se musela kontrolovat konzistentnost každé proměnné. To by také pro programátora znamenalo ztrátu kontroly nad kódem a značnou komplikaci jazyka. 32 0x200 Programování Zatímco jednoduchost Céčka zvyšuje kontrolu a efektivnost výsledného kódu, také zvyšuje náchylnost na přetečení paměti a také na plýtvání pamětí, pokud není programátor pečlivý. To znamená, že jakmile je proměnná alokovaná v paměti, neexistují žádné zabudované bezpečnostní mechanismy, které by zajistily, že se celý obsah opravdu do proměnné vejde. Jestliže chce programátor vložit deset bajtů dat do bufferu, který má alokovaných pouze devět bajtů, je tento typ akce povolen, ačkoliv to může vyvolat pád programu. Této chybě se říká buffer overrun nebo overflow (neboli přetečení paměti), protože dva bajty na víc přetečou přes konec paměti a přepíšou její konec, ať už je na něm cokoliv. Pokud jsou přepsána kriticky důležitá data, program spadne, viz následující příklad.

Výpis: over f low.c



void overflow_function (char *str)
{
char buffer[20];
strcpy(buffer, str); // Funkce zkopíruje str do buffer
}
int main()
{
char big_string[128];
int i;
for(i=0; i < 128; i++) // 128 opakování
{
big_string[i] = 'A'; // vyplň big_string znaky 'A'
}
overflow_function(big_string);
exit(0);
}



V předešlém kódu je funkce nazvaná overflow_function(), která jako vstup bere ukazatel na řetězec str a poté celý řetězec zkopíruje do proměnné buffer, která má alokovaných 20 bajtů. Hlavní funkce programu alokuje 128bajtový buffer big_string a použije cyklus for na vyplnění bufferu samými A. Potom zavolá overflow_function() s ukazatelem na onen 128bajtový buffer jako argument funkce. To způsobí problém, protože se funkce pokusí umístit do bufferu 128 bajtů, i když jich má alokovaných jen 20. Zbývajících 108 bajtů dat přepíše data za koncem proměnné.


$ gcc -o overflow overflow.c
$ ./overflow
Segmentation fault
$


Z důvodu přetečení paměti program zhavaroval. Pro programátora jsou tyto typy chyb časté a lze je jednoduše odstranit, pokud programátor ví, jak velký bude očekávaný vstup. Programátoři často spoléhají na to, že uživatelský vstup bude mít určitou velikost a berou to jako pravidlo. Ale ještě jednou, hacking v sobě zahrnuje přemýšlení o věcech, které nebyly původně zamýšleny – program, který léta fungoval bez problému může spadnout, pokud se hacker pokusí poslat tisíce znaků na vstup, kam jich obyčejně uživatelé zadávají jen pár desítek, jako třeba políčko pro zadání uživatelského jména. Takže chytří hackeři mohou způsobit pád programu zasláním nepředvídaných dat na jeho vstup, ale jak se dá chyba zneužít pro získání kontroly nad vykonáváním programu? Odpověď můžeme získat prozkoumáním dat, která byla přepsána.