Простой обход фаервола KIS 7 — Архив WASM.RU
Привет всем. Сегодня поговорим о простом, но, тем не менее, эффективном методе обхода фаервола Kaspersky Internet Security 7.0 – сетевого экрана, компонента одной из самых популярных и известных защит для персонального пользователя на сегодняшний день. Кто-то хвалит данный продукт, кто-то им восхищается, а кто-то откровенно недолюбливает =) Есть за что или нет, решать Вам. Тут будут только факты. Рассмотрим самую свежую на данное время версию 7.0.0.125. Факт обхода будет заключаться в скрытой отправке данных, лик, утечка - ну как угодно. Доказательства концепции не будет, дабы не сильно радовать наших младших братьев – скрипт-киддисов. Кому надо код можно написать вместе с отладкой за 30 минут. Меньше слов – больше дела.
Существует очень известная и чрезвычайно распространенная техника – инжект. О ней много написано, и большинство из того, что написано, уже детектируется нашем сегодяшним подопытным кроликом. Суть техники сводится к исполнению кода уже доверенного приложения, каким угодно способом. Большинство пользователей, у которых есть Интернет пользуются браузером, а стало быть и серфят Интернет с помощью браузера, а следовательно, должно быть правило в сетевом экране, которое разрешает браузеру по умолчанию передавать данные на 80 порт любому серверу. Отлично, будем этим пользоваться – инжектим код в браузер, и от его имени передаем или получаем данные. Ну, это-то знают все =) А как инжектится? Как обойти преграду проактивной защиты KIS? Просто, даже очень.
Итак, сам процесс инжекта состоит из двух этапов – 1) запись кода 2) передача ему управления. Запись кода… Тут можно много чего придумать, но я расскажу всего один секрет применимый исключительно для KIS. Вообще запись кода в чужой процесс осуществляется функцией KERNEL32!WriteProcessMemory, спускаясь ниже - ее нативным аналогом NTDLL!NtWriteVirtualMemory. Параметры конечно рассказывать не буду, для этого есть исходные источники – IDA =), шутка – Micro$oft. Обычно попытки запись в чужой процесс KIS предупреждает, но не всегда. Взлом любой защиты основан на ее допущениях. Допущение KIS – возможность записи в область виртуальной памяти, НЕ помеченной как исполняемая, конкретно – у области нет атрибута EXECUTABLE. Если данного атрибута нет – то можно писать свободно – KIS и ухом не поведет. Этот факт был получен чисто экспериментальным путем. Отлично. Запись мы сделаем. Но вот куда? Есть простое решение – это область памяти называемая стеком. Но тут кроется самое интересное – записывая код в определенное место в стеке мы убиваем одном выстрелом двух зайцев, а зайцы эти - как раз два пункта процесса инжекта. Все, наверное, уже догадались, о чем идет речь. Кто не догадался - читает дальше. С записью итак понятно, выполнять код будем тоже записью в стек – в стек потока, который дальше будет исполнять наш код. Дело в том, что потоки постоянно вызывают функции и с очень большой вероятностью адрес возврата записывают в стек. Подменив адрес возврата на свой, мы заставим поток исполнять наш код, который также записан в стеке. Знаю, что код в стеке не всегда исполняется, учитывая современные тенденции. Ну, записать код можно и не только в стек. Оставлю это Вам. Т.о. план простого инжекта вычерчивается очень четко следующими пунктами
- Создаем процесс, на основе исполняемого файла браузера по умолчанию
- После некоторого времени исполнения останавливаем поток браузера
- Получаем его контекст – нас интересует значение указателя стека
- Анализируем стек на предмет адреса возврата
- Пишем адрес нашего кода, который будет что-то качать или передавать по адресу в стеке, где находиться адрес возврата
- Возобновляем исполнение потока
В этом алгоритме есть один возможно не самый понятный момент – как анализировать стек на предмет адреса возврата. Я использую следующий метод – двигаемся «вниз» по стеку, и получаем DWORD’ы. Каждый из них может быть адресом возврата. Это можно проверить - читаем по адресу, который соответствует данному DWORD’у, и дизассембируем по адресам вниз. Если там находится инструкция CALL, значит это и есть адрес возврата. Маленькая иллюстрация:
Код (Text):
CALL X RET_ADDRESS: PROC X ….Пусть мы остановили поток во время исполнения функции X, в стеке присутствуют (или могут) локальные переменные, сохраненные неизменяемые регистры (при STDCALL), просто данные помещенные в стек (временно) и конечно адрес возврата. Адрес возврата – это RET_ADDRESS. Его значение мы должны найти в результате анализа стека. При этом можно предположить, что при анализе можно полагаться на значение EBP, как правило, тоже сохраняемое в стеке – тут полезно вспомнить стандартный код пролога многих функций. И значение EBP мы можем получить из контекста. Но практика показала, что к этому нельзя привязываться, т.к. стек останавливаемого потока в контексте вызова конкретной функции может содержать просто адрес возврата и больше ничего. Дизассемблер длин плюс разбор по полям, понятно, нам для реализации техники непременно потребуется. Пустяк. Что получилось в итоге… Получился псевдокод мнимого языка с мнимыми функциями для простого обхода KIS 7:
Код (Text):
CreateProcess(BrowserFilePath,…,ProcessInformation); // Создаем процесс Sleep(1000); // Поспим немного SuspendThread(ProcessInformation.hThread); // Приостанавливаем первично-порожденный поток GetThreadContext(ProcessInformation.hThread,&Context);// Получаем контекст ReadProcessMemory(ProcessInformation.hProcess,Context.Esp,StackChunk,1000*4);// Читаем 1000 DWORD’ов c ESP for (i=0;i<1000;i++) // анализ стека потока { ReadProcessMemory(ProcessInformation.hProcess,StackChunk[i]-10,CodeBuffer,10); // читаем 10 байт – если это адрес возврата, то эти 10 байт содержат инструкцию CALL for (j=0;j<10;j++) { disasm(&(CodeBuffer[9-j]),&Instr); // разбор инструкции «назад» if ( ( Instr.Length == j+1 ) && (Instr.OpCode == 0xe8 || Instr.OpCode == 0xff || Instr.OpCode == 0x9a) ) // это CALL? { WriteProcessMemory(ProcessInformation.hProcess, (Context.Esp+StackChunk[i] - StackChunk),&ShellCodeAddress,4); // пишем адрес нашего shell-кода ResumeThread(ProcessInformation.hThread); // возобновляем исполнение потока } } }Респект dead_body из команды WASM за вклад в идею обхода. Памяти безвременного ушедшего кудесника кода Ms-Rem’а. Ждем официальной реакции команды разработчиков KIS. До скорой встречи. mailto – mental_mirror@freed0m.org © Mental_Mirror
Простой обход фаервола KIS 7
Дата публикации 25 окт 2007