DRUHÉ, UPRAVENÉ A DOPLNĚ NÉ VYDÁNÍ. Foto: Jiří Heller



Podobné dokumenty
Pochvalná vyjádření k prvnímu vydání Hacking umění exploitace

Co je programování? 18 0x200 Programování

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

programování formulářů Windows

Zrychlete své WWW stránky!

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

Čtvrtek 8. prosince. Pascal - opakování základů. Struktura programu:

Programovací jazyky. imperativní (procedurální) neimperativní (neprocedurální) assembler (jazyk symbolických instrukcí)

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7

RAW s programem Adobe Photoshop CS

6 Příkazy řízení toku

Programovací jazyk Pascal

8 Třídy, objekty, metody, předávání argumentů metod

Program a životní cyklus programu

Programovací jazyky. imperativní (procedurální) neimperativní (neprocedurální) assembler (jazyk symbolických instrukcí)

PHP tutoriál (základy PHP snadno a rychle)

Operační systémy. Cvičení 4: Programování v C pod Unixem

Program převod z desítkové na dvojkovou soustavu: /* Prevod desitkove na binarni */ #include <stdio.h>

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5

Lekce 6 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Princip funkce počítače

Algoritmizace a programování

Koncepce (větších) programů. Základy programování 2 Tomáš Kühr

6. Příkazy a řídící struktury v Javě

Programování v C++, 2. cvičení

Algoritmizace a programování

Martin Hejtmánek hejtmmar

Profilová část maturitní zkoušky 2017/2018

Operátory, výrazy. Tomáš Pitner, upravil Marek Šabo

Stručný návod k programu Octave

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Paměť počítače. alg2 1

Překladač a jeho struktura

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

ANOTACE vytvořených/inovovaných materiálů

Tabulkový procesor. Základní rysy

Základní datové typy, proměnné - deklarujeme předem - C je case sensitive rozlišuje malá a velká písmena v názvech proměnných a funkcí

ALGORITMIZACE A PROGRAMOVÁNÍ

Matematika v programovacích

Struktura programu v době běhu

C2115 Praktický úvod do superpočítání

PSK3-9. Základy skriptování. Hlavička

Formátové specifikace formátovací řetězce

Př. další použití pointerů

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

Jazyk C Program v jazyku C má následující strukturu: konstanty nebo proměnné musí Jednoduché datové typy: Strukturované datové typy Výrazy operátory

Vzorce. StatSoft. Vzorce. Kde všude se dá zadat vzorec

Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů

LEKCE 6. Operátory. V této lekci najdete:

MAXScript výukový kurz

7. Datové typy v Javě

Assembler - 5.část. poslední změna této stránky: Zpět

Poslední nenulová číslice faktoriálu

Operační systémy. Cvičení 3: Programování v C pod Unixem

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

- jak udělat konstantu long int: L long velka = 78L;

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

5 Přehled operátorů, příkazy, přetypování

2 Datové typy v jazyce C

Maturitní otázky z předmětu PROGRAMOVÁNÍ

Architektury počítačů a procesorů

Vstupní požadavky, doporučení a metodické pokyny

Základy algoritmizace a programování

1/1 ČESKÁ ZEMĚDĚLSKÁ UNIVERZITA V PRAZE PROVOZNĚ EKONOMICKÁ FAKULTA PŘIJÍMACÍ ŘÍZENÍ 2017/2018

Funkční objekty v C++.

PROGRAMOVÁNÍ V JAZYCE C V PŘÍKLADECH 11 Dynamické datové struktury 11.1 Spojové struktury Příklad PROG_

Skripta ke školení. Základy VBA. vypracoval: Tomáš Herout. tel:

Proměnná. Datový typ. IAJCE Cvičení č. 3. Pojmenované místo v paměti sloužící pro uložení hodnoty.

6. lekce Úvod do jazyka C knihovny datové typy, definice proměnných základní struktura programu a jeho editace Miroslav Jílek

Operační systémy. Jednoduché stránkování. Virtuální paměť. Příklad: jednoduché stránkování. Virtuální paměť se stránkování. Memory Management Unit

Úvod. Programovací paradigmata

Čtvrtek 3. listopadu. Makra v Excelu. Obecná definice makra: Spouštění makra: Druhy maker, způsoby tvorby a jejich ukládání

PROGRAMOVÁNÍ V SHELLU

Vlastnosti algoritmu. elementárnost. determinovanost. rezultativnost. konečnost. hromadnost. efektivnost

Programujeme v softwaru Statistica

5a. Makra Visual Basic pro Microsoft Escel. Vytvořil Institut biostatistiky a analýz, Masarykova univerzita J. Kalina

Profilová část maturitní zkoušky 2013/2014

Souhrn Apendixu A doporučení VHDL

Zapomeňte už na FTP a přenášejte soubory bezpečně

Maturitní témata. IKT, školní rok 2017/18. 1 Struktura osobního počítače. 2 Operační systém. 3 Uživatelský software.

Vyučovací hodina. 1vyučovací hodina: 2vyučovací hodiny: Opakování z minulé hodiny. Procvičení nové látky

EVROPSKÝ SOCIÁLNÍ FOND. Úvod do PHP PRAHA & EU INVESTUJEME DO VAŠÍ BUDOUCNOSTI

- dělají se také pomocí #define - podobné (použitím) funkcím - předpřipravená jsou např. v ctype.h. - jak na vlastní makro:

