Поглед върху експлоатацията на уязвимости

Тъй като очаквах с нетърпение да продължа да обсъждам тази тема, нека ви разкажа малко история, теория и практика относно уязвимостите. Досега всички сме чували, че недостатъците в сигурността могат да струват много, всички знаем, че трябва да поддържаме софтуера си актуален, всички знаем, че много актуализации са причинени от грешки в сигурността. Но днес ще ви разкажа малко за това как се откриват и експлоатират тези грешки 🙂 Но преди това ще изясним няколко подробности, за да имаме по-добър преглед.

Преди да започнете

Първо искам да ви кажа, че ще се съсредоточим върху първата уязвимост, която се научих да използвам, известната Препълване на буфера, в тази уязвимост се възползваме от липсата на проверка на паметта, за да правим забавни неща 🙂 Но нека изясним малко повече за нея.

Това няма да е реален сценарий

Не мога да си позволя да ги науча да нарушават всяка програма, която гледат - първо, защото е опасно за компютрите им, второ, защото това би отнело повече от обичайната ми квота от думи.

Отиваме на пътешествие през 80-те

Това, което ще ви покажа, мога да правя на своя лаптоп, но това не означава, че това може да стане днес по прост начин 🙂 много от тези концепции вече са били използвани толкова много пъти, че нови методи за защита и нови методи за избягване те са се появили 😛, но това ни връща на същото място, няма място да кажем всичко това 🙂

Възможно е да не работи на вашия процесор

Въпреки че ще използвам много прост пример, искам да е съвсем ясно от самото начало, че подробностите за това са толкова много и толкова разнообразни, че точно както може да излезе същото като мен, ако искате да опитате , желаният ефект може също да не бъде постигнат 🙂 Но можете да си представите, че не мога да обясня, че в това пространство, особено след като с това въведение вече взех повече от 300 думи, така че стигаме направо до нашата точка.

Какво е a Препълване на буфера

За да отговорим на това, първо трябва да разберем първата половина на тази комбинация.

Буфери

Тъй като всичко е свързано с паметта в компютър, логично е да има някакъв тип информационен контейнер. Когато говорим за входове изходи, стигаме директно до концепцията за буфери. За да бъде кратък, a буфер Това е пространство на паметта с определен размер, в което ще съхраняваме количество информация, просто 🙂

Препълванията възникват, както подсказва името, когато буфер се запълва с повече информация, отколкото може да обработи. Но защо това е важно?

Стек

Известни също като стекове, те са абстрактен тип данни, в който можем стек информация, основната им характеристика е, че имат подреждане LIFO (Последно в първото излизане). Нека помислим за секунда за купчина чинии, поставяме ги отгоре една по една и след това ги изваждаме една по една отгоре, това прави последната плоча, която сме сложили (тази, която е отгоре ) е първата плоча Какво ще извадим, очевидно, ако можем да извадим само по една плоча и решим да го направим в този ред: P.

След като вече знаете тези две понятия, трябва да ги подредим. Стековете са важни, защото всяка програма, която изпълняваме, има своя изпълнение стек. Но този стек има a особена характеристикарасте надолу. Единственото нещо, което трябва да знаете за това е, че докато се изпълнява програма, когато се извика функция, стекът преминава от число X в паметта към число (Xn). Но за да продължим, трябва да разберем още една концепция.

Указатели

Това е концепция, която подлудява много програмисти, когато стартират в света на C, всъщност голямата сила на C програмирането се дължи отчасти на използването на указатели. За да бъде по-лесно, показалец сочи към адрес в паметта. Това звучи сложно, но не е толкова сложно, всички имаме RAM в нашите машини, нали? Е, това може да се определи като a последователно подреждане на блокове, тези местоположения обикновено се изразяват в шестнадесетични числа (от 0 до 9 и след това от A до F, като 0x0, 0x1, 0x6, 0xA, 0xF, 0x10). Тук като любопитна бележка, 0x10 НЕ е равно на 10 😛, ако го преобразуваме в десетичен ред, ще бъде същото като да кажем 15. Това е нещо, което също обърква повече от едно в началото, но нека да стигнем до него.

