Zranitelnost formátovacích řetězců

Od konce devadesátých let je zranitelnost formátovacích řetězců veřejně známá. Při zneužití dokáže útočník kromě čtení paměti i paměť měnit a dokonce spustit vlastní kód. Tato přehledová studie se zabývá principem a možnostmi zneužití zranitelnosti formátovacích řetězců zejména v jazycích C a C++. Možnosti využití zranitelnosti jsou popsané do hloubky a jsou k nim uvedeny i pomocné techniky využívané útočníky. Studie se dále věnuje i možnostem obrany proti této zranitelnosti a přidává pár ukázek z jiných jazyků.

ÚVOD

Na konci devadesátých let se začaly objevovat zranitelnosti formátovacích řetězců v jazycích C a C++. Velkou pozornost si tato zranitelnost získala v červnu roku 2000, kdy se objevila v balíčku WU-FTPD – FTP serveru napsaném Washingtonskou univerzitou [8]. Tato zranitelnost nabízí útočníkovi široké pole působnosti, a při správném zneužití může útočník dokonce získat administrátorský přístup do systému.

Tato studie se zabývá všemi možnostmi zneužití této zranitelnosti a ukazuje je na příkladech. Studie nejdříve rozebírá, co jsou formátovací řetězce a funkce, a jak v jazycích C a C++ fungují. V další sekci se pak práce zabývá detailnějším popisem zranitelnosti a popisem možných útoků na tuto zranitelnost – od čtení hodnot ze zásobníku až po spouštění vlastního kódu. Po vysvětlení těchto útoků jsou dále popsány pomocné metody útočníků, které jsou využívány pro zjednodušení útoků. V neposlední řadě je zmíněna situace ohledně obrany vůči této zranitelnosti – tato sekce popisuje ideální možnosti řešení, které ale bohužel ve skutečném světě není možné aplikovat a ukazuje dva nástroje vytvořené pro eliminaci této zranitelnosti. Na konci práce ukazuje příklady této zranitelnosti z jiných jazyků.

Mohlo By Vás Zajímat

[]Exploiting Format String Vulnerabilities
[]Hacking: The Art of Exploitation
[]Format-String Vulnerability

FORMÁTOVACÍ ŘETĚZCE A FUNKCE

Formátovací řetězec je ASCIIZ řetězec, který obsahuje text a formátovací parametry (viz Tabulka I) a používá se v tzv. formátovacích funkcích. V příkladu níže se jedná o první argument funkce printf, tedy: "Cisla: %d %d %d\n".

Formátovací funkce je speciální typ ANSI C funkce, která přijímá proměnný počet argumentů, z nichž jeden se nazývá formátovací řetězec. Jedná se o funkci, která slouží ke zobrazování běžných datových typů jazyka C do podoby čitelné pro člověka [1], [2], [7], [9]. Funkce přepisuje formátovací řetězec na výstup a případně nahrazuje formátovací parametry za hodnotu daného argumentu ze zásobníku viz Sekce Zásobník. Pokud tedy funkce obsahuje například tři formátovací parametry, měla by funkce obsahovat kromě formátovacího řetězce další tři argumenty [1], [2], [7].

Ukázka správného počtu argumentů ke správnému počtu formátovacích parametrů:

printf("Cisla: %d %d %d\n", 1, 2, 3);

Uvedený kód vypíše: Cisla: 1 2 3 (ukončené novým řádkem).

Formátovací funkce přistupují k dalším argumentům pomocí makra va_arg, které vrací ukazatel na argument a posouvá tento ukazatel na další argument v poli va_list. Problém nastává v momentě, kdy se ve formátovacím řetězci nachází více formátovacích parametrů. Makro va_arg nepozná, že již prošlo všechny argumenty, a tak pokračuje v načítání dat ze zásobníku a posouvá ukazatel dále [3], [7].

Příklady funkcí

