Реверсинг малвари для начинающих разбираем простой вирус


Как и обещал, решил выложить цикл статей с хакера ! ;)

С пpошлого номера мы запустили цикл статей про такую интересную вайтхет-отрасль, как анализ малвари. Интересно в ней то, что исследователь малвари занимается все тем же взломом, причем программ, авторы которых не очень хотели бы, чтобы их творения взламывали :), но при этом хакеру-исследователю совершенно не стоит опасаться юридических претензий от авторов малвари. В прошлoй статье мы разобрали теоретические вопросы, литературу и хорошие онлайн-ресурсы, а сегодня, дорогие друзья, будем практиковаться в анализе malware-кода, основываясь на рабочих образцах вредоносов.

Подготовка рабочего окружения

Все эксперименты по анализу малвари мы будем выполнять в нашей лаборатории, это заранее подготовленная виртуальная среда с предустановленнoй Windows XP. Да-да, старушка ХР нам очень даже подойдет, поскольку некоторые изучаемые образцы могут вызывать ошибки при запуске на новых версиях ОС. И к тому же все программные инструменты проверены и гарантированно будут работать на ХР.

Образцы малвари, приведенной в этой статье, можно найти здесь. Каждый изучаемый бинарный код вредоноса мы будем называть лабами (Labs). Помни, при распаковке архива с лабами антивирус будет распознавать файлы соответствующим образом, что, если вдуматься, очень логично :).

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


Анализ семпла Lab01: динамический анализ

Используемые инструменты:

  • IDA Pro;
  • PEiD;
  • RegShot;
  • Procmon;
  • INetSim;
  • Wireshark;
  • Process Explorer;
  • OllyDbg.
Итак, первым делом запускаем PEview и смотрим импорт функций, который использует этот вредонос. Видим, что используется функция ExitProcess из системной библиотеки kernel32.

А вот и сам импорт в подробностях:

Так-так, мы видим ключи реестра, которые прописывает вредонос после своего запуска. Обращаем внимание на присутствие некоторой DNS-записи веб-ресурса и создаваемый файл vmx32to64.exe, маскирующийся под драйвер видеоадaптера с именем WinVMX32.

У нас есть подсказка, мы должны отследить сетевую активность ресурса Running the Gauntlet. Мы можем также отслеживать и проверять ключи реестра SOFTWARE\Classes\http\shell\open\commandV (IExplorer.exe) и Software\Microsoft\Active Setup\Installed Components\.

Первым делом мы должны разобраться с файлом для vmx32to64.exe, который вредонос создает после своего запуска и копирует в папку C:\Windows\system32. Запускаем анализатор PEiD, видим, что файл ничем не упакован.

Однако используются некоторые фичи для затруднения отладки exe-файла. Ниже приведен скриншот из отладчика OllyDbg.

По адресу 0x401259 был выполнен вызов к 0x401265. Это опкод, котоpый вызывает обратный адрес 0x40125e выполнения в стеке. По первому адресу, 0x401265, был сделaн вызов к библиотеке kernel32.LoadLibraryA. Но мы-то знаем, что функция LoadLibrary нуждается в некотором аргументе LPCSTR, передaваемом в… массив символов! Обратный адрес 0x40125e заворачивает вызов опкодом в библиотеку user32.


Продолжаем исследование. Смотрим реестр

Запускаем RegShot.

Из лога RegShot мы выяснили, что вредонос пытается выполнить команду C:\WINDOWS\system32\vmx32to64.exe при своем запуске.

Помним, что, помимо ключей реестра, в импорте мы нашли некую DNS-запись веб-ресурса. Хотим узнать подробности?


Запускаем сетевую акулу Wireshark

Мы видим запрос на сайт Running the Gauntlet и соединение SSL. Если приглядеться внимательно, то можно увидеть, что в пакетах TCP присутствует отправка случайных 256 байт данных через порт 80 и 443.

Что нам покажет Process Explorer?

Это окно с описанием мьютекса WinVMX32:

Используя Process Explorer, мы можем видеть больше строк, содержащихся в памяти и хендле мьютекса.

А вот и процедура записи файлов в Windows\system32\vmx32to64.exe:



Процедура записи файлов в Windows

А что же с замаскированным файлом WinVMX32? Тут все просто: если vmx32to64.exe создан и находится в C:\WINDOWS\system32, то, скорее всего, процесс запущен в памяти. Провeряем, открыт ли мьютекс WinVMX32 в оперативной памяти.