Records

Процесорите работят с редица записи, които работят за предаване на местоположения от физическа памет към процесора, за архитектури, които използват 64-бита, броят на регистрите е голям и е трудно да се опише тук, но за да добиете идеята, регистрите са като указатели, те посочват наред с други неща , място в паметта (местоположение).

Сега практикувайте

Знам, че досега е било обработвано много информация, но в действителност те са малко сложни въпроси, които се опитвам да обясня по много прост начин, ще видим малка програма, която използва буфери и ще разбийте го, за да разберете това за преливанията, очевидно това не е. Това е истинска програма и ние ще "избегнем" много от контрамерките, които се използват днес, само за да покажем как са се правили нещата преди 🙂 и защото някои от тях принципите са необходими, за да може да се научат по-сложни неща 😉

GDB

Страхотна програма, която несъмнено е една от най-използваните от програмистите C. Сред многото й добродетели имаме факта, че тя ни позволява да видим всичко това, за което говорихме досега, регистри, стека, буфери и др. 🙂 Нека видим програмата, която ще използваме за нашия пример.

retinput.c

Собствен. Кристофър Диас Риверос

Това е доста проста програма, ще използваме библиотеката stdio.h за да можете да получавате информация и да я показвате в терминал. Можем да видим функция, наречена return_input което генерира a буфер наречен масив, който има дължина 30 байта (типът данни char е 1 байт).

Функцията gets(array); изискайте информация чрез конзола и функция printf() връща съдържанието на масива и го показва на екрана.

Всяка програма, написана на C, започва с функцията main(), това ще отговаря само за извикване return_input, сега ще компилираме програмата.

Собствен. Кристофър Диас Риверос

Нека вземем малко от това, което току-що направих. Опцията -ggdb казва на gcc, че трябва да компилира програмата с информация за gdb, за да може правилно да отстранява грешки. -fno-stack-protector Това е опция, която очевидно не трябва да използваме, но която ще използваме, защото в противен случай би било възможно да се генерира препълване на буфера в стека. В крайна сметка тествах резултата. ./a.out той просто изпълнява това, което току-що съм компилирал, той ме пита за информация и я връща. Тичане 🙂

предупреждения

Още една бележка тук. Виждате ли предупрежденията? очевидно е нещо, което трябва да се вземе предвид, когато работим с код или компилираме, това е малко очевидно и има малко програми, които днес имат функцията gets() В кода. Едно от предимствата на Gentoo е, че като съставям всяка програма, виждам какво може да се обърка, „идеалната“ програма не трябва да ги има, но ще се изненадате колко големи програми имат тези предупреждения, защото те са МНОГО големи и това е трудно е да се следят опасните им функции, когато има много предупреждения едновременно. Сега ако продължим

Отстраняване на грешки в програмата

Собствен. Кристофър Диас Риверос

Сега тази част може да е малко объркваща, но тъй като вече писах доста, не мога да си позволя да обясня всичко, така че съжалявам, ако виждате, че вървя твърде бързо 🙂

Дезактивиране на кода

Нека започнем с разглеждането на нашата компилирана програма за машинен език.

Собствен. Кристофър Диас Риверос

Това е кодът на нашата основна функция в Монтаж, това е, което разбира нашият процесор, редът вляво е физическият адрес в паметта, <+ n> Е познат като офсет, основно разстоянието от началото на функцията (main) до това изявление (известно като Кодът). След това виждаме типа инструкция (push / mov / callq ...) и един или повече регистри. Обобщено можем да кажем, че това е индикацията, последвана от източника / произхода и дестинацията. <return_input> се отнася до втората ни функция, нека погледнем.

return_input

Собствен. Кристофър Диас Риверос

Това е малко по-сложно, но искам само да проверите няколко неща, има таг, наречен <gets@plt> и един последен наречен opcode retq указващ края на функцията. Ще поставим няколко точки на прекъсване, едната във функцията gets и друг в retq.

Собствен. Кристофър Диас Риверос

бягане

