![]() |
Граната для обезьяны (на базе MS04-019 utilman)
Acknowledgement: Спасибо 0x90 за консультации.
Ссылки: http://www.wasm.ru/article.php?article=win32appbyhand http://www.security.nnov.ru/files/da-um_ex.c В некоторых офисах параноидальные и не очень квалифицированные сисадмины применяют достаточно экзотический способ защиты. А именно, вырубают дисководы, интернет и USB порты, дают пользователям права Guest или User, пускают их только в локальную сеть с минимальными правами и думают что все в порядке. Цель этой статьи показать этим сисадминам, что еще не все кончено. Что пользователь вполне может написать эксплойт и для начала, получить права администратора. А потом уже по вкусу, можно поломать сетку, забраться в компьютер директора и украсть коды запуска американских ракет :-))) Кроме указания администраторам на уязвимости, вторая цель статьи – образовательная, что и определяет структуру статьи. В статье обсуждается три в общем-то отдельных вопроса: 1. Эксплуатирование системных прав Utility Manger с целью получения коммандного интерпретатора с системными же правами. 2. Написание исполнимого Win32 файла минимального размера. 3. Ввод бинарного файла с клавиатуры. Именно сочетание всех этих трех премудростей и позволило мне назвать результат «Гранатой для Обезьяны». Начнем с написания минимального размера эксплойта на повышение прав. Возьмем за основу систему повышения прав, основанную на том, что Utility Manger запускается с правами системы. Соответствующий полноценный эксплойт в авторстве 0x90 описан здесь: http://www.security.nnov.ru/files/da-um_ex.c Наша цель состоит в том, чтобы как можно сильнее его сократить. Кстати еще одна причина, почему я выбрал именно этот эксплойт состоит в том, что значительную часть действий здесь можно выполнить с клавиатуры. Общий смысл состоит в том, что путем некоторых манипуляций удается заставить Utilman открыть OpenDialog, который будет обладать системными правами, а затем из этого OpenDialog’а можно уже выполнить cmd.exe, соответственно тоже с правами системы :-))) Писать код будем сначала на си, потом на ассемблере, а потом вообще в кодах. Конечно хватило бы одного из этих способов, но ужо я вас помучаю. Если три раза повторить - может понятнее будет. Сначала опишем наши действия на русском языке (можно сверяться с кодом 0x90): 1. Запустить Utility Manger 2. Найти хэндлер окна Utility Manger 3. Послать Utility Manger через WINAPI сообщение 0x365 которое приведет к тому, что Utility Manger попытается открыть не существующий hlp файл. Возникнет окошко, которое спросит нас, хотим ли мы открыть этот файл в ручном режиме. 4. Найти хэндлер окна winhelp 5. Нажать Enter 6. В открывшемся OpenDialog поменять фильтр загружаемых файлов, так, чтобы отобразился cmd.exe, например в качестве фильтра поставим cmd.ex? 7. Кликаем правой кнопкой мыши по показанному cmd.exe 8. Выполняем команду «Open» и получаем окно cmd с правами системы. Прелесть этого эксплойта в том, что все кроме пункта 3 можно сделать руками. Ну и еще, чтобы послать Message придется сначала все-таки найти хэндлер. Но уж все остальное только руками. Tip: Прошу обратить внимание. Перед запуском эксплойта и вообще перед опытами, следует запустить utilman и убрать галки, которые заставляют одновременно с запуском utilman запускать еще и некоторые другие сервисы. Запускать ulilman надо нажатием клавиш WinKey+U, потому что если у вас права User или Guest, он не запустится командой utilman /start. После того, как написали программу на русском языке, напишем то же самое на условном (т.е. cи без лишних слов) языке программирования: HANDLE h1=FindWindow(NULL, “Utility Manager”); SendMessage(h1,0x365,0,0x1); Вот и все, дальше можно все руками. Почти все. Почти, потому что, во первых после запуска, программа должна нам дать время запустить Utility Manager, а во-вторых после посылки месседжа, должна ждать, пока мы понажимаем нужные кнопки или вообще выйти. Поэтому дописываем: Sleep(0xA00); HANDLE h1=FindWindow(NULL, “Utility Manager”); SendMessage(h1,0x365,0,0x1); ExitProcess(0x00); Теперь можно написать код на си: Код:
#include <windows.h>Загружаем программу под дебаггер (любой, тот который у вас в IDE или внешний, например OllyDbg, без разницы) и находим там наш (вот именно наш, а не дописанный компилером!) исполнимый код. Дебаггер как правило показывает названия вызываемых функций, наш участок кода должен начинаться с вызова функции Sleep из KERNEL32.DLL. В дебаггере из IDE это сделать проще, потому что можно поставить брекпойнт прямо на первый Sleep. Нужный нам код выглядит примерно так: Код:
00401154 /. 68 000A0000 PUSH 0A00 ; /Timeout = 2560. msPUSH – означает поместить в стек. Стек это такая фигня (область в памяти) которая применяется для передачи аргументов подпрограммам (функциям) в том случае, если свободных регистров процессора мало. Кстати, если вы хорошо знаете си, то запись __fastcall перед функцией означает, что по возможности, аргументы нужно передавать через регистры а не через стек. CALL – выполнить подпрограмму (функцию) которая находится по определенному адресу. MOV – переписать, скопировать, эквивалент знака «=» в обычном языке программирования. MOV A,B то же самое, что и A=B EBP,EAX – регистры процессора. Это такие очень быстро доступные ячейки памяти, которые находятся в самом процессоре. Их мало. <JMP.&KERNEL32.Sleep> - Вообще говоря, в коде вместо этого на самом деле написано [A2 7C 00 00], но дебаггер понял, что по этому адресу находится запись таблицы импорта, которая указывает на адрес функции Sleep из модуля KERNEL32.DLL. Далее мы еще будем разбираться с таблицей импорта. Здесь скажу, что при запуске нашего экзешника, виндоус по адресу A2 7C 00 00 вписала адрес, по которому у конкретной версии винды находится функция Sleep из KERNEL32.DLL. Значек & у дебаггера и квадратные скобочки у меня означают, что нужно не выполнить функцию по адресу A2 7C 00 00, а нужно выполнить функцию, адрес которой записан по адресу A2 7C 00 00. expl.0040914C – моя программа называется expl, поэтому expl.0040914C означает адрес 0040914C в адресном пространстве expl. По этому адресу находится начало строки «Utility Manager», т.е. это «область данных». Конец строки «Utility Manager» определяется по байт-символу 0x00. [EBP-4] – очевидно, компилятор позаботился, чтобы в регистре EBP на данный момент было такое значение, чтобы по адресу EBP-4 находилась наша переменная, которую мы обозвали h1 в тексте нашей программы на си. Отметим, что после выполнения функции FindWindowA, искомый хэндлер окна будет находится в регистре EAX. Теперь тут я хотел писать описание как ручками (в шестнадцатиричном редакторе) сделать маленький экзешник. Сам я умею, но писать описание замаялся. Половину написал, а потом плюнул. Если откомпилировать в fasm’е то получится 1536 байт. Я могу сделать руками экзешник вдвое меньший. Если народ захочет, я буду дописывать описание процесса и, может быть, когда-нибудь опубликую. На основе кода который нам выдал дебаггер пишем код для фасма: Код:
include 'win32ax.inc'Компилируем, получили экзе 1536 байт. Все-таки влезем в него хексэдитором и потрем лишнее, так чтобы начало выглядело так: Код:
00000000 4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 MZ..............Архивируем экзешник в zip. У меня получилось 371 байт. Осталось его набрать с клавиатуры на целевой машине, распаковать и запустить. Если у вас нет возможности распаковать – наверное лучше всего набирать целый экзешник. Теперь как набирать. Я предлагаю с помощью утилиты debug. Возможно вы предложите другие способы. Коротко про debug. Это такая тулза которая позволяет редактировать содержимое памяти и потом что надо сбросить в файл. Ставится вместе с виндоус. Запускается – командой debug из командной строки. Появляется приглашение – знак минус. Команды которые понадобятся: f 0,200,0 Заполнить с адреса 0 по адрес 200 все байтом 0. a 0 Начать ввод с адреса 0 После этого db 01,F2,43,24,25 ….и т.д. Вводите в память то что вам нужно. Выход из режима ввода – нажать лишний раз Enter. d 0 Распечатать содержимое памяти начиная с адреса 0. При этом распечатается 0x80 байт памяти. Запись в файл. debug не будет писать в файл первые 0x100 байт из того, что ему сказали писать. Поэтому нужно передвинуть наши данные, которые начинаются с адреса 0 на 0x100, это делается так: m 0 xxx 100 где xxx – сколько байт двигать. Запись в файл делается так: n uti.bin где uti.bin – имя файла, который в который делается запись. Потом: r cx xxx w где xxx – сколько байт писать в файл. Усе готово. Теперь нужно разархивировать, запустить, быстренько нажать WinKey+U, а что делать дальше вы должны уже знать, если внимательно читали начало :-))) ============================================= Автор: Scandy. проект www.wapbbs.com/bbs/ |
| Время: 23:38 |