Не так давно прочитал (статья Криса Касперского) интересный способ защиты своих приложений от переполенния в стеке и соответственно выполнения произвольного кода. Суть заключается в объявлении двух контрольных переменных расположенных в стеке перед переполняемым буфером. При выходе из выполняющейся функции просто проверяем ее значение. В случае переполнения переменная соответственно оказывается затерта и уже не соответствует прежнему значению. Ниже приведу тестовый код. В параметрах ехе файла передается некоторая величина. Если она больше 4 символов, происходит переполнение:
Код:
#include <windows.h>
BOOL WINAPI SomeFunction(char*);
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPTSTR lpszParam,int)
{
if(!lstrcmp(lpszParam,"")) MessageBox(0,"No Parametr!","title",0);
else SomeFunction(lpszParam);
return 0;
}
BOOL WINAPI SomeFunction(char* buf)
{
int dwValueOne=0x00;
char buffer[4]={0};
int dwValueTwo=0x00;
lstrcpy(&buffer[0],buf);
MessageBox(0,buf,"Parametr",0);
if(dwValueOne!=dwValueTwo)
{
MessageBox(0,"Buffer Overflow!\nRegister EIP probably specifies a shell-code!","WARNING",0);
}
return true;
}
ЗЫ в своей статье Крис Касперский предлагает для обьявления локальных переменных в функции использовать структуру, т.к. нельзя с 100% гарантией утверждать о размещении компилятором переменных в стеке именно в том порядке, в котором они были объявлены. Также отмечу, что данный способ все таки не даст полной гарантии защиты от выполнения шелл-кода.