V jazyce ANSI C se nachází mnoho formátovacích funkcí, které mají různé užití, níže jsou vypsány funkce z rodiny printf:

  • printf
  • fprintf
  • dprintf
  • sprintf
  • snprintf
  • vprintf
  • vfprintf
  • vdprintf
  • vsprintf
  • vsnprintf

Funkcí však existuje ještě více, a to např.: syslog, setproctitle, err*, verr*, warn*, vwarn* [1], [8], [10].

Formátovací parametry

V Tabulce I jsou popsány některé formátovací parametry, které se mohou vyskytovat ve formátovacím řetězci. Tyto parametry jsou identifikovány na základě znaku % před příslušným písmenem, je ale nutno dodat, že v kódu se nemusí nacházet přímo znak %. Např. \x25 bude při překladu nahrazeno za znak procenta, jelikož hodnota 0x25 je v ASCII právě znak % [1].

Tabulka I: Ukázka formátovacích parametrů
Parametr Vstup Výstup
%d Hodnota Číslo
%u Hodnota Nezáporné číslo
%x Hodnota Číslo v šestnáctkové soustavě
%s Ukazatel Textový řetězec
%n Ukazatel Počet již vypsaných bajtů

Zásobník

Formátovací funkce při svém vyhodnocování prochází formátovací řetězec znak po znaku. V případě, že se jedná o normální znak, je zkopírován na výstup. Pokud se ale jedná o začátek formátovacího parametru (znak %), očekává se za ním nějaký formátovací parametr. Funkce poté zvýší pomocný ukazatel v zásobníku a očekává, že na daném místě nalezne hodnotu požadovaného argumentu funkce a podle formátovacího parametru ji převede na výstup [1], [2], [5].

Parametry funkce jsou na zásobníku uložené pozpátku, viz ukázka níže [2], [5], [10]: printf("Test: %d, %d, %08x", one, two, &three);

zásobník
  • šipka znázorňuje směr růstu zásobníku
  • one – hodnota proměnné one
  • two – hodnota proměnné two
  • &three – adresa proměnné three

ZRANITELNOST

Zranitelnost formátovacích řetězců se v programu nachází v momentě, kdy útočník může zadat do programu takový textový řetězec, který bude následně programem vyhodnocen jinak, než bylo původně zamýšleno [1], [5]-[7], [9], [10]. Díky tomu může být chování formátovací funkce změněno a útočník tak může např. způsobit pád programu, číst libovolné adresy z paměti, nebo na ně zapisovat a případně spustit škodlivý kód [1], [5], [7], [10]. Pokud se mu podaří zapsat na správné místo, může dokonce získat administrátorská práva [5].

Podobně jako u buffer overflow je i tato zranitelnost způsobená programátorskou chybou, na rozdíl od buffer overflow se dá ale v programu celkem jednoduše nalézt [2], [6]. V některých případech se programátoři uchylují k zápisu printf(string_var); místo správného printf("%s", string_var); – funkce takhle tedy vezme textový řetězec proměnné a považuje jej za formátovací řetězec. Oba způsoby zápisu fungují tak, jak bychom očekávali, nicméně v momentě, kdy se do proměnné dostane formátovací parametr, začne funkce přistupovat k hodnotám zásobníku, aniž by na něm byly uloženy další argumenty, jak již bylo zmíněno v sekci Formátovací řetězce a funkce [1], [8], [10]. Toto samo o sobě netvoří až tak velký problém, ten nastává v momentě, kdy je útočník schopen ovlivnit proměnnou, která vstupuje do funkce.

good.c:

#include<stdio.h>

int main(int argc, char* argv[]){
    char* var = argv[1];
    printf("Jmeno: %s\n", var);
    return 0;
}
    
$ ./good Jan
Jmeno: Jan
$ ./good %d
Jmeno: %d

bad.c:

#include<stdio.h>

