OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
//write our shellcode to the file
WriteFile(file,writeme,65,&written,NULL);
CloseHandle(file);
//we’re done
return 1;
}
Современные способы переполнения буфера
После изучения обязательного минимума пришло время познакомиться с современными способами переполнения буфера. Одни из них применимы повсеместно, другие – в частных случаях. С течением времени злоумышленники узнают о переполнении буфера все больше, поэтому сегодня для успешной защиты от атак переполнения буфера необходимо знать изощренные способы извлечения из него пользы.
Фильтрация входных данных
Современные программисты, стремясь как можно лучше защититься от атак переполнения буфера, начинают создавать программы, которые перед записью входных данных в буфер проверяют, нет ли в них выполняемого программного кода. Подобные программы серьезно затрудняют деятельность злоумышленника, не позволяя ему запросто поместить злонамеренный код в программе. Большие неприятности сулят нулевые байты в буфере, поэтому современные программисты тщательно исследуют безопасность записываемых в буфер данных.
Способов анализа безопасности данных много, и каждый из них по-своему препятствует переполнению буфера.
Например, некоторые программисты проверяют значения входных данных. Если ожидается ввод чисел, то перед записью в буфер проверяется, является ли каждое введенное значение числом. В стандартной библиотеке языка C есть несколько функций, которые проверяют значение введенных данных. Ниже приведены некоторые из них для платформы Win32. Для работы в 16-битном стандарте кодирования символов Unicode существуют аналогичные функции проверки «широких» символов.
int isalnum( int c ); checks if it is in A-Z,a-z,0-9
int isalpha( int c ); checks if it is in A-Z,a-z
int __isascii( int c ); checks if it is in 0x00-0x7f
int isdigit( int c ); checks if it is in 0-9
isxdigit( int c ); checks if it is in 0-9, A-F
Подобные функции реализованы во многих библиотеках С для UNIX.
Хорошая программа переполнения буфера должна преодолевать фильтрацию входных данных. Для этого создаются специальные программы кодирования входных данных, позволяющие обмануть фильтрацию.
Было проведено много исследований в области создания программного кода полезной нагрузки, состоящего из алфавитно-цифровых символов и младших символов кода ASCII. При возможности реализации этим способом необходимых функциональных возможностей исследования увенчались успехом. В частности, был разработан способ кодирования полезной нагрузки по стандартам MIME (MIME – набор стандартов для передачи мультимедийной информации посредством электронной почты) или командой XOR, выполненной над последовательностью из нескольких байт. Применяемая кодировка позволяет маскировать странную последовательность байтов под программный код полезной нагрузки из ASCII-символов.
Другой способ преодоления проверки входных данных заключается в том, чтобы избежать фильтрации данных. Например, присвоив переменной окружения или переменной сессии двоичную строку программного кода полезной нагрузки, можно сократить число байтов, которые должны удовлетворять условиям проверки входных данных.
Частичное переполнение буфера и искажение данных
В последнее время значительно увеличилось число программистов, начавших использовать строковые функции с ограничениями, например функцию strncpy() вместо strcpy(). Этих программистов научили, что функции с ограничениями защищают от переполнения буфера. Как же они удивятся, когда узнают, что зачастую применяют их неправильно.
Широко известна общая ошибка использования функций с ограничениями, получившая название «минус один», когда максимальная длина записываемой в буфер строки приравнивается размеру буфера. При этом часто забывают об обязательном признаке конца строки – завершающем строку нулевом байте. Некоторые функции с ограничениями могут не включать в строку завершающего символа, позволяя строке незаметно слиться со строкой из рядом расположенного буфера. Если позднее обратиться к ней, то два буфера могут рассматриваться как один, способствуя переполнению буфера.
Рассмотрим пример:
[buf1 – 32 bytes \0][buf2 – 32 bytes \0]
После записи в буфер в bufl ровно 32 байтов два буфера выглядят следующим образом:
[buf1 – 32 bytes of data ][buf2 – 32 bytes \0]
Любая последующая попытка переслать из буфера bufl данные может привести к копированию 64-байтной строки данных и переполнению буфера, в который записываются данные.
Другое часто встречающееся неверное использование функций с ограничениями заключается в ошибках программирования или в неправильном расчете контролирующих величин во время выполнения программы. Это может произойти из-за нелепой ошибки или несогласованных изменений в программе в процессе разработки, например в программе был определен буфер фиксированного размера, размер которого не был откорректирован в соответствии с внесенными в программу изменениями. Помните, что размер обрабатываемых данных должен быть согласован с размером буфера получателя информации, а не ее источника. Известны примеры использования в проверках функций strlen(), которые во время выполнения программы подсчитывали число байт в буфере, из которого данные копировались. Эта простая ошибка делает бесполезной любую проверку размеров буферов.
Читать дальше
Конец ознакомительного отрывка
Купить книгу