
dex-vm используется для защиты файла classes.dex в Android
Запуск байт-кода dalvik на основе dex-vm для защиты dex и усложнения декомпиляции. Проект состоит из двух частей: nmm-protect — это чисто java-проект, который преобразует dex, переводя данные из dex в c-структуры, рандомизирует опкоды и генерирует ndk-проект, а после компиляции создаёт защищённый apk. nmmvm — это android-проект, содержащий реализацию dex-vm и тесты различных инструкций dalvik и т.п.
Если не компилировать nmm-protect, можно сразу посмотреть, как с его помощью сгенерировать проект и итоговый apk, пример обработки apk.
Пример тестировался в среде Linux, в Windows тоже должно работать без проблем, сначала установите JDK, Android SDK и NDK.
Скачайте vm-protect.jar, настройте переменные среды ANDROID_SDK_HOME, ANDROID_NDK_HOME:
export ANDROID_SDK_HOME=/opt/android-sdk
export ANDROID_NDK_HOME=/opt/android-sdk/ndk/22.1.7171670
export CMAKE_PATH=/opt/android-sdk/cmake/3.18.1/ #可选,不配置的话直接使用/bin/cmake
java -jar vm-protect-xxx.jar apk input.apk convertRules.txt mapping.txt
После завершения выполнения в каталоге, где находится input.apk, будет создан каталог build, содержащий итоговый выходной apk (build/input-protect.apk), полный C-проект dex2c (на основе cmake) и сгенерированные в процессе обработки .dex и другие файлы.
После первого запуска в месте расположения jar будет создан каталог tools, в котором находится config.json — его можно отредактировать, чтобы настроить пути, связанные с Android SDK и NDK.
Есть друг, который написал GUI-интерфейс, чтобы было удобнее пользоваться; кому нужно, можете попробовать, https://github.com/TimScriptov/nmmp
Сгенерированный apk необходимо выровнять с помощью zipalign (в новых версиях apk уже обрабатывается через zipflinger, поэтому отдельный zipalign можно не использовать) и подписать через apksigner, только после этого его можно устанавливать и использовать
apksigner sign --ks ~/.myapp.jks build/input-protect-align.apk
java -jar vm-protect-xxx.jar aab test.aab convertRules.txt
После этого необходимо подписать с помощью jarsigner, также можно интегрировать signflinger для подписи.
jarsigner -keystore ~/.myapp.jks -storepass pass -keypass pass test-protect.aab keyAlias
java -jar vm-protect-xxx.jar aar testModule.aar convertRules.txt
git clone https://github.com/maoabc/nmmp.git
cd nmmp/nmm-protect
./gradlew arsc:build
./gradlew build
После успешного выполнения в build/libs будет создан исполняемый fatjar.
Если файл правил преобразования отсутствует, будут преобразованы методы во всех классах в dex (кроме конструкторов и методов статической инициализации). Правила поддерживают только несколько простых случаев:
//支持的规则比较简单,*只是被转成正则表达式的.*,支持一些简单的继承关系
class * extends android.app.Activity
class * implements java.io.Serializable
class my.package.AClass
class my.package.* { *; }
class * extends java.util.ArrayList {
if*;
}
class A {
}
class B extends A {
}
class C extends B {
}
//比如'class * extends A' 只会匹配B而不会再匹配C
nmmvm — это конкретная реализация dex-виртуальной машины, точка входа всего одна функция:
jvalue vmInterpret(
JNIEnv *env,
const vmCode *code,
const vmResolver *dvmResolver
);
typedef struct {
const u2 *insns; //指令
const u4 insnsSize; //指令大小
regptr_t *regs; //寄存器
u1 *reg_flags; //寄存器数据类型标记,主要标记是否为对象
const u1 *triesHandlers; //异常表
} vmCode;
typedef struct {
const vmField *(*dvmResolveField)(JNIEnv *env, u4 idx, bool isStatic);
const vmMethod *(*dvmResolveMethod)(JNIEnv *env, u4 idx, bool isStatic);
//从类型常量池取得类型名
const char *(*dvmResolveTypeUtf)(JNIEnv *env, u4 idx);
//直接返回jclass对象,本地引用需要释放引用
jclass (*dvmResolveClass)(JNIEnv *env, u4 idx);
//根据类型名得到class
jclass (*dvmFindClass)(JNIEnv *env, const char *type);
//const_string指令加载的字符串对象
jstring (*dvmConstantString)(JNIEnv *env, u4 idx);
} vmResolver;
vmCode предоставляет инструкции, таблицу исключений и регистровое пространство, необходимые для выполнения, а vmResolver содержит набор указателей на функции, предоставляющих символы времени выполнения, такие как field, method и т.д. Путём кастомизации этих двух параметров реализуются различные способы защиты; например, в проекте в test.cpp есть простой vmResolver на основе libdex, который в основном используется для разработки и тестирования. А nmm-protect реализует преобразование данных, связанных с .dex, в структуры C, а также включает рандомизацию опкодов и т.п., и в основном пригоден для практического использования.
В настоящее время реализована защита, связанная с модулями, использование аналогично защите apk; при возникновении проблем можно создать issue.
nmm-protect распространяется под лицензией GPL, nmm-protect licence, часть dex-vm распространяется под лицензией Apache, nmmvm licence. В apk упаковывается только часть vm, nmm-protect лишь преобразует dex, и лицензия не влияет на сгенерированный результат.