Показать сообщение отдельно
Старый 01.10.2011, 00:43   #1
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Переполнение буфера - модификация стека

#include<iostream.h>
#include<string.h>
#include<conio.h>

void F1(){
	cout<<"hello"<<endl;
	getch();
}

char mbf[13];

int main(){
	char t[4];
	for(int i=0;i<8;i++)mbf[i]=1;
	((int*)(&mbf))[2]=int(&F1);
	mbf[12]=0;
	strcpy(t,mbf);
	return 0;
}
Пример эксплуатации уязвимости «переполнение буфера в стеке».
Ну как "эксплуатации уязвимости" - скорее демонстрация того, как переполнение буфера, может поменять стек таким образом, что изменится поведение атакуемой программы. В данном случае программа "нападает" сама на себя (мазохизм), так что я не несу ответственности за какие-либо противоправные действия, которые вы можете совершить под влияниям данной статьи (или после доработки приводимых кодов). Приводимый материал и фрагмент кода призваны были показать студентам (т.е. я - показывал им), как важно контролировать границы записи при работе со строками.
Функция strcpy не контролирует размер переданных в неё данных, в связи с чем, копируемая строка mbf будет записана не только в отведенную область памяти строки t, но и далее, что перезапишет значение адреса возврата, хранящееся в стеке. После завершения (штатного!) функции копирования в регистры EIP и EBP будут вытолкнуты ложные (отличающиеся от сохранённых ранее) данные. Программа будет продолжена по адресу, помещённому в регистр EIP (в данном случае адрес функции F1, которая нигде не вызывается явно).
Кто забыл основы архитектуры:
EIP____Адрес команды, которая будет выполнена процессором
ESP____Указывает на адреса данных, которые будут вынуты из стека
EBP____Указатель на базу (для удобства адресации)

При вызове функции main в стек будет помещено значение адреса возврата. Стек растёт вниз, т.е. самое первое значение, размещённое в стеке, имеет бОльший адрес (конкретные числовые значения нам не важны, но для удобства обозначим логически связанные группы байтов последовательностями, поименованными с префиксом #).
#A
#A
#A
#A
ESP хранит адрес вершины стека (т.е. на 4 байта ниже, т.к. они уже заняты адресом возврата из main). В EBP хранится нечто.
Далее в стек выталкивается значение регистра EBP.
#A
#A
#A
#A
#B
#B
#B
#B
В регистр EBP сохраняется состояние (значение) регистра ESP. Затем в программе объявляется локальный массив размером 4 байта. Массив также записывается в стек. Регистр ESP уменьшается ещё на 4 байта. Регистр EBP по-прежнему хранит состояние регистра ESP на момент «начала» функции.
#A
#A
#A
#A
#B
#B
#B
#B
#M
#M
#M
#M
Теперь, если мы разместим в массиве нуль-терминированную строку «123» (элементы которой адресуются возрастающими индексами), то стек примет вид:
#A
#A
#A
#A
#B
#B
#B
#B
NULL
'3'
'2'
'1'
Дальнейшее присвоение значений элементам строки приведёт к перезаписи последовательности #B (значение регистра EBP на момент начала выполнения функции main), и #A (адрес возврата из функции main, который инструкция RET вытолкнет в регистр EIP).

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

ЗЫЖ SBJoker верно уточняет, что с хр сп2 в винде существует нативная защита от выполнения данных, а современные камни от интел и амд обладают и аппаратной.
Тем не менее, пример в посте работает и под сп3: фактически он выполняет не данные, а инструкции (т.к. в стек записали адрес функции, а не шеллкод) и, сверх того, не посягает на чужую память.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?

Последний раз редактировалось impersonalis, 01.10.2011 в 18:33.
(Offline)
 
Ответить с цитированием
Эти 7 пользователя(ей) сказали Спасибо impersonalis за это полезное сообщение:
ABTOMAT (01.10.2011), den (01.10.2011), HolyDel (01.10.2011), Igor (01.10.2011), moka (01.10.2011), Randomize (04.10.2011), SBJoker (01.10.2011)