Exploit.SWF.Agent.br Pdfka.asd Pidief.cvl TDSS TDSS removal binary planting bios infection blind sqli bootkit bootkit remover browser exploitation com hijacking disassembling dll hijacking drive-by downloads hack online banks heap-spray hijack botnet ibank kernel protection kernel-mode rootkit keylogger malware analysis rootkit detection trojan virus removal


Некоторые приёмы статического анализа кода из арсенала вирусного аналитика

Дмитрий Андриянков
разработчик ЗАО «АСТ»
andriyankovdn@acti.ru

Вирусному аналитику нередко приходится сталкиваться с полиморфными объектами — исполнимыми файлами, упакованными средствами защиты программ от ручного или автоматизированного анализа. Данная статья описывает ряд приёмов работы с такими объектами при помощи редактора Hiew (Hacker's View). Статья ориентирована на начинающих специалистов, в задачи которых входит анализ исполнимых файлов в форматах PE или ELF, и предполагает знакомство с архитектурой x86 и ассемблером Intel.

Приложение к статье

Загрузить архив (390 кБ)

Пароль к архиву: nobunkum.ru

Hiew

Загрузить/купить

Приёмы навигации по коду

Анализ кода в полиморфных объектах обычно затруднён большим количеством инструкций, передающих управление на другие участки кода. Зачастую «ненужные» инструкции запутывают код настолько, что понять его логику можно, только разработав специальный анализатор кода. В задачи такого анализатора может входить выяснение размера и смещения зашифрованных данных, поиск ключа для их расшифровки, определение адреса перехода на изначальную точку входа и другие функции.

Типичный вопрос, встающий перед разработчиком анализатора кода, — «Поддержку каких инструкций необходимо добавить?» Можно выяснить это с помощью дизассемблера IDA Pro, но запускать такое мощное средство анализа кода только, чтобы увидеть одну-две инструкции, было бы нерациональным. Куда быстрее ту же задачу можно решить с помощью Hiew.

Совет от разработчика Hiew

Евгений Сусликов
sen@kemtel.ru

Некоторое время назад я прочитал статью «Коварный и ужасный sndrec32.exe». По моему мнению, вместо описанного там применения четырёх различных инструментов достаточно одного Hiew. Вся правка «коварного и ужасного» сводится к следующему:

1. Найти функцию определения количества свободных байт в оперативной памяти. Автор статьи умолчал, каким образом он пришел именно к GlobalMemoryStatus, но с помощью Hiew это можно сделать так:

F4, F3 — переключение в режим дизассемблера.
F8, F7 — просмотр функций импорта.
F9, *memory* — поиск имён по маске.

Последний шаг делается в предположении, что искомая функция будет содержать слово «memory» в имени. Оказывается, всего одна импортируемая функция соответствует такому фильтру — GlobalMemoryStatus.

2. Найти вызовы данной функции в коде. Для этого достаточно нажать Enter. Ctrl-Enter позволяет найти следующий вызов. На интересные фрагменты кода можно сделать закладки с помощью клавиши + на цифровой клавиатуре. В нашем случае второй и третий вызовы по адресам .10077AC и .100789A почти идентичны.

3. Исправить код. Клавишами Alt-1 вернёмся к первой закладке, прочтём код и примем решение заменить знаковый переход jle на беззнаковый jbe по адресу .10077D5. В строке по этому адресу нажмём F3 для редактирования и F2 для ввода ассемблерного кода, затем вместо «jle» введём «jbe» и нажмём Enter. После этого нажатием Esc выйдем из ассемблера и сохраним изменения клавишей F9.

Заметим, что автор оригинальной статьи не упомянул о коде на адресе .100789A. Перейдя на вторую закладку клавишами Alt-2, обнаружим там аналогичную ошибку и исправим её.

Многие вирусные аналитики назначают Hiew в качестве альтернативного средства просмотра (Alt-F3) в настройках менеджера файлов. Автор статьи рекомендует сэкономить ещё один шаг и добавить к команде запуска Hiew параметр /Oc=OEP, чтобы просмотр исполнимых файлов всегда начинался с точки входа. Если же задать в файле hiew8.ini настройку StartMode = Hex, то режимом просмотра по умолчанию станет шестнадцатеричный.

К точке входа можно перейти в любой момент, нажав последовательно F8 и F5.

Удобная возможность Hiew — следовать по смещениям, указанным в инструкциях передачи управления, например, call или jmp. Справа от каждой такой инструкции редактор показывает цифру, нажав которую на клавиатуре, можно перейти по указанному в инструкции смещению. Вернуться назад после такого перехода можно, нажав клавишу 0. (Автор находит более удобным использовать для этой цели клавишу z, для чего в файле hiew8.ini следует задать настройку JumpTable = "z123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").

Иногда оказывается полезной возможность перенастройки шкалы смещений Hiew путём сопоставления её нулевой точки с адресом произвольной инструкции. Для этого необходимо, установив указатель на нужный адрес, дважды нажать Ctrl-F5. При этом новая настройка шкалы сохраняется в виде соответствующей записи в окне, отображаемом при однократном нажатии Ctrl-F5, и может быть использована повторно. Перенастройка шкалы может быть полезна для оценки размера зашифрованных данных, а также для повышения наглядности адресов переходов типа call и jmp, отсчитываемых в режиме адресации Local (Alt-F1) от «нуля» шкалы.

Расшифровка данных

Несложные скрипты для расшифровки данных можно разрабатывать и применять непосредственно в Hiew, экономя время на запуск отладчика.

Разберём для примера известный crackme/keygenme от Ms-Rem, в котором проверка производится байт-кодом в виртуальной машине. Рассмотрим начало байт-кода программы:

Байт-код

Байт-код

Код функции, декодирующей очередную инструкцию виртуальной машины, выглядит так:

.00401284: 8A0C18       mov     cl,[eax][ebx]
.00401287: 88CD         mov     ch,cl
.00401289: C0ED04       shr     ch,4
.0040128C: 30E9         xor     cl,ch
.0040128E: 80E107       and     cl,7
.00401291: C3           retn    ; -^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-

Чтобы расшифровать данные с помощью Hiew, следует прежде всего выделить блок зашифрованных данных клавишей * и нажать Alt-F3 (CryBlk). Затем в окне редактирования кода напишем код расшифровки, аналогичный вышеприведённому. Hiew поддерживает выполнение ограниченного набора инструкций, список которых приведён в разделе «Crypt commands» справочного файла. С учётом ограничений код будет выглядеть так:

mov     ah,al
ror     ah,4
and     ah,0fh
xor     al,ah
and     al,7

Нажав F7 после редактирования кода, получим расшифрованные данные.

Расшифрованный байт-код

Расшифрованный байт-код

При необходимости сохранить скрипт расшифровки в файл можно вернуться в редактор нажатием Alt-F3, после чего нажать F9.

Нередко возникает необходимость в расшифровке данных, зашифрованных по алгоритму XOR с длинным ключом. В таком случае можно воспользоваться встроенной возможностью Hiew по расшифровке: перейти в режим правки клавишей F3 в режимах Code или Hex, нажать F8 и задать ключ шифрования. Установить новый ключ можно клавишами Ctrl-F8.

Восстановление обнулённых дескрипторов секций

Для затруднения распаковки многие упаковщики обнуляют области памяти модуля, в которых находится дескрипторы секций. Каждый дескриптор описывается структурой IMAGE_SECTION_HEADER.

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

Возьмем вредоносную программу, упакованную таким полиморфным упаковщиком, и увидим после снятия дампа следующее:

Обнулённые дескрипторы секций

Обнулённые дескрипторы секций

Чтобы восстановить дескрипторы секций, прежде всего скопируем их из оригинального, упакованного файла. Для этого откроем этот файл, выделим начало и конец области дескрипторов клавишей *, а затем запишем выделенные байты в файл с дампом памяти, нажав F2 и указав имя файла и смещение (1e8).

Выделенные дескрипторы в оригинальном файле

Выделенные дескрипторы в оригинальном файле

Затем, открыв файл с дампом, исправим смещения, указанные в дескрипторах (F8, F6). Нажатие F3 позволяет начать редактирование выбранного дескриптора, а F9 — принять сделанные изменения.

Редактирование дескриптора секции

Редактирование дескриптора секции

Статическая распаковка файла

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

Для примера рассмотрим образец test.bin из приложения к статье. Он упакован простейшим полиморфным упаковщиком, предназначенным для сокрытия вредоносного кода от обнаружения.

Открыв файл для анализа в Hiew и пройдя несколько переходов, мы увидим характерный код для доступа к данным, расшифровки и перехода на OEP:

; Получение адреса зашифрованных данных:
.10007012:  60              pushad
.1000703F:  E829000000      call        .01000706D --↓1
.1000706D:  5E              pop         esi
.10007098:  81C670FFFFFF    add         esi,0FFFFFF70 ;'   p'

; Расшифровка:
.10007117:  8B16            mov         edx,[esi]
.10007145:  03D6            add         edx,esi
.10007168:  8B4604          mov         eax,[esi][4]
.1000718C:  812ADEEC02E9    sub         d,[edx],0E902ECDE ;'щ☻ь▐'
.100071AD:  83C204          add         edx,4
.100071E0:  83E801          sub         eax,1
.1000721C:  83C608          add         esi,8
.100070A5:  833E00          cmp         d,[esi],0
.100070C1:  0F84C7010000    jz          .01000728E --↓1

; Переход на OEP:
.100072BC:  61              popad
.100072BE:  EB02            jmps        .0100072C2 --↓1
.100072C2:   E998B7FFFF     jmp         .010002A5F --↑1

Для распаковки достаточно сложить адрес следующей инструкции после call (10007044) и значение в инструкции add (0FFFFFF70). Сложение можно выполнить непосредственно в Hiew, нажав Alt-=. Зашифрованные данные, находящиеся по вычисленному адресу, удобнее всего представить как массив двойных слов (DWORD). Для этого следует нажать Shift-F9 и при необходимости выбрать режим показа двойных слов клавишей Tab.

Массив двойных слов

Массив двойных слов

Нетрудно видеть, что для распаковки первого объекта нужно вычислить его адрес (для этого сложим смещение 10006FB8 с величиной FFFFA048), запомнить размер объекта (17ED) и применить ключ расшифровки (0E902ECDE).

Заметим, что, если в массиве двойных слов окажется значение, похожее на RVA, перейти по нему можно клавишей Enter.

Обнаружение вредоносных программ

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

В начале файлов tukuhegu.dll и welolazu.dll (см. приложение к статье) можно увидеть такие участки:

Переход посредством установки SEH-обработчика

Переход посредством установки SEH-обработчика

Установка перехвата с помощью инструкции jmp

Установка перехвата с помощью инструкции jmp

Первый признак, пригодный для обнаружения, заключается в использования SEH-обработчика с последующей его активацией путём сознательного вызова исключения. Это «трюк», практически никогда не встречающийся в легитимных программах. Во втором случае происходит запись значения 1DA79 по адресу 1001ED17+1. Затем — запись в память опкода инструкции jmp и смещения 1001ED17, что является типичным признаком процедуры перехвата функций. При наличии столь подозрительных инструкций не требуется понимания того, как именно работает код и что хранится по указанным смещениям: найденные инструкции могут быть использованы в качестве сигнатур для обнаружения данной программы антивирусом. С целью предварительной фильтрации файлов и уменьшения числа ложных срабатываний антивирус обычно выполняет дешёвые предварительные проверки перед поиском сигнатур, например, проверку на наличие у секции кода атрибута «writeable».

Возьмем еще один пример, на котором можно увидеть ошибки генератора кода в полиморфном движке. Для этого откроем в Hiew образец A0330534.bin:

Бессмысленная конструкция

Бессмысленная конструкция

Ещё одна бессмысленная конструкция

Ещё одна бессмысленная конструкция

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

Рассмотрим более сложный случай: модуль трояна «Зевс» (файл zeus_hz0132.bin в приложении), полученный автором статьи по ссылке из спама. Образец интересен тем, что код распаковщика занимает всего 136 байт.

Распаковщик «Зевса»

Распаковщик «Зевса»

Сразу после открытия файла в Hiew бросается в глаза переход на третью инструкцию с помощью инструкций push и ret, нехарактерный для современных компиляторов. Ещё одной особенностью является то, что код не использует результаты после вызовов GetCommandLineW и GetOEMCP. Начиная с инструкции lodsd, можно видеть цикл расшифровки и ключи шифрования. Просматривая код далее, заметим переход назад с достаточно большим смещением в участок расшифрованного кода, который, очевидно, является переходом на OEP. На этом анализ завершён, и можно быстро написать статический распаковщик.

Last updated: 17.03.2012