int main(int argc, char* argv[]){
    char* var = argv[1];
    printf("Jmeno: ");
    printf(var); // Zranitelnost!!!
    printf("\n");
    return 0;
}
    
$ ./bad Jan
Name: Jan
$ ./bad %d
Name: 1370186400

Pád programu - chyba segmentace

Pokud je cílem útočníka pouze způsobit pád programu, jedná se o nejjednodušší variantu útoku na formátovací řetězce. Útočníkovi stačí do formátovacího řetězce dostat tolik formátovacích parametrů, aby některý z nich ukazoval na neplatnou adresu. Téměř ve všech UNIXových systémech se přístup na neplatnou adresu zachytí v jádře, a proces obdrží signál SIGSEV – chyba segmentace, a program je ukončen [2], [3], [5].

$ ./bad %s%s%s%s%s%s%s

Výstup:

Segmentation fault (core dumped)

Příkladem útoku by mohla být situace, kdy se provádí útok, který zahrnuje překlad doménového názvu v systému DNS. V tento moment může útočníkovi přijít vhod shodit DNS server [1], [7].

Čtení dat ze zásobníku

V případě, že útočník vidí výstup formátovací funkce, může jej využít ke zobrazení zásobníku, jelikož může funkci ovládat svými vstupy [1], [4]. Tento výstup se útočníkovi hodí pro další fáze útoku, například pro zjištění správného offsetu na zásobníku [1].

Pro zobrazování dat ze zásobníku je vhodné používat formátovací parametr %08x, který zobrazuje hodnoty ze zásobníku jako šestnáctková čísla zarovnaná na osm míst [1], [5]. V příkladu níže tedy funkce předpokládá, že na zásobníku jsou uloženy čtyři parametry:

printf("%08x_%08x_%08x_%08x\n");

Výstup:

a90382c8_a90382d8_aaf3fdc0_125fdf10

Pomocí této metody se tedy dá zobrazovat zásobník (směrem zespodu nahoru – za předpokladu, že zásobník roste směrem k nízkým adresám). Nicméně zde útočník může narazit na určité limity, a to velikost bufferu formátovacího řetězce a výstupního bufferu. V některých případech je ale možné zobrazit celý zásobník [1].

Čtení dat z libovolné adresy

Čtení zásobníku může být pro útočníka zajímavé, nicméně čtení libovolné paměti má pro útoky větší hodnotu. Útočník by mohl například chtít znát hodnotu konkrétní tajné proměnné. U zranitelnosti formátovacích řetězců je to možné.

Pro úspěšný útok je nutné zvládnout dvě fáze: podstrčit adresu v paměti, ze které chceme číst a hodnotu z dané adresy přečíst. Pro tento účel útočník využije formátovací parametr %s, jelikož tento parametr očekává ukazatel na data viz Tabulka I. V tento moment tedy zbývá podstrčit adresu, ze které chce útočník číst [1].

Jak již bylo zmíněno v sekci Zásobník, parametry formátovací funkce se dostávají na zásobník, a je možné se k nim dostat. Kromě ostatních parametrů se na zásobník dostane i samotný formátovací řetězec. Zde útočník použije primitivní techniku pro nalezení formátovacího řetězce na zásobníku. Do formátovacího řetězce dosadí na začátek písmena AAAA, a poté se je snaží na zásobníku najít např. pomocí %08x. Ve výstupu funkce útočník hledá 41414141, tedy hexadecimálně AAAA [1], [2], [5].

Formátovací řetězec:

AAAA_%08x_%08x_%08x_%08x

Výstup:

AAAA_6758b2a0_6652100e_6758b2a0_41414141

Pokud útočník zvolí správný počet formátovacích parametrů, tak se mu hledaný text podaří najít, v příkladu výše se tedy formátovací řetězec nachází jako čtvrtý parametr na zásobníku. Pokud by útočník nahradil poslední parametr za %s, přiměl by tím funkci číst hodnotu adresy uložené na čtvrtém parametru (tedy z adresy 0x41414141) [2], [5].