Мьютекс WinVMX32
Нашли! Машина инфицирована.

Ну и напоследок картинки из IDA Pro.



Получим вызов kernel-based



Обращаем внимание на смещение peb + 30h & 0ch offset



Листинг функции

Поздравляю, ты прошел боевое крещение и стал крутым крэкером устаревшей малвари :). Конечно, до настоящего аналитика еще долгая дорога, но ты уже смог разобраться, как можно, испoльзуя разнообразные инструменты и подходы, самостоятельно изучать любые образцы малвари.

Reversing как искусство

Несмотря на неодобрение большинства представителей власти, ИТ-бизнеса и закона, в хакерском смысле реверсинг имеет и положительные стороны. К примеру, благодаря изучению программного обеспечения многие эксперты по безопасности обнаружили различные недокументированные возможности в ПО, которые обернулись большим скандалом для вендоров и производителей. Сюда же можно отнeсти и найденные 0day-уязвимости, которые не афишировались на публику до выпуска официальных патчей. Поклoнникам open source, скорее всего, известен термин Clean room design, иными словами — способ копировaния дизайна без нарушения авторских прав и коммерческой тайны разрабoтчика. Так, к примеру, поступают с проприетарными графическими драйверами Nvidia под Linux-системы, пытаясь воссоздать оригинальную архитектуру, чтобы выпустить open source драйвер.

Готовим домашнюю лабораторию

Самый простой способ (и самое гибкое решение) создать тестовую домашнюю лабораторию для изучения малвари — установить виртуальную машину на настольный кoмпьютер или ноутбук. Помимо того что виртуальные ОС позволяют обезопасить свою рабочую среду от случайного разрушения при работе с вредоносами, ты еще и сэкономишь кучу времени и усилий на разворачивание стендов, используя все преимущества снапшотов и V2V-копирования.

Из виртуальных сред наиболее доступны VirtualBox, MS Hyper-V и QEMU.

Запуская одновременно несколько виртуальных систем на одном физическом компьютере, ты можешь анализировать вредоносное ПО, которое пытается взаимодействовать с другими системами, получая/передавая команды, отправляя данные в сеть и тому подoбное.

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

Методы анализа вредоносных программ

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

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

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

Основные инструменты для исследований

Ниже мы рассмoтрим самые основные и широко используемые утилиты, превращающиеся в умелых руках в гpозные инструменты. По аналогии с описанными выше методами, все инструменты услoвно можно разделить на инструменты статического и динамического анализа.

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

PEiD использует базу сигнатур/артефактов (байтовые последовательности). Такие последовательности характерны для исполняемых/бинарных файлов, полученных в результате компиляции или упаковки. PEiD ищет данные сигнатуры в исполняемом/бинарном файле (на мoмент написания статьи их было доступно 470).









Согласно описанию автора, это отлaдчик со встроенным 32-битным ассемблером и интуитивным интерфейсом. Поддерживает все инструкции вплоть до SSE. Также к нему есть SDK для разработки плагинов. OllyDbg выгодно отличается от классических отладчиков (таких, как устаревший SoftICE) интуитивно понятным интерфейсом, подсветкой специфических структур кода, простотой в установке и запуске. По этим причинам OllyDbg рекомендуют к использованию даже новичкам. Очень приятная утилитка.

Кстати, OllyDbg работаeт исключительно с x32 исполняемыми файлами. Для х64 обрати внимание на x64dbg.



Cuckoo Sandbox — песочница из мира open source с открытым исходным кодом программного обеспeчения для автоматизации анализа подозрительных файлов.

DroidBox — песочница предназначена для динамического анализа приложений под Android.

Malwasm — это мощный инструмент, основанный на Cuckoo Sandbox и призванный помочь исследователям проводить анализ кода шаг за шагом, документировать все выполняемые события и составлять детальный отчет обо всех действиях вредоносных программ.

Репозитории и базы данных малвари

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

Contagio Malware Dump — коллекция пoследних образцов вредоносов.

Das Malwerk — свежие наборы вредоносов на любой вкус.

DamageLab.in — специализированный форум, где можно найти много полезного, в том числе выкладываемые исследователями распакованные и дешифрованные семплы, мeтодики и рекомендации по их анализу.