Сега ще стартираме програмата, за да видим как започва действието.

Собствен. Кристофър Диас Риверос

Можем да видим, че се появява малка стрелка, показваща кода на операционната система, където се намираме, искам те да вземат предвид посоката 0x000055555555469b, това е адресът след обаждането до return_input във функция main , това е важно, тъй като тук трябва да се върне програмата, когато приключите с получаването на вход, нека да влезем във функцията. Сега ще проверим паметта, преди да влезем във функцията gets.

Собствен. Кристофър Диас Риверос

Поставих обратно основната функция за вас и подчертах кода, към който се позовавах, както виждате, поради крайност е разделен на два сегмента, искам те да вземат предвид посоката 0x7fffffffdbf0 (първият отляво след командоса x/20x $rsp) тъй като това е местоположението, което трябва да използваме, за да проверим резултатите от get, нека продължим:

Нарушаване на програмата

Собствен. Кристофър Диас Риверос

Подчертах тези 0x44444444защото те са представяне на нашите Ds 🙂 сега започнахме да добавяме вход към програмата и както можете да видите, ние сме само на два реда от желания от нас адрес, ще го попълним, докато не сме точно преди адресите, които сме подчертали в предишната стъпка.

Промяна на пътя за връщане

Сега, след като успяхме да въведем този раздел на кода, където той показва връщането на функцията, нека видим какво ще стане, ако сменим адреса 🙂, вместо да отидем до местоположението на кода за действие, който следва този, който имахме преди малко, какво мислите, ако се върнем return_input? Но за това е необходимо да напишем адреса, който искаме, в двоичен файл, ще го направим с функцията printf от баш 🙂

Собствен. Кристофър Диас Риверос

Сега сме получили информацията два пъти 😀 със сигурност програмата не е създадена за това, но успяхме да разбием кода и да го накара да повтори нещо, което не е трябвало да прави.

Размисли

Тази проста промяна може да се счита за a използват много основно 🙂 той е успял да прекъсне програмата и да направи нещо, което искаме от него.

Това е само първата стъпка в почти безкраен списък от неща, които трябва да видите и добавите, има начини да добавите повече неща, отколкото просто да повторите поръчка, но този път съм писал много и всичко свързано с черупково кодиране това е тема за писане на повече от статии, пълни книги бих казал. Извинете, ако не успях да се задълбоча малко повече в теми, които бих искал, но със сигурност ще има шанс 🙂 Поздрави и благодарности, че стигнахте тук.


Оставете вашия коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

*

