Avira – heuristic disasm

Дата публикации 15 авг 2011

Avira – heuristic disasm — Архив WASM.RU

Avira – heuristic disasm

Вступление
1. Поиск имени нужного детекта в модулях авиры
2. Поиск нужной проверки от антивируса
3. Анализ проверяемых флагов
Заключение

?

Вступление

Приветствую. Эта статья будет посвящена самому неадекватному антивирусу – авире. Мне всегда было интересно, как же она умудряется отличать вирус от невируса, какие критерии она использует. В этой статье я покажу, как нужно ее реверсить. Некоторые моменты будут озвучены просто как факт, я не буду рассказывать, как я к ним пришел – я просто этого не помню. Также хочу заранее сказать, что я не реверсер, поэтому многие вещи, возможно, я делал не совсем оптимально. Итак, приступим. ?

1. Поиск имени нужного детекта в модулях авиры

Для анализа нам потребуются IDA Pro с HexRays, OllyDbg, возможно PE Tools. Исследование будет проводиться на примере одного из моих файлов. Назовем его sample.exe. Проверяем его авирой – получаем TR/Crypt.XPACK.Gen2.

Очевидно, чтобы определить нужные нам признаки, нужно найти эту строку в авире, а потом проанализировать код, который к ней обращается.

Весь код анализатора, который нам нужен, находится в библиотеке aeheur.dll. Не буду рассказывать, как я это узнал – это долго и не имеет никакого значения. Загружаем указанную библиотеку в IDA Pro и через поиск (ALT+T) пытаемся найти "TR/Crypt.XPACK.Gen2".

Поиск не дает результатов. Что ж, значит переходим во вкладку Strings (Shift+F12) и начинаем просматривать строки – вдруг найдутся похожие или аналогичные имена, ну или просто что-то интересное.

И что мы видим – очень много переменных, которые напоминают текст, причем однотипный, но нечитаемый. Логично предположить, что это зашифрованный текст. Осталось выяснить, по какому алгоритму он был зашифрован. Я сделал так: выбирал строки наугад и смотрел, каким функциям они передаются. Я очень долго перебирал эти функции, и среди них мне попалась функция расшифровки. Оказалось, что все эти строки зашифрованы обычным XOR с ключом 0х38. Чтобы упростить нам задачу в дальнейшем, создаем скриптовый файл для IDA Pro avira_decrypt.idc с таким содержанием (он нам еще не раз пригодится):

Код (Text):
  1.  
  2. static main(void){
  3.   auto i;
  4.   i = ScreenEA();
  5.   while (Byte(i) != 0x00){
  6.     PatchByte(i,Byte(i)^0x38);
  7.     i = i+1;
  8.   }
  9. }

Итак, теперь мы знаем, как спрятаны строки. Чтобы найти нужную нам строку в авире, нужно зашифровать ее, а потом искать в уже зашифрованном виде. Для этого я написал утилиту, которая обычный текст зашифровывает по такому же алгоритму, а потом сохраняет в шестнадцатеричном виде. Написание такой утилиты я оставляю за Вами. Итак, берем строку "TR/Crypt.XPACK.Gen2", применяем к каждому байту XOR с ключом 0х38, переводим в текстовый вид. Получаем такую строку: "6C 6A 17 7B 4A 41 48 4C 16 60 68 79 7B". Забегая вперед, скажу, что индекс 2 в конце строки авира не хранит вместе со строкой, она добавляет его кодом. Поэтому обрезаем нашу строку на 1 байт, получаем "6C 6A 17 7B 4A 41 48 4C 16 60 68 79". Именно ее мы будем искать в нашей длл. Для этого переходим в IDA Pro на вкладку IDA View-A, открываем бинарный поиск (ALT+B) и вбиваем зашифрованную строку

Отлично, строка найдена. IDA Pro перебрасывает нас как раз на нее.

Теперь, для нашего удобства, строку неплохо бы расшифровать. Помните наш скрипт? Ставим курсор на начало строки и запускаем наш скрипт. Для первого запуска скрипта нужно нажать ALT+F7 и выбрать файл скрипта. Сразу получаем расшифрованную строку. Чтобы было еще удобнее, не убирая с нее курсор, нажимаем A – IDA Pro даст полноценное имя нашей переменной

2. Поиск нужной проверки от антивируса

Первая часть нашего исследования завершена – у нас есть имя детекта. Осталось самое сложное – проанализировать код и флаги, которые используют этот детект. Не снимая курсор со строки, нажимаем CTRL+X, чтобы увидеть, откуда идут ссылки на эту строку