Pomocí této techniky se tedy útočník dozví, kde se na zásobníku nachází začátek formátovacího řetězce – tedy místo v paměti, které je schopen ovládat. Poté už útočníkovi tedy stačí nahradit písmena AAAA za skutečnou adresu a následně hodnotu na ní uloženou zobrazit pomocí formátovacího parametru %s, jelikož tento parametr čte data ze zadané adresy [2], [5], [6].

Níže příklad podstrčení adresy do formátovacího řetězce z minulé ukázky:

Adresa:

0x12345678

Formátovací řetězec:

\x78\x56\x34\x12_%08x_%08x_%08x_%s

Při vkládání vlastní adresy je nutné zadat ji v opačném pořadí kvůli formátu little endian [1], [2], [5]. Kromě toho je nutné si dát pozor na to, jak se zpracovává vstupní řetězec. Např. v Bash shellu při zadání vstupu přes argument příkazové řádky je text: \x11\x22\x33\x44 interpretován jako: x11x22x33x44. Je proto vhodné jej vložit pomocí využití příkazu printf:

./bad $(printf "\x78\x56\x34\x12")...

Pokud se útočníkovi nepodaří narazit na přesnou hranici formátovacího řetězce pomocí 4bajtových skoků, musí zarovnat formátovací řetězec pomocí jednoho až tří zbytečných znaků – jelikož není možné se po zásobníku posouvat po bajtech. Místo toho je nutné posunout samotný formátovací řetězec tak, aby bylo možné na něj dosáhnout pomocí skoků po čtyřech bajtech [1].

Jelikož se v jazyce C řetězec ukončuje znakem \0 (tzv. Null byte), který je hexadecimálně reprezentován jako \x00, je útočník limitován na adresy, které v sobě neobsahují dvojici 00, která by ukončila formátovací řetězec předčasně. Toto může být problém například u operačního systému Windows, kde se často vyskytují adresy s předponou 00 [6].

Změna dat v paměti

Poté, co útočník umí zobrazit hodnotu na libovolné adrese v paměti, neměl by pro něj být takový problém na libovolnou adresu něco zapsat [2]. V tomto případě útočník využije formátovacího parametru %n, který do příslušného ukazatele zapisuje počet již vypsaných bajtů danou formátovací funkcí, viz příklad níže [6]:

int pocet;
printf("TEST\n%n", &pocet);
printf("Count = %d\n", pocet);

Výstup: Pocet = 5

V tomto případě program do proměnné pocet zapsal hodnotu 5, jelikož se před formátovacím parametrem %n nacházely 4 písmena a 1 znak nového řádku.

Pokud chce tedy útočník zapsat na danou adresu v paměti, musí ji podstrčit jako v Sekci Čtení z libovolné adresy, a následně zajistit, aby se číslo, které chce na adresu zapsat, rovnalo počtu již vypsaných znaků – tedy znaků před %n [2].

Zde může útočníkovi pomoct zarovnání čísel na daný počet číslic. Tohoto triku je možné si všimnout např. u parametru %x, kde se adresy zarovnávají na 8 znaků pomocí %08x. Číslo je možné vložit i před jiné formátovací parametry, např. %u [1], [6].

V příkladu níže je ukázka změny hodnoty proměnné na známé adrese v paměti:

  • Adresa proměnné: 0x12345678
  • Adresa pro podstrčení: \x78\x56\x34\x12

  • Formátovací řetězec: \x78\x56\x34\x12_%08x_%08x_%08x_%n
  • Příklad výstupu: xV4_b87152a0_00000000_b7d3800e_
  • Výsledná hodnota proměnné: 31
    • 7 znaků (x,v,4, 4*"_")
    • 3*8 znaků adres= 24

  • Formátovací řetězec: \x78\x56\x34\x12_%08x_%08x_%108x_%n
  • Výsledná hodnota proměnné: 131
    • stejné jak výše + poslední %x je zarovnané na 108 znaků místo na 8

