Повышение привилегий в системе - вечная тема для обсуждений. Сколько
эксплоитов было сделано, сколько rootkit'ов было написано, и ради чего? Кодить, кодить, кодить... Дни и ночи напролет... Каждый пытается найти уязвимость, получить права рута, получить ВСЕ! Я
не понимаю откуда берется это желание. Может это жажда власти? Какими бы небыли причины, я надеюсь, эта статья будет вам интересна.
Статья посвящена вполне легальным способам получения прав администратора в Windows системах.
Итак приступим...
Windows Messages
Этим летом многие могли видеть документы о получении прав локальной системы с помощью сообщений в
Windows (те, кто не знаком с этой проблемой, могут прочитать
перевод). Все дело в том, что некий FOON описал новый вид атак на основе
самого принципа функционирования Windows API. Если быть точнее, не всего API а именно той части которая отвечает за взаимодействие окон приложений с системой. Представленный им
пример с гордым названием
Shatter (именно поэтому этот тип атак называют "атаками
класса Shatter") демонстрирует использование этой уязвимости. Исправить эту ошибку на уровне API практически невозможно. Единственная возможность
улучшить устойчивость системы ложится на плечи
разработчиков ПО. Прочитать подробнее про способы защиты можно
тут.
А совсем недавно в форуме на BUGTRAQ снова появилось
упоминание про эту уязвимость. На этот раз внимание к этой проблеме привлек Serus, написавший
эксплоит (бинарник)
под Windows 2000 и Windows XP. Эксплоит использует в качестве
цели агент NetDDE. Посмотрев поближе на исходники
можно понять как он работает. Этот код может служить хорошей основой для rootkit'а. Давайте упростим модель
эксплоита и рассмотрим принципы его работы.
Для начала ищем дескриптор NDDEAgnt:
hWnd = FindWindow("NDDEAgnt","NetDDE
Agent");
Допустим наш шеллкод находится в переменной shellcode(unsigned char). Действия шеллкода зависят только от атакующего. Но в нашем случае удобнее будет запускать себя с неким параметром. Этот параметр будет
использоваться как флаг, указывающий нашему приложению, что оно имеет права localsystem,
или же используя API просто узнавать права нашего приложения. Так или иначе, мы должны использовать функцию CreateProcessA. А для этого нам нужно узнать адрес входа в функцию CreateProcess. Вот псевдо-исходный код:
hMod = GetModuleHandle("kernel32.dll");
ProcAddr = (DWORD)GetProcAddress(hMod, "CreateProcessA");
*(DWORD *)(shellcode + offsetModuleAddr) = ProcAddr;
ProcAddr = (DWORD)GetProcAddress(hMod, "CreateMutexA");
*(DWORD *)(shellcode + offsetProcAddr) = ProcAddr;
После всего этого можно продолжать атаку: скопировать шеллкод в heap область NetDDE, и запустить:
buf = (char *)malloc(1000);
memset(buf, 0xC3, 1000);
memcpy(buf, shellcode, sizeof(shellcode));
cds.cbData = 1000;
cds.dwData = 0;
cds.lpData=(PVOID)buf;
SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds);
PostMessage(hWnd, WM_TIMER, 0, (LPARAM)Addr);
Но хочу сразу оговорится, что реализовать этот тип атаки вам
не удастся без знаний ассемблера, а точнее написания шеллкодов. Но в
эксплоите от Serus'а можно исправить шеллкод. Все дело в том, что в нем хранится строка, указывающая какое именно приложение следует запустить. В данном случае это "cmd". Эту строку можно легко найти
по сигнатуре: 0x63, 0x6D, 0x64. Вместо нее можно вписать другие символы и следовательно запустить иное приложение. Но помните, это не выход!
Более детальное техническое описание проблемы можно найти на сайте
Microsoft.
Screen Saver
И снова ошибка класса дизайна. На этот раз это
работа с хранителями экрана. Система, запуская скринсейвер, автоматически наделяет его правами активного пользователя. Это очень удобно использовать для повышения привилегий своего приложения в системе. Давайте
разберемся, что такое скринсейвер. Это тоже приложение, просто с
расширением *.SCR Еще отличительное чертой является то, что система запускает Screen
Saver как приложение с параметром /S. Следовательно, если наше приложение запустилось с ключом
/S, то мы имеем права активного пользователя. Но дело в том, что мы не знаем какой именно хранитель установлен в качестве активного для
привилегированного пользователя. Следующий вопрос, который может возникнуть, это способы запуска себя в качестве хранителя экрана. Проблема заключается в том, что если не найден файл установленного хранителя
экрана, то запускается logon.scr. А это именно то, что нам надо. Для запуска нашего приложения удаляем все скринсейверы и копируем себя в директорию c:\windows\system32\ под именем logon.scr. Теперь, когда в системе администратор, попытка запуска скринсейвера приведет к запуску нашего приложения.
Программно настройки хранителя экрана можно
изменить в реестре Windows. Все настройки
связанные с Screen Saver'ом хранятся в разделе HKEY_CURRENT_USER\Control Panel\Desktop. Интересными для изменения являются параметры:
ScreenSaveTimeOut - период бездействия, необходимый
для активации
ScreenSaveActive - флаг включения. Если указанное
значение 1, хранитель запускается
SCRNSAVE.EXE - имя файла, используемого в качестве хранителя экрана
Следовательно если указать следующие настройки наше приложение активируется спустя минуту бездействия пользователя:
ScreenSaveTimeOut=1
ScreenSaveActive=60
SCRNSAVE.EXE=screensaver.scr //Где program.scr это наше приложение.
Запустить текущий хранитель можно и исполнив следующий код:
SendMessage(Application.Handle,WM_SYSCOMMAND,SC_SCREENSAVE,0);
Поскольку Windows достаточно сложная система, для организации ее роботы построен сложный механизм. Поэтому избавится от ошибок такого типа достаточно сложно. Будем
надеяться, что в скором времени ситуация не изменится к
лучшему. Пожалуй на этом пока что все. Я надеюсь, что данный материал благотворно повлияет на "разработчиков троянного обеспечения" 🙂