*

  1. Отговорен за данните: Мигел Анхел Гатон
  2. Предназначение на данните: Контрол на СПАМ, управление на коментари.
  3. Легитимация: Вашето съгласие
  4. Съобщаване на данните: Данните няма да бъдат съобщени на трети страни, освен по законово задължение.
  5. Съхранение на данни: База данни, хоствана от Occentus Networks (ЕС)
  6. Права: По всяко време можете да ограничите, възстановите и изтриете информацията си.

  1.   2p2 каза той

    Бъдете по-директни. Пишете по-малко и се фокусирайте върху важното

    1.    ChrisADR каза той

      Здравейте, благодаря за коментара.

      Честно казано, изрязах добра част от идеите, но въпреки това ми се струваше, че оставих минимума, за да може някой, който няма познания по програмиране, да получи идея.

      поздрави

      1.    анонимен каза той

        Проблемът е, че тези, които нямат познания по програмиране, няма да научат за нищо, защото е твърде сложно за начало, но тези, които знаят как да програмират, оценяват по-директността.

        Предполагам, че не можете да достигнете до всички, трябва да изберете и в този случай сте съгрешили, че искате да покриете много.

        Между другото, казвам ви като конструктивна критика, обичам тези теми и бих искал да продължите да пишете статии, поздравления!

    2.    анонимен каза той

      Мисля, че същото.

      1.    ChrisADR каза той

        Благодаря много и на двамата !! Със сигурност е трудно да се разбере как да се достигне до целевата аудитория, когато истината е, че броят на хората с напреднало ниво на програмиране, които четат тези статии, е нисък (поне това може да се заключи въз основа на коментарите)

        Със сигурност съм съгрешил от желанието да опростя нещо, което изисква широка база от знания, за да се разбере. Надявам се, че разбирате, че тъй като тепърва започвам да пиша блогове, все още не съм открил точната точка, в която читателите ми знаят и разбират какво казвам. Това би улеснило много казването на истината 🙂

        Ще се опитам да бъда по-кратък, когато заслужава, без да обезличавам формата, тъй като разделянето на начина на писане от съдържанието е малко по-сложно, отколкото може да си представим, поне ги имам доста свързани, но предполагам, че в крайна сметка ще мога за да добавите линии вместо да изрежете съдържание.

        поздрави

  2.   Mario каза той

    Къде бихте могли да научите повече за темата? Всяка препоръчана книга?

    1.    ChrisADR каза той

      Примерът е взет от Наръчника на Shellcoder от Chris Anley, John Heasman, Felix Linder и Gerardo Richarte, но за да направя 64-битовия превод, трябваше да науча за моята архитектура, ръководството за разработчици на Intel, томове 2 и 3 са доста надежден източник за това. Също така е добре да прочетете документацията на GDB, която идва с командата 'info gdb'. За да научите Assembly и C има много много добри книги, с изключение на това, че книгите за събрание са малко стари, така че има празнина, която да запълните с друга типова документация.

      Самият шелкод вече не е толкова ефективен в наши дни по различни причини, но все пак е интересно да се научат нови техники.

      Надявам се да помогне малко 🙂 Поздрави

  3.   Франц каза той

    Добра статия, стар блог desdelinux се прероди отново =)
    Когато казвате, че отдалечената обвивка не е толкова ефективна, имате предвид противодействия, предназначени да смекчат атаките, те го наричат ​​обидна сигурност.
    Поздрави и продължавайте така

    1.    ChrisADR каза той

      Благодаря ви много, Франц, много мили думи, всъщност имах предвид, че Shellcoding днес е много по-сложен от това, което виждаме тук. Разполагаме с ASLR (генератор на произволни местоположения на паметта) защитник на стека, различните мерки и контрамерки, които ограничават броя на опкодовете, които могат да бъдат инжектирани в програма, и това е само началото.

      С уважение,

  4.   Безплатен софтуер каза той

    Здравейте, ще направите ли друга част, разширяваща темата? Интересно е

    1.    ChrisADR каза той

      Здравейте, темата със сигурност е доста интересна, но нивото на сложност, което бихме поели, би станало много високо, вероятно включващо голям брой публикации, които да обяснят различните предпоставки за разбиране на другия. Вероятно ще пиша за това, но това няма да са следващите публикации, искам да напиша няколко теми, преди да продължа с тази.

      Поздрави и благодаря за споделянето

  5.   кактус каза той

    Много добра че! Вие допринасяте за страхотни публикации! Един въпрос, започвам това нещо за ИТ сигурност, като чета книга, озаглавена „Осигуряване на сигурност чрез тестване на писалка“. Препоръчва ли се тази книга? Как предлагате да започна да се интересувам по тези въпроси?

    1.    ChrisADR каза той

      Здравейте кактус, това е цяла вселена за уязвимостите, и други, честно казано, зависи много от това, което привлича вниманието ви и нуждите, които имате, ИТ мениджърът не трябва да знае същото като тестер за писалки, Или изследовател на уязвимости, или съдебен анализатор, екип за възстановяване при бедствия има съвсем различен набор от умения. Очевидно всеки от тях изисква различно ниво на технически познания, препоръчвам ви да започнете да откривате точно това, което ви харесва, и да започнете да поглъщате книги, статии и други, и най-важното е да практикувате всичко, което сте прочели, дори и да е остаряло, това ще направи разлика в крайна сметка.
      С уважение,

  6.   Айцен каза той

    Здравейте.
    Благодаря ви много, че обяснихте тази тема, както и коментирахте, че за допълнителна информация имаме "Наръчник на Shellcoder". Вече имам предстоящо четене 😉