Да, друзья, искомый нами детект присваивается в десятках мест! И нам нужно найти именно то единственное, где срабатывает проверка. Выхода нет – переходим по первой ссылке и оказываемся в незнакомой функции. Если нажмем F5, HexRays покажет нам С-подобный код функции. Много непонятного, правда?

Я опять вынужден пропустить значительную часть своих исследований, т.к. это все долго и нудно. HexRays пока можно закрыть, он нам не нужен. Перед нами сейчас стоит комплексная задача – сначала найти функцию проверки, которая срабатывает на наш файл. Потом найти внутри этой функции нужную проверку (а их очень много для каждого из детектов). И только после этого можно смотреть на конкретные флаги, которые сравнивает Avira.

Итак, сейчас мы находимся внутри функции, которая дает один из детектов с нужным нам именем. Нажимаем CTRL+P – появляется окно со списком функций. Просто жмем Enter.

Так мы попадаем к началу функции, в которой мы были (листать колесиком мышки было бы слишком долго). Жмем CTRL+X и снова Enter – попадаем в то место, откуда вызывается наша проверка. Обратите внимание на однотипный код – вызов функции, сравнение с 0. Если не 0, тогда вызывается следующая функция. Если 0, тогда на выход. Это вызываются подряд проверки для самых разных детектов. Следовательно, если функция возвращает 0 – файл признан вирусом, если не 0 – файл чист.

Кстати, можем переименовать нашу функцию, чтобы было удобнее читать. Ставим курсор на нашу функцию, нажмем N, вводим имя.

Итак, что мы имеем – огромное количество функций с огромным количеством проверок внутри каждой. Как найти нужную нам? В этом нам поможет отладчик. Для начала несколько слов о том, как работать с авирой в отладчике. В последних версиях этого антивируса появилась защита собственных процессов. Чтобы она нам не мешала, возьмите папку авиры из Program Files и скопируйте в любое место – именно из него мы и будем работать. Также нам стоит переименовать avscan.exe в любое другое имя – его мы будем загружать в отладчик. Собственная защита авиры не даст загрузить в отладчик ни один файл с таким именем. Поэтому просто переименовываем. Напоминаю, что мы работаем со скопированной папкой авиры, а не с оригинальной! В оригинальной вам ничего не позволят сделать!

Теперь о запуске сканирования. Чтобы просканировать файл, нужно создать конфигурационный файл, внутри которого будет прописан путь к нашему файлу. А потом нужно передать путь к конфигурационному файлу в командную строку avscan.exe (в статье я буду применять это имя, но помните – мы этот файл переименовали!). Конфигурационный файл имеет такое содержание:

Код (Text):
  1.  
  2. #########################################################
  3. # $AV$SCANNER$AVP
  4. #########################################################
  5. # This file has been created automatically.
  6. # DO NOT MODIFY!!
  7. #########################################################
  8. [CFG]
  9. GuiMode=1
  10. ExitMode=1
  11.  
  12. [SEARCH]
  13. Parameterx00300432
  14. Path0=C:\sample.exe
  15.  
  16. [CONTROLCENTER]
  17. ProfileName=ShlExt
  18.  
  19. [SCANNER]
  20.  

Порядок отладки такой: создаем текстовый файл cfg.txt с таким содержанием, только вместо c:\sample.exe прописываем путь к своему сканируемому файлу. Потом в отладчике открываем avscan.exe, а в качестве параметра прописываем путь к cfg.txt. Вот как это выглядит у меня:

С запуском разобрались, можно приступать к отладке. Кстати, забыл предупредить – после каждого сканирования файл конфигурации удаляется, его придется создавать заново. Итак, сначала возвращаемся к IDA Pro. Помните тот длинный список вызовов функций проверки? Перейдем в начало этого списка и запомним его адрес:

В моем случае этот адрес равен 100CDADB. Нам нужно определить самую первую функцию из списка проверок, которая вернет 0. Поэтому нам нужно поставить точку останова в начале списка и протрассировать его, пока не получим 0.

Для этого открываем в OllyDbg файл aeheur.dll и в командной строке пишем bp 100CDADB (помните, у вас этот адрес может быть другим). Теперь, когда мы будем отлаживать avscan.exe, отладчик остановится на этом самом адресе. Все, можно закрывать в отладчике aeheur.dll и открываем avscan.exe (не забываем про параметры в командной строке). Файл загружен, смело жмем F9. Авира подгружает свои длл читает файл, выполняет проверки и останавливается на том самом адресе, где мы поставили точку останова:

Мы находимся в самом начале списка проверок. Все, что нам теперь требуется – трассировать код клавишей F8 и смотреть на значение еах после вызова каждой из функций. Уверен, этот процесс можно автоматизировать, но я не реверсер и не умею этого. Итак, мы дошли уже трассировкой до самого ret, а 0 в еах так и не появился. Расстраиваться не стоит – функции проверок разбросаны в куче мест. Просто продолжаем трассировать, пока не получим 0 в еах. Трассировать приходится не долго, попадаем вот в это место:

Видите вызов функции, а за ним еах сразу равен 0? Эта та самая функция, которая нужна нам. Ставим на ее вызов точку останова. Не забываем в IDA Pro сразу же переходить на это же самое место, чтобы не заблудиться:

Вот так это место выглядит в IDA Pro. Сразу даем этой функции аналогичное название для удобства. Неопытный читатель заметит, что адреса в OllyDbg и IDA Pro отличаются – это все потому, что IDA грузит библиотеку по одному и тому же адресу, а OllyDbg всегда по разному. Чтобы не запутаться, сравнивайте адреса по последним 4 цифрам и все будет ясно.

Итак, мы нашли функцию, которая определяет файл, как вирус. Заходим в нее в IDA Pro и жмем F5. Мы видим кучу разных проверок. Как найти из них нужную? Правильно, опять нам поможет отладчик. Помните, мы поставили точку останова на этой функции? Перезапускаем avscan.exe в отладчике (напоминаю, что cfg.txt нужно будет создать заново! он уже удален авирой!) и жмем два раза F9 (два раза потому, что первый раз сработает точка останова в начале списка проверок – помните еще про нее? Впрочем, она нам не нужна и можно ее удалить – в этом случае жать F9 нужно будет один раз).

Точка останова сработала, мы стоим на вызове функции, которая дает детект. Заходим в нее (F7). Теперь трассируем по F8 все проверки, пока не будет вызвана функция расшифровки нужной нам строки. Как это определить? Я не буду это описывать. Немного опыта и Вы сами научитесь определять этот момент. Просто трассируйте до первого JMP (это совет навскидку, все-таки лучше потренируйтесь пару раз). Скажу честно, трассировать придется долго. Запаситесь терпением и хорошей реакцией.

Трассировал я долго, пока не вышел на этот момент (показываю в IDA Pro):

Знакомая картина? Помните тот список вызовов функций с проверками? Похоже, правда? Скажу по секрету, так оно и есть – это точно такой же список вызовов, но только других функций с другими проверками. Видимо, ни одна из проверок в текущей функции не дала результата и она полезла в подфункции с аналогичными проверками. Вобщем, пугаться не стоит, просто дальше трассируем по F8, пока не увидим в еах 0 после вызова. Как только увидели 0, ставим точку останова на этот вызов (все остальные точки останова удаляем), даем этой функции имя в IDA Pro:

Теперь в IDA Pro заходим в эту функцию, в OllyDbg снова перезапускаем avscan.exe, жмем F9 и после точки останова заходим в функцию (F7). Теперь мы внутри функции. Снова ищем нужную нам проверку – снова трассируем по F8, пока не найдем расшифровщик или JMP. Еще раз напоминаю – я делаю это для своего файла. На вашем файле, пусть даже детект с таким же именем, проверка может находиться совершенно в другом месте. Но алгоритм и логика поиска та же самая.

На этот раз долго трассировать не пришлось. Место заветного прыжка обнаружилось довольно быстро. Я покажу код сразу в IDA Pro (в OllyDbg не буду показывать):

В моем случае был выполнен прыжок:

Код (Text):
  1.  
  2. 102D2021                 ja      short loc_102D2093
  3.  

Как вы видите из листинга, в том месте, куда идет прыжок, идет обращение к строке, которую мы искали с самого начала, а потом безусловный JMP, который мы искали только что трассировкой по F8.

Итак, место проверки найдено. Теперь в IDA Pro нажимаем F5. Перед нами отличный С-подобный код, который четко показывает все проверки, выполнение которых ведет к детекту. Половина пути пройдена, могу Вас с этим поздравить. Но остается не менее сложная и трудоемкая задача – определить, какие же конкретно флаги сравниваются и что за функции вызываются. Готовы? Поехали дальше. ?

3. Анализ проверяемых флагов

Поиск и анализ флагов – нема не менее трудоемкая, чем вся эта статья. Я не буду описывать всю логику реверсинга. Я лишь остановлюсь на основных принципах, которые вам следует использовать для анализа. Авира в своем анализе использует две структуры. Я назову их AVIRA_INFO и SCAN_INFO. В первой больше информации о файле и черт знает чем еще, во второй – самые разные части РЕ и флаги, которые она выставляет в зависимости от разных значений РЕ.

