Алгоритм обнаружения и обхода антиотладочных

on

Введение В ве де ни е Одним из эффективных методов анализа вредоносного программного обеспечения (ПО) является выполнение кода в среде отладчика или эмулятора. Отладчики обычно используются как инструмент вирусного аналитика, в свою очередь эмуляторы встраиваются в антивирусные продукты для автоматического поиска опасного или нежелательного ПО. Действительно, ряд задач анализа вредоносного кода, например поиск полиморфных вирусов, можно решить, только запустив программный код на выполнение и отслеживая результаты его работы. Чтобы препятствовать работе отладчиков и эмуляторов, авторами вредоносного кода разработан ряд методов. В настоящее время поиск и деактивация таких методов может быть эффективно проведена только в ручном режиме при тщательном анализе алгоритма защиты. В работе предложен алгоритм для обнаружения защищенного от отладчиков и эмуляторов кода. Предлагаемый алгоритм не только облегчает поиск антиотладочных и антиэмуляционных приемов, но и может работать в автоматическом режиме (без участия аналитика). П ри нц ип ы р аб от ы иу яз ви мо ст и о тл ад чи каиэ му ля то ра Отладчик -приложение, которое либо перехватывает окружение отлаживаемой программы во время ее выполнения, либо исполняет ее в виртуальной машине, таким образом помогая находить ошибки. Отладчик позволяет контролировать окружение выполнения (например, память), в котором функционирует отлаживаемая программа . В дальнейшем под отладчиком мы будем понимать приложение, работающее в том же окружении, что и отлаживаемая программа, и использующее отладочные возможности процессора и операционной системы (ОС). Существуют две разновидности отладчиков — пользовательского режима и режима ядра . Первые в большинстве своем используют функции ОС, например интерфейс отладки Debug API (Application Program Interface) ОС Windows, вторые -непосредственно возможности отладки процессоров. Далее в работе рассматривается архитектура процессора x86 и ОС Windows как наиболее распространенные. Любой отладчик должен обеспечивать трассировку приложения и установку точек останова. Трассировка обычно задается выбором специального режима процессора (при котором после каждой инструкции управление передается отладчику). Существует три типа точек останова : аппаратные -используют специальные отладочные регистры, программные -вставляют в выполняемый код специальные команды останова (int 3) и на доступ к памяти -изменяют атрибут доступа к странице памяти и при обращении к ней производят обработку. Для защиты от отладчика программа может использовать следующие методы : № 2, 2011 ИНФОРМАЦИОННО-УПРАВЛЯЮЩИЕ СИСТЕМЫ 51 ЗАЩИТА ИНФОРМАЦИИ 1) проверку регистров, флагов процессора, отвечающих за аппаратную отладку, например проверку того, установлен ли флаг трассировки (Trace Flag -TF), а также изменение этих флагов и регистров, что может вести к аварийному завершению отладчика; 2) проверку целостности кода для защиты от программных точек прерывания; 3) поиск структур отладчика в памяти, например в контексте потока (Thread Infomation Block) — для этой цели можно использовать функцию IsDebuggerPresent (Debug API ОС Windows); 4) поиск конкретных отладчиков в системе. В основе эмулятора лежит другой принцип работы. Эмулятор -это система, имитирующая работу процессора, оперативной памяти, аппаратного обеспечения и ОС . В общем случае эмулятор может имитировать ту же систему, на которой он запущен. Таким образом, его можно использовать при анализе вредоносного ПО, поскольку программа, исполняемая в эмуляторе, не может влиять на реальную систему . Далее мы будем рассматривать эмуляторы для имитации выполнения программ переносимого формата исполняемых файлов (Portable Executable), работающих в ОС Windows. Эмулятор загружает программный код в буфер и, читая последовательно инструкции, имитирует их выполнение. При этом все изменения происходят в переменных эмулятора (виртуальные регистры, виртуальный стек, буфер с программой), а не на реальной машине. Процесс имитации проходит в несколько этапов : анализ -выявляет размер, параметры имитируемой инструкции; пересчет адресов -должен быть выполнен для всех инструкций, обращающихся к памяти, поскольку нет практической возможности загрузить программу в буфер по адресу, который бы она имела, исполняясь на реальной машине; проверка адресов -выявляет ошибки адресации; проверка дополнительных условий (например, для операции div -деление -эмулятор проверяет неравенство операнда нулю); непосредственно имитация инструкции, при которой эмулятор согласно коду инструкции меняет состояние виртуальных регистров, виртуального стека и буфера с кодом и данными программы; перевод указателя инструкций (Extended Instruction Pointer -EIP) на следующую команду. Принципиально алгоритм работы эмулятора имеет два существенных недостатка: значительное время имитации команды по сравнению с ее выполнением на реальной машине и сложность правильного имитирования всевозможных инструкций процессора и функций ОС. Для полной эмуляции ОС фактически необходимо переписать все ее функции заново. Исходя из этих недостатков программа может предпринять следующие атаки на эмулятор, чтобы обнаружить его или прекратить эмуляцию : использовать неизвестные эмулятору команды процессора (например, MMX, SSE, SSE2 или недокументированные инструкции). Не зная текущую команду, эмулятор не сможет продолжить выполнение кода; использовать команды, реализованные в эмуляторе, с ошибками (если команда выполняется ошибочно, то последующая работа программ будет некорректна); использовать неизвестные эмулятору возможности системы (имитировать все API-функции ОС Windows практически невозможно); реализовать длинные циклы, вычисляющие какой-либо параметр для исполняемого кода. На реальной машине такой код будет выполняться достаточно быстро, а эмуляция подобных циклов займет значительное время (для имитации одной команды процессора требуется выполнить десятки или даже сотни инструкций). Антиотладочные и антиэмуляционные приемы в значительной мере распространены во вредоносном ПО. На данный момент для их обнаружения может быть использован сигнатурный анализ для поиска подозрительных мест по известным сигнатурам. Также в некоторых случаях эмулятор или отладчик может сообщить о потенциальном антиотладочном приеме. Эмулятор, например, может встретить неизвестную команду, которую расценит как попытку антиэмуляции. Отладчик может дополнительно проверять, не сбросила ли программа флаги и регистры отладки. Однако описанные методы не способны находить новые антиотладочные приемы, неизвестные на момент создания отладчика или эмулятора, что во многом затрудняет анализ вредоносного ПО. А лг ор ит м о бн ар уж ен иян ов ых а нт иэ му ля ци он ны х иа нт ио тл ад оч ны х п ри ем ов Как видно из приведенного выше описания, методы защиты от отладчиков и эмуляторов используют различные механизмы. На основании этого предлагается алгоритм поиска новых антиотладочных и антиэмуляционных приемов, заключающийся в сравнении работы одного и того же кода в отладчике и эмуляторе. Действительно, приемы для обхода отладчика во многих случаях будут успешно выполняться в среде эмулятора. И наоборот, код, который невозможно ис52 ИНФОРМАЦИОННО-УПРАВЛЯЮЩИЕ СИСТЕМЫ № 2, 2011 ЗАЩИТА ИНФОРМАЦИИ полнить в эмуляторе, будет корректно работать в отладчике. Рассмотрим особенности алгоритма для поиска антиотладочных и антиэмуляционных приемов. На каждом шаге работы выполняется одна инструкция в среде эмулятора и отладчика и сравнивается результат ее выполнения. Инструкции процессора x86 могут влиять на регистры (в том числе на регистр флагов и на EIP), а также на содержимое оперативной памяти. В простейшем случае нам достаточно сравнивать указатель инструкций. Его расхождение будет означать, что программа исполняется по разным веткам алгоритма, что в свою очередь говорит об ошибочности работы отладчика или эмулятора. Однако легко сформировать атаку против такого отладчика-эмулятора (листинг 1). Листинг ———-1. А лг ор ит м о бн ар уж ен ияо тл ад чи ка э му ля то ра, п ро ве ря ющ ег о т ол ьк о з на че ни е EIP. EAX = 1, е сл и п ри су тс тв уе т о тл ад чи к, и на че0 ECX = 1, е сл и о бн ар уж енэ му ля то р, и на че0 EAX = EAX — ECX е сл и EAX 0, о бн ар уж ено тл ад чи к и лиэ му ля то р Следовательно, необходимо также сравнение и регистров общего назначения, и регистра флагов на каждом шаге. Для частных случаев возможно организовать обман предложенного метода, при котором значения регистров (в том числе регистра флагов и EIP) будут одинаковы, а различаться будут только состояния памяти (листинг 2). Поэтому для надежности и отсечения подобных вариантов следует производить сравнение содержимого памяти после некоторых, изменяющих ее, инструкций. Например, к «опасным» инструкциям можно отнести те, которые не содержат в качестве операнда регистры (stos, lods, movs, cmps и ряд других), а также сложные инструкции, которые могут быть реализованы в эмуляторе не полностью или с ошибками. Листинг 2. П ри ме р о бм ан а э му ля то рао тл ад чи ка п ро ве ря ющ ег о ц ел ос тн ос тьк од а ир аб от ос по со бн ос тьи нс тр ук ци и add. Start: mov ecx,End-Start-4 ; -4, ч то быз ах ва ти тьп ер ем ен ну ю for-add mov edi,Start mov esi, DataCopy add dword ,0FFFFFFFFh ; for-add = 0 ;П ре дп ол аг ае тс я, ч тои нс тр ук ци я ;ADD р еа ли зо ва навэ му ля то ресо ши бк ой ;ивс лу ча е п ер еп ол не ни я о пе ра нд а н е п ро из во ди т с ло же ни я. repe cmpsb ; С ра вн ив ат ь б ай тып о а др ес амEDI иESI, ; п ок а о нир ав ны jnz EmulatorDebuggerDetected jmp NotDetected End: for-add dd 1 CodeCopyStart: Т оч на я к оп ияб ай т о т Start д о End, д ляс ра вн ен ия CodeCopyEnd: for-add-test dd 0 К достоинствам алгоритма для поиска антиотладочных и антиэмуляционных приемов относятся: 1) возможность находить новые, ранее неизвестные антиотладочные или антиэмуляционные приемы в автоматическом режиме; 2) локализация местонахождения приема, вызвавшего расхождение. Действительно, для о наружения антиотладочного или антиэмуляционного приема аналитику достаточно проанализировать последовательность инструкций, выполненных до расхождения и ведущих к разным состояниям отладчика и эмулятора; 3) устойчивость к приемам, направленным против виртуальных машин. Недостатки данного алгоритма: 1) он не способен без дополнительного анализа отличить антиотладочные приемы от антиэмуляционных. В качестве средств дополнительного анализа могут быть использованы, например, сигнатурный или эвристический анализ. Эвристический анализ может, в частности, учитывать тот факт, что исследуемая программа после обнаружения отладчика или эмулятора обычно сразу завершается, а в противном случае выполняет свои функции; 2) за антиэмуляционный прием может быть принята случайная ошибка в эмуляторе, ведущая к неправильному выполнению инструкции процессора и, как следствие, к расхождению выполнения кода в предложенном алгоритме. Однако вероятность такой ошибки уменьшается с улучшением качества эмулятора; 3) скорость выполнения кода при анализе в предложенном алгоритме меньше, чем в эмуляторе и отладчике. Действительно, после каждой операции необходимо проводить дополнительное сравнение полученных результатов, что требует определенных временных затрат. Поэтому алгоритм не способен обнаруживать атаки, использующие тот факт, что в эмуляторе код выполняется значительно медленнее, чем на реальной машине. Для обнаружения таких атак необходимо использовать другие методы. Итак, предлагаемый алгоритм способен в автоматическом режиме обнаруживать новые антиотладочные и антиэмуляционные приемы, а также помогает их локализовать для дополнительного анализа экспертом. Р еа ли за ци я п ро гр ам мыд ляп ои ск а а нт ио тл ад оч ны х иа нт иэ му ля ци он ны х п ри ем ов Для демонстрации предлагаемого алгоритма была реализована программа, осуществляющая поиск антиотладочных и антиэмуляционных приемов в автоматическом режиме. № 2, 2011 ИНФОРМАЦИОННО-УПРАВЛЯЮЩИЕ СИСТЕМЫ 53 ЗАЩИТА ИНФОРМАЦИИ Для отладки анализируемого кода используется отладочной интерфейс Windows Debug API, выполняющий программу в пошаговом режиме (установлен TF). Для имитации инструкций используется модифицированный эмулятор от свободно распространяемого антивируса Exploision Antivirus v.11. Рассмотрим некоторые особенности реализации. Значение регистров эмулятора при запуске инициализируется регистрами отладчика. Это необходимо для последующей проверки регистров на эквивалентность. Эмулятор имитирует расположение стека по адресу стека отладчика. Это необходимо для эквивалентности указателя стека (Extended Stack Pointer). Эмулятор пересчитывает регистр EIP, имитируя расположение кода по базовому адресу образа (ImageBase), хотя реально код расположен по другому адресу. В процессе выполнения программа не сверяет TF регистра флагов. Для упрощения разработки сравнение участков памяти не осуществляется. Проведем демонстрацию предложенного алгоритма обнаружения обманных приемов на примерах. П ри ме р 1. Защищенный код сверяет значение TF и, в случае если он установлен, сообщает об отладке (листинг 3). После сравнения TF исследуемый код продолжит выполняться по разным путям в отладчике и эмуляторе, что и обнаружит разработанное приложение. Листинг 3. П ои ско тл ад чи кап о ф ла гут ра сс ир ов ки pushfd ;с ох ра ни м р ег ис трф ла го в вс те к pop eax ;з аг ру зи м е говEAX and eax,-100 ;с бр ос имв се к ро меTF test eax,eax ;п ро ве ри м, у ст ан ов ле н л и TF jnz .Debug ;е сл и у ст ан ов ле н, н асо тл аж ив аю т П ри ме р 2. В структуре блока переменных окружения процесса (Process Enviroment Block — PEB) есть поле Nt-lobalFlag, которое может использоваться для выявления отладчика. Это поле находится по смещению 0x68 от начала PEB. Поле представлено рядом флагов. Значение, которое предполагает присутствие отладчика, складывается из значений следующих полей: FLG-HEAP-ENABLE-TAIL-CHECK (0x10) FLG-HEAP-ENABLE-FREE-CHECK (0x20) FLG-HEAP-VALIDATE-PARAMETERS (0x40) Листинг 4. П ои ско тл ад чи касп ом ощ ью Nt-lobalFlag. mov eax, and al,70h cmp al,70h je .Debug После команды mov al, регистр al будет содержать разные значения в отладчике и эмуляторе, что обнаружит антиотладочный прием. П ри ме р 3. Воспользуемся приемом CALL-POP для определения реального адреса кода. Поскольку в эмуляторе код будет загружен по адресу, отличному от ImageBase, сравнивая «виртуальное» расположение кода с реальным, мы можем обнаружить наличие эмулятора (листинг 5). Реализованная программа успешно находит такой прием. Листинг 5. О бн ар уж ен иеэ му ля то рап о р еа ль н ом у а др ес у р ас по ло же ни я к од а. call .Next ;call-pop п ри ем .Next: pop eax ;вEAX -а др есу ка за те ля.Next cmp eax,.Next ;с ра вн имEAX ср еа ль ны м р ас по ло же ни ем jnz .Emul ;п ер ех од е сл и м ы вэ му ля то ре П ри ме р 4. Следующий прием (листинг 6) использует системное прерывание int 2e — inc edx для выявления отладчика. Поскольку эмулятор не может правильно выполнить команду, содержимое регистра eax будет отличаться в отладчике и эмуляторе, что обнаружит антиэмуляционный прием. Листинг 6