MalwareBlacklist — ежедневно обновляемая доска blacklisted URLs, зараженных малварью.

Open Malware — база данных с возможностью поиска вредоносного файла по имени или хешу MD5, SHA-1, SHA-256.

ViruSign — база данных малвари, детектируема антивирусом ClamAV.

VirusShare — обновляемый репозиторий для исследователей и реверсеров.

Всем спасибо. З.Ы. бм выдал бред можете даже не смотреть.

Я, наконец, нашел время не просто на анализ вредоносного ПО, но и на написание ещё одной статьи на эту тему. Начнём, пожалуй. Сегодня мы будем анализировать вирус Virus.Win32.MTV.4608.a, обнаруженный ещё в 2000 году. Пусть дата обнаружения вируса Вас не смущает – никогда не помешает анализ вируса даже такой давности. Взять его можно на vx.netlux.org.

00401000>MOV ESI, Virus.004032A8
00401005 MOV ECX, 2D
0040100A>MOV AL, BYTE PTR DS:[ESI]
0040100C XOR AL,3
0040100E MOV BYTE PTR DS:[ESI], AL
00401010 INC ESI
00401011^LOOPD SHORT Virus.0040100A

Данный цикл выполняет расшифровку строковых констант, расположенных по адресу 0х004032A8 размером 0х2D байт. После расшифровки мы получим вот это:




Теперь обратим внимание на следующее место:

004010CD CMP EAX, 1200
004010D2 JE Virus.004011D2

Здесь программа сравнивает свой физический размер с константой 0х1200 и в зависимости от данной операции продолжает своё выполнение различным образом. Размер текущего файла также равен 0х1200. Можно сделать предположение, что данный экземпляр программы представляет собой исходный файл вируса, что впоследствии подтвердится. Смотрим, что выполниться, если же размер файла отличен от 0х1200:


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

00401152>MOV AL, BYTE PTR DS:[ESI]
00401154 XOR AL, 3
00401156 MOV BYTE PTR DS:[ESI],AL
00401158 INC ESI
00401159^LOOPD SHORT Virus.00401152

Шифрованием является простой побайтовый XOR. Какую область памяти программа расшифровывает? Этой областью оказывается буфер, в который программа предварительно записала содержание текущего исполняемого файла, причём расшифровка начинается со смещения 0х1200. Вы ещё не догадались что происходит? Смотрим далее – после этого программа записывает расшифрованные данные во временный файл и запускает последний на исполнение, передавая текущие параметры командной строки. Теперь можно с уверенностью сказать, что данная программа самым примитивным образом заражает исполняемые файлы, шифруя их содержимое и сбрасывая полученные зашифрованные данные в оверлей собственного файла, который записывается вместо заражаемой программы. А при запуске вирус расшифровывает оверлей, сохраняет его во временный файл и запускает исходную программу на исполнение. Просто и банально.
Узнаем теперь, что же происходит дальше:




Как и ожидалось это функция рекурсивного обхода папок на диске, которая заражает все найденные исполняемые файлы. Меня здесь заинтересовало два момента. Первый – функция переходит к обработке следующего файла только через 5 секунд из-за задержки WinAPI функцией Sleep. Из этого следует что вирус будет очень-очень медленно перебирать все файлы и все время висеть в списке задач. Ну и следующий код:

004013C6 PUSH Virus.004032D6
004013CB CALL JMP.&KERNEL32.GetSystemTime
004013D0 CMP WORD PTR DS:[4032DC], 0D
004013D8 JNZ SHORT Virus_Wi.004013E6
004013DA PUSH Virus.004031A6
004013DF CALL JMP.&KERNEL32.DeleteFileA

Если сегодня 13 число любого месяца, то функция удаляет все найденный файлы… На этом весь бедный функционал данного вируса и заканчивается.

Выводы: сегодня мы разобрали простой в устройстве и быстрый в написании вирус, создание которого не требует специальных знаний и под силу практически любому начинающему программисту. При этом функционал вируса так же крайне беден. Видно, что у программиста не было никакой тяги к творчеству — всё было нацелено на быстрый результат. Хотя… Я совершенно не могу понять для какой цели данный вирус, вообще, предназначен? Все-таки за 10 лет вредоносное ПО сделало большой шаг в своём развитии.

Прежде чем продолжать углубляться в реверсинг, мы сделаем ещё одно упражнение по распаковке на другом примере. Этим файлом будет UNPACKME_ASPACK 2.2.

