Мировая общественность всполошилась после заявления "эксперта" FOON о том, что все члены семейства Windows содержат неисправимую Design Error, могущую привести к локальной эскалации
привилегий вплоть до LocalSystem.
http://www.void.ru/content/994
http://www.xakep.ru/post/16039/default.asp
По мнению FOON'а, посылка определенных Windows Messages может привести к выполнению произвольного кода в контексте другого приложения, в том числе сервиса, запущенного с правами LocalSystem, и это является ошибкой класса Design Error, т.к. проблема вызвана неспособностью отличить сообщение, посланное системой, от сообщения, посланного "зловредным" приложением.
Однако, давайте разберемся. Для начала, НИКАКИЕ Windows Messages НЕ ПРИВОДЯТ к выполнению произвольного кода "сами по себе", в том числе, упомянутый в эксплоите WM_TIMER, который в качестве параметра может принимать адрес любой процедуры.
Проверить это можно с помощью простенькой программы:
int x(){
printf("Exploited!\n");
}
int main(){
PostMessage(GetActiveWindow(),WM_TIMER,0,(long)&x);
for(;;)
}
Запустив эту программу, мы не увидим сообщения "Exploited". Почему? Потому, что реакция на сообщение WM_TIMER, так же, как и на любые другие Windows Messages, производится из функции DispatchMessage, которой в нашей программе нет.
А вот как может выглядеть программа, реагирующая на WM_TIMER:
int main(){
MSG msg;
PostMessage(GetActiveWindow(),WM_TIMER,1,(long)&x);
printf("WM_TIMER=%d addr(x)=%x\n",WM_TIMER,(long)&x);
for(;;){
GetMessage(&msg,GetActiveWindow(),0,65535);
printf("got WM=%d wparam=%x
lparam=%x\n",msg.message,msg.wParam,msg.lParam);
DispatchMessage(&msg);
printf("dispatched\n");
}
}
Запустив ее, мы получим:
WM_TIMER=275 addr(x)=401005
got WM=275 wparam=1 lparam=401005
Exploited!
dispatched
Первая строка показывает, что сообщение WM_TIMER имеет код 275, а адрес процедуры x() - 401005. Далее видно, что срабатывает функция GetMessage, а затем выводится строка "получено сообщение с кодом 275, первый параметр - 1, второй параметр -
401005". Далее вызывается функция DispatchMessage, и, очевидно, уже из нее происходит вызов x(), нарисовавшей
"Exploited". Совершенно понятно, что нет никаких проблем программно отфильтровать любые "левые" сообщения, например, вот так:
for(;;){
GetMessage(&msg,GetActiveWindow(),0,65535);
printf("got WM=%d wparam=%x
lparam=%x\n",msg.message,msg.wParam,msg.lParam);
if((msg.message==WM_TIMER) && (msg.lParam!=USED_TIMER)){
printf("Hehe. Coolhatsking attempt!\n");
continue;
}
DispatchMessage(&msg);
printf("dispatched\n");
}
И вместо "Exploited" мы получим милую фразу "Hehe. Coolhatsking
attempt!"... Является ли это новостью? Нет. Microsoft
документировала это еще 5 лет назад!
Очевидно, что проблема не столько в самой организации Windows Messages, сколько в незнании механизмов ее работы как у авторов некоторых приложений, оказавшихся уязвимыми, так и у некоторых "security
experts".