Pomocí šířky čísla můžeme upravovat počet vypsaných znaků, ale bohužel pomocí tohoto triku nebudeme schopni zapisovat velká čísla, jako jsou například adresy v paměti [1], [2].

Adresy v paměti se ukládají pozpátku, a tedy nejméně významný bajt se v paměti nachází jako první. V případě, že chce útočník do paměti zapsat celou adresu, je schopen to udělat pomocí čtyř zápisů do po sobě jdoucí paměti, kde vždy přepíše nejméně významný bajt [1], [2].

Uvažujme, že útočník chce zapsat do proměnné na adrese 0x08049794 adresu 0xDDCCBBAA. Udělá to tedy pomocí čtyř zápisů následovně [2]:

Paměť 94 95 96 97
1. zápis na 0x08049794 AA 00 00 00
2. zápis na 0x08049795 BB 00 00 00
3. zápis na 0x08049796 CC 00 00 00
4. zápis na 0x08049797 DD 00 00 00
Výsledek AA BB CC DD

Pro zapsání adresy si tedy útočník musí vytvořit formátovací řetězec, který bude obsahovat tři části [1], [6]:

  1. Podstrčené adresy
  2. Formátovací parametry pro posun ukazatele na podstrčené adresy
  3. Formátovací parametry pro zápis

V příkladu výše by si tedy útočník připravil na začátek formátovacího řetězce čtyři adresy pro zápis (posunuté o jeden bajt), následované formátovacími parametry, které zajistí správný zápis adresy. Jelikož na každou adresu bude chtít zapsat specifickou hodnotu, tak si adresy oddělí libovolnými čtyřmi znaky. Toto udělá z důvodu, aby mohl na každou adresu vložit jinou hodnotu – bude zde využívat zarovnávání délky čísel, a tím pádem posouvat ukazatel v paměti, vložením čtyř znaků mezi adresy si tedy pohlídá, že každý další zápis bude správně ukazovat na další adresu. Dále je nutné vzít v potaz, že zápisem vlastní adresy se v paměti přepíší další tři bajty, viz schéma zápisu výše [2].

Výsledný formátovací řetězec bude tedy vypadat následovně [2]:

\x94\x97\x04\x08JUNK\x95\x97\x04\x08JUNK\x96\x97\x04\x08JUNK\x97\x97\x04\x08%x%x%126x%n%17x%n%17x%n%17x%n

Na začátku tohoto řetězce se tedy nacházejí podstrčené adresy oddělené čtyřmi libovolnými znaky. Dále se v něm nachází tři formátovací parametry pro posun ukazatele na podstrčenou adresu (z nichž jeden je už upravený tak, aby do první adresy zapsal správné číslo) a za nimi parametr pro první zápis (%n). Na konci se pak nacházejí tři dvojice, které slouží k přičtení požadovaného počtu znaků pro další zápis a samotný zápis.

Je zřejmé, že útočník před vytvořením formátovacího řetězce musí dopočítat správná čísla pro zápis chtěných částí výsledné adresy. Pro zápis 0xaa potřebuje útočník vypsat před prvním %n 170 znaků (0xaa desítkově). Formátovací řetězec obsahuje už čtyři adresy a tři pomocná slova, tedy dohromady 28 znaků. Dále obsahuje dvakrát %x, jehož výstup je na osmi znacích, dohromady tedy zatím 44 znaků. Aby tedy útočník do prvního zápisu dostal hodnotu 170, zarovná poslední parametr před zápisem na 126 číslic. Tímto docílí zápisu 0xaa. Pro další zápisy už útočník jen přičítá k již vypsaným znakům pomocí dalších zarovnání, v tomto případě vždy 17 (0xbb - 0xaa = 17 atd.).