Зайдите в таблицу экспорта файла aeheur.dll. Видите функцию module_get_api? Зайдите в нее. Она возвращает адрес массива ссылок. Перейдите по первой ссылке в этом массиве. Вы попадете в функцию. Откройте ее в хексрейсе, так наглядней. Видите вызов сначала колбека, а потом memset(v23, 0, 0x3720u) ? Это выделение памяти и ее обнуление для структуры AVIRA_INFO. Дальше ряд функций инициализируют некоторые значения этой структуры. Например,

Код (Text):
  1.  
  2. memcpy((char *)v24 + 64, v29, 0x40u)
  3.  

Эта функция копирует первые 64 байта с точки входа в отдельный буфер структуры AVIRA_INFO. Особо париться из-за этой структуры не стоит, в ней мало чего интересного.

Значительно ниже вы увидите вызов sub_10005E2B(v23). Зайдите в нее. Видите сначала вызов колбека, а потом:

Код (Text):
  1.  
  2.  memset((void *)result, 0, 0x2478u)
  3.  
?

Это уже создание структуры SCAN_INFO. Она является куда более интересной – все основные флаги находятся в ней. Чуть ниже идет вызов sub_1001604E – это самая важная функция. Она устанавливает если не все, то абсолютное большинство флагов в SCAN_INFO. Она довольно легкая для анализа. Просто очень длинная. Во всех проверках авира только сверяет разные флаги. Но их инициализация происходит именно в этой функции.

Возвращаемся к нашей функции проверки. Перед Вами С-подобный код, верно? Видите, очень много проверок полей переменной v1 и почти нет a1? Так вот, v1 – это указатель на SCAN_INFO, а1 – на AVIRA_INFO. Если присвоить этим переменным соответствующие типы (Y), анализ станет на порядки проще и удобнее. Это справедливо для всех функций проверки.

Имея все это, как продолжить анализ? Элементарно! Или смотрите в OllyDbg значения конкретных флагов и сравниваете их с полями РЕ (тут вам пригодится PE Tools), или в IDA Pro анализируете ту функцию, которая устанавливает флаги (можно иногда подглядывать в OllyDbg). На самом деле, это не сложно. За пару вечеров можно смело разобрать свой детект.

Еще пару слов о функциях в авире. Видите, она кроме флагов сравнивает и результаты некоторых функций? Причем, эти функции получают в качестве параметра указатели на шифрованные строки. Так вот, берем скрипт (помните, мы скрипт писали?) и расшифровываем эти строки. После этого становится четко видно, какие параметры принимают функции. Если в параметрах идет имя 1 длл и 1 функции, значит функция проверяет наличие этой функции в импортах (ну и каламбур). Если в параметрах только имя длл – значит проверяется наличие длл. Если в параметрах только длл, а результат функции сравнивается с каким-либо числом, то эта функция возвращает количество функций в импорте из данной длл. Т.е. у авиры не нужно рассматривать каждый байт – большинство кода интуитивно понятно.

Хочется дополнительно остановиться на некоторых косяках авиры. Судя по всему, в штаты к себе они набирают или пьяных китайских студентов, или пьяных индийских студентов. Вобщем, Вы часто можете встретить несколько функций одинакового назначения. Я находил около 5 копий одной и той же функции по расшифровке строки!!! Несколько копий проверки функции в импорте. Для проверки энтропии я видел около 7-10 абсолютно одинаковых функций!!! Это ахтунг, товарищи. То же самое касается и флагов – таблица директорий, разные части РЕ – все это дублируется по несколько раз в SCAN_INFO. Зачем? Одному Аллаху известно. Поэтому, если увидите функцию, которая делает примерно то же, что и предыдущая – не впадайте в панику. Это не косяк Вашего реверсинга, это скорее всего одна и так же функция. Ну или ее копия.

Также Вы можете встретить код в стиле:

Код (Text):
  1.  
  2. dwTrue = 0;
  3. if ()
  4. {
  5.     dwTrue = 1;
  6. }
  7. else
  8. {
  9.     dwTrue = 1;
  10.     ...
  11. }
  12.  

Кстати, небольшое предупреждение – в авире также есть функции, которые проверяют наличие сразу нескольких длл в импорте. Количество параметров у них не фиксированное. Но HexRays покажет Вам только один параметр! Старайтесь сверять количество параметров HexRays и обычного листинга. ?

Заключение

После краткого и беглого анализа С-подобный код для моей проверки стал выглядеть так:

Как видите, ничего сложного. Можно углубиться еще сильнее, а можно остановиться и на этом.

Успехов! (с) Михрютка


0 2.088
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532