
dex-vm zum Schutz der Android-Datei classes.dex
Basierend auf dex-vm wird Dalvik-Bytecode ausgeführt, um dex zu schützen und die Schwierigkeit der Dekompilierung zu erhöhen. Das Projekt ist in zwei Teile gegliedert: nmm-protect ist ein reines Java-Projekt, das dex konvertiert, die Daten in dex in C-Strukturen umwandelt und durch Opcode-Randomisierung ein NDK-Projekt generiert; nach der Kompilierung wird eine gehärtete APK erzeugt. nmmvm ist ein Android-Projekt, das die dex-vm-Implementierung sowie Tests verschiedener Dalvik-Anweisungen usw. enthält.
Wenn Sie nmm-protect nicht kompilieren möchten, können Sie direkt nachsehen, wie damit ein Projekt und die endgültige APK erzeugt wird, ein Beispiel für die Verarbeitung einer APK.
Das Beispiel wurde in einer Linux-Umgebung getestet, unter Windows sollte es ebenfalls problemlos funktionieren; installieren Sie zuerst JDK sowie das Android SDK und NDK.
Laden Sie vm-protect.jar herunter und konfigurieren Sie die Umgebungsvariablen ANDROID_SDK_HOME und 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
Nach der Ausführung wird im Verzeichnis, in dem sich input.apk befindet, ein build-Verzeichnis erzeugt, das die schließlich ausgegebene apk (build/input-protect.apk), das vollständige C-Projekt dex2c (basierend auf cmake) sowie die während der Verarbeitung erzeugten .dex-Dateien usw. enthält.
Nach dem ersten Lauf wird am jar-Speicherort ein tools-Verzeichnis erzeugt, in dem sich config.json befindet; darin können die relevanten Pfade für das Android SDK und NDK konfiguriert werden.
Ein Freund hat eine GUI-Oberfläche geschrieben, die die Nutzung bequemer macht. Wer sie braucht, kann sie gerne ausprobieren: https://github.com/TimScriptov/nmmp
Die erzeugte apk muss mit zipalign ausgerichtet (in neueren Versionen wird die apk bereits mit zipflinger verarbeitet, sodass ein separates zipalign nicht erforderlich ist) und mit apksigner signiert werden, bevor sie installiert und verwendet werden kann
apksigner sign --ks ~/.myapp.jks build/input-protect-align.apk
java -jar vm-protect-xxx.jar aab test.aab convertRules.txt
Danach muss mit jarsigner signiert werden; alternativ kann signflinger zur Signierung integriert werden.
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
Nach Erfolg wird im Verzeichnis build/libs ein direkt ausführbares Fat-JAR erzeugt.
Ohne Konvertierungsregeldatei werden die Methoden aller Klassen im Dex konvertiert (außer Konstruktoren und statischen Initialisierungsmethoden). Die Regeln unterstützen nur einige einfache Fälle:
//支持的规则比较简单,*只是被转成正则表达式的.*,支持一些简单的继承关系
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 ist die konkrete Implementierung der dex-Virtual-Maschine, der Einstiegspunkt ist eine einzige Funktion:
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 stellt die zur Ausführung benötigten Anweisungen, die Exception-Tabelle und den Registerspeicher bereit, während vmResolver eine Reihe von Funktionszeigern enthält, die Laufzeit-Symbole wie field, method usw. bereitstellen. Durch die Anpassung dieser beiden Parameter lassen sich unterschiedliche Härtungsmethoden umsetzen. So enthält beispielsweise die Datei test.cpp im Projekt einen einfachen, auf libdex basierenden vmResolver, der hauptsächlich für Entwicklungs- und Testzwecke dient. nmm-protect hingegen wandelt die .dex-bezogenen Daten in C-Strukturen um und umfasst zusätzlich Opcode-Randomisierung usw., sodass es grundsätzlich praktisch einsetzbar ist.
Derzeit ist die Härtung des Moduls bereits implementiert; die Verwendung ähnelt der apk-Härtung. Bei Problemen kann ein Issue erstellt werden.
nmm-protect wird unter der GPL-Lizenz veröffentlicht, nmm-protect licence, der dex-vm-Teil wird unter der Apache-Lizenz veröffentlicht, nmmvm licence. Nur der vm-Teil wird in die apk gepackt, nmm-protect konvertiert lediglich dex, und die Lizenz hat keinen Einfluss auf die erzeugten Ergebnisse.