Он относится к категории простых. Далее в курсе, мы вернёмся к расширенной распаковке после изучения других тем.


Здесь, видим EP упакованного файла. Она начинается с инструкции PUSHAD, которую мы, пока, не видели среди часто используемых инструкций, но её работа заключается в том, что она ПОМЕЩАЕТ(КЛАДЁТ) каждый регистр в стек, т.е.

Инструкция PUSHAD равносильна инструкции PUSH, т.е. сохраняет в стек регистры в следующем порядке:


Инструкция POPAD - это обратная инструкция. Она ИЗВЛЕКАЕТ(ВЫТАЛКИВАЕТ) содержимое стека, сохраняя его в регистрах в следующем порядке (за исключением регистра ESP, который не меняется командой POPAD):


В простых упаковщиках, большинство из них использовали инструкцию PUSHAD для сохранения первоначального состояния регистров при запуске программы и использовали POPAD для их восстановления, до перехода в OEP, для выполнения программы, уже распакованной в памяти.

Благодаря этому, была возможность легко найти OEP, используя метод PUSHAD – POPAD. Очевидно, в более современных упаковщиках, создатели заметили это и избегают использование этих инструкции.

Что такое метод PUSHAD – POPAD?

Прежде всего, мы должны выбрать отладчик и запустить его. Мы уже знаем как это сделать. Идём в меню DEBUGGER → SELECT DEBUGGER и выбираем пункт LOCAL WIN32 DEBUGGER.

Теперь, чтобы попрактиковаться, запустим отладчик через PYTHON. Вы можете вводить инструкции одну за другой в панели PYTHON или использовать плагин IPYIDA, который мы установили и которой более удобный. Я сделаю это именно так.


Видим, что если набрать idc.Load и нажать TAB, плагин скажет, что idc.LoadDebugger уже существует. Проверим это.


В нашем случае, мы должны выбрать WIN32 и 0, для локального отладчика(1 используется для удаленного отладчика).

Проверим это. Для этого вводим такую команду.


Кажется, что плагину понравился наш выбор. Он вернул нам TRUE.


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

Метод PUSHAD основывается на выполнении инструкции PUSHAD. В следующей инструкции, видим регистры, которые сохранились в стек и устанавливаем там BP, чтобы остановить выполнение, когда программа попытается восстановить их с помощью инструкции POPAD, непосредственно перед переходом в OEP, после распаковки первоначального кода.

Другими словами, я устанавливаю BP с помощью F2 после инструкции PUSHAD. Дебаггер должен остановиться после выполнения этой инструкции. (Инструкция PUSHA похожа на инструкцию PUSHAD).


Если вы хотите установить BP с помощью PYTHON, Вы можете ввести следующую команду:

idaapi.add_bpt(0x46B002, 0, BPT_SOFT)

С помощью этой команды, Вы установите BP прям из PYTHON. Первый аргумент - это адрес BP, второй - размер и третий аргумент - его тип. Т.е обычный программный BP устанавливается командой BPT_SOFT или 0.

Мы уже выбрали ОТЛАДЧИК и установили первый BP. Сейчас нам нужно запустить отладчик, для того, чтобы остановиться на этом BP. Это очень просто. Это можно сделать с помощью F9 или из самого PYTHON, командой:

StartDebugger("","","");

С помощью этой команды выбранный отладчик будет запущен. Если всё сделано правильно, то отладчик остановится на BP, который мы установили по адресу 0x46B002.


Здесь мы должны увидеть стек и установить BP на первой строке, чтобы остановиться на ней, потому что это место, где сохраняются значения регистров, сохраненные инструкцией PUSHAD, и они восстанавливаются позже с помощью инструкции POPAD.


Как видно из рисунка, мы должны установить BP по адресу 0x19FF64 в моём случае, а в Вашем случае - это будет первый адрес стека, на который указывает регистр ESP.

Теперь, я помещаю курсор в окно дизассемблированного списка и нажимаю стрелку, которая находится рядом с регистром ESP.


Нажав стрелку рядом с регистром, отладчик будет пытаться показать этот адрес, если он существует, в окне где находится курсор. Таким образом, мы можем установить BP вручную с помощью F2, но мы должны настроить этот BP, так как в нашем случае, он должен сработать при ЧТЕНИИ и ЗАПИСИ, а не при ИСПОЛНЕНИИ, так как здесь он будет останавливаться, когда восстановит или прочитает значение. Он не выполнит здесь код.

