• Авторизация


Защита программ от переполнения буфера с помощью GCC. Часть 2. Stack Smashing Protect 31-08-2009 13:05 к комментариям - к полной версии - понравилось!


   SSP (Stack Smashing Protector) — это расширение GCC позволяющее защитить программу от атак основных на переполнении стека. Программы написанные на языках C, C++, Obj, и Obj++ защищаются методом добавления в функции, во время компиляции, защищающего кода.

   SSP работает по следующему принципу: в пролог функции добавляется код сохраняющий сторожевую константу в стеке, а в эпилог — код сравнивающий число сохранённое в стеке со сторожевой константой, если эти числа не равны, то программа аварийно завершается. Таким образом SSP не позволяет взломщику воспользоваться уязвимостью для захвата управления (но помогает в организации DoS;) ). Сторожевая константа сохраняется выше регистра указателя базы кадра стека ebp, поэтому невозможно, при переполнении буфера, изменит адреса возврата или ebp, не затерев сторожевую константу, но остается возможность изменения значения локальных переменных. Для того чтобы невозможно было изменить значение скалярных переменных SSP изменяет порядок локальных переменных: на вершину кадра стека помещаются скалярные переменные, а массивы располагаются ниже (взломщик может переполнением одного массива изменить содержимое другого).

          
Ниже приведён код пролога для i386:

pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl %gs:20, %eax
movl %eax, -4(%ebp)


          
Эпилог для i386 выглядит так:

xorl %gs:20, %eax
jne .L33
...
.L33:
call __stack_chk_fail // выводит сообщение и завершает работу приложения

   Область хранения сторожевой константы зависит от платформы, для Linux i386 — сохраняется в сегменте GS по смещению 0x14, в Linux x86-64 — в сегменте FS по смещению 0x28. Значение сторожевой константе присваивается при старте программы в функции _guard_setup(void), которая выглядит так:

static void __attribute__ ((constructor)) __guard_setup (void)
{
unsigned char *p;
int fd;

if (__stack_chk_guard != 0)
return;

fd = open ("/dev/urandom", O_RDONLY);
if (fd != -1)
{
ssize_t size = read (fd, &__stack_chk_guard,
sizeof (__stack_chk_guard));
close (fd);
if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0)
return;
}

/* If a random generator can't be used, the protector switches the guard
to the "terminator canary". */
p = (unsigned char *) &__stack_chk_guard;
p[sizeof(__stack_chk_guard)-1] = 255;
p[sizeof(__stack_chk_guard)-2] = '\n';
p[0] = 0;
}

   Как видно из кода, значение читается из /dev/urandom, если /dev/urandom недоступно, то в качестве сторожевой константы будет использоваться число 0xff0a0000.

   SSP включается с помощью опций -fstack-protector или -fstack-protector-all. Опция -fstack-protector — добавляет защитный код только к функциям, которые содержат буфер больше 8 байт (дополнительно смотрите в документации параметр ssp-buffer-size) либо выделяют память с помощью функции alloca(). -fstack-protector-all — добавляет защищающий код во все функции.

   Для дополнительной информации смотрите:
http://en.wikipedia.org/wiki/ProPolice
ProPolice
Переполняющиеся буфера - активные средства защиты
вверх^ к полной версии понравилось! в evernote


Вы сейчас не можете прокомментировать это сообщение.

Дневник Защита программ от переполнения буфера с помощью GCC. Часть 2. Stack Smashing Protect | whitewin - Дневник whitewin | Лента друзей whitewin / Полная версия Добавить в друзья Страницы: раньше»