-
Автор темы
- #1
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Цель данного анализа - предоставить образовательные ресурсы о борьбе с вредоносным ПО. Все действия выполняются на ваш страх и риск.
Тестируемая версия - 6.9.0.0. Под прицелом самое интересное, остальное легко снимается.
1. Native EXE File
Протектор предлагает возможность обернуть файл в нативный стаб. Архитектура - x86. К сожалению малдева, легко снимается. Использует COM.
Первым делом стаб проверяет, идет ли профилирование процесса. Также он ищет DLL, относящиеся к JIT`у, и если находит, то закрывает хендл CreateToolhelp32Snapshot`a и выходит:
Затем стаб читает ресурс "__" и расшифровывает его:
Расшифровка идет в 2 или 3 функции, внутри которых идут еще функции и так далее. Например, decrypt1:
Затем начинается работа с CLR:
Заметили memcpy_0? Это наш ключ к победе.
Я составил паттерн вызова -
8B 44 24 48 55 57 50 E8 ?? ?? ?? ??
.Паттерн самой функции -
55 8B EC 57 56 8B 75 0C 8B 4D 10 8B 7D 08 8B C1 8B D1 03 C6 3B FE
.Время контрить. Запускаем отладчик, ждем CTRL + SHIFT + B, вводим какой-либо из паттернов. В первом случае будет как на скрине, во втором отладчик выдаст 2 совпадения - брякаем второе. Жмете F9, пока не попадете на бряк. По [esp+4] вы должны увидеть MZ. Если да, переходите по указателю в дамп. Нет - жмякайте F9 до последнего.
Вам понадобится плагин xSelectBlock. Перейдя в дамп, тыкайте ПКМ по 4D, затем xSelectBlock -> Select block. Смотрите на скрине.
Далее сохраняем в файл:
Работа с нативом закончена. Наш дамп оказался дотнетовской DLL. Кидаем в dnSpy. Оказывается, это еще один стаб. Все на скрине:
Это единственный класс. Как мы заметили, никакого шифрования. Это значит, что оригинальный файл лежит в ресурсах в чистом виде. Сохраняем, проверяем:
Итак, мы извлекли файл из стаба.
2. Виртуализация
Ассоциируется с истериками, мозгоеблей. Но тут у нас си-решеточка, все решаемо :)
Прежде всего: вот так выглядит метод decryptByte(я не уверен, правильно ли назвал, но выглядит правдоподобно):
Магия виртуализации начинается с вызова виртуализированного метода, где 0 - индекс, array - аргументы:
Прежде всего проверяется инициализация. Если false, то вызывается метод readBytecodeResourceAndDoStuff:
Затем начинается чтение байткода согласно индексу. Подготавливаются некоторые данные, включая токен метода, количество виртуальных инструкций. Парсятся параметры:
Проверяется валиднось опкода, подготавливаются некоторые данные и добавляется опкод + операнд в список инструкций:
Во время отладки я заглянул в этот список и увидел некоторые сходства с оригинальным набором инструкций:
Вот оригинал:
После еще некоторой подготовки начинается выполнение. Я заметил класс, в котором есть метод, выполняющий наш байткод:
Сам метод:
Метод resolveHandlerAndExecute содержит огромную конструкцию switch, которая ищет хандлер согласно номеру опкода:
Проблема реверса этой ВМ в количестве опкодов. Вот конец switch`a:
Отлаживая, я рассмотрел носколько хандлеров. Вот, например, хандлек call`a:
Самое сочное:
Напоследок, вот так выглядит (часть?) стека:
На этом с виртуализацией все. У меня мало времени, а еще я умудрился сломать файл из-за некорректного ремапа ^^.
В теории можно хукнуть с помощью Harmony и логгировать все, и этого будет достаточно. Еще в dnSpy можно настроить бряки(условия, кол-во хитов, фильтр и логгирование при хите). Брякаем VmStack.Push() и Invoke(), и пишем аргументы в консоль.
Особо усидчивые могут реверснуть каждый хандлер и сделать девиртуализатор. Я не уверен, уникальна ли ВМ в каждом билде. Девиртуализация займет много времени, и могут возникнуть сложности(например, опкоды уникальны, и придется искать хандлеры по паттернам), но оно того стоит, и это намного легче любого натива.