Начинающий
- Статус
- Онлайн
- Регистрация
- 21 Сен 2024
- Сообщения
- 117
- Реакции
- 4
Виртуализация — один из самых эффективных способов защиты приложений. Вместо родного MSIL кода, протектор превращает вашу логику в кастомный байткод, а в программу встраивает виртуальную машину, которая исполняет этот байткод. Реверсер видит лишь хаотичную математику и спецсимволы.
Как RikaVM ищет свой код
Любая ВМ должна где‑то хранить зашифрованный байткод методов. Вместо стандартных ресурсов, RikaVM использует более хитрый подход:- Windows: через unsafe и указатели читает PE-заголовки напрямую, ищет секцию ".{B$;" (метод VmDecryptor.InitDecryptor).
- Другие ОС: открывает собственный файл с диска через FileStream и извлекает байткод из секции.
Криптографическая защита: больше чем XOR
Авторы RikaVM продумали защиту от статического анализа. Ключом служит случайный GUID, от которого вычисляются MD5 и SHA256:Далее применяется ARX-подобный шифр (Add-Rotate-Xor) с 64-битными блоками. Функция VmDecryptor.RotL64 многократно сдвигает и ксорит данные. Байткод расшифровывается кусками по 8 байт и сохраняется в массив operand_ByteArray_141. Чтобы написать скрипт-расшифровщик, необходимо воссоздать всю цепочку математики 1-в-1 — это сильно затрудняет автоматический статический анализ.
Архитектура: стековый виртуальный процессор
После расшифровки работу начинает VmContext — виртуальный CPU. Стек значений (StackValue) умеет хранить любые типы: int, float, object, IntPtr и сложные структуры. ВМ автоматически адаптируется под битность платформы:
Архитектура: стековый виртуальный процессор:
public int NormToInt32 => IntPtr.Size == 4 ? (int)this.value : (int)((long)this.value);
«МегаМакросы» — когда один опкод делает 30+ действий
Классические ВМ (например, KoiVM) используют простые опкоды: положить число, сложить, перейти. RikaVM идёт дальше и объединяет множество операций в один виртуальный опкод. Взгляните на Opcode_MegaMacro15 — он выполняет вызовы через рефлексию, грузит локальные переменные, создаёт массивы, арифметику и ещё 200 строк логики:
МегаМакросы:
VmLocalVarPusher.GetLocalVarContext(ctx).LoadLocal(this.operand_Int32Array_273[0]).PushValue();
methodBase = ctx.Metadata.ResolveMethod((int)this.operand_UInt32Array_274[0]);
VmReflectionHelper.ExecuteMethodCall(methodBase, ctx, true);
Почему это эффективно? Обычные дизассемблеры ожидают, что один опкод = одно действие. В RikaVM разбор макросов требует ручного восстановления цепочек IL-инструкций, что делает автоматический деобфускатор крайне сложным, а для малоизвестного протектора — часто нецелесообразным.
Вызовы нативных методов через рефлексию + динамический код
Поскольку ВМ написана на C#, ей нужно вызывать настоящие методы .NET (например, Environment.Exit). RikaVM использует рефлексию, но для неизвестных заранее виртуальных методов генерирует код на лету через VmReflectionHelper.CreateVirtDelegate. Это создаёт дополнительные уровни косвенности, запутывая трассировку.Как девиртуализировать RikaVM (план действий)
Несмотря на мощную защиту, подход к девиртуализации остаётся системным:- Извлечь чистый байткод — дамп в рантайме или анализ секций.
- Маппинг опкодов — найти класс-диспетчер (аналог OpcodeResolver), сопоставить идентификаторы с обработчиками.
- Разбор макросов — написать транслятор, который раскрывает один "мега-опкод" в последовательность стандартных IL-инструкций.
- Символьное выполнение — восстановить граф потока управления, обойдя постоянное ксорение виртуального InstructionPointer.
Author: t.me/junk_code