Привет, Хабр. На связи Вячеслав Закоржевский, старший вирусный аналитик ЛК. Пока редакторы пишут очередные анонсы и прочую поэзию, есть возможность удивить вас мало-мальски техническим материалом.
Все, наверное, знают, что есть множество разных фишек, с помощью которых малварщики защищают свои детища. Обычно они пытаются определить, работает ли приложение под виртуалкой, обойти эвристическую или проактивную защиту и т.д. Мы решили написать небольшой пример того, как в современном FakeAV (получен буквально пару дней назад) вирусописатели пытаются обойти АВ-продукты, песочницы и т.д. В исследуемом файле я обнаружил вызов экспортируемой функции с любопытным именем:
Скриншот зловреда из Hiew
Название функции «antiemu33» говорит само за себя — ANTiEMUlation — анти-эмуляция. На скрине видно, что проверяется результат функции. Если он не равен «0», то зловред продолжает работать дальше. А если результат — «0» — передаётся управление на код, выполняющий завершение процесса. Заглянем вовнутрь функции уже с помощью IDA.
Скрин функции antiemu33 из IDA
В этой процедуре происходит вызов достаточно редкой API-функции «ldap_count_references» из библиотеки «WLDAP32.dll». А дальше возможно два варианта развития событий:
1) Ничего не произойдёт, функция вернёт управление, и antiemu33 вернёт «0»;
2) Сгенерируется исключение, вызовется обработчик исключения по адресу 0x401025, который вернёт желанную «1».
Генерация исключения в IDA
Обработчик исключения поставлен с помощью C++ try/catch, IDA даже смогла статично это определить, выведя структуру на экран целиком. Таким образом, расчёт злоумышленников заключается в том, что какой-нибудь эмулятор или эвристический анализатор неправильно обработает вызов этой API-функции или обработку исключения, что приведёт к возвращению «0» и последующему завершению файла.
И ещё один пример антиэмуляции на уже другом, но совсем свежем FakeAV. Ниже я приложил скриншот из Hiew, курсор указывает прямо на точку входа.
Скриншот FakeAV с точки входа
По порядку — вызывается функция EnumResourceTypesA, а затем проверяется, равно ли возвращаемое значение нулю или нет. Если функция вернула нуль, то программа уйдёт в бесконечный цикл, что, очевидно, не должно происходить на нормальной системе. Таким образом, это первая антиэмуляция, достаточно простая, но вполне возможно, способная обойти что-то. Далее, вызывается функция GetLastError, и возвращаемое значение сдвигается направо на 7 бит и складывается с адресом 0x1003C9. Затем с помощью call’а выполняется переход по полученному значению. На нормальной машине в eax’е после GetLastError’а должно лежать 0x714, после сдвига — 0xE, после сложения — 0x1003D7. Таким образом, в живой системе будет выполнен переход именно по этому адресу. А если эвристический анализатор или эмулятор не смогли адекватно обработать вызов GetLastError, то приложение завершится или упадёт.
Скриншот этого же FakeAV из IDA
Но на этом всё не заканчивается — если посмотреть на код, то видно, что дальше вызывается функция EnumSystemLocalesA, после которой выполняется … переход на ExitProcess! А вся фишка в том, что в эту функцию первым параметром передаётся указать на CALLBACK (LOCALE_ENUMPROC), который вызывается системой. Именно в этом CALLBACK’е располагается вся «полезная нагрузка» зловреда. Здесь опять же малварщики рассчитывают на несовершенство антивирусов, обрабатывающих API-функции.
Все, наверное, знают, что есть множество разных фишек, с помощью которых малварщики защищают свои детища. Обычно они пытаются определить, работает ли приложение под виртуалкой, обойти эвристическую или проактивную защиту и т.д. Мы решили написать небольшой пример того, как в современном FakeAV (получен буквально пару дней назад) вирусописатели пытаются обойти АВ-продукты, песочницы и т.д. В исследуемом файле я обнаружил вызов экспортируемой функции с любопытным именем:
Скриншот зловреда из Hiew
Название функции «antiemu33» говорит само за себя — ANTiEMUlation — анти-эмуляция. На скрине видно, что проверяется результат функции. Если он не равен «0», то зловред продолжает работать дальше. А если результат — «0» — передаётся управление на код, выполняющий завершение процесса. Заглянем вовнутрь функции уже с помощью IDA.
Скрин функции antiemu33 из IDA
В этой процедуре происходит вызов достаточно редкой API-функции «ldap_count_references» из библиотеки «WLDAP32.dll». А дальше возможно два варианта развития событий:
1) Ничего не произойдёт, функция вернёт управление, и antiemu33 вернёт «0»;
2) Сгенерируется исключение, вызовется обработчик исключения по адресу 0x401025, который вернёт желанную «1».
Генерация исключения в IDA
Обработчик исключения поставлен с помощью C++ try/catch, IDA даже смогла статично это определить, выведя структуру на экран целиком. Таким образом, расчёт злоумышленников заключается в том, что какой-нибудь эмулятор или эвристический анализатор неправильно обработает вызов этой API-функции или обработку исключения, что приведёт к возвращению «0» и последующему завершению файла.
И ещё один пример антиэмуляции на уже другом, но совсем свежем FakeAV. Ниже я приложил скриншот из Hiew, курсор указывает прямо на точку входа.
Скриншот FakeAV с точки входа
По порядку — вызывается функция EnumResourceTypesA, а затем проверяется, равно ли возвращаемое значение нулю или нет. Если функция вернула нуль, то программа уйдёт в бесконечный цикл, что, очевидно, не должно происходить на нормальной системе. Таким образом, это первая антиэмуляция, достаточно простая, но вполне возможно, способная обойти что-то. Далее, вызывается функция GetLastError, и возвращаемое значение сдвигается направо на 7 бит и складывается с адресом 0x1003C9. Затем с помощью call’а выполняется переход по полученному значению. На нормальной машине в eax’е после GetLastError’а должно лежать 0x714, после сдвига — 0xE, после сложения — 0x1003D7. Таким образом, в живой системе будет выполнен переход именно по этому адресу. А если эвристический анализатор или эмулятор не смогли адекватно обработать вызов GetLastError, то приложение завершится или упадёт.
Скриншот этого же FakeAV из IDA
Но на этом всё не заканчивается — если посмотреть на код, то видно, что дальше вызывается функция EnumSystemLocalesA, после которой выполняется … переход на ExitProcess! А вся фишка в том, что в эту функцию первым параметром передаётся указать на CALLBACK (LOCALE_ENUMPROC), который вызывается системой. Именно в этом CALLBACK’е располагается вся «полезная нагрузка» зловреда. Здесь опять же малварщики рассчитывают на несовершенство антивирусов, обрабатывающих API-функции.