V předchozím příkladě to měl útočník poměrně jednoduché, jelikož v každém dalším zápisu se jednalo o vyšší číslo. Může se ale stát, že útočník bude chtít podstrčit adresu, u které to nebude tak jednoduché, jelikož v adrese budou následovat menší čísla po větších [2].

Pro tento případ je možné využít techniku obalení zápisu vyšším číslem. V případě, že by chtěl útočník do příkladu výše podstrčit adresu 0x0806abcd, bude pro něj jednoduché zapsat první část (0xcd ~ 205). Problém ale nastane u druhé části (0xab ~ 171). Pro první zápis musel útočník vypsat 205 znaků, nicméně pro zápis druhé části by potřeboval mít vypsaných pouze 171 znaků, bohužel ale počet již vypsaných znaků změnit nelze. Útočník tedy místo 0xab do paměti zapíše 0x1ab, a tím problém vyřeší. Tuto techniku pak může použít i pro následující zápisy [1], [2].

Provedení kódu

Ve většině případů nebude útočník chtít přepsat jen hodnotu proměnné, ale spíše se bude snažit o spuštění vlastního škodlivého kódu. Aby toho byl útočník schopen, bude muset vložit škodlivý kód na zásobník, zjistit, na jaké adrese tento kód začíná a změnit nějaký ukazatel na spustitelný kód tak, aby ukazoval na začátek škodlivého kódu [1], [3].