Aplikovaná informatika. Podklady předmětu Aplikovaná informatika pro akademický rok 2006/2007 Radim Farana. Obsah. Obsah předmětu

type Obdelnik = array [1..3, 1..4] of integer; var M: Obdelnik;

Logické operace. Datový typ bool. Relační operátory. Logické operátory. IAJCE Přednáška č. 3. může nabýt hodnot: o true o false

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

Přednáška 7. Celočíselná aritmetika. Návratový kód. Příkazy pro větvení výpočtu. Cykly. Předčasné ukončení cyklu.

09. Memory management. ZOS 2006, L.Pešička

Základy jazyka C. Základy programování 1 Martin Kauer (Tomáš Kühr)

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

4a. Makra Visual Basic pro Microsoft Excel Cyklické odkazy a iterace Makra funkce a metody

Transkript:

E N C Y K L O P E D I E Z O N E R P R E S S DRUHÉ, UPRAVENÉ A DOPLNĚ NÉ VYDÁNÍ HACKING umění exploitace Foto: Jiří Heller Jon ERICKSON

Pochvalná vyjádření k prvnímu vydání Hacking umění exploitace Nejkompletnější výuka hackerských technik. Konečně kniha, která jen nepředvádí, jak využívat exploity, ale také ukazuje, jak je vyvíjet. PHRACK Ze všech knih, co jsem doposud četl, tuto považuji za vynikající hackerskou příručku. SECURITY FORUMS Tuto knihu doporučuji už jen kvůli její programovací sekci. UNIX REVIEW Vřele tuto knihu doporučuji. Napsal ji člověk, který ví, co čem mluví, navíc s použitelným kódem, nástroji a příklady. IEEE CIPHER Ericksonova kniha, hutný a seriózní průvodce pro začínající hackery, je naplněna až po okraj nejenom kódem a hackerskými technikami ze skutečného světa, ale také vysvětleními, jak fungují. COMPUTER POWER USER (CPU) MAGAZINE Tohle je vynikající kniha. Ti, kdo se právě chystají přejít na další úroveň, měli by si ji opatřit a pečlivě pročíst. ABOUT.COM INTERNET/NETWORK SECURITY

Hacking umění exploitace Druhé, upravené a doplněné vydání Jon Erickson

HACKING: THE ART OF EXPLOITATION, 2ND EDITION Jon Erickson Copyright 2008 by Jon Erickson. Title of English-language original: Hacking: The Art of Exploitation, 2nd Edition, ISBN 978-1-59327-144-2 published by No Starch Press. Czech-language edition copyright 2009 by ZONER software s.r.o. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from No Starch Press. Copyright 2008 Jon Erickson. Název originálního anglického vydání: Hacking: The Art of Exploitation, 2nd Edition, ISBN 978-1-59327-144-2, vydal No Starch Press. České vydání copyright 2009 ZONER software s.r.o. Všechna práva vyhrazena. Žádná část této publikace nesmí být reprodukována nebo předávána žádnou formou nebo způsobem, elektronicky ani mechanicky, včetně fotokopií, natáčení ani žádnými jinými systémy pro ukládání bez výslovného svolení No Starch Press. Hacking umění exploitace Autor: Jon Erickson Copyright ZONER software, s.r.o. Druhé, upravené a doplněné vydání v roce 2009. Všechna práva vyhrazena. Zoner Press Katalogové číslo: ZR803 ZONER software, s.r.o. Nové sady 18, 602 00 Brno Překlad: RNDr. Jan Pokorný Odpovědný redaktor: Miroslav Kučera Odborná korektura: Miroslav Kučera Šéfredaktor: Ing. Pavel Kristián DTP: Miroslav Kučera Obraz bootovatelného LiveCD ke stažení: http://zonerpress.cz/download/hacking.zip (750 MB) Informace, které jsou v této knize zveřejněny, mohou byt chráněny jako patent. Jména produktů byla uvedena bez záruky jejich volného použití. Při tvorbě textů a vyobrazení bylo sice postupováno s maximální péčí, ale přesto nelze zcela vyloučit možnost výskytu chyb. Vydavatelé a autoři nepřebírají právní odpovědnost ani žádnou jinou záruku za použití chybných údajů a z toho vyplývajících důsledků. Všechna práva vyhrazena. Žádná část této publikace nesmí být reprodukována ani distribuována žádným způsobem ani prostředkem, ani reprodukována v databázi či na jiném záznamovém prostředku či v jiném systému bez výslovného svolení vydavatele, s výjimkou zveřejnění krátkých částí textu pro potřeby recenzí. Veškeré dotazy týkající se distribuce směřujte na: Zoner Press ZONER software, s.r.o. Nové sady 18, 602 00 Brno tel.: 532 190 883, fax: 543 257 245 e-mail: knihy@zoner.cz http://www.zonerpress.cz ISBN 978-80-7413-022-9

