наверное все знают, о такой штуке как nx/xd биты, делающие стек и кучу неисполняемыми, что предотвращает засылку shell-кода. некоторые "эсперты" даже пишут # на сегодняшний день не существует ни одного хотя бы # концептуального эксплойта, на практике доказывающего # возможность поражения Windows XP с установленным SP2. я вот тут от нефиг делать поломал голову над этим на досуге и нашел универсальное решение, пробивающее вынь и линух, но... как показал поиск по иннету, я был не первым, котому это пришло в голову... об этом уже знает дофига народа. тем не менее, мож кому будет полезно. вот картинка из одной статьи. с первого взгляда становиться все ясно. http://www.mastropaolo.com/blogpics/hack2_scheme.png а вот сама статья: http://www.mastropaolo.com/?p=13 так что очередная защита на проверку оказалась лажей.
15й пост Это про Buffer Security Check чтоли? Непонял чем оно может помешать - просто придется обойти обе защиты. Вот если бы _security_cookie был per-thread, неконстантой и менялся, желательно рандомно - тогда да, поксоренный esp, которым защищается адрес возврата всегда неконстанта и buffer overflow пролетает, иначе надо просто определить эту константу(поксореный esp) и не портить ее. Или я неправ?
n2k > "так что очередная защита на проверку оказалась лажей" Дык ИМХО только писаки от микрософт представляют nx\xd биты как защиту от зловредных эксплойтов. В действительности же это просто довесок к логике защищенного режима и вообще удивительно почему этого не предусмотрели сразу - наверное битов в PDE\PTE не хватило Главное на уровне сегментов эта защита есть (сегменты данных, включая стек, не подлежат исполнению), а на уровне страниц - нет, и соответсвенно при плоской модели памяти вся защита на уровне сегментов летит к чертям. Даже в сообщениях об ошибках GP проявляется эта глупость: при попытке jmp\call\ret на несуществующий адрес в процах без nx\xd выдается "Память не может быть read", хотя на самом деле была попытка execute - вот и пойми А что касается защиты от затирания адреса возврата в стеке, то разработчики камней на эту тему просто не думали или им это нафиг не нужно, т.к. решить эту задачку в принципе довольно просто в рамках существующей архитектуры. В упрощенном варианте и делать-то особо ничего не нужно. Дело в том, что для предсказания адреса возврата во всех современных процах используется Return Stack Buffer (RSB) - при каждом call проц заталкивает в RSB предполагаемый адрес возврата и при каждом ret вытаскивает этот адрес из RSB, предполагая что все call и ret согласованы. Соответсвенно если по каким-то причинам (из-за несогласованности call\ret или из-за подмены адреса в стеке) при исполнении ret адрес возврата оказывается другим, то проц сбрасывает конвеер и отменяет спекулятивное исполнение кода по адресу из RSB. Поэтому остается только предусмотреть генерацию исключения при таком несоответсвии и какой-нить управляющий бит для вкл\выкл такой защиты. По кр.мере будет работать для программ со сбалансированными call\ret, ну а для любителей использовать call не по назначению или подменять адрес возврата - можно, например, ввести префикс отмены проверки для конкретного call и ret
> Дык ИМХО только писаки от > микрософт представляют nx\xd > биты как защиту от зловредных > эксплойтов. В действительности не только. унихи их тоже поддерживают. и с теми же целями. да и раньше были патчи, которые делали стек неисполняемым... > же это просто довесок к логике > защищенного режима и вообще > удивительно почему этого не > предусмотрели сразу - наверное > битов в PDE\PTE не хватило скорее всего для обеспечения совместимости со старым ПО, которое исполняется в стеке, ведь и сейчас у ms большая головная боль куча программ отказывается выполняться, если включить dep для всех, в том числе и некоторые библиотеки от бормана, а не только студенческие поделки и протекторы > Главное на уровне сегментов эта > защита есть (сегменты данных, > включая стек, не подлежат > исполнению), а на уровне страниц > - нет, и соответсвенно при > плоской модели памяти вся защита > на уровне сегментов летит к > чертям. в том-то и дело. я вообще не понимаю, нафига ms избрала такую модель... можно было свободно разнести стек, данные и код и кучу по разным сегментам... так ведь нет! > ошибках GP проявляется эта > глупость: при попытке > jmp\call\ret на несуществующий > адрес в процах без nx\xd выдается > "Память не может быть read", хотя > на самом деле была попытка > execute - вот и пойми я не так давно ковырял bsod на предет написания утилиты которая его пытается обойти, вернувшись в нормальный режим, так вот в ядре куча всяких "вкусностей" типа обломали нас с памятью, а мы вызываем kebugcheckex c кодом типа аццес виолатион > оказывается другим, то проц > сбрасывает конвеер и отменяет > спекулятивное исполнение кода по > адресу из RSB. Поэтому остается ща. посчитай сколько программ после этого слеят ласты
n2k Чего я не понимаю, так это глобалистких устремлений микрософтов придумать какой-то новый законопорядок и навязать его всему миру И ты похоже в том же направлении мыслишь: "посчитай сколько программ после этого слеят ласты". А зачем вообще вводить тотальный контроль исполнения данных и подмены адресов возврата ? Ведь и микрософт оставил возможность отключения DEP для части или даже для всех программ, да и исполнять любой кусок памяти можно (пока , если установить соотв.атрибуты страниц. И с контролем соответствия адреса возврата можно дать возможность включать\отключать контроль. Пусть он по умолчанию будет отключен для совместимости со старым ПО, а в новых программах можно было бы использовать эту возможность и для отладки, и так - "на всякий случай". Примерно также, как с маскируемыми исключениями FPU - хочешь исключения - пожалуйста, включай и наслаждайся И пользы видимо было бы больше, чем от нынешнего DEP, по крайней мере эксплойтом такую защиту так просто не выключишь
> А зачем вообще вводить тотальный контроль исполнения данных и подмены адресов > возврата? это один из способов защиты программ от нападения. "зачем" - это не ко мне. такие решения принимаются как минимум на уровне СЕО мыщъх'а никто и не спросит. а если бы и спросили -- что бы я ответил? > Ведь и микрософт оставил возможность отключения DEP для части или > даже для всех программ, да и исполнять любой кусок памяти можно (пока , вот потому его и можно легко атаковать. пока я собственно что хотел показать -- что dep это лажа, и даже если он включен, его можно обойти, заслав shell-код. может, кто-то как раз размышляет над этим и ссылка на картнику ему пригодится. может, кто-то считает, что с dep он может спать спокойно и никакие хакеры ему не страшны, ибо на его страже стоит ms в этом случае, статья его разорчарует. > установить соотв.атрибуты страниц. И с контролем соответствия адреса возврата > можно дать возможность включать\отключать контроль. ...однажды в греции стали проектировать новую баню. и призадумались: если доски не построгать, то это же... занозиться можно! а если построгать... можно так дерябнуться, что костей не соберешь! короче, они потрогали и прибили строганным вниз
n2k 1. Все таки я не согласен с "тоталиторизмом". Каждый должен отвечать за свой "участок фронта", достаточно того чтобы разработчики камней предоставили некоторые аппаратные возможности контроля, а MS предусмотрел способы защиты своих сервисов и дал рекомендации другим разработчикам ПО. А там уж время и добровольный выбор юзверей сами расставят все на свои места - хочешь "чувствовать себя защищенным", отказывайся от устаревших уязвимых осей и прог и переходи на новые. Из-за проблем с совместимостью и из-за разных требований к защите, необходимо предусматривать возможности и тотального контроля и локального (чтобы "хорошая" ось или прога могла реализовывать меры защиты независимо от кучи прог, "клеящих ласты" при включении общего контроля) 2. Все таки DEP нельзя назвать лажей, это часть защиты, затрудняющая жизнь зловредным жучкам и червячкам. Но пример простого и изящного обхода DEP показывает, что основная дыра в которую лезут shell-коды это не само исполнение данных, а принцип хранения в стеке адресов возврата и параметров функций, плюс известные фиксированные адреса этих функций и фиксированные значения параметров. Вот в чем "корень зла" - не нужно ничего исполнять в стеке, достаточно записать в стек в нужном месте нужную последовательность байт и процессор сам все исполнит. Ну прям какая-то программируемость через стек на языке Win API, можно даже конкурсы устраивать, кто более длинную и интересную последовательность вызовов придумает Поэтому и защиту следовало бы строить, избавляясь от этих уязвимостей: проверять адрес возврата, передавать в важные функции переменные параметры, к 3-му тысячелетию можно было бы пересмотреть организацию импорта (фиксированные ImageBase системных dll и JMP-санки в таблице импорта в смысле защиты от червяков никуда не годятся - нужен простой косвенный вызов без всяких JMP). Кстати, не знаешь почему в XP адреса TEB и PEB прыгают произвольным образом - хитроумная защита или что ? Вот еще одна бредовая фантазия пришла на ум - можно задействовать аппаратную поддержку LBR (Last Branch Recording) для проверки того был ли вызов VirtualAlloc по call\jmp или нет (значит по ret => alarm), насчет performance degradation ничего сказать не могу, но параноидальная защищенность может быть превыше всего Ес-но с кардинальными софтварными решениями хлопот не оберешься с совместимостью, поэтому мне аппаратная защита адреса возврата и представляется более реальным решением в обозримом будущем. И твоя ирония с греками и банями мне чего-то не понятна. Какой такой эксплойт можно придумать, если в проге включена генерация исключения при несоответсвии адреса возврата ? Пусть даже ее можно отключить программно, пусть вирусы ее могут отключить, но shell-код то этого сделать не может. Если не можешь защитить все и сразу, так хоть по частям и постепенно. Отладил прогу, все call\ret сбалансированы - защита от эксплойтов готова, дешево и сердито. А если еще и привелигированный битик добавить, то ось может запрещать выключение контроля для своих сервисов и других важных программ. Фантазия конечно, но вполне реальная и главное - безобидная и не нарушающая совместимости с существующим ПО. Да ладно, ну ее Остается ждать ответного хода MS, раз Сам Великий Мыщьх вынес свой уничижительный вердикт в отношении DEP ))
leo Ещё как можно! Переполнение буфера в стеке с подменой адреса возврата не является обязательным условием для эксплойтинга, это просто один из многочисленных способов А ирония с грецкой баней думаю в том, что MS не идет по пути улучшения\оптимизации\исправления ошибок в своих исходниках(так сказать в сторону профессионализма) видимо это долго и дорого, хотя причина кроется именно в некорректной обработке данных, а они лечат уже следствие (вводя запрет на исполнение "чужого" кода, добавляют всякие обработчики и т.д.), и получается что вместо легкой программы-дельтоплана мы имеем супер-боинг с тенисными кортами и бассейном на борту (которые таки и не работают), я как-то посмотрел в отладчике на код IE - одним словом это ужас (там лишнего кода, вы даже не представляете сколько ... и это уже стало нормой)
> достаточно того чтобы разработчики камней предоставили некоторые аппаратные > возможности контроля, а MS предусмотрел способы защиты своих сервисов и дал > рекомендации другим разработчикам ПО. ms всегда идет своим особым путем, который умом не понять в статье была ссыла на блок одного мудрого чувка, который дал в свою очередь ссылки на то, как это сделали на линухе и бзди. там сделали это граммотно 1) nx/xd проэумулировали даже там где их нет, через защиту на уровне сегментов, сохранив плоскую модель памяти и без потери производительности 2) адресное пространство радномизовали, чтобы хакер хрен мог вызвать mmprotect для установки прав доступа 3) установка права "исполняемый" доступна только системе, но не юзеру а ms ни хрена не сделала. наберите "dep" в базе знаний и посмотрите сколько проблем возникает только у продуктов от самой ms! про сторонних разработчиков я вообще молчу. факт - dep несет кучу проблем, причем мало от чего защищает, даже если он включен... короче - очередная лажа и червей хоронить еще рано так что готовьтесь к новым атакам! > А там уж время и добровольный выбор > юзверей сами расставят все на свои места - хочешь "чувствовать себя > защищенным", отказывайся от устаревших уязвимых осей и прог и переходи на речь идет о том, что даже если dep включен его можно обойти, по механизму описанному в стате. причем, даже если используется защита стека (ключ /GS в ms vc 7), остается переполенение кучи, которое так же позволяет добиться аналогичного эффекта... да и другие типы переполнение тоже... так что даже на максимальном уровне защиты (включен аппаратный dep для всех приложений и все приложения перекомпилированы vc 7 ) c ключом /GS _все_равно_ чувство защищенности только в головах тех, кто верит ms на слово > новые. Из-за проблем с совместимостью и из-за разных требований к защите, > необходимо предусматривать возможности и тотального контроля и локального > (чтобы "хорошая" ось или прога могла реализовывать меры защиты независимо от > кучи прог, "клеящих ласты" при включении общего контроля) все это уже давно есть (на аппаратном уровне), начиная с 286 ) > 2. Все таки DEP нельзя назвать лажей, это часть защиты, затрудняющая жизнь > зловредным жучкам и червячкам. Но пример простого и изящного обхода DEP нормально реализованный dep должен быть сделать выполнение shell-кода невозможным как это сделали в W^X и Exec Shield в юнихе. но он (dep) этого не сделал... это и называется _лажей_ > показывает, что основная дыра в которую лезут shell-коды это не само исполнение > данных, ты что?! если будет нельзя заслать свой shell-код, то это ласты. придется довольствоваться вызовом уже сущесвтующих функций, и хотя на юнихе существует реальная возможность установить шелл или повысить свои права до рута, под виндами конь не валялся в смысле возможности атакуюзего будут _очень_ ограничены... > а принцип хранения в стеке адресов возврата и параметров функций, угу. а еще вспоминим указатели и переполнение кучи уже куча эксплоитов лезет в эту дыру. она не трогает адреса возврата, а просто перезаписывает указатели на функции и... > известные фиксированные адреса этих функций и фиксированные значения > параметров. Вот в чем "корень зла" - не нужно ничего исполнять в стеке, вот про это я и говорю. нужно делать рандомизатор типа ASLR (Address Space Layout Randomization), хоть он и не дает 100% защиты, но все-таки... > достаточно записать в стек в нужном месте нужную последовательность байт и > процессор сам все исполнит. в dep'ом - нет, не исполнит. ты читаел статью? сразу видно что нет почитай. там идет последовательность v_alloc -> cpy -> shell-code код исполняется не на стеке. ибо он уже не исполняемый > Поэтому и защиту следовало бы строить, избавляясь от этих уязвимостей: > проверять адрес возврата, передавать в важные функции переменные параметры, к > 3-му тысячелетию можно было бы пересмотреть организацию импорта угу. отсуствтии got делает свое дело. а в юнихе она вообще в регистре. хрена его перезапишешь ) а про защиту стека вообще смех. записали кукис в writeble область памяти ) > защиты от червяков никуда не годятся - нужен простой косвенный вызов без всяких > JMP). Кстати, не знаешь почему в XP адреса TEB и PEB прыгают произвольным > образом - хитроумная защита или что ? это и есть защита. программный dep только его уже обошли. куча статей валяется в иннете. > Вот еще одна бредовая фантазия пришла на ум - можно задействовать аппаратную > поддержку LBR (Last Branch Recording) для проверки того был ли вызов > VirtualAlloc по call\jmp или нет (значит по ret => alarm), насчет performance это действительно бредовая идея. аппаратура тут причем? да и совместимость теряется... > более реальным решением в обозримом будущем. И твоя ирония с греками и банями > мне чего-то не понятна. Какой такой эксплойт можно придумать, если в проге 1) если реализовать DEP "как надо" ничего ни хрена не будет работать 2) если реализовать DEP "чтобы все работало" он ни хрена не будет защищать что сделала ms? она сделала так, чтобы ни хрена не работало, и ни хрена ничего не защищало ) > включена генерация исключения при несоответсвии адреса возврата ? сколько прог сразу "свалиться" ты подумал? где хранить это соответствие? особенно при глубокой рекурсии ) что делать при возникновении прерываний? короче, ничего не получится... проще сделать раздельных стек для хранения адресов возврата и локальных переменных > и постепенно. Отладил прогу, все call\ret сбалансированы - защита от эксплойтов если говорить о _новых_ прогах, то там можно предусмотреть кучу других типов защит, контролирующих целостность стека и кучи... речь-то идет о уже написанных > Остается ждать ответного хода MS, раз Сам Великий Мыщьх вынес свой уничижительный я вообще-то сказать по правде совсем не собирался затевать флейм "как надо бороться с переполнениями". существует куча готовых решений в том же юнихе (хотя в нем переполнения и так достаточно редки, намного реже, чем у вины), я просто кинул ссылку на статью, показывающую как эту защиту обойти а тот тут мне уже один товарищ предлагал $10.000 за эксплоит, пробивающий dep теперь он (товарищ) отмазывается как может ))
n2k Умный ты, книжки толковые пишешь, а вот дискутировать с тобой весьма непросто Если разбивать предложения на фразы и интерпретировать их по своему, то можно дискутировать до бесконечности 1. Говоря об "основной дыре в которую лезут shell-коды" я имел в виду, что необходимым условием исполнения шелл-кода является возможность передачи на него управления - если такой возможности нет или она существенно ограничена, то и DEP отходит на второй план. К тому же зловредный шелл может и вовсе не иметь своего кода - веселый червячок может например организовать простую цепочку вызовов DeleteFile и никакой крутой DEP, реализованный "как надо" ему помешать не сможет. Самое интересное, что закончив "разбор" предложения ты прямо или косвенно соглашаешься с тем что нужно предотвращать именно передачу управления - нужно делать рандомизаторы адресов стека, кучи и прочие хитрости а-ля PaX 2. Говоря о том, что "достаточно записать в стек в нужном месте нужную последовательность байт" я имел в виду не сам внедряемый код, а перенаправление вызовов, приводящую к изменению логики работы программы. Только одна эта возможность, даже без внедрения кода, позволяет червячкам веселиться и пакостить. Хотя без внедрения кода возможностей для веселья меньше, но тем не менее их достаточно чтобы у юзверя крыша поехала и никакой DEP и антивири ему тут не помогут - все "в рамках закона" 3. "Да застраховался я !", т.е. прочитал эту "суперстатью", и не раз, и по ссылкам всем пробежался Идея оригинальная, ну и что ? Никакого революционного открытия не вижу. Зато в первых же строках вижу сомнительную фигню типа "I tried was calling VirtualProtect.. However it requires to know the exact address that was used in a previous call to VirtualAlloc" ?! Откуда это, ничего она не requires - в VirtualProtect можно передавать любой адрес. Конечно на 100% ручаться не могу, т.к. нет под рукой проца с хардварным DEP, но сама по себе VirtualProtect в XP SP2 нормально работает c любым адресом и позволяет делать страницу(ы) стека executable - по кр.мере VirtualQuery возвращает Protect = PAGE_EXECUTE_READWRITE. Поэтому, DEP вроде как и не запрещает в принципе исполнять код в стеке, но делать это можно только легально через вызов VirtualProtect (или я не прав ?). А ты почему-то "торжествуешь" по поводу того, что в предлагаемом варианте код исполняется не в стеке, а в специально выделенной памяти, и не устаешь повторять, что DEP это лажа, хотя возможность исполнения данных (но только) при наличии соответсвующих атрибутов страниц вроде как изначально провозглашалась MS и обсуждалась\выяснялась множество раз в т.ч. и здесь на форуме. Поэтому твоей "эйфории" по поводу "взлома" DEP вроде как здесь никто и не разделяет (судя по отсутствию восторженных откликов - чего тут ломать если MS любезно прилагает к DEP ключики, доступные всем желающим Отсюда и флейм "как надо бороться с переполнениями", т.к. кроме твоего товарища со $10.000 наверное все давно поняли, что DEP это просто один из камушков на пути червячков, который в некоторой степени затрудняет их путешествия, но легко обходится - пока Да и нафиг MS голову было ломать над этим DEP, когда процев с NX\XD пока еще капля в море. А вот со временем MS может принять вызов и ответить тебе за "оскорбления" - и то хорошо, будет возможность отработать свои $10.000 PS: Интересно сколько на этот раз ты надергаешь цитат из моего флейма и увидишь тайного смысла, о котором я по простоте душевной и не подозреваю
leo > Умный ты, книжки толковые пишешь, а вот дискутировать с тобой весьма непросто без измен и без обид мыщъх не спорит. он вращает хвостом. вот. > PS: Интересно сколько на этот раз ты надергаешь цитат из моего флейма и увидишь > тайного смысла, о котором я по простоте душевной и не подозреваю уж бедному мыщъху и пофлеймить нельзя я же совсем не спорю... просто кинул ссылку на статью, которая мыщъх'у показалась интересной. и все. > 1. Говоря об "основной дыре в которую лезут shell-коды" я имел в виду, что > необходимым условием исполнения шелл-кода является возможность передачи на него > управления - если такой возможности нет или она существенно ограничена, ...и далее по тексту ты сам себе противоречишь, описывая атаку типа return2libc. от передачи управления все равно не уйти, пока сущесвтуют переполняющиеся буфера (стек/куча/целочисленное переполнение/спецификаторы) и в памяти имеются writeable-указатели, передача управления будет процветать > DEP отходит на второй план. если бы ms сказала, что DEP это просто поддержка x-атрибута, дарованного аппаратурой, то никаких бы претензий и не возникало. но ведь она объявила это _защитным_механизмом_, призванным предотвратить удаленные атаки, основанные на засылке shell-кода! > не сможет. Самое интересное, что закончив "разбор" предложения ты прямо или > косвенно соглашаешься с тем что нужно предотвращать именно передачу управления > нужно делать рандомизаторы адресов стека, кучи и прочие хитрости а-ля PaX так я об этом и говорю. "неисполняемый стек" это всего лишь один из китов, на которых должна держаться защита... а вот рандомизация (теоритически) очень сильно усложняет атаку, но практически все равно остается достаточное кол-во предсказуемых адресов ;( > Да и нафиг MS голову было ломать над этим DEP, когда процев с NX\XD пока еще > капля в море. вот мыщъх и говорит, что DEP идет нафиг. ставьте себе BufferShield (порт PaX на NT) и радуйтесь жизни. по крайней мере, IE с Лисом защитить все-таки стоит, тем более, что BufferShield действительно защищает, а не создает видимость бурной деятельности в лучших традициях ms и работает он на всей линейке x86 o http://www.sys-manage.com/index10.htm
вот тут небольшой фрагмент моей статьи на эту тему. замечания всячески привествуются. атака на DEP Microsoft подтвердила возможность обхода DEP еще в январе 2005, когда на maxpatrol'е появилась статья Александра Анисимова "Defeating Microsoft Windows XP SP2 Heap protection and DEP bypass", однако, не придала этому большего значения, заявив, что реализовать удаленную атаку все равно не удастся: "An attacker cannot use this method by itself to attempt to run malicious code on a user's system. There is no attack that utilizes this, and customers are not at risk from the situation," a spokesperson for the software giant told eWEEK.com" (Атакующий не может использовать этот метод для запуска зловредного кода на целевой системе. До сих пор не было продемонстрировано ни одной таки, использующей этот трюк и потребители находятся вне риска - http://www.eweek.com/article2/0,1759,1757786,00.asp). Это - наглая ложь! Механизм DEP легко пробивается с любого расстояния, хоть из Антарктики. Результатом атаки становится переданный и успешно выполненный shell-код, выполняющий команды заранее подготовленные злоумышленником. Чтобы понять как это делается, сначала необходимо разобраться с классическими методами переполнения, подробно разобранных в статье "ошибки переполнения буфера извне и изнутри как обобщенный опыт реальных атак". Напомним читателю основные положения: отсутствие контроля границ локальных буферов позволяет затирать адрес возврата из функции, помещая сюда указатель на shell-код, который находится здесь же, в стеке. Другой тип переполнения связан с кучей. С его помощью хакер может модифицировать любую writable ячейку в адресном пространстве уязвимого процесса (например, подменить указатель на виртуальную функцию или подделать адрес возврата). Имеются и другие возможности (в частности, атакующий может изменить обычный порядок выделения блоков памяти из кучи, разместив следующий выделяемый блок поверх ключевых структур данных), но для простоты изложения мы ограничимся модификацией адреса возврата. Существует множество защитных механизмов, контролирующих целость кучи и адреса возврата, но: со своей задачей они не справляются. Это отдельная большая тема, никак не связанная ни с NX/XD-битами, ни с технологией DEP. В следующих статьях мы подробно рассмотрим ее, но... это будет потом. Сейчас же ограничимся тем, что DEP никак не препятствует модификации адреса возврата и существует множество программ действительно позволяющих это делать (Internet Explorer, FireFox и др.) Манипулируя адресом возврата, хакер может вызывать произвольные функции уязвимой программы (в том числе и API-функции операционной системы) передавая необходимые параметры через стек. Конечно, при этом он будет очень ограничен в своих возможностях, поскольку среди готовых функций полезных для хакерствования не так уж и много, однако, если покурить хорошей травы (добытой на rastaman-talses.ru) и как следует подумать головой, попутно напрягая и другие части тела, проблему удается решить путем вызова API-функции CreateProcess или функции System из библиотеки MSVCRT, запустить стандартную программу типа tftp.exe и закачать на атакуемый компьютер двоичный файл, который можно исполнить с помощью CreateProcess/System (атака типа return-to-libc). Механизм DEP этому сценарию _никак_ не препятствует, поскольку в этом случае shell-код передается не через стек/кучу, а через легальный исполняемый файл. На стеке содержаться лишь аргументы вызываемых функций и "поддельные" адреса возврата, указывающие на них. Таким образом, даже при включенном DEP у хакера сохраняется возможность передать на атакуемую машину свой код и передать на него управление. Наличие tftp.exe не является необходимым условием для атаки. Даже если его удалить, хакер может вызвать cmd.exe и: нет, удалять все файлы с диска необязательно (хотя и возможно), достаточно перенаправить вывод в файл и с помощью ECHO создать крохотный com, делающий что-то "полезное". Да и в самой уязвимой программе наверняка содержаться функции, через которые можно загрузить файл из Интернета... Словом, возможностей - море! Атаки этого типа хорошо изучены хакерами и описаны в литературе. Только специалисты из Microsoft похоже об этом ничего не знают (они не в курсе - они в танке), иначе как можно объяснить тот загадочный факт, что успешность атаки данного типа никак не зависит от активности DEP и старые эксплоиты полностью сохраняют свою работоспособность. Распространение червей останавливается только потому, что вместе с DEP пакет обновлений включает в себя заплатки на все известные дыры. Однако, стоит хакерам найти еще одну ошибку переполнения (а это всего лишь вопрос времени), как Интернет захлестнет новая эпидемия и никакой DEP ее не остановит. (Вообще-то, нет, не захлестнет, ведь автоматическое обновление теперь включено по умолчанию). Некоторые могут сказать, что это "не настоящая" атака, поскольку в ней отсутствует явная передача shell-кода через стек, а ведь именно на это DEP и нацелен! Мысль, конечно, умная, но забавная. И какой это хакер броситься на амбразуру если можно сходить в обход? Неужели в Microsoft всерьез считают, что атакующий играет по "правилам" и идет по пути наибольшего сопротивления, карабкаясь по извилистой горной тропинке, напичканной патрулями, когда столбовая дорога никем не охраняется?! В качестве разминки для мозгов рассмотрим альтернативный сценарий атаки, передающий shell-код через стек. Засунуть shell-код в локальный буфер - не проблема, подменить адрес возврата тоже, но: при попытке передачи управления на shell-код при активном DEP будет возникать исключение, ведь x-атрибута у нас нет, хотя: это смотря, что мы переполняем. Как уже говорилось выше, некоторые приложения (в том числе и браузеры) нуждаются в исполняемом стеке, в который они складывают откомпилированный java-код. Но не будем смягчать себе условия. Давайте считать, что никаких исполняемых страниц в нашем стеке нет. Чтобы их заполучить, необходимо либо сбросить NX/XD-бит (но это можно делать только система), либо: вызывать функцию VirtualProtect, назначая атрибуты защиты по своему желанию! Но как же мы вызовем VirtualProtect без возможности выполнения shell-кода? Да очень просто - скорректируем адрес возврата так, чтобы он указывал на VirtualProtect, тогда при выполнении команды return она передаст на нее управление! На самом деле, это только идея. До практической реализации ей еще далеко. В жизни все происходит намного сложнее и: элегантнее. Допустим, вызвали мы VirtualProtect. А дальше что? Куда она возвратит управление? И как узнать адрес выделенного блока? Это великолепная головоломка на решение которой мыщъх потратил целый день и был очень разочарован, когда узнал, что он не один такой умный, и все загадки уже разгадали еще до него. Итак, все по порядку. Начнем с ответа на вопрос: куда возвращает управление VirtualProtect? Ответ очевиден: по указателю, который лежит за модифицированным адресом возврата! В момент выхода из VirtualProtect, процессор стакливает текущий адрес возврата с вершины стека и удаляет переданные ей аргументы. Так происходит потому, что VirtualProtect (как и все API-функции) придерживается соглашения о передаче параметров типа stdcall, при котором аргументы удаляются самой вызываемой функцией. Таким образом, мы можем вызывать столько stdcall-функций, сколько захотим. Процессор будет послушно стягивать их со стека, поступательно двигаясь от вершины вглубь. Техника вызова cdecl-функций выглядит чуть сложнее. Они не очищают аргументы при выходе, и это атакующему приходится это делать самостоятельно. Проще всего перенаправить адрес возврата на код типа ADD ESP,n/RET, расположенный где-то внутри уязвимой программы, где n - количество байт, занятых аргументами. Такую комбинацию можно встретить практически в любом оптимизированном эпилоге. Ну а нужное n подобрать совсем не сложно! Теперь мы знаем как вызывать функцию для изменения атрибутов доступа и вернуться обратно в shell-код, но это еще не все. Функция VirtualProtect требует, чтобы ей передали адрес уже выделенного региона, а shell-коду он неизвестен. К тому же, по слухам Microsoft собирается встроить в VirtualProtect дополнительную проверку, запрещающую назначать x-атрибут, если он не был присвоен еще при выделении. Тупик? Не совсем, ведь мы можем выделить новый регион, назначить нужные права, скопировать туда свой shell-код и передать ему управление. С выделением никаких проблем нет - берем VirtualAlloc и вперед. Как прочитать возвращенный указатель - вот в чем вопрос! Функция передает его в регистре EAX, и заранее предсказать его значение невозможно. А ведь хакер должен сформировать указатель и затолкать его в стек еще на стадии проектирования shell-кода, то есть задолго до вызова VirtualAlloc. Ну теперь уж точно тупик: А вот и нет! Внимательное чтение SDK (или Рихтера) показывает, что Windows позволяет COMMIT'ить (то есть передавать) уже переданную память по заданному адресу и хотя последствия такого выделения могут быть очень печальными (для кучи) - кого это волнует?! Главное, чтобы shell-код получил управление и он его получит! Оторвать мыщъх'у хвост, если это не так! Выбираем произвольный адрес, который с высокой степенью вероятности не будет занят ничем полезным (например, 191000h), и передаем его функции VirtualAlloc вместе с флагом MEM_COMMIT и атрибутами PAGE_EXECUTE_READWRITE. Все! Первая стадия атаки благополучно завершилась и теперь модно курнуть травы или глотнуть пива. На втором шаге мы вызываем функцию memcpy и копируем shell-код в только что выделенный регион памяти, целевой адрес которого заранее известен. После этой операции, shell-код оказывается в области памяти, где разрешено выполнение и нам остается только заснуть в стек еще один подложный адрес возврата, который будет указывать на него (внимание! функция memcpy в отличии от VirtualAlloc придерживается cdecl соглашения, поэтому после нее мы уже не можем выполнять никакие другие функции, предварительно не удалив аргументы со стека). Последовательность вызовов, реализующих атаку выглядит так (напоминаем: это не shell-код, это последовательность вызовов API-функций, осуществляемая путем подмены адреса возврата): VirtualAlloc(REMOTE_BASE, SHELLCODE_LENGTH, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(REMOTE_BASE, SHELLCODE_BASE, SHELLCODE_LENGTH); GOTO shell_code; Листинг 1 последовательность вызова функций, реализующих атаку типа commit-n-copy Маленький нюанс - 64-битные редакции NT передают аргументы API-функциям через регистры и потому вызывать VirtualAlloc на них уже не удастся (разумеется, речь идет только о 64-битных приложениях). То есть, вызывать-то удастся, а вот передать аргументы - нет, поэтому этот сценарий уже не сработает, однако, вызов функций уязвимой программы через подмену адреса возврата будет действовать по-прежнему (то есть, запустить tftp.exe мы все-таки сможем). Подведем итог: стечение ряда неблагоприятных для DEP обстоятельств делает эту технологию практически полностью бесполезной. Да, она отсекает целый класс атак, основанных на переполнении, однако, дает пишу для новых и в целом ситуация никак не меняется. Забавно, но большинство людей (в том числе и администраторов!) совершенно не понимают, что такое DEP, зачем он нужен, какие цели преследует и в чем заключается взлом. Достаточно почитать дискуссию, развернувшуюся на http://www.mastropaolo.com/?p=13, чтобы убедится, что оба предложенных сценария обхода DEP не считаются взломом, поскольку x-атрибут присваивается "легальным" способом через вызов VirtualAlloc. На самом деле, суть взлома вовсе не в том, чтобы выполнить код в области памяти без x-атрибута (это действительно невозможно), а в том, чтобы использовать уязвимое ПО в своих хакерских целях. В идеале, DEP должен представлять собой целый комплекс защитных мер, предотвращающих это, но ничего подобного он не делает, ограничиваясь простой формальной поддержкой NX/XD-атрибутов. Перечислим те обстоятельства, которые ему мешают: q параметры API-функций передаются через стек; q адреса API-функций и положение вершины стека легко предсказуемы; q всякий процесс может пометить любой регион памяти как "исполняемый"; q функция VituallAlloc позволяет выделять/передавать уже переданную память;
Как еще может развиваться аппаратная защита: Прозрачно разделение стека на data-stack и code-stack. В первый будут благополучно срабатывать все варианты сохранения данных (push,mov,etc), а во второй будут писать только call, int. Есстно возникнет несовместимость с программами которые любят делать push x и ret. В этом случае действительно нужно возбуждать исключение (адреса возврата в стеке данных и кода несовпадают ведь), обработкой которого пускай занимается система. А система наверняка успеет до заражения, по разным приложениям накопить статистику нестандартных возвратов/вызовов и как-то отреагировать на появление адреса возврата в стеке, ранее не происходившего, и дать возможность пользователю как-то обработать ситуацию (в худшем случае - снизить привилегии процесса до плинтуса, если он конечно не системный).
n2k > "замечания всячески привествуются" В целом все хорошо, за исключением сомнительных "измышлизмов" насчет VirtualProtect - такое впечатление, что они за уши притянуты, чтобы выпятить "суперметод" VirtualAlloc + memcpy Логика страдает: во-первых, адрес шелл-кода должен быть известен (хотя бы примерно, иначе и memcpy не будет работать), во-вторых, VirtualProtect (пока) работает с любыми адресами, а не только с адресом начала commit-региона, да и адрес начала этого региона определить (заранее) не составляет особого труда - он кратен 4К и ошибиться тут сложно. Поэтому ИМХО лучше не критиковать этот метод, а написать что-то в стиле: "..но это еще не все. Не исключено, что в будущем MS может вообще запретить исполнение кода в стеке или изменять x-атрибут только в том случае, если он не был присвоен еще при выделении." PS: хотел еще пофлеймить на тему усиления защиты VirtualAlloc\Protect (типа добавления заранее неизвестного параметра к флагу Protect и т.п.), да решил - ну его нафиг, пусть микрософты голову ломают