V dnešní době je možné dohledat mnoho již připravených tzv. shellkódů na internetu (např. na adrese http://shell-storm.org/shellcode/index.html). Shellkód je kus kódu, který se vloží do formátovacího řetězce a následně se využije k provedení nějaké akce (např. ke získání administrátorského shellu).

Adresu ukazatele, který je potřeba změnit, může útočník najít například v Global Offset Table (GOT). Jedná se o tabulku, která obsahuje adresy knihovních funkcí, které jsou v programu použité. Uvažujme, že se v programu nachází funkce exit. Útočník si tedy pomocí příkazu objdump -R ./nazev_binarky může najít, na které adrese se nachází ukazatel na tuto funkci, a poté na tuto adresu zapíše adresu začátku vloženého shellkódu. Program tedy v momentě volání funkce exit spustí vložený kód [1]-[3].

Výhodou u této metody je, že záznamy v tabulce GOT jsou vázené na binárku, a tedy pokud více systémů používá stejnou binárku, budou hodnoty této tabulky stejné [1], [2].

Výstupy GNU C překladače zahrnují speciální oddíl v tabulce, která se nazývá DTORS. V této části se nacházejí destruktory, kterými se dá zařídit provedení kódu před ukončením programu [1], [2], [5]. K prohlédnutí tohoto oddílu pro daný program použije útočník příkaz: objdump -s -j .dtors ./nazev_binarky nebo nm ./nazev_binarky | grep DTOR [2], [5]. Pro provedení vlastního kódu musí útočník zjistit adresu __DTOR_LIST__, přičíst k ní čtyři bajty a do výsledné adresy vložit ukazatel na jeho shellkód [1], [2], [5].

Tyto dvě metody jsou více do hloubky rozebrané v knihách Hacking: The Art of Exploitation [2] a Hacking: the hacker’s manual [5].

UKÁZKY Z JINÝCH JAZYKŮ

Jazyky C a C++ nejsou jedinými, které trpí zranitelností formátovacích řetězců. Jiné jazyky, které obsahují formátovací parametry, mohou také obsahovat tuto zranitelnost [8]. Níže jsou popsané příklady některých dalších jazyků.

Perl

V roce 2005 objevil Stefan Schmidt problém v programu Postgrey napsaném v Perlu. Bylo zjištěno, že program padá při zadání emailu ve tvaru: foo_bar%nowhere.co.xy@[622.622.615.619]. Interpret jazyka Perl umí detekovat situaci, kdy formátovací řetězec obsahuje %n, ale neobsahuje odpovídající parametr funkce pro zápis hodnoty. V tomto případě se tedy email dostal do formátovacího řetězce a vykonávání programu bylo ukončeno s chybovou hláškou [8]:

Modification of read-only value attempted at...

PHP

Jazyk PHP nepodporuje formátovací parametr %n, a v případě, že počet formátovacích parametrů je vyšší než počet poskytnutých argumentů funkce, vypíše se varování v podobě:

Warning: sprintf(): Too few arguments in file.php on line...

Vykonávání programu se nezastaví, nicméně řetězec, který měl být vytvořen funkcí sprintf, zůstane prázdný. Díky tomu mohou vznikat například prázdné zprávy logů a nebo další problémy [8].

Java

Od verze Java 1.5 byla přidána podpora formátovacích řetězců ve stylu printf. Java na špatně zadané formátovací parametry reaguje výjimkou. V případě, že výjimky nejsou správně zpracované, mohou být útočníky využité k DoS útokům [8].

Ruby

V případě, že jazyk Ruby obdrží formátovací parametr, který nezná (např. %z), nebo pokud funkce obsahuje více formátovacích parametrů než argumentů, je vykonávání programu ukončeno s chybovými hláškami:

‘sprintf’: malformed format string - %z (ArgumentError) nebo

‘sprintf’: too few arguments (ArgumentError) [8].

ZÁVĚR

Ačkoli je zranitelnost formátovacích řetězců stará již přes již přes dvacet let, dodnes se v reálných systémech nachází každoročně v řádu desítek (viz CVE). Díky této chybě při nesprávném ohlídání formátovacího řetězce mohou v reálných systémech nastávat velké problémy – od pádu programů, přes únik informací, změnu dat v paměti, až po získání administrátorských práv.

Při psaní nových programů je tedy nutné dávat si pozor na správné užívání formátovacích řetězců, ideálně je ponechat statické, a v případě, že to není možné, důkladně kontrolovat, jestli se do nich nedostává uživatelský vstup. Výhodou je, že se jazyky C a C++ před použitím musí kompilovat. Díky tomu může programátor této zranitelnosti zamezit, jelikož je na ni překladačem upozorněn. Pro její zamezení může programátor mimo jiné použít vytvořené nástroje, zmíněné v sekci věnující se obraně.

LITERATURA

[1] scut/team teso, “Exploiting Format String Vulnerabilities,” ver. 1.2, September 2001.

[2] J. Erickson, “Hacking: The Art of Exploitation,“ 2nd ed, No Starch Press, 2008.

[3] F. Zhang, “Format-String Vulnerability,“ Southern University of Science and Technology, CS 315 Computer Security

[4] S. El-sherei, “Format String Exploitation-Tutorial“

[5] S. Harris, “Hacking: manu´al hackera.“ Praha: Grada, 2008.

[6] G. Hoglund and G. McGraw, “Exploiting software: how to break code.“ Boston: Addison-Wesley, 2004.

[7] J. Koziol and D. Litchfield, “Shellcoder´s handbook: discovering and exploiting security holes.“ Indianapolis: Wiley Publishing, 2004.

[8] H. Burch and R. C. Seacord, “Programming language format string vulnerabilities”, Dr. Dobb’s Journal, vol. 32, no. 3, p. 22, 2007.

[9] K. -suk Lhee and S. J. Chapin, “Buffer overflow and format string overflow vulnerabilities”, Software, practice & experience, vol. 33, no. 5, pp. 423-460, 2003.

[10] “Kimchi: A Binary Rewriting Defense Against Format String Attacks”, in Lecture notes in computer science, 2006, pp. 179-193.

[11] M. Barringer, M. Frantzen, and J. Lokier, “FormatGuard: Automatic Protection From printf Format String Vulnerabilities,” Aug. 2001.

Mohlo By Vás Zajímat

[]Exploiting Format String Vulnerabilities
[]Hacking: The Art of Exploitation
[]Format-String Vulnerability