![]() |
Переполнение буфера -базовый уровень - написание шелл кода
Что такое эксплоиты? Эксплоит (Exploit) - это программа которая использует ту или иную уязвимость в программном обеспечении. Цели эксплоита могут быть различны. Некоторые служат для выполнения произвольного кода на компьютере жертвы, другие для отказа в обслуживании (DoS - Denial Of Service). Эксплоит может быть написан практически на любом языке программирования. Чаще всего для их написания используют C, C++, Perl. Для того, чтобы понять как написать эксплоит, нужно понять, как распределяется память и какие процессы происходят при запуске программ.1.1 Память В начале, память компьютера может показаться пугающей и непонятной. Но в последствии можно убедиться, что это не какие-то чудеса, и по сути ее можно сравнить с гиганским калькулятором. Это просто байты, хранящиеся во временной памяти, на которые указывают их адреса. Эта память может быть доступна по ее адресам, и каждый байт, имеющий определенный адрес может быть прочитан или записан в нее. Процессор Intel x86 использует 32 битную адресацию, а это значит что может быть 2^32 или 4,294,967,296 возможных адресов. Существуют также специальные типы переменных, которые называются указатели. Они используются для хранения адресов памяти которые ссылаются на какую либо информацию. Процессор имеет свою специальную память, которая относительно мала. Указатели в этой памяти называются регистры. Один из более "заметных" указателей - EIP (Extended Instruction Pointer). EIP - это указатель, который содержит адрес текущей исполняемой инструкции. Другие 32-битные регистры используют EBP (Extended Base Pointer) и ESP (Extended Stack Pointer) указатели. Все три регистра важны для исполнения программы. 1.2 Распределение памяти Когда объявляют переменные в языках высокого уровня, таких как C, используют тип данных. Для этих переменных выделяется место в памяти компьютера. Например для данных типа int (integer) нужно 4 байта, а символьным данным (типа char) всего 1 байт. Это значит, что int имеет 32 бита в памяти (4,294,967,296 возможных значений), тогда как char только 8 бит (256 возможных значений). Также могут быть объявлены массивы. Массив это просто список из N элементов, определенного типа данных. Так 10-символьный массив, это 10 смешанных символов, находящихся в памяти. Часто массив называют "буффер", а символьный массив - "строка". Вот несколько примеров объявления переменных в языке C: Код:
int integer_variable; //Переменная типа int1.3 Нуль-байты Иногда 10-байтовый символьный массив использует только 4 байта. Если поместить в 10-байтовый массив слово "test", то в конце массива будут находиться дополнительные байты, которые не нужны. Нуль, или нуль-байт, служит "ограничителем". Он сообщает функции, о прекращении ее выполнения. Пример: Код:
0 1 2 3 4 5 6 7 8 91.4 Ceгментация программной памяти Программа делится на 5 сегментов: text, data, bss, heap и stack. Каждый из сегментов "представляется" в специальной части памяти, отведенной под него. Сегмент текста (text segment) также называется иногда сегментом кода (code segment). Он будет переведен в машинный код. Выполнение инструкций в этом сегменте не линейное. При выполнении программы в EIP помещается первая инструкция в text-сегменте. Дальше процессор начинает выполнять цикл, который состоит из следующего: 1. Прочитать инструкцию на которую указывает EIP 2. Добавить длинну (в байтах) инструкции в EIP 3. Выполнить инструкцию которая была прочитана при шаге #1 4. Перейти на шаг #1 Иногда это может быть jump или call инструкция, которая изменяет EIP на другой адрес в памяти. Процессор не волнует это изменение, так как выполнение инструкций не линейное. Тоесть, если EIP изменится в шаге #3, то процессор просто вернется на шаг #1 и прочитает инструкцию найденную по адресу, на который изменился EIP. Data и bss сегменты используются для хранения глобальных и статических переменных. Data сегмент инициализируется глобальными переменными, строками и другими константами, которые используются в программе. В оба эти сегмента можно записывать данные, и у них фиксированый размер. Heap сегмент используется для хранения остальных программных переменных. Этот сегмент не имеет фиксированный размер, а значит может быть больше или меньше в зависимости от надобности. Stack сегмент также имеет непостоянный размер, и используется для временного хранения контекста во время вызова функции. Когда программа вызывает функцию, эта функция содержит свои переменные, и код функции будет находиться в различных местах сегмента кода (text segment). Вообще стек это структура представления данных, которая используется достаточно часто. Он имеет порядок FILO (First-in last-out). Это значит, что первое значение помещается в стек, а последнее забирается оттуда. Помещение значения в стек известно как pushing, а перемещение значения из стека называется popping. ESP регистр используется для обозначения конечного адреса стека, который постоянно меняется из-за добавления и перемещения данных в и из стека. FILO стека может показаться странным, так как стек используется для хранения контекста, что очень полезно. Когда функция вызвана, несколько значений помещаются в стек вместе в структуру называемую stack frame (стековый фрейм).EBP регистр (иногда называется фреймовым указателем (FP) или локальным базовым указателем (LB)) используется для распределения переменных в определенном стековом фрейме. Каждый стековый фрейм содержит параметры функции, ее локальные переменные и два указателя, которые необходимы для возврата данных назад по пути состоящем из двух этапов: SFP (Saved frame pointer) и адрес возврата. Фреймовый указатель (имеется в виду SFP а не EBP) используется для восстановления педидущего значения EBP. Адрес возврата используется для загрузки в EIP следующей инструкции, найденной после вызова функции. 1.5 Переполнение буффера. Пишем эксплоит Давайте для начала напишем программу, в которой можно будет вызвать переполнение буффера: Код:
int main(int argc, char *argv[]) {Код:
[user@gasolina hack]# gcc -o target target.cКод:
[root@gasolina hack]# sudo chown root targetПервое что нужно учесть - это NOP sled. Это однобайтовая инструкция которая не делает абсолютно ничего. В нашем случае эта NOP инструкция служит для различных целей; Рядом с NOP инструкцией мы создаем большой массив, и располагаем его перед шеллкодом (более подробно написание шеллкода рассмотрено здесь). Если EIP возвращает некоторый адрес, найденный в NOP инструкции, EIP будет увеличиваться пока выполняется NOP инструкция, и в конце концов достигнет шеллкода. Это значит, что адрес возврата будет перезаписан другим адресом, который находиться в NOP. EIP сдвинеться на начало шеллкода, а значит он будет выполнен. Ниже показано представление данного буффера: Код:
|-----NOP Sled-----|SHELLCODE|-----REPEATED RETURN ADRESS-----|Код:
#include Это результат компиляции и выполнения эксплоита: Код:
[user@gasolina hack]# gcc -o exploit exploit.c------------------------------ P.S. Тестировалось на Mandrake 10.0 ------------------------------ статья не моя, автор - неизвестен (незапомнен). Мой перевод с английского + дополнения и комментарии. |
Более привычно видеть Lifo, а не Filo, но это придирки :) А так статья норм, особенно для новичков, которые хотят научится писать эксплойты.
|
Статья довольно интересная, если сам писал - то молодец! Но у меня есть несколько замечаний/вопросов:
1. Цитата:
2. Цитата:
Цитата:
А так в общем-то интересно почитать. Вот, есть еще довольно интересная статья по теме... Хм, хотел ссылку дать, а там на сервере технические работы какие-то проводятся. А пару дней назад все работало.. Хорошо, что я ее сохранил :) В общем залил на свой хост http://lanham.nm.ru/modern_kinds_of_...ttacks.mht.bz2 (на русском) P.S. Статью надо бы перенести в "Статьи", ибо тут ей не место. Поэтому просьба, отписаться - кто автор. Если не ты - тогда поставь копирайты! |
Спасибо за замечание подправил. Имеется ввиду не Ebp а Sfp. Насчет Lifo сам в сомнении. У знакомого брал книжку там написано Filo. В других местах Lifo. Поэтому в сомнении :)
Насчет авторства, незнаю какое ставить. Такой статьи на русском нет. Вообще давно писал переводил и дополнял. Если так, то какое авторство ставить? P.S. Спасибо за литератуту. Интересная вещь |
Цитата:
|
Сделано :)
|
Только тему преименую не в "Пишем эксплоит" а например "Переполнение буфера -базовый уровень - написание шелл кода"
|
ИМХО норм. А Lifo или Filo не принципиально важно ибо одно и тоже (: Вряд ли у кого-нибудь возникнут проблемы с этим, а если и возникнут, то стоит после прочтения статьи поучить архитектуру ЭВМ. Молодца однозначно. Отдельное спаибо за перевод и комментарии.
[From: groundhog] [17.12.2007 08:50] LIFO и FIFO это разные вещи. Если вы в состоянии раскрыть эти буквы, то поймёте сразу, первый - Last In First Out, а второй - First In First Out. Поэтому воздержитесь от использования терминов, о которых имеете слабое представление, дабы не вводить своей ложной информацией в заблуждение неискушенный таким знанием люд... |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
По-моему, это из книги Д.Эриксона "Хакинг. Искусство Эксплойта" (или он взял оттуда). Кажется, это работает только на старых ядрах (где не было рандомизации стека). Или на 2.6 тоже работает?
|
| Время: 03:51 |