Main page www.securesize.com  
Main page GeSWall BOWall Resources  
BOWall
 

Мониторинг уязвимых функций

Данный метод предназначен для защиты от атак с подменой адреса возврата из функции и относится ко второму классу. Суть его работы вытекает из самой причины возникновения практически всех уязвимостей переполнения буфера. Эта причина заключается в использовании уязвимых функций С для работы со строками.

Например, к числу этих функций относятся следующие: strcpy, strcat, sprintf, gets и другие. О рекомендациях замены указанных функций на аналогичные с контролем размера строки (strncpy, strncat, snprintf) упоминалось выше. Данный метод предусматривает замену данных функций осуществлять не в исходном коде а в исполняемом файле. Отметим, что функции с контролем длины строки имеют один дополнительный аргумент - максимальный размер строки, по которому проверяется выход за границы буфера. Однако, правильность этого аргумента контролирует программист, который легко может ошибиться. К тому же дополнительный аргумент потребует изменить вызовы всех указанных функций, что для исполнимого файла является практически нереализуемым.

Опираясь на указанное выше был разработан новый алгоритм работы подменяемых функций, который позволяет детектировать переполнение буфера без использование дополнительных аргументов. Это алгоритм основан на стандартном прологе подпрограмм, имеющих локальные переменные. Так для функции следующего вида:

void func(void)

{

char buf[30];

gets(buf);

}

будет сгенерирован следующий пролог:

push ebp

mov ebp,esp

sub esp,30

Где sub esp,30 - резервирует буфер для строки в стеке, а ebp - содержит указатель базы кадра локальных переменных.

Впоследствии обращение к buf происходит посредством регистра ebp, например: lea eax, [ebp - 30] - заносит адрес buf в регистр eax. Очевидно, что стек при этом будет иметь структуру, показанную на следующем рисунке.

Структура стека для функции с локальной переменной

Таким образом, исходя из содержимого адреса базы кадра локальных переменных, т.е. содержимого регистра EBP, можно определить расположение адреса возврата:

Адрес возврата = [EBP+4]

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

Итак, получаем следующий алгоритм работы подменяемой функции:

1. Получить и сохранить адрес возрата

2. Выполнить требуемую уязвимую функцию

3. Получить адрес возврата

4. Проверить целостность адресов возврата

В случае нарушения целостности генерируется сообщение нарушения защиты. Отметим, что переполнятся может буфер, который находится не в текущем кадре локальных переменных в одном из предыдущих.

Структура стека с несколькими кадрами локальных переменных

В таком случае необходимо "пройти" по цепочке кадров и выбрать первый кадр, база которого имеет адрес больший адреса строки - параметра уязвимой функции. Например, для ситуации, изображенной на риcунке, адрес текущего кадра меньше адреса буфера строки, значит нужно выбрать следующий кадр и т.д. Отметим также, что некоторые компиляторы оптимизируют код так, что для экономии регистра указатель базы не используется, но применяются относительные смещения относительно текущего указателя стека. Поэтому для кода оптимизированного по такой схеме данный метод не будет функционировать.

 
© 2003-2008 Andrey Kolishchak
Designed by a.shoshin