После нажатия F2 открывается окно конфигурации BP.


Если окно не появляется, то переходим в меню DEBUGGER → BREAKPOINTS → BREAKPOINT LIST


И я делаю правый щелчок и выбираю пункт EDIT, чтобы изменить конфигурацию, на ту, которую нам нужна.

Можем ли мы установить этот BP с помощью PYTHON?. Да, для этого существует такая команда:


idaapi.add_bpt(0x019FF64, 1, 3)

Аргумент 1 - это длина BP и 3 - это тип BP, в этом случае это соответствует типу READ-WRITE ACCESS как видно из таблицы. Если я напечатаю эту команду, появится такой же BP, который мы установили, недавно, вручную.

Мы отключаем предыдущие BP, установленные вручную в списке BP, с помощью правого щелчка и выбора пункта DISABLE. А из PYTHON, это можно сделать так:

EnableBpt(0x46B002, 0)

Когда второй аргумент равен 1, Вы включаете BP, а с помощью 0 - выключаете.


Как видно из картинки, здесь он зеленый, т.е. выключен, а тот BP, который красный, принадлежит стеку.


Сейчас, мы должны продолжить с помощью F9 или напечатать в PYTHON команду:
idaapi.continue_process()


Отладчик остановится сразу после инструкции POPAD, когда он восстанавливает регистры и видим, что из СТАБА он собирается перейти в OEP по адресу 0x4271B0, так как последовательность инструкций PUSH XXX – RET, это то же, что и инструкция JMP XXX. Так что, давайте потраcсируем, немного, до прибытия в OEP.


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


Следующий шаг, который нужно сделать - это дамп. Для этого, мы должны найти IB и конечный адрес в последнем сегменте исполняемого файла.

В СЕГМЕНТАХ мы видим, что IB равна 0x400000 и заканчивается по адресу 0x46E000.


Вместо того, чтобы использовать скрипт, который мы использовали в части 15, мы используем версию для самого PYTHON.


Поскольку скрипт имеет много строк, я создаю его в текстовом редакторе и сохраняю его как файл IPYTHON_DUMP.PY, который также приложен к данному туториалу.

Сейчас, из меню FILE → SCRIPT FILE, я открываю этот скрипт. Он исполняется и создаёт файл ASPACK.BIN, который не имеет иконку. Для её восстановления, я буду использовать PEEDITOR.



Делаем правый щелчок и выбираем пункт DUMP FIXER.


Теперь, изменив расширение файла на EXE, появляется иконка файла.

Сейчас, мы открываем программу SCYLLA 0.98. В этой части, я приложил более свежую версию. Как и раньше, будем искать процесс, который все ещё остановлен на OEP.


Сейчас, мы вводим OEP, который равен 0x004271B0 и нажимаем по очереди кнопки IAT AUTOSEARCH и GET IMPORTS.

Если нажмём кнопку SHOW INVALIDS и выберем режим ADVANCED, увидим, что существует несколько плохих записей. Давайте посмотрим, сможем ли мы починить их автоматически.

Видим, что программа не смогла их исправить сама. Так что давайте действовать вручную.


Здесь, видим первую запись по адресу 0x460818, она правильная и совпадает с нужным вызовом.

Более того, выше начинаются недействительные записи. Давайте посмотрим, что есть в первой неверной записи, которая находится по адресу 0x4600EC.

Если я изменяю порядок байт с помощью D и затем перегруппирую их, то


Видно, что содержимое не указывает ни на какой действительный адрес, а также, если я нажму CTRL + X, то увижу, что ссылок не существует.


В то время, как в действительной записи, будут существовать ссылки при использовании API. Например так.


Так что - это пример недействительные записи IAT. Такие мы будем удалять.

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


Мы видим, что IAT сейчас начинается по адресу 0x460810. Видно, что нет плохих записей, которые ошибочно добавил РЕЖИМ ADVANCED.

Так что, сейчас, я могу выбрать наш дамп и нажать на нём FIX DUMP.


И отремонтировав сдампленный файл, я запускаю его без проблем.


И мы написали этот туториал, потому что он сам попросил нас об этом.

Читайте также:

Пожалуйста, не занимайтесь самолечением!
При симпотмах заболевания - обратитесь к врачу.