Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

articles:exploit4uself [2017/09/05 02:55] (текущий)
Строка 1: Строка 1:
 +====== exploit4uself ======
 +<​sub>​{{exploit4uself.odt|Original file}}</​sub>​
 +
 +====== как заточить exploit под себя ======
 +
 +крис касперски ака мыщъх, no-email
 +
 +**в сети валяется множество демонстрационных (****proof****-****of****-****concept****) ****exploit****'​ов,​ создающих файл на "​жертвенном"​ диске или выводящих сообщение об уязвимости на экран. для атаки на удаленные системы они не пригодны,​ и даже если нам посчастливиться встреть боевой ****exploit****,​ открывающий ****shell****,​ вовсе не факт, что он заведется без предварительной доработки…**
 +
 +===== введение =====
 +
 +Начну с главного. С отречения. Ни к чему деструктивному мыщъх не призывает и употребляет термин "​хакер"​ со всем позитивом,​ на которое только способен. Атаковать чужие системы можно только с явного разрешения их владельцев,​ в противном смысле это будет не хакерство,​ а чистая уголовщина со всеми отсюда вытекающими... В то же время, протянуть шнурок к приятелю-хакеру и махаться с ним exploit'​ми никакое законодательство не запрещает. На этом и закончим.
 +
 +===== где брать? =====
 +
 +Поиск новых exploit'​ов очень похож на охоту: всемирная сеть велика,​ а дичь гнездиться там, где никогда бы не подумал ее искать. Самые свежие exploit'​ы обычно выкладываются на немодерируемые хакерские форумы с высоким трафиком (среди которых выделяется **__http://​lists.grok.org.uk/​pipermail/​full-disclosure/​__**),​ откуда они с некоторой степенью оперативности попадают на **__http__****__://​__****__www__****__.__****__securityforcus__****__.__****__com__** и другие "​накопители дыр",​ превратившиеся в последнее время в сплошные помойки,​ источающие зловонный запах давно непроветриваемых отстойников.
 +
 +Кстати говоря,​ securityforcus как-то очень странно устроен. Вразделе "​exploit"​ обычноприсутствуеттолькотекст "​**currently we are not aware of any exploits for this issue. If you feel we are in error or are aware of more recent information,​ please mail us at: vuldb@securityfocus.com**"​ (//​в////​настоящее////​время////​мы////​не////​знаем////​ни////​об////​этом////​ exploit'////​е////​для////​этой////​дыры////​. ////​если////​вы////​считаете////,​ ////​что////​мы////​ошибаемся////​или////​имеете////​более////​свежую////​информацию////,​ ////​пожалуйста////,​ ////​шлите////​нам////​на////​ vuldb@securityfocus.com//​). Не верьте им! Они гонят! Ссылки на exploit'​ы часто (но не всегда!) находятся в соседнем разделе — "​reference"​. Если же их там нет — вводим название дыры (брать только значимые слова! например,​ "//​Microsoft////​Internet////​Explorer////​Unspecified////​OBJECT////​Tag////​Memory////​Corruption////​Variant////​Vulnerability//"​ лучше всего отыскивается по запросу "​**IE****OBJECT****tag**"​) добавляем ключевое слово "​exploit"​ и идем курить гугол, обязательно обращая внимание на дату публикации,​ а то ведь так недолго и в позапрошлогоднюю дырку залететь,​ а потом долго недоумевать,​ какого хрена exploit не фурычит.
 +
 +{{exploit4uself_Image_0.png?​552}}
 +
 +Рисунок 1 на www.securitysocus.com все самое ценное не в разделе "​exploit",​ а в "​references"​
 +
 +Модерируемые форумы (типа **bugtraq** на **__http://​seclists.org__**//​**/​**//​) содержат намного более концентрированную информацию,​ но прежде,​ чем откопать рабочий exploit приходится очень долго ковыряться. Но зачем гнаться за свежестью?​ Все равно, даже с учетом Windows Update,​ множество машин не латаются годами! Намного проще отправится в "​лавку exploit'​ов",​ где выложен разный антиквариат,​ среди которого хотелось бы отметить **Metaexpolit****Framework****Project**(__http____://​____www____.____metasploit____.____com__) – своеобразный универсальный "​движок",​ изначально написанный на Perl'​e,​ а начиная с версии 3.0 переписанный на Ruby и работающий как из командной строки,​ так и через WEB-интерфейс. К движку подключаются "​топливные модули"​ — гибкие и высококонфигурабельные exploit'​ы,​ способные нести на своем борту любую боевую нагрузку (**payload**). Собственно говоря,​ разделение кода на "​движок",​ "​exploit"​ и "​payload"​ и есть главное преимущество MetaexpolitFramework'​а перед обычными exploit'​ами,​ где все эти три агрегата смешаны в кучу и чтобы подключить свою собственную боевую начинку приходится каждый раз разбираться что, как и куда. Исходный код движка распространяется бесплатно и неплохо документирован. Там же, на сайте проекта,​ можно найти достаточно оперативно пополняемую базу exploit'​ов и минимальный комплект боевой нагрузки (**__www.metasploit.com/​sc/​win32msf20payloads.tar.gz__**),​ дающий в том числе и удаленный shell (а большего,​ для атаки, как правило,​ и не требуется).
 +
 +{{exploit4uself_Image_1.png?​553}}
 +
 +Рисунок 2 главный сайт проекта MetaexploitFramework – универсального атакующего "​движка"​ с обширной базой свежих explot'​ов
 +
 +Другой полезный сайт — **MilW****0****rm** (**__http://​milw0rm.com/​__**) содержит огромную коллекцию exploit'​ов под всевозможные системы. Достаточно оперативно обновляемую и к тому же неплохо классифицированную,​ что значительно упрощает поиск, избавляя нас от необходимости качать всякую непонятую хрень. Здесь же находятся примеры shell-кода с готовой боевой нагрузкой и немногочисленный инструментарий.
 +
 +{{exploit4uself_Image_2.png?​552}}
 +
 +Рисунок 3 www.MilW0rm.com – хорошая копилка exploit'​ов плюс сподручный инструментарии
 +
 +Популярный **Packet****Storm** (**__http__****__://​__****__www__****__.__****__packetstormsecurity__****__.__****__org__****__/​__**) значительно реже обновляется,​ да и коллекция exploit'​ов у него победнее будет, зато на нем выложено умопомрачительное количество статей и до черта всякого полезного инструментария — от сканеров безопасности,​ до мелких утилит в десяток строк.
 +
 +{{exploit4uself_Image_3.png?​553}}
 +
 +Рисунок 4 packetstorm – немного exploit'​ов зато какой инструментарий!
 +
 +Кстати говоря,​ мыщъх чаще всего узнает о новых дырах не через форумы,​ а от знакомых. Достаточно завести обширную переписку,​ и можно быть в курс дел, происходящих на всех континентах! Один услышит одно, другой — узнает другое,​ а все вместе мы знаем обо всем! Силами одного человека отслеживать появление новых дыр просто нереально,​ разве что полностью посвятить свою жизнь дырам целиком.
 +
 +===== чем компилировать?​ =====
 +
 +Чаще всего exploit'​ы пишутся на Си/​Си++,​ Perl, Python и PHP, реже на всякой экзотике типа Ruby, причем тип языка указывается далеко не всегда,​ а о версии транслятора и ключах компиляции остается только догадываться. Вот такая культура программирования,​ с которой нам приходится жить.
 +
 +Ладно, Perl узнается с первого взгляда по строке "#​!/​usr/​bin/​perl",​ идущей впереди листинга. Если же ее нет, смотрим на следующее:​
 +
 +  - присутствуют директивы в стиле "use IO::​Socket;"​
 +  - точка с запятой ставится в конце каждой строки;​
 +  - тело функций и многострочечных циклов/​операторов if заключено в фигурные скобки;​
 +  - отступ внутри тела роли не играет и часто отсутствует;​
 +  - мнострочечные строковые константы соединяются через точку;
 +Выполнение всех этих условий свидетельствует о том, что перед нами Perl. Язык Python внешне похож на него, но содержит ряд принципиальных отличий (и обычно предваряется строкой "#​!/​usr/​bin/​python",​ которой,​ впрочем,​ может и не быть):
 +
 +  - присутствуют директивы в стиле "​importsocket",​ "​import sys";
 +  - точка с запятой в конце строки _не_ ставится;​
 +  - тело функций и многострочечных циклов,​ операторов if _не_ берется в скобки;​
 +  - отступ внутри тела функций,​ оператор if и циклов строго обязателен;​
 +  - мнострочечные строковые константы соединяются как в Си ("<​ENTER>"​);​
 +
 +
 +Выполнение всех этих условиях — верный признак Питона,​ который как и Perl портирован на множество платформ и распространяется на бесплатной основе.
 +
 +Наибольшие проблемы вызывает комплект поставки. Достаточно часто хакеры выкладывают не весь exploit, а только его часть и транслятор начинает материться на отсутствующие включаемые файлы/​библиотеки. Такие exploit'​ы следует сразу отправлять в топку, хотя при наличии большого количества свободного времени и некоторого опыта работы с языком недостающие файлы можно (теоретически) воссоздать и самостоятельно. Но… зачем?​!
 +
 +Исключение составляют листинги,​ содержащие в себе строку "​ThisfileispartoftheMetasploitFramework"​ и являющиеся модулями Framework'​а,​ без которого они, естественно,​ не запускаются. Присутствие такой строки необязательно,​ но сама структура модуля настолько характерна,​ что увидев такую штуку один-единственный раз, будешь распознавать ее всегда,​ вот, например:​ http://​milw0rm.com/​exploits/​1788.
 +
 +С диалектами Си/Си++ все намного сложнее. Компиляторов просто море, а разногласиями в понимании Стандарта можно было бы утопить целый океан, поэтому,​ очень часто случается так, что программу,​ написанную под один компилятор не удается (без переделок) откомпилировать ничем другим. Последняя версия компилятора далеко не всегда оказывается самой лучшей (в особенности это касается gcc, в ядро которого вносится большое количество изменений,​ зачастую не без ущерба для обратной совместимости).
 +
 +Первым делом необходимо определить:​ приплюснутый это си или классический?​ Вот характерные черты приплюснутого:​
 +
 +  - объявление переменных по месту использования,​ а не в начале функции;​
 +  - наличие ключевых слов класс и двух двоеточий "::";​
 +  - использование new для выделения памяти или явное преобразование типа после malloc;
 +  - отсутствует printf, а весь ввод/​вывод осуществляется операторами "<<"​ и ">>"​
 +Если хоть одно из этих условий выполняется,​ программа явно написана на приплюснутом си, в противном случае используется классический. Кстати говоря,​ си/си++ отличается от perl/python своими директивами "#​include"​ и еще тем, что символ "#"​ в нем никогда не используется для оформления комментариев.
 +
 +В отличии от интерпретируемых языков,​ библиотеки которых более или менее стандартизированы,​ си-компиляторы включают в себя большое количество системно-зависимых библиотек,​ в результате чего, программа может вызывать функции,​ отсутствующие в нашем трансляторе или использовать специфические особенности конкретной версии языка. В первую очередь это касается сырых сокетов (по разному реализованных в LINUX и *BSD) и прочих системно-зависимых фич. Некоторые exploit'​ы пишутся в расчете на Windows и вместо "​общепринятых"​ функций типа fopen/​fclose используют громоздкие API-вызовы CreateFile/​CloseHandle. Откомпилировать такой exploit под UNIX'​ом вполне возможно,​ но для этого придется заменять API-вызовы на соответствующие им Си-функции или syscall'​ы. Самое неприятное в том, что у Microsoft имеется свой собственный,​ особый взгляд на интерфейс сокетов и для переноса Windows-кода,​ работающего с сокетами,​ под UNIX приходится осуществлять большие телодвижения или… искать альтернативный UNIX-exploit. Формальным признаком форточной природы кода является наличие функции WSAStartup, которая в UNIX-подобных системах и не ночевала. Но классический си — это только цветочки. Самое страшное как всегда впереди.
 +
 +Приплюснутый си — это настоящий кошмар. Компиляторы (и поставляемые вместе с ними библиотеки) различаются просто колоссально! Приходится иметь в своем распоряжении целую артиллерию GCC различных версий,​ а в рукавах держать всякую экзотику типа INTEL C++, но и тогда будут встречаться программы,​ которые упорно не хотят компилироваться!
 +
 +{{exploit4uself_Image_4.png?​552}}
 +
 +Рисунок 5 попытка компиляции файла beta.cpp и ее результат
 +
 +Яркий тому пример — **__http://​milw0rm.com/​shellcode/​656__** (прилагается к статье под именем beta.cpp). Пропускаем его через gcc и получаем следующий список ошибок (не считая варнигов):​
 +
 +beta.cpp:​34:​21:​ windows.h: No such file or directory
 +
 +beta.cpp: In function `int main(int, char**, char**)':​
 +
 +beta.cpp:​165:​ error: `stricmp'​ undeclared (first use this function)
 +
 +beta.cpp:​185:​ error: `strnicmp'​ undeclared (first use this function)
 +
 +beta.cpp:​245:​ error: `isalnum'​ undeclared (first use this function)
 +
 +beta.cpp:​250:​ error: `isprint'​ undeclared (first use this function)
 +
 +beta.cpp:​339:​ error: invalid conversion from `void*'​ to `char*'​
 +
 +beta.cpp:​356:​ error: `O_BINARY'​ undeclared (first use this function)
 +
 +beta.cpp:​361:​ error: `lseek'​ undeclared (first use this function)
 +
 +beta.cpp:​377:​ error: invalid conversion from `void*'​ to `char*'​
 +
 +beta.cpp:​384:​ error: `read' undeclared (first use this function)
 +
 +beta.cpp:​398:​ error: `close'​ undeclared (first use this function)
 +
 +Листинг 1 список ошибок,​ выдаваемый компилятором gcc при попытке трансляции файла beta.cpp
 +
 +Ну, с ошибкой 34 все понятно — программа усиленно косит под форточки,​ не понятно за каким хреном таща за собой файл <​windows.h>,​ но тут же использует стандартные POSIX- вызовы:​ **open** (со странным флагом O_BINARY), **lseek**, **read** и **close**, которых ни в самом windows, ни в одном из win32-компиляторов никогда не существовало (см. ошибки 356, 361, 384 и 398). Убираем строку "#​include <​windows.h>",​ заменяя ее на "#​include <​unistd.h>"​ и удаляем глупый флаг O_BINARY, поскольку по умолчанию файл уже является двоичным (узнать какие заголовочные файлы соответствуют данной функции можно из man'​а,​ например,​ "​man 2 open"​). Дляизбавленияотругательства "this file include <​malloc.h>​ witch is deprecated, use <​stdlib.h>​ instead"​ удаляеми "#​include <​malloc.h>"​.
 +
 +Ошибки 245 и 250 устраняются подключением их "​родного"​ заголовочного файла, в котором они были объявлены "#​include <​ctype.h>"​ (см. "​man isalnum"​). А вот функций **stricmp** и **strnicmp** в gcc действительно нет, однако,​ они могут быть заменены на аналогичные им **strcmp** и **strncmp** даже без коррекции аргументов!
 +
 +Ошибки 339 и 377 исправляется еще проще: достаточно взять строку "​buffer=malloc(MAX_BUFFER_SIZE)"​ и добавить явное преобразование типов, так же называемое ксатингом:​ "​buffer=**(****char*****)**malloc(MAX_BUFFER_SIZE)"​.
 +
 +Исправленный вариант лежит в файле beta-fixed.cpp и компилируется безо всяких нареканий.
 +
 +Короче,​ будем считать,​ что с идентификацией транслятора мы разобрались и exploit откомпилировался нормально,​ но... это еще не конец, а только начало. Ведь программный листинг это только оболочка (образна говоря "​тетива"​),​ а разящие острие — загадочный и таинственный shell-код,​ засунутый в строковой "​иероглифический"​ массив "​\x29\xc9\x83…\xe9\xb0\xd9"​ или типа того. Что делать,​ если он не работает,​ или работает не так, как нам этого хочется?​
 +
 +===== доработка напильником =====
 +
 +shell-код имеет сложную структуру и обычно состоит из несколько частей. Например,​ exploit**http****://​****milw****0****rm****.****com****/​****exploits****/​1075** (приложенный в файле 1075.с) использует 6 (!) "​иероглифических"​ массивов:​ dce_rpc_header1,​ tag_private,​ dce_rpc_header2,​ dce_rpc_header3,​ offsets, bind_shellcode. Первые пять — это служебные структуры,​ атакующие жертву,​ срывающие буферу крышу и передающие управление на bind_shellcode. Последний представляет собой "​чистый"​ shell-код,​ который может быть беспрепятственно заменен любым другим. На самом деле, тут все не так просто и произвола хоть отбавляй. Как минимум необходимо убедиться,​ что мы используем shell-код совместимый с атакуемой системой и точки входа у них совпадают. Часто (но не всегда) точка входа расположена в самом начале shell-кода,​ реже — в его конце или середине. Гораздо хуже, если exploit написан "​пионером"​ и все блоки идут одним большим кусом, внутри которого присутствует в том числе и shell-код.
 +
 +Чтобы определить положение дел, необходимо преобразовать "​иероглифический"​ текст в двоичный файл и дизассемблировать его. Разыскивать соответствующий конвертор совершенно необязательно. Проще переложить эту задачу на плечи компилятора си, написав простенькую программку всего из одной строки:​
 +
 +main(){FILE *f;​if(f=fopen("​shellcode","​wb"​))fwrite(shellcode,​ sizeof(shellcode),​1,​f);​}
 +
 +Листинг 2 простейший конвертор для преобразования строковых констант в двоичный код
 +
 +Сам shell-код должен быть размещен в массиве,​ объявленном как "​**char shellcode[]**"​ (см. прилагаемый файл hex2bin.c) и приведенным к синтаксису си (то есть, если shell-код выдернут из perl'​а необходимо удалить точки в конце строковых констант). Компилируем наш импровизированный конвертор,​ запускаем его на выполнение и тут же на диске образуется файл "​shellcode",​ который можно загрузить в HTE, IDA Pro или любой другой дизассемблер по вкусу, не забывая,​ конечно,​ переключить его в 32-битный режим.
 +
 +В данном случае мы получим следующий код:
 +
 +00000000: 29C9subecx,​ecx
 +
 +00000002: 83E9B0subecx,​-050 ;"​P"​
 +
 +00000005: D9EEfldz
 +
 +00000007: D97424F4fstenv[esp][-000C]
 +
 +0000000B: 5Bpopebx
 +
 +0000000C: 81731319F50437xord,​[ebx][00013],​03704F519 ;"​7♦o↓"​
 +
 +00000013: 83EBFCsubebx,​-004 ;"​♦"​
 +
 +00000016: E2F4loop00000000C ​ -------- (1)
 +
 +Листинг 3 первые 16-байт shell-кода содержат осмысленный код расшифровщика
 +
 +Ага! Вполне типичный расшифровщик,​ значит,​ точка входа в shell-код действительно находится в начале массива и он может быть беспрепятственно заменен любым таким же. Если же вместо осмысленно кода нас встречает мусор, значит,​ нужно последовательно отступать на один байт от начала до тех пор, пока мы не получим что-то удобоваримое. Естественно,​ для этого необходимо знать ассемблер и хотя бы общих чертах представлять себе устройство операционной системы.
 +
 +Правильно спроектированный shell-код работает на всех версиях операционных систем для которых он предназначен,​ однако,​ в последнее время все чаще и чаще приходится сталкиваться с "​пионерством",​ привязывающимся к фиксированным адресам и функционирующих только под определенной сборкой LINUX-ядра или заранее заданным сервис-паком,​ наложенным на Windows. Постойте-постойте! Какой такой Windows?! Мы же ведь сидим на LINUX/BSD и никуда с этих замечательных систем сходить не собираемся! Все правильно! Но даже LINUX/​BSD-хакерам частенько приходится атаковать Windows-машины и обходить этот вопрос стороной мыщъх просто не имеет моральных прав! (см. врезку)
 +
 +UNIX-подобные системы в этом плане намного менее изменчивы и там проблема "​фиксированных адресов"​ практически сведена на нет. Обычно shell-код вызывает необходимые ему функции через системные вызовы,​ интерфейс с которыми обеспечивается прерыванием INT 80h или дальним вызовом по адресу 0007h:​00000000h,​ что позволяет shell-коду функционировать под всей линейкой осей, для которых он предназначен. Тем не менее, определенные системные вызовы в различных версиях ядер реализованы сильно неодинаково,​ что порождает проблемы совместимости. К счастью,​ базовый набор системных вызовов остается единым для всех осей и грамотно спроектированный exploit поражает как LINUX, так и BSD, а если не поражает,​ то не задумываясь отправляется в /dev/nul.
 +
 +===== >>>​ врезка explouit'​ы,​ атакующие Windows, фиксированные адреса и все-все-все =====
 +
 +Вот типичный пример учебного exploit'​а http://​milw0rm.com/​shellcode/​1675 (см. прилагаемый файл 1675.c):
 +
 +unsigned char beepsp1[] =
 +
 +"​\x55\x89\xE5\x83\xEC\x18\xC7\x45\xFC"​
 +
 +**"​\x10\xC9\xEA\x77"​**//​Address \x10\xC9\xEA\x77 = SP1
 +
 +...
 +
 +"​\x00\x00\x8B\x45\xFC\xFF\xD0\xC9\xC3";​
 +
 +unsigned char beepsp2[] =
 +
 +"​\x55\x89\xE5\x83\xEC\x18\xC7\x45\xFC"​
 +
 +**"​\x53\x8A\x83\x7C"​**//​Address \x53\x8A\x83\x7C = SP2
 +
 +
 +
 +"​\x00\x00\x8B\x45\xFC\xFF\xD0\xC9\xC3";​
 +
 +int main()
 +
 +{
 +
 +void (*function)();​
 +
 +*(long*)&​function = (long)beepsp1;​
 +
 +function();
 +
 +}
 +
 +Листинг 4 фрагмент простейшего exploit'​а,​ работающего под Windows, и привязывающего к фиксированным адресам
 +
 +Данный shell-код вызывает функцию beep из KERNEL32.DLL,​ обращаясь к ней по ее непосредственным адресам,​ которые в разных версиях Windows, естественно,​ будут сильно неодинаковые. На наш выбор предоставляется всего два варианта — XP SP1 и XP SP2, причем,​ никакого автодетекта не производится и нужный shell-код приходится подключать самостоятельно. А как быть, если мы хотим атаковать W2K SP5?
 +
 +Используем утилиту DUMPBIN из SDK для определения адреса функции beep, вызывая ее со следующими ключами:​ "​DUMPBIN /​EXPORTS /​HEADERS KERNEL32.DLL >​ out.txt"​ (при этом KERNEL32.DLL соответствующей версии должен быть в нашем распоряжении).
 +
 +OPTIONAL HEADER VALUES
 +
 +79430000 image base
 +
 +...
 +
 +ordinalhintRVAname
 +
 +13C0000D4D1Beep
 +
 +Листинг 5 фрагмент информации,​ сообщенной dumpbin
 +
 +Вычисляем адрес функции Beep – к imagebase (79430000h) добавляем RVA адрес самой функции (0000D4D1h),​ получаем — 7943D4D1h, который и записываем в shell-код,​ не забывая про обратный порядок байт в x86: "​\xD1\xD4\x43\x79"​.
 +
 +К чести создателя exploit'​а,​ в нем, по крайней мере, присутствуют комментарии. Другие хакеры их не оставляют! В результате,​ exploit падает под всеми версиями Windows, кроме одной. Вопрос — какой именно?​ Дизассемблер показывает ничего не значащие адреса,​ над которыми для "​изгнания"​ нулей могут проводится всякие математические манипуляции.
 +
 +00000006: C745FC1396EA77movd,​[ebp][-04],​**77EA9613**
 +
 +0000000D: 806DFC13subb,​[ebp][-04],​**13**
 +
 +Листинг 6 фрагмент shell-кода,​ привязывающего к фиксированным адресам
 +
 +В ячейку [ebp-04] заносится значение 77EA9613h из которого тут же вычитается 13h, следовательно эффективный адрес равен 77EA9600h. Это легко. Сложнее разобраться — какой функции он принадлежит. Приходится перебирать все версии Windows, какие только есть в нашем распоряжении в надежде,​ что хоть в одной из них по заданному адресу окажется начало функции и эта функция будет той, которую ожидает увидеть exploit (проверять можно хоть soft-ice, хоть dumpbin).
 +
 +Занятие это трудное и неблагодарное. К черту такой exploit! В статье "​техника написания переносимого shell-кода",​ опубликованной в одном из прошлых номеров "​хакера"​ наглядно показывалось как находить API-функции в памяти,​ освобождаясь от фиксированных адресов и чехарды версий. Изначально кривую программу легче переписать с нуля, чем каждый раз подкладывать новые подпорки и костыли. Впрочем,​ на этот счет есть разные мнения,​ так что свой путь выбирает каждый.
 +
 +===== заключение =====
 +
 +Последние версии UNIX'​ов оснащены мощными защитными механизмами:​ неисполняемым стеком,​ рандомизатором адресного пространства и т. д. Обычным exploit'​ом такую штуку уже не пробить,​ а потому техника написания shell-кодов в ближайшем будущем обещает круто измениться,​ но прежде чем бросаться на неисполняемый стек, необходимо разобраться в существующих exploit'​ах,​ что мы сейчас и попытались сделать.
 +
 +