
dex-vm se utiliza para proteger el archivo classes.dex de Android
Ejecuta código de bytes dalvik basado en dex-vm para proteger el dex y aumentar la dificultad de la descompilación. El proyecto se divide en dos partes: nmm-protect es un proyecto puramente Java que transforma el dex, convierte los datos del dex en estructuras C, aleatoriza los opcodes y genera un proyecto NDK; tras la compilación se genera un apk reforzado. nmmvm es un proyecto de Android que incluye la implementación de dex-vm y pruebas de diversas instrucciones dalvik, etc.
Sin compilar nmm-protect, puedes ver directamente cómo usarlo para generar el proyecto y el apk final, un ejemplo de procesamiento de apk.
El ejemplo se probó en un entorno Linux; en Windows tampoco debería haber problemas. Primero instala el JDK, el Android SDK y el NDK.
Descarga vm-protect.jar y configura las variables de entorno ANDROID_SDK_HOME y 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
Una vez completada la ejecución, se generará un directorio build en el directorio donde se encuentra input.apk, que contiene el apk de salida final (build/input-protect.apk), el proyecto C completo dex2c (basado en cmake) y los archivos .dex generados durante el procesamiento, etc.
Después de la primera ejecución, se generará un directorio tools en la ubicación del jar, dentro del cual hay un config.json que se puede editar para configurar las rutas relacionadas con el SDK y NDK de Android.
Un amigo escribió una interfaz GUI que facilita su uso; si la necesitas, puedes probarla en https://github.com/TimScriptov/nmmp
El apk generado debe alinearse con zipalign (las versiones nuevas ya usan zipflinger para procesar el apk, por lo que no es necesario usar zipalign por separado) y firmarse con apksigner para poder instalarse y usarse
apksigner sign --ks ~/.myapp.jks build/input-protect-align.apk
java -jar vm-protect-xxx.jar aab test.aab convertRules.txt
Después es necesario firmar con jarsigner, también se puede integrar signflinger para firmar
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
Tras un éxito, se generará un fatjar ejecutable directamente en build/libs.
Si no hay archivo de reglas de conversión, se convertirán los métodos de todas las clases en el dex (excepto los métodos constructores y los métodos de inicialización estática). Las reglas solo admiten algunos casos simples:
//支持的规则比较简单,*只是被转成正则表达式的.*,支持一些简单的继承关系
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 es la implementación concreta de la máquina virtual dex, con una única función de entrada:
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 proporciona las instrucciones, la tabla de excepciones y el espacio de registros necesarios para la ejecución; vmResolver contiene un conjunto de punteros a funciones que proporcionan los símbolos en tiempo de ejecución, como field, method, etc. Mediante la personalización de estos dos parámetros se implementan diferentes modos de refuerzo; por ejemplo, el archivo test.cpp del proyecto incluye un vmResolver sencillo basado en libdex, que se utiliza principalmente para desarrollo y pruebas. Por su parte, nmm-protect implementa la conversión de los datos relacionados con .dex en estructuras de C, e incluye además la aleatorización de opcodes, entre otras cosas, por lo que es básicamente apto para uso real.
Actualmente ya se ha implementado el refuerzo relacionado con módulos, y su uso es similar al refuerzo de apk; si surge algún problema, puedes abrir un issue.
nmm-protect se publica bajo la licencia GPL, nmm-protect licence; la parte dex-vm se publica bajo la licencia Apache, nmmvm licence. Solo la parte vm se empaqueta en el apk; nmm-protect solo convierte el dex, por lo que la licencia no afecta al resultado generado.