Mivel várom, hogy folytassam a téma folytatását, hadd mondjak el egy kis történelmet, elméletet és gyakorlatot a sebezhetőségekről. Mindannyian hallottuk már, hogy a biztonsági hibák sokba kerülhetnek, mindannyian tudjuk, hogy szoftverünket naprakészen kell tartanunk, mindannyian tudjuk, hogy sok frissítést biztonsági hibák okoznak. De ma elmondok egy kicsit arról, hogyan találják meg és használják ki ezeket a hibákat 🙂 De előtte tisztázni fogunk néhány részletet a jobb áttekintés érdekében.
Mielőtt elkezdené
Először szeretném elmondani, hogy az első sebezhetőségre fogunk összpontosítani, amelyet megtanultam kihasználni, az ismertre Puffer túlcsordul, ebben a biztonsági résben kihasználjuk a memóriaellenőrzés hiányát, hogy szórakoztató dolgokat végezzünk 🙂 De tisztázzunk még egy kicsit többet róla.
Ez nem valós forgatókönyv lesz
Nem engedhetem meg magamnak, hogy megtanítsam őket megszakítani az általuk nézett programokat - egyrészt azért, mert veszélyes a számítógépükre, másrészt azért, mert ehhez több kellene, mint a szokásos szavakból.
Kirándulunk a 80-as évekbe
Amit megmutatni fogok, azt megtehetem a laptopomon, de ez nem azt jelenti, hogy ezt ma egyszerű módon meg lehet valósítani 🙂 sok ilyen fogalmat már annyiszor kihasználtak, hogy új védelmi módszerek és új módszerek kerülhetők el megjelentek 😛 de ez visszavezet minket ugyanoda, nincs hely mindennek elmondani 🙂
Lehet, hogy nem működik a processzorán
Bár egy nagyon egyszerű példát fogok használni, azt szeretném, ha a kezdetektől fogva teljesen világos lenne, hogy ennek a részletei annyira sokfélék és annyira változatosak, hogy ugyanúgy kijöhet, mint én, ha ki akarja próbálni , a kívánt hatást szintén nem lehet elérni 🙂 De elképzelheti, hogy ezt nem tudom megmagyarázni ezen a téren, főleg, hogy ezzel a bevezetéssel már több mint 300 szót vettem fel, így egyenesen a lényegünkhöz jutunk.
Mi az a Puffer túlcsordulás
Ennek megválaszolásához először meg kell értenünk ennek a kombinációnak az első felét.
Pufferek
Mivel minden a számítógép memóriájáról szól, logikus, hogy léteznie kell valamilyen típusú információtartálynak. Amikor arról beszélünk bemenet o kimenetek, közvetlenül a pufferek. Hogy rövid legyen, a ütköző Ez egy meghatározott méretű memóriaterület, amelyben egyszerű mennyiségű információt tárolunk
Túlcsordulások következnek be, ahogy a neve is mutatja, amikor egy puffer több információval tölt fel, mint amennyit képes kezelni. De miért fontos ez?
Stack
Veremként is ismert, absztrakt adattípus, amelyben megtehetjük Kazal információ, fő jellemzőjük, hogy rendelés van LIFO (Last In First Out). Gondoljunk egy pillanatra egy halom tányérra, ezeket egyenként tegyük a tetejére, majd egyenként kivesszük a tetejéről, ez teszi az utolsó tányért, amelyet feltettünk (azt, ami a tetején van) ) az első lemez, amelyet elő fogunk venni, nyilvánvalóan, ha egyszerre csak egy lemezt tudunk elővenni, és úgy döntünk, hogy ebben a sorrendben csináljuk: P.
Most, hogy ismeri ezt a két fogalmat, rendbe kell hoznunk őket. A kötegek azért fontosak, mert minden általunk futtatott programnak megvan a maga végrehajtási verem. De ennek a veremnek van egy sajátos jellemzője, lefelé nő. Az egyetlen dolog, amit tudnia kell erről: az, hogy egy program futása közben egy függvény meghívásakor a verem a memóriában lévő X számtól egy számig (Xn) megy. De a folytatáshoz meg kell értenünk még egy fogalmat.
Mutatók
Ez egy olyan koncepció, amely sok programozót megőrjít, amikor elindulnak a C világában, valójában a C programozás nagy ereje részben a mutatók használatának köszönhető. Az egyszerűség kedvéért mutató memóriacímre mutat. Ez összetettnek hangzik, de nem annyira összetett, mindannyiunkban van RAM a gépeinkben, igaz? Nos, ez meghatározható a blokkok egymást követő elrendezése, ezeket a helyeket általában hexadecimális számokban fejezzük ki (0 és 9, majd A és F között, például 0x0, 0x1, 0x6, 0xA, 0xF, 0x10). Érdekes megjegyzésként itt 0x10 NEM egyenlő 10 😛 -vel, ha decimális sorrendbe konvertáljuk, az ugyanaz lenne, mint a 15. mondás. Ez egy olyan dolog, amely eleinte többet is összekever, de térjünk rá.
Records
A processzorok számos nyilvántartások, amelyek a fizikai memóriából a processzorba továbbítják a helyeket, a 64 bites architektúrák esetében a regiszterek száma nagy és nehéz itt leírni, de az ötlet megalkotása érdekében a regiszterek olyanok, mint a mutatók, többek között jeleznek , egy memóriahely (hely).
Most gyakoroljon
Tudom, hogy sok információ feldolgozása volt eddig, de a valóságban ezek kissé összetett kérdések, amelyeket megpróbálok nagyon egyszerű módon elmagyarázni. Meglátunk egy kis programot, amely puffereket használ, és törd meg, hogy megértsd ezt a túlcsordulásokról, nyilván ez nem az. Ez egy igazi program, és "elkerüljük" a ma alkalmazott ellenintézkedéseket, csak azért, hogy megmutassuk, hogyan tették a dolgokat korábban 🙂, és mert ezek egy része alapelvekre van szükség ahhoz, hogy összetettebb dolgokat tanulhassunk
GDB
Remek program, amelyet kétségtelenül az egyik leggyakrabban használ a C programozó. Számos erénye között megvan az a tény, hogy lehetővé teszi számunkra, hogy lássuk mindazt, amiről eddig beszéltünk, regisztereket, verem, pufferek stb. 🙂 Lássuk azt a programot, amelyet a példánkban használni fogunk.
retinput.c
Ez egy meglehetősen egyszerű program, a könyvtárat fogjuk használni stdio.h
hogy információkat szerezhessen és megjeleníthessen egy terminálon. Láthatjuk az úgynevezett függvényt return_input
amely generálja a ütköző hívott sor, amelynek hossza 30 bájt (a char adattípus 1 bájt hosszú).
A funkció gets(array);
információt kérhet konzol és funkció szerint printf()
visszaadja a tömb tartalmát és megjeleníti a képernyőn.
Minden C-ben írt program a függvénnyel kezdődik main()
, ez csak a return_input meghívásáért felel, most lefordítjuk a programot.
Vegyünk egy kicsit abból, amit éppen tettem. Az opció -ggdb
azt mondja a gcc-nek, hogy a programot információkkal kell lefordítania ahhoz, hogy a gdb megfelelően hibakereshető legyen. -fno-stack-protector
Ez egy olyan opció, amelyet nyilvánvalóan nem használnánk, hanem használni fogunk, mert különben lehetséges lenne a puffer túlcsordulását a veremben létrehozni. Végül kipróbáltam az eredményt. ./a.out
csak azt futtatja, amit az imént összeállítottam, információkat kér tőlem és visszaadja. Futás 🙂
Figyelmeztetések
Egy másik megjegyzés itt. Látja a figyelmeztetéseket? egyértelműen ezt figyelembe kell venni, ha kóddal dolgozunk vagy fordítunk, ez egy kicsit nyilvánvaló, és kevés olyan program van, amely ma a funkcióval rendelkezik gets()
A kódban. A Gentoo egyik előnye, hogy az egyes programok összeállításával látom, hogy mi lehet a baj, egy "ideális" programnak nem szabadna, de meglepődne, hogy hány nagy programnál vannak ezek a figyelmeztetések, mert csak NAGYON nagyok és veszélyes funkciók, ha egyszerre sok figyelmeztetés van. Most, ha folytatjuk
A program hibakeresése
Most ez a rész kissé zavaró lehet, de mivel már elég sokat írtam, nem engedhetem meg magamnak, hogy mindent elmagyarázzak, ezért sajnálom, ha látja, hogy túl gyorsan megyek 🙂
A kód hatástalanítása
Kezdjük azzal, hogy megnézzük az összeállított gépnyelvi programunkat.
Ez a fő funkciónk kódja a Assembly, ezt a processzorunk érti, a bal oldali sor a memóriában lévő fizikai cím, a <+ n> úgy is ismert mint eltolt, alapvetően a függvény (main) elejétől az állításig (más néven műveleti kód). Ezután megnézzük az utasítás típusát (push / mov / callq…) és egy vagy több regisztert. Összefoglalva elmondhatjuk, hogy ez a forrás / eredet és a cél utáni jelzés. <return_input>
második funkciónkra utal, nézzük meg.
return_input
Ez egy kicsit összetettebb, de csak azt akarom, hogy ellenőrizzen pár dolgot, van egy címke <gets@plt>
és egy utolsó opcode hívott retq
jelezve a funkció végét. Helyezni fogunk néhány töréspontot, egyet a függvénybe gets
másik pedig a retq
.
futás
Most futtatjuk a programot, hogy lássuk, hogyan kezdődik a cselekvés.
Láthatjuk, hogy megjelenik egy kis nyíl, amely jelzi az opkódot, ahol vagyunk, szeretném, ha figyelembe vennék az irányt 0x000055555555469b
, ez a cím a hívás után return_input
funkcióban main
, ez fontos, mivel a programnak vissza kell térnie, amikor befejezte a bemenet, térjünk be a függvényre. Most megnézzük a memóriát, mielőtt belépnénk a funkcióba gets
.
Visszatettem az ön számára a fő funkciót, és kiemeltem a kódot, amelyre utaltam, amint láthatja, a végesség két részre osztották, szeretném, ha figyelembe vennék az irányt 0x7fffffffdbf0
(az első balról a kommandós után x/20x $rsp
) mivel ezt a helyet kell használnunk a get eredményeinek ellenőrzéséhez, folytassuk:
A program megtörése
Ezeket kiemeltem 0x44444444
mert ezek képviselik a Ds-t 🙂 most elkezdtük hozzáadni bemenet a programhoz, és amint láthatja, csak két sorra vagyunk a kívánt címetől, addig fogjuk kitölteni, amíg közvetlenül az előző lépésben kiemelt címek elé nem kerülünk.
A visszatérési útvonal módosítása
Most, hogy sikerült beírnunk a kódnak ezt a részét, ahol ez a függvény visszatérését jelzi, nézzük meg, mi történik, ha megváltoztatjuk a 🙂 címet, ahelyett, hogy az opcode helyére lépnénk, amely követi azt, amelyet egy pillanatra megéltünk, mit gondolsz, ha visszatérünk return_input
? Ehhez azonban binárisan kell megírnunk a kívánt címet, ezt a függvénnyel fogjuk megtenni printf
bash-ból 🙂
Most már kétszer megkaptuk az információkat 😀 biztosan nem erre készült a program, de sikerült megtörnünk a kódot, és megismételnünk valamit, amit nem kellett volna tennie.
Gondolatok
Ez az egyszerű változás a kihasználni nagyon alapvető: sikerült megtörnie a programot, és megtenni valamit, amit szeretnénk.
Ez csak az első lépés a szinte végtelen listában a látnivalókról és a hozzáadható dolgokról, többféleképpen is lehet hozzáadni, mint egyszerűen megismételni a megrendelést, de ezúttal sokat és mindent írtam héjkódolás tárgy, hogy többet írjak, mint cikkeket, komplett könyveket, mondhatnám. Bocsánat, ha nem sikerült egy kicsit többet elmélyülnöm olyan témákban, amelyek tetszettek volna, de biztosan lesz esély 🙂 Üdvözlet és köszönet, hogy ideértem.
Legyen közvetlenebb. Írj kevesebbet, és koncentrálj arra, ami számít
Szia, köszönöm a megjegyzést.
Az igazat megvallva az ötletek jó részét levágtam, de még így is számomra úgy tűnt, hogy elhagytam a minimumot, hogy valaki, aki nem rendelkezik programozási ismeretekkel, ötletet szerezzen.
Üdvözlet
A probléma az, hogy akik nem rendelkeznek programozási ismeretekkel, nem fognak semmit megtudni, mert túl bonyolult a kezdéshez, de akik tudnak programozni, azok értékelik, hogy közvetlenebbek.
Feltételezem, hogy nem érhet el mindenkit, választania kell, és ebben az esetben vétett, hogy sokat akar fedezni.
Egyébként építő kritikaként mondom neked, imádom ezeket a témákat, és szeretném, ha továbbra is cikkeket írnál, gratulálok!
Ugyanezt érzem.
Nagyon köszönöm mindkettőnek !! Minden bizonnyal nehéz megérteni, hogyan lehet elérni a célközönséget, ha az az igazság, hogy alacsony a fejlett programozási szinttel rendelkezők száma, akik elolvassák ezeket a cikkeket (legalábbis erre a következtetések alapján lehet következtetni)
Mindenképpen vétkeztem abból, hogy le akarok egyszerűsíteni valamit, amelynek megértéséhez széles körű tudásbázisra van szükség. Remélem, megértette, hogy mivel most kezdem a blogolást, még nem fedeztem fel azt a pontos pontot, ahol olvasóim tudják és értik, amit mondok. Ez sokkal megkönnyítené az igazmondást 🙂
Igyekszem rövidebb lenni, amikor megérdemli, anélkül, hogy személyteleníteném a formátumot, mivel az írás és a tartalom elkülönítése kissé bonyolultabb, mint azt elképzelni lehetne, legalábbis eléggé összekapcsoltam őket, de feltételezem, hogy végül képes leszek vonalak hozzáadása a tartalom vágása helyett.
Üdvözlet
Hol tudhat többet a témáról? Ajánlott könyv?
A példát a The Shellcoder kézikönyvéből Chris Anley, John Heasman, Felix Linder és Gerardo Richarte vette át, de a 64 bites fordítás elvégzéséhez meg kellett tanulnom az architektúrámat, az Intel fejlesztői kézikönyv 2. és 3. kötete egy elég megbízható forrás erre. Jó elolvasni a GDB dokumentációt is, amely az 'info gdb' paranccsal jár együtt. Az Assembly és a C megtanulásához sok nagyon jó könyv létezik, csakhogy az Assembly könyvek egy kicsit régiek, így hiányosságok vannak kitöltéssel típusdokumentáció.
Maga a héjkód különböző okok miatt manapság már nem olyan hatékony, de mégis érdekes új technikákat elsajátítani.
Remélem, ez segít egy kicsit 🙂 Üdvözlet
Jó cikk, régi blog desdelinux újjászületett =)
Amikor azt állítja, hogy a távoli héj nem olyan hatékony, akkor a támadások enyhítésére tervezett ellenintézkedéseket kell értenie, sértő biztonságnak nevezik.
Üdvözlet, és így tovább
Nagyon köszönöm Franz 🙂 nagyon kedves szavakat, valójában arra gondoltam, hogy a Shellcoding ma sokkal összetettebb, mint amit itt látunk. Rendelkezünk az ASLR (véletlenszerű memóriahely-generátor) veremvédővel, a különféle intézkedésekkel és ellenintézkedésekkel, amelyek korlátozzák a programba befecskendezhető opkódok számát, és ez csak a kezdet.
Üdvözlettel,
Helló, csinálsz még egy részt a téma kibővítésével? Érdekes
Helló, a téma minden bizonnyal meglehetősen érdekes, de a komplexitás szintje, amelyet elfogadnánk, nagyon magasra emelkedne, valószínűleg sok hozzászólással jár, amelyek elmagyarázzák a másik megértésének különféle előfeltételeit. Valószínűleg írok róla, de nem a következő bejegyzések lesznek, szeretnék írni néhány témát, mielőtt folytatnám ezt.
Üdvözlet és köszönet a megosztásért
Nagyon jó che! Remek bejegyzésekkel járul hozzá! Egy kérdés, hogy ezt az informatikai biztonsági dolgot azzal kezdem, hogy elolvastam egy "Biztonság biztosítása tollteszteléssel" című könyvet. Ajánlott ez a könyv? Hogyan javasolja, hogy kezdjek érdeklődni ezekről a kérdésekről?
Helló kaktusz, egy egész univerzum a sérülékenységekről, és mások, az igazat megvallva, nagyon sok múlik azon, hogy mi vonzza a figyelmedet, és hogy milyen igényeid vannak, az informatikai vezető nem követeli meg ugyanazt, mint a toll-tesztelő, Or egy sebezhetőségi nyomozó vagy igazságügyi elemző, egy katasztrófa utáni helyreállítási csapat nagyon különböző készségekkel rendelkezik. Nyilvánvaló, hogy mindegyiküknek más szintű technikai ismeretekre van szüksége, javasoljuk, hogy kezdje el felfedezni pontosan azt, ami tetszik, és kezdje el felfalni a könyveket, cikkeket és másokat, és ami a legfontosabb, gyakoroljon mindent, amit elolvasott, még akkor is, ha elavult. a végén változást hoz.
Üdvözlettel,
Hello.
Köszönöm szépen, hogy elmagyarázta ezt a témát, valamint megjegyezte, hogy további információkért rendelkezünk a "The Shellcoder kézikönyvével". Már van függőben lévő olvasmányom 😉