Windows Messages - не баг

Windows Messages - не баг

Мировая общественность всполошилась после заявления "эксперта" FOON о том, что все члены семейства Windows содержат неисправимую Design Error, могущую привести к локальной эскалации привелегий вплоть до LocalSystem. Однако НИКАКИЕ Windows Messages НЕ ПРИВОДЯТ к выполнению произвольного кода "сами по себе", в том числе, упомянутый в эксплоите WM_TIMER, который в качестве параметра может принимать адрес любой процедуры.

 "Сикретный Огент", sikogent@mail.ru

Мировая общественность всполошилась после заявления "эксперта" FOON о том, что все члены семейства Windows содержат неисправимую Design Error, могущую привести к локальной эскалации привелегий вплоть до LocalSystem.

http://www.void.ru/content/994
http://www1.xakep.ru/post/16039/default.asp
http://securitylab.ru/?ID=32281

По мнению 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 лет назад:

http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0397/hood/hood0397.htm&nav=/msj/0397/newnav.htm

Очевидно, что проблема не столько в самой организации Windows Messages, сколько в незнании механизмов ее работы как у авторов некоторых приложений, оказавшихся уязвимыми, так и у некоторых "security experts".

Тени в интернете всегда следят за вами

Станьте невидимкой – подключайтесь к нашему каналу.