С чего все началось? С апатичного замечания одного из коллег, читавшего новости: "А вы в курсе, что в Виндах нашли баг, который позволяет получить системные права и который невозможно запатчить?" Я воспринял это столь же апатично. В Виндах постоянно находят баги, связанные с Internet Explorer, просмотрщиками, IIS, и столь же постоянно их латают. Конца краю этому пока не предвидится. "Запатчат..." - равнодушно сказал я. Дел было много: открыть верховую езду, помириться с греками, отхапать железо у персов, поднять столицу до 8 и прочее и прочее...
"Его нельзя запатчить без коренной переделки Виндов. По крайней мере так пишут. Обмен сообщений между окнами приложений. Сам почитай," - не успокаивался коллега. Короче говоря, персам повезло - отхапать железо мне не дали. В Интернете нашли статью мужика, обнаружившего баг, и программу, написанную by Serus. Статья всем известна, пересказывать ее смысла не имеет, замечу только, что искать вручную код под отладчиком - занятие для настоящих джигитов, к коим я себя не причисляю.
Прога, написанная by Serus, - шедевр краткости и четкости. (Снимаю шляпу перед Вами, господин Serus!) Если опустить рутину и прибамбасы, то прога состоит из:
Как видим, ничего сверхъестественного и даже просто сложного нет. Все функции документированы и хорошо знакомы. Однако принцип и механизм работы данной программы несколько сложнее. Вот их мы и рассмотрим в данной статье.
Основная идея повышения прав - заставить "ошибиться" программу, исполняемую с системными правами, и запустить посторонний код. В рассматриваемой программе использована именно эта идея. Специально созданный код пересылается с помощью функции SendMessage в окно (а следовательно в адресное пространство) процесса winlogon.exe. Далее с помощью функции PostMessage передается управление на начало кода. Все! права повышены! А теперь последовательно рассмотрим все этапы подробнее.
Первое, что надо сделать, это найти окно-жертву. Сначала отыскиваем все системные процессы. Чтобы найти окна процессов, находим все потоки, потом находим все окна потоков. Теперь у нас имеется набор кандидатов в окно-жертву. Лично я - сторонник безопасного сек... э-ээ, взло... э-ээ, повышения прав. Поэтому передавать управление вслепую отказываюсь. Хорошо бы, перед тем как что-то выполнять, посмотреть - а тот ли код будет выполняться. Следовательно, нужно отобрать те системные процессы, память которых можно читать. Итого, в Windows 2000 на моем компе остались три процесса: nvsvc32.exe, mstask.exe и наш любимый winlogon.exe. На эти процессы приходится 4 окна. Для Windows XP есть только одно окно того же самого winlogon.exe. А вот под Windows NT таких окон я вообще не обнаружил, увы. Не будем оригинальничать, для Windows 2000 в качестве окна жертвы возьмем окно winlogon.exe с номером 1001e.
Будем считать, что интересующий нас код для запуска с системными правами уже есть. Что? Нет, я не знаю, что нас интересует! И не знаю, где его брать! Никогда сам не писал в кодах и уже слишком стар и ленив, чтобы начинать. Это работа компилятора - переводить в коды. Можно вырезать код из обычного экзешника, наверное...
Теперь начинается самое интересное - отправка кода-засланца в пространство процесса. При вызове функции SendMessage вкратце происходит следующее: сообщение копируется в системную память, откуда потом копируется в память процесса-жертвы. Куда именно попадает сообщение легко определить с помощью отладчика SoftIce, где предусмотрена специальная ловушка на получение окном события. В нашем случае точка останова ставится командой bmsg 1001e wm_copydata. Вот тут и всплывает адрес 0x0080FA78. При первом логоне при длине сообщения, равной 1000, сообщение всегда копируется по адресу 0x0080FA60, а наш исполняемый код попадает по адресу 0x0080FA78. Но... это только при первом логоне и длине 1000. Если Ваш код занимает больше килобайта, примите поздравления, сообщение попадет по другому адресу. Можно ли определить заранее, куда будет скопировано сообщение? Теоретически да, практически... Адрес, куда копируется сообщение, определяется следующим куском системного кода:
mov eax, [ffdff124]
mov eax, [eax+128]
mov eax, [eax+74]
...
mov ebx, [eax]
В ebx и попадает искомый адрес. Проще говоря - элемент из трехмерного массива. Проблема в том, что массив лежит в системной памяти. Так что, на практике, адрес кода можно определить только методом научного тыка.
Наконец, апофеоз - вызов функции PostMessage. Если до этого, ничего криминального с точки зрения безопасности не происходило, то добавление в пул потоков нового потока с явно указываемым адресом - явное безобразие. Я бы даже сказал, вредительство. При передаче управления данному потоку выполняется код с полномочиями winlogon.exe, то есть с системными правами.
Непонятно, почему Microsoft отрицала столь явную дыру в безопасности. Однако, мне столь же непонятно, почему автор статьи утверждал, что это нельзя запатчить. Непонятно это и компании Microsoft, которая уже запатчила этот баг. Но даже и без патча, практическое использование данного бага весьма и весьма затруднено. Во-первых, надо заранее знать адрес, по-которому будет скопировано сообщение, а он, как мы помним, зависит от длины кода. Во-вторых, между вызовами функций SendMessage и PostMessage память с нашим кодом может быть освобождена или переписана системой, так как сразу после вызова SendMessage память считается неиспользуемой. В этом случае передача управления абы чему, чревата синим экраном. В третьих, очень трудно передать в чужой процесс параметры, а без этого код лишен гибкости.
Я не утверждаю, что эти проблемы нельзя преодолеть, но все вместе они отбивают охоту писать эксплойты. Впрочем, береженого бог бережет.
Вот, собственно, и все. А теперь, дайте же мне, наконец, отхапать у персов железо!!!
Комментарий BugTraq. Заинтересовавшимся этой темой имеет смысл ознакомиться и с другой статьей на эту тему.
обсудить | все отзывы (0) | |
[27911; 8; 4] |
|
|