5 Obsah Předmluva 11 Poděkování 11 Kapitola 0x100 Úvod 13 0x110 Obraz LiveCD ke stažení 16 Kapitola 0x200 Programování 17 0x210 Co je programování? 18 0x220 Pseudokód 19 0x230 Řídicí struktury 19 0x231 If-Then-Else 19 0x232 Cykly While/Until 21 0x233 Cykly For 22 0x240 Další základní programovací pojmy 23 0x241 Proměnné 23 0x242 Aritmetické operátory 24 0x243 Porovnávací operátory 26 0x244 Funkce 28 0x250 Nejvyšší čas zkusit něco prakticky 31 0x251 Blíž k celkovému obrazu 32 0x252 Procesory architektury x86 36 0x253 Assembler 37 0x260 Zpět k základům 51 0x261 Řetězce 51 0x262 Signed, unsigned, long a short 55 0x263 Ukazatele 57 0x264 Formátovací řetězce 62 0x265 Přetypování 65 0x266 Argumenty příkazového řádku 73 0x267 Obor proměnných 77 0x270 Segmentace paměti 85 0x271 Paměťové segmenty v C 93 0x272 Jak se pracuje s haldou 95 0x273 Funkce malloc() s kontrolou, zdali se alokace podařila 98

6 0x280 Stavění na solidních základech 100 0x281 Přístup k souboru 100 0x282 Souborová oprávnění 106 0x283 Uživatelská ID 108 0x284 Struktury 117 0x285 Ukazatele funkce 121 0x286 Pseudonáhodná čísla 122 0x287 Sada hazardních her 124 Kapitola 0x300 Exploitace 141 0x310 Všeobecné exploitační techniky 144 0x320 Přetečení paměti 144 0x321 Zranitelnosti způsobené přetečením bufferu založeného na zásobníku 148 0x330 Experimenty s BASH 161 0x331 Používání proměnných prostředí 172 0x340 Přetečení v jiných segmentech 181 0x341 Základní přetečení založené na haldě 181 0x342 Přetečení ukazatelů na funkce 187 0x350 Formátovací řetězce 201 0x351 Formátovací parametry 202 0x352 Zranitelnost spojená s formátovacím řetězcem 204 0x353 Čtení z libovolné adresy paměti 207 0x354 Zápis na libovolnou adresu paměti 208 0x355 Přímý přístup k parametru 216 0x356 Zápisy dvoubajtových slov 218 0x357 Odbočka s.dtors 220 0x358 Další zranitelnost programu notesearch 226 0x359 Přepisování tabulky globálních offsetů 228 Kapitola 0x400 Sítě 233 0x410 Model OSI 233 0x420 Sockety 235 0x421 Socketové funkce 236 0x422 Socketové adresy 238 0x423 Síťové pořadí bajtů 240 0x424 Konverze internetové adresy 240

7 0x425 Ukázka jednoduchého serveru 241 0x426 Ukázka webového klienta 245 0x427 Maličký webový server 251 0x430 Loupání slupek nižších vrstev 256 0x431 Spojová vrstva 257 0x432 Síťová vrstva 258 0x433 Transportní vrstva 261 0x440 Odposlouchávání provozu na síti (network sniffing) 264 0x441 Odposlouchávání nezpracovaných socketů 266 0x442 Odposlouchávací knihovna libpcap 268 0x443 Dekódování vrstev 270 0x444 Aktivní odposlouchávání 281 0x450 Odmítnutí služby 295 0x451 Zahlcení podvrženými SYN pakety 296 0x452 Ping smrti 301 0x453 Slza 301 0x454 Zahlcení přes ping 301 0x455 Zesilující se útoky 302 0x456 Útok DDoS 302 0x460 Únos TCP/IP 303 0x461 Únos RST 304 0x462 Pokračování únosu 309 0x470 Skenování portů 310 0x471 Tajné skenování SYN 310 0x472 Skenování FIN, X-mas a Null 310 0x473 Podvržené návnady 311 0x474 Nečinné skenování 311 0x475 Aktivnější obrana 313 0x480 K lidu blíž někoho hackneme 320 0x481 Analýza s GDB 321 0x482 Téměř vždy počítejte s ručními granáty 323 0x483 Shellkód, který se navazuje na port 326 Kapitola 0x500 Shellkód 331 0x510 Assembler versus C 331 0x511 Linuxová systémová volání v assembleru 334

8 0x520 Cesta k shellkódu 337 0x521 Assemblerové instrukce používající zásobník 337 0x522 Vyšetřování s GDB 340 0x523 Odstranění bajtů null 341 0x530 Shellkód, který zplodí shell 347 0x531 Otázka oprávnění 351 0x532 Ještě menší shellkód 354 0x540 Shellkód, který se navazuje na port 356 0x541 Duplikace standardních souborových deskriptorů 361 0x542 Řídicí struktury pro větvení 363 0x550 Shellkód připojující se zpět 368 Kapitola 0x600 Protiopatření 375 0x610 Detekující protiopatření 376 0x620 Systémoví démoni 376 0x621 Signály letem-světem 378 0x622 Démon tinyweb 381 0x630 Nástroje našeho řemesla 386 0x631 Nástroj pro exploitaci tinywebd 386 0x640 Protokolovací soubory 392 0x641 Jak splynout s davem 392 0x650 Přehlížení očividného 394 0x651 Krok za krokem 395 0x652 A dejme zase všechno dohromady 400 0x653 Dceřiní nádeníci 406 0x660 Pokročilá kamufláž 408 0x661 Podvržení přihlášené IP adresy 409 0x662 Nezaprotokolovaná exploitace 414 0x670 Kompletní infrastruktura 417 0x671 Opětovné použití socketu 417 0x680 Propašování nálože 422 0x681 Zašifrování řetězců 422 0x682 Jak skrýt sled 426 0x690 Restriktivní opatření na buffer 427 0x691 Polymorfní tisknutelný ASCII shellkód 430 0x6a0 Vylepšená protiopatření 442

9 0x6b0 Nespustitelný zásobník 442 0x6b1 ret2libc 442 0x6b2 Návrat do system() 443 0x6c0 Náhodné rozvržení paměti zásobníku 445 0x6c1 Výzkumy s BASH a GDB 447 0x6c2 Odskakování od linux-gate 451 0x6c3 Umění aplikovat získané znalosti v praxi 455 0x6c4 První pokus 456 0x6c5 Pohrajeme si s šancemi 458 Kapitola 0x700 Kryptologie 461 0x710 Teorie informace 462 0x711 Nepodmíněná bezpečnost 462 0x712 Jednorázové zašifrování 462 0x713 Distribuce kvantového klíče 463 0x714 Výpočetní bezpečnost 464 0x720 Doba běhu algoritmu 464 0x721 Asymptotická notace 465 0x730 Symetrické šifrování 466 0x731 Lov Groverův kvantový vyhledávací algoritmus 467 0x740 Asymetrické šifrování 468 0x741 RSA 468 0x742 Kvantový faktorizační algoritmus Petera Shora 472 0x750 Hybridní šifry 473 0x751 Útoky typu "Muž uprostřed" 473 0x752 Rozdíly v otiscích prstů hostitele protokolu SSH 478 0x753 Fuzzy otisky prstů 482 0x760 Prolamování hesel 487 0x761 Slovníkové útoky 489 0x762 Vyčerpávající útok hrubou silou 492 0x763 Vyhledávací tabulka hašů 493 0x764 Pravděpodobnostní matice hesla 494 0x770 Bezdrátové šifrování 802.11b 506 0x771 Šifrovací metoda WEP (Wired Equivalent Privacy) 506 0x772 Proudová šifra RC4 508 0x780 Útoky na WEP 508

10 0x781 Offline útoky hrubou silou 509 0x782 Opětovné použití stejného proudového klíče 509 0x783 Dešifrovací slovníkové tabulky založené na inicializačním vektoru 510 0x784 Přesměrování IP adresy 511 0x785 Útoky typu Fluhrer, Mantin a Shamir (FMS) 512 Kapitola 0x800 Shrnutí 523 0x810 Seznam zdrojů 524 0x820 Užitečné nástroje 525 Rejstřík 527

Předmluva Cílem této knihy je podělit se s vámi všemi o umění hackingu. Často není snadné pochopit techniky hackingu, protože k tomu potřebujete poměrně mnoho důkladně zvládnutých vědomostí. Mnohé texty o hackingu se vám mohou zdát jako nesrozumitelné a matoucí, protože bez jistých předběžných znalostí se nelze obejít a vy v tomto druhu vzdělání jednoduše máte několik mezer. Druhé vydání knihy Hacking umění exploitace by vám mělo zpřístupnit svět hackingu, protože o něm dostanete kompletní informace. Od programování přes strojový kód až k exploitaci. K tomuto vydání si navíc můžete stáhnout obraz bootovacího CD (z http://zonerpress.cz/download/hacking.zip), který v sobě obsahuje upravenou linuxovou distribuci Ubuntu. Jakmile tento obraz stáhnete, rozbalíte a vypálíte na CD/DVD médium, můžete ho použít na jakémkoliv počítači s procesorem x86 bez toho, aby došlo k poškození stávajícího operačního systému vašeho počítače. Obsahuje veškerý zdrojový kód z knihy a poskytuje jak vývojové, tak i exploitační prostředí, v němž můžete při četbě souběžně zkoušet všechny příklady uvedené v knize a provádět své vlastní experimenty. Poděkování Mé vřelé díky si zaslouží Bill Pollock a všichni ostatní ve vydavatelství No Starch Press, že konali tak, aby tato kniha mohla spatřit světlo světa, a že jsem mohl kreativně ovlivňovat všechny fáze procesu jejího vzniku. Dále bych rád poděkoval svým přátelům, Sethu Bensonovi a Aaronu Adamsovi, za korektury a úpravy, Jacku Mathesonnovi, že mi vypomohl s assemblerem, Dr. Seidelovi, že udržel můj zájem o počítačovou vědu, rodičům, že mi koupili první Commodore VIC-20, a komunitě hackerů, jejichž inovace a kreativita vytvořila techniky vysvětlované v této knize. 11

12

0x200 PROGRAMOVÁNÍ Hacker je termín, kterým se označují nejenom ti, kdo píší kód, ale také ti, kdo kód exploitují. I když mají obě skupiny hackerů různé finální cíle, používají při řešení úloh podobné techniky. Protože těm, kdo exploitují, pomáhá, když umějí programovat, a naopak vědomosti o tom, jak se exploituje, pomáhají těm, kdo programují, dělají mnozí hackeři obojí. Zajímavé hackerské postupy najdete jak v technikách, které se používají proto, aby vznikl elegantní kód, tak i v technikách, jež se používají za účelem exploitace programů. Hacking opravdu znamená jen akt nalezení chytrého a překvapivého řešení dané úlohy. Hacky, které najdete v exploitačních programech (říká se jim exploity), obvykle využívají počítačová pravidla ( postupy, příkazy atd.) nevšedním způsobem, aby se obešla bezpečnostní opatření tak, jak to zatím nikoho ani nenapadlo. Programovací hacky jsou podobné v tom smyslu, že také využívají počítačová pravidla nově a vynalézavě, ale jejich konečným cílem je efektivnější nebo kratší zdrojový kód, nemusí se nutně jednat o narušení bezpečnosti. Programů, které řeší zadanou úlohu, se dá napsat nekonečně mnoho, ale většina z těchto řešení je zbytečně velkých, příliš složitých a ledabylých. Těch pár řešení, co zbudou, jsou kompaktní, efektivní a úhledná. Programy, které mají tyto kvality, jsou elegantní. Chytrým a vynalézavým řešením, která vedou k této efektivitě, se říká hacky. Hackeři obou skupin oceňují krásu elegantního kódu i důvtipnost chytrých hacků. Ve světě byznysu se víc důrazu klade na to, aby se co nejdříve vychrlil kód, který funguje, než aby obsahoval chytré algoritmy a byl elegantní. Vzhledem k nesmírnému exponenciálnímu růstu výpočetní síly a paměti nemá, z hlediska byznysu, u moderních počítačů se zpracovatelskými cykly v gigahertzech a pamětí v gigabajtech valný smysl strávit pět hodin navíc jen proto, aby se vytvořil úsek kódu, který bude o něco málo rychlejší a efektivnější (co do využití paměti). I když optimalizaci doby trvání a využití paměti ponechá bez povšimnutí valná většina uživatelů kromě těch nejnáročnějších, je to charakteristika, kterou by šlo zpeněžit. Pokud jsou ale na prvním místě okamžité finanční výnosy, trávit čas tvorbou rafinovaných postupů se prostě nevyplatí. Opravdové zhodnocení programovací elegance je tedy na hackerech: na počítačových nadšencích, jejichž konečným cílem není zisk, ale vymačkat až do mrtě ze svého starého Commodore 64 každý bit funkcionality; na autorech programů zvaných exploity, což jsou drobounké a okouzlující

18 0x200 Programování fragmenty kódu, jimiž se dá proklouznout úzkými skulinami v zabezpečení, a na všech ostatních, kdo dokáží ocenit honbu za dokonalostí, kdo se stavějí čelem výzvě najít nejlepší možné řešení. To jsou lidé, které programování vzrušuje. Ti dokáží patřičně ohodnotit krásu elegantního fragmentu kódu nebo důvtipnost důmyslného postupu. Abyste ale pochopili, jak se dají programy exploitovat, musíte nejprve dobře rozumět programování toto je naprosto nezbytná podmínka. Proto je přirozené, že prvním předmětem našeho výkladu bude programování. 0x210 Co je programování? Programování je velmi přirozený a intuitivní pojem. Program není nic víc než posloupnost příkazů napsaných v nějakém konkrétním jazyku. Programy jsou všude okolo nás dokonce i ti, kdo mají panickou hrůzu z technologií, používají programy každý den. Itineráře pro jízdu autem, kuchařské recepty, fotbalové zápasy, DNA, to všechno jsou různé typy programů. Typický itinerář pro jízdu autem může vypadat například takto: Jeďte východním směrem po Main Street. Pokračujte po Main Street, dokud neuvidíte napravo kostel. Jestliže je ulice zavřená kvůli opravám, zde zabočte doprava na 15th Street, zabočte doleva na Pine Street, a pak doprava na 16th Street. Jinak prostě jeďte dál a zabočte doprava na 16th Street. Pokračujte po 16th Street a zabočte doleva na Destination Road. Jeďte rovně 5 mil po Destination Road, pak uvidíte napravo dům. Adresa je 743 Destination Road. Kdo umí česky, tyto pokyny pochopí, a protože jsou napsány v češtině, bude se jimi při jízdě řídit. Jistě není to žádná krásná literatura, ale každý z pokynů je jasný a snadno srozumitelný, přinejmenším pro ty, kdo umějí alespoň trochu česky. Počítače ale žádnému lidskému jazyku nerozumějí, ani angličtině, natož češtině; rozumějí jen strojovému kódu. Chcete-li dát počítači pokyny, aby něco udělal, musejí být tyto pokyny, neboli instrukce, napsány v jeho jazyku. Strojový kód je ovšem tajemný a pracuje se s ním obtížně skládá se z nijak nezpracovaných bitů a bajtů, a na každé architektuře je jiný. Pokud byste chtěli napsat program ve strojovém kódu pro procesor Intel x86, museli byste si zjistit hodnoty sdružené s jednotlivými instrukcemi, vypátrat jak spolu instrukce komunikují, a zvládnout myriády dalších nízkoúrovňových podrobností. Programování tohoto druhu je pracné a rozhodně neintuitivní. Abychom překonali komplikace spojené s psaním ve strojovém kódu, potřebujeme překladač. Jednou z forem překladače strojového jazyka je assembler to je program, který překládá kód assembleru do kódu, jenž bude stroj schopen přečíst. Assembler je méně záhadný než strojový kód, protože používá pro instrukce slovní názvy a proměnné, nikoliv pouhá čísla. Přesto je i assembler na hony vzdálen intuitivnímu jazyku. Názvy instrukcí jsou srozumitelné jen zasvěceným, přičemž jazyk je pro každou architekturu jiný. Právě tak, jako je strojový kód pro procesor Intel x86 jiný než strojový kód pro procesory Sparc, je i assembler určený pro x86 odlišný od assembleru pro Sparc. Program napsaný v assembleru pro architekturu jednoho procesoru nebude fungovat na

Hacking umění exploitace 19 architektuře jiného procesoru. Je-li program napsaný v assembleru pro x86, musí se přepsat, má-li běžet na architektuře Sparc. A navíc abyste mohli psát efektivní programy v assembleru, musíte rovněž znát řadu nízkoúrovňových detailů o architektuře procesoru, pro který píšete. Uvedené potíže se dají zmírnit další formou překladače, kterému se říká kompilátor. Kompilátor převádí jazyk vysoké úrovně do strojového kódu. Vysokoúrovňové jazyky jsou mnohem intuitivnější než assembler (jsou obvykle založené na slovech a frázích z angličtiny) a dají se konvertovat do mnoha různých typů strojového kódu, tj. pro různé procesorové architektury. To znamená, že je-li program napsaný v nějakém vysokoúrovňovém jazyku, stačí ho napsat jednou; stejný programový kód se dá zkompilovat do strojového kódu různých konkrétních architektur. Mezi vysokoúrovňové jazyky patří například C, C++ či Fortran. Ačkoliv program napsaný ve vysokoúrovňovém jazyku se mnohem snadněji čte a více se podobá angličtině než assembler nebo strojový kód, přesto se musejí dodržovat velmi striktní pravidla pro zápis jednotlivých instrukcí. V opačném případě kompilátor nebude schopen pochopit takový kód. 0x220 Pseudokód Programátoři využívají ještě jednu formu programovacího jazyka, které se říká pseudokód. Pseudokód je jednoduchá řeč, která je uspořádána do obecné struktury podobající se nějakému vysokoúrovňovému jazyku. (Teoreticky se dá pseudokód psát v jakékoliv mluvené řeči, nicméně angličtina je nejvýhodnější, protože v ní se pseudokód nejvíc podobá skutečnému kódu, který na jeho základě vznikne.) Ačkoliv kompilátory, assemblery a počítače pseudokódu nerozumějí, je to velmi šikovný způsob zápisu, jímž si programátor může uspořádávat své instrukce. Pseudokód není konkrétně definovaný každý programátor píše pseudokód trochu jinak. Je to jistý mlhavý druh chybějícího propojení mezi mluvenou řečí (obvykle angličtinou) a vysokoúrovňovými jazyky, jako je C. Pseudokód ovšem může posloužit jako skvělý úvodní nástroj pro vysvětlení běžných univerzálních programovacích pojmů. 0x230 Řídicí struktury Bez řídicích struktur by byl program jen pouhou sérií instrukcí, které se vykonávají sekvenčně (jedna za druhou). U velmi jednoduchých programů to stačí, ale většina programů, včetně našeho itineráře s pokyny k jízdě, tak jednoduchá není. Mezi pokyny k jízdě najdeme příkazy jako Jeďte po Main Street, dokud neuvidíte napravo kostel a Jestliže je ulice zavřená kvůli opravám... Tyto příkazy patří mezi řídicí struktury, protože mění tok vykonávání programu z jednoduchého sekvenčního zpracování (jedna instrukce za druhou) na složitější a užitečnější tok. 0x231 If-Then-Else V našich pokynech k jízdě je zmíněno, že Main Street může být zavřená, protože se opravuje. Pokud tomu tak je, měla by se s takovou situací vypořádat speciální sada instrukcí, jinak se bude

20 0x200 Programování v programu postupovat dál podle původní sady instrukcí. S těmito speciálními případy se dá v programu vypořádat pomocí jedné z nejpřirozenějších řídicích struktur: strukturou if-then-else (jestliže-pak-jinak). Všeobecně to vypadá nějak takhle: If (podmínka) then { Sada instrukcí, která se má vykonat, když podmínka platí; Else { Sada instrukcí, která se má vykonat, když podmínka neplatí; V této knize budeme občas používat pseudokód podobající se jazyku C, takže každá instrukce bude končit středníkem, sady instrukcí budou obklopeny složenými závorkami a budou odsazené. Struktura if-then-else předchozích pokynů k jízdě může v pseudokódu vypadat takto: Jeďte po Main Street; If (ulice je zavřená kvůli opravám) { Zabočte doprava na 15th Street; Zabočte doleva na Pine Street; Zabočte doprava na 16th Street; Else { Zabočte doprava na 16th Street; Povšimněte si, že každá instrukce je na samostatném řádku, a že jednotlivé sady podmínkových instrukcí jsou obklopeny složenými závorkami (a že jsou rovněž odsazeny, aby se text lépe četl). V C a v mnohých dalších programovacích jazycích se klíčové slovo then předpokládá implicitně, takže se nemusí uvádět v předchozím pseudokódu jsme ho vynechali. V jiných jazycích může být samozřejmě stanoveno, že klíčové slovo then je v syntaxi povinné sem patří nejenom BASIC a Fortran, ale také Pascal. Tyto druhy syntaktických odlišností v jednotlivých programovacích jazycích jsou pouze drobné detaily; podkladová struktura je stále stejná. Jakmile programátor pochopí pojmy, které se jazyky snaží vyjádřit, zvládne hravě různé variace syntaxe. Protože v následujících sekcích budeme pracovat s jazykem C, budeme v této knize používat pseudokód, jehož syntaxe se bude podobat syntaxi jazyka C. Uvědomte si ovšem, že pseudokód může mít různé, někdy i dost odlišné formy. Další běžné pravidlo syntaxe à la C říká, že pokud sada instrukcí uzavřených ve složených závorkách obsahuje pouze jedinou instrukci, nejsou složené závorky povinné. Kvůli lepší čitelnosti a jasnosti úmyslů je ovšem vhodné takové instrukce odsazovat (z hlediska syntaxe to povinné není).

Hacking umění exploitace 21 Výše uvedené pokyny k jízdě lze s využitím tohoto pravidla přepsat následovně (stále ovšem máme ekvivalentní fragment pseudokódu): Jeďte po Main Street; If (ulice je zavřená kvůli opravám) { Zabočte doprava na 15th Street; Zabočte doleva na Pine Street; Zabočte doprava na 16th Street; Else Zabočte doprava na 16th Street; Toto pravidlo o sadách instrukcí platí pro všechny řídicí struktury zmiňované v této knize. Toto pravidlo samotné je rovněž možné popsat prostřednictvím pseudokódu: If (v sadě instrukcí je jen jediná instrukce) Složené závorky vymezující skupinu instrukcí nejsou povinné; Else { Složené závorky vymezující skupinu instrukcí jsou povinné; Musíme mít k dispozici nějaký způsob, jak tyto instrukce logicky seskupit; I samotný popis syntaxe se dá považovat za jednoduchý program. Existují různé varianty if-then- -else, jako je například příkaz select/case. Logika je v zásadě pořád stejná jestliže podmínka platí, udělej tyto věci, jinak udělej tamty jiné věci (mezi ně mohou patřit i další příkazy if-then). 0x232 Cykly While/Until Dalším elementárním programovacím pojmem je řídicí struktura while, což je druh cyklu. Programátor si často přeje vykonat jistou sadu instrukcí víckrát za sebou, ne pouze jednou. Program může tento úkol splnit prostřednictvím cyklu, požaduje k tomu ovšem sadu podmínek, které mu řeknou, kdy má s cyklováním přestat, jinak by cykloval až do skonání věků. Cyklus while říká, aby se následná sada instrukcí cyklu vykonávala tak dlouho, dokud (while) platí podmínka cyklu. Jednoduchý program pro hladovou myš by mohl vypadat takto: While (máš hlad) { Najdi něco k snědku; Sněz to;

22 0x200 Programování Sada dvou instrukcí za příkazem while se bude opakovat tak dlouho, dokud (while) bude mít myš hlad. Množství jídla, které myška v jednotlivých průchodech cyklem najde, může být různé, od nepatrného drobečku až k celému bochníku chleba. A obdobně počet průchodů sadou instrukcí v cyklu while může být závislý na tom, kolik jídla myš vlastně najde. Jistou variantou cyklu while je cyklus until, což je syntaxe, která je k dispozici například v programovacím jazyku Perl (v C se tato syntaxe nepoužívá). Cyklus until je prostě cyklus while s invertovanou podmínkou cyklu. Tentýž program krmení myši vypadá s cyklem until takto: Until (nemáš hlad) { Najdi něco k snědku; Sněz to; Je jasné, že každý příkaz until se dá převést na cyklus while. Výše uvedené pokyny k jízdě obsahují příkaz Jeďte po Main Street, dokud neuvidíte napravo kostel. Toto se dá snadno změnit na standardní cyklus while, když prostě podmínku obrátíme na opačnou. While (napravo není kostel) Jeďte po Main Street; 0x233 Cykly For Další řídicí konstrukcí cyklu je cyklus for. Obvykle se používá tehdy, když chce programátor provést konkrétní počet iterací. Pokyn k jízdě Jeďte přímo 5 mil po Destination Road se dá převést na cyklus for v tomto tvaru: For (5 iterací) Jeďte přímo 1 míli; Ve skutečnosti je cyklus for vlastně cyklem while s čítačem (počitadlem průchodů). Stejný příkaz lze totiž zapsat i takto: Nastavit čítač na 0; While (hodnota čítače je menší než 5) { Jeďte přímo 1 míli; Přičíst 1 k čítači; V syntaxi pseudokódu podobném jazyku C je podstata cyklu for ještě zřejmější: For (i=0; i<5; i++) Jeďte přímo 1 míli;

Hacking umění exploitace 23 V tomto případě se čítač jmenuje i a příkaz for je rozdělen do tří sekcí oddělených středníky. První sekce deklaruje čítač a nastavuje ho na počáteční hodnotu, v tomto případě na 0 (nulu). Druhá sekce je něco jako příkaz while využívající čítač: dokud (while) čítač splňuje uvedenou podmínku, pokračovat v cyklování. Třetí, poslední, sekce popisuje, jaká akce se má podniknout s čítačem při každé iteraci. V tomto případě je touto akcí i++, což je zkrácený zápis výroku "Přičti 1 k čítači i". S využitím všech dosud probraných řídicích struktur se pokyny k jízdě dají převést do pseudokódu ve stylu podobném jazyku C takto: Jeďte východním směrem po Main Street; While (napravo není kostel) Jeďte po Main Street; If (ulice je zavřená) { Zabočte doprava na 15th Street; Zabočte doleva na Pine Street; Zabočte doprava na 16th Street; Else Zabočte doprava na 16th Street; For (i=0; i<5; i++) Jeďte přímo 1 míli; Zastavte na 743 Destination Road; 0x240 Další základní programovací pojmy V následujících sekcích probereme univerzálnější programovací pojmy, které se používají v mnohých programovacích jazycích (i když s jistými drobnými syntaktickými odlišnostmi). Poté, co tyto pojmy uvedu, je budu prostřednictvím syntaxe podobné jazyku C integrovat do příkladu pseudokódu. Na konci se bude tento pseudokód velmi podobat kódu C. 0x241 Proměnné Čítač, který jsme použili v cyklu for, je ve skutečnosti jeden z typů proměnných. Proměnná se dá jednoduše chápat jako objekt obsahující data, která lze měnit odtud ten název. Existují i proměnné, které se nemění, a trefně se jim říká konstanty. Vrátíme-li se k našemu příkladu s pokyny k jízdě, rychlost auta lze označit za proměnnou, zatímco barva auta je konstanta. Ačkoliv v pseudokódu jsou proměnné jednoduché abstraktní pojmy, v jazyce C (a v mnoha dalších) se proměnné musejí deklarovat a musí se jim přidělit typ. Teprve pak se mohou použít. Je tomu tak proto, že program C se bude nakonec kompilovat do spustitelného programu. Podobně jako u kuchařského receptu, v němž se seznam potřebných ingrediencí uvádí před pokyny, jak kuchtit, deklarace proměnné umožňují vykonat potřebné přípravné akce, než se pustíme do hlavní části programu. Nakonec se

24 0x200 Programování všechny proměnné uloží někde v paměti, přičemž jejich deklarace umožňují kompilátoru, aby si tuto paměť zorganizoval efektivněji. Ovšem na úplném konci, navzdory všem těm deklaracím typů proměnných, je všechno pouze paměť. V C dostane každá proměnná typ, který popisuje, jaké informace hodláte do této proměnné ukládat. Mezi nejběžnější typy patří int ( celočíselné hodnoty), float ( hodnoty s pohyblivou desetinnou čárkou) a char ( hodnota obsahující jediný znak). Proměnné se deklarují velmi jednoduše dané klíčové slovo se uvede před seznamem proměnných, jako to vidíte zde: int a, b; float k; char z; Proměnné a a b jsou nyní definované jako celočíselné. Do k se dá uložit hodnota s desetinným místem (například hodnota 3.14). O proměnné z se předpokládá, že v ní bude uložený nějaký znak, jako například A nebo w. Hodnoty se dají proměnným přiřadit už při deklaraci, nebo kdykoliv později, prostřednictvím operátoru =. int a = 13, b; float k; char z = 'A'; k = 3.14; z = 'w'; b = a + 5; Až se výše uvedené instrukce vykonají, bude proměnná a obsahovat hodnotu 13, k bude obsahovat číslo 3.14, z bude obsahovat znak w a b bude obsahovat hodnotu 18, protože 13 plus 5 se rovná 18. Stručně řečeno proměnné jsou prostě jeden ze způsobů, jak se dají zapamatovat hodnoty; v jazyce C však musíte nejprve deklarovat typ každé proměnné. 0x242 Aritmetické operátory Příkaz b = a + 7 je ukázka velmi jednoduchého aritmetického operátoru. V C se pro jednotlivé aritmetické operace používají symboly uvedené v následující tabulce. První čtyři operace v tabulce by měly být zřejmé. Ačkoliv modulo vám možná připadá jako nový pojem, jedná se pouze o zbytek po dělení. Má-li a hodnotu 13, pak 13 děleno 5 se rovná 2, zbytek je 3, což znamená, že a % 5 = 3. Dále, protože proměnné a i b jsou celá čísla (int), příkaz b = a / 5 vede na výsledek 2, který se uloží do b, protože je to celá část výsledku operace dělení. Chcete-li získat přesnější výsledek 2,6, musíte použít proměnné s pohyblivou čárku (float). Operace Symbol Ukázka Sčítání + b = a + 5

Hacking umění exploitace 25 Operace Symbol Ukázka Odčítání - b = a 5 Násobení * b = a * 5 Dělení / b = a / 5 Modulo % b = a % 5 Pokud chcete dostat tyto koncepty do programu, musíte mluvit jeho jazykem. Jazyk C dále poskytuje pro aritmetické operace několik zkrácených zápisů. Jeden z nich jsem už zmínil výše a běžně se používá v cyklech for. Výraz Zkrácený zápis Vysvětlení i = i + 1 i++ nebo ++i Přičte 1 k proměnné. i = i - 1 i-- nebo --i Odečte 1 od proměnné. Tyto zkrácené zápisy se dají zkombinovat s ostatními aritmetickými operacemi, takže mohou vzniknout složitější výrazy. Zde pak lépe vynikne rozdíl mezi i++ a ++i. První výraz znamená zvýšit hodnotu i o 1 poté, co se vyhodnotí aritmetická operace, zatímco druhý znamená zvýšit hodnotu i o 1 předtím, než se vyhodnotí aritmetická operace. Podívejte se na tento příklad: int a, b; a = 5; b = a++ * 6; Na konci této sady instrukcí bude b obsahovat 30 a a bude obsahovat 6, protože zkrácený zápis b = a++ * 6; je ekvivalentní těmto příkazům: b = a * 6; a = a + 1; Pokud bychom ale použili instrukci b = ++a * 6;, pořadí operací sčítání se změní, což znamená, že tentokrát budou ekvivalentní tyto instrukce: a = a + 1; b = a * 6; Protože se změnilo pořadí operací, b bude nyní obsahovat hodnotu 36; a bude stále obsahovat 6. V programech dost často potřebujeme modifikovat obsah proměnné na místě. Například potřebujete k proměnné přičíst nějakou hodnotu, řekněme 12, a výsledek ihned uložit zpět do této proměnné (například i = i + 12). To se děje tak často, že i pro tyto výrazy existují zkrácené zápisy, viz následující tabulka.