
dex-vm usado para proteger o arquivo classes.dex do Android
Executa bytecode dalvik com base em dex-vm para proteger o dex, aumentando a dificuldade de descompilação. O projeto é dividido em duas partes: nmm-protect é um projeto puramente Java que converte o dex, transformando os dados do dex em estruturas C, randomiza os opcodes e gera um projeto NDK; após a compilação, gera um apk reforçado. nmmvm é um projeto Android que inclui a implementação da dex-vm e testes de várias instruções dalvik, etc.
Sem compilar o nmm-protect, você pode ver diretamente como usá-lo para gerar o projeto e o apk final, um exemplo de processamento de apk.
O exemplo foi testado em ambiente Linux, o Windows também deve funcionar sem problemas, primeiro instale o JDK, o android sdk e o ndk.
Baixe o vm-protect.jar, configure as variáveis de ambiente ANDROID_SDK_HOME e 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
Após a execução, será gerado um diretório build no diretório onde o input.apk está localizado, contendo o apk final de saída (build/input-protect.apk), o projeto C completo dex2c (baseado em cmake) e os arquivos .dex gerados durante o processamento.
Após a primeira execução, será gerado um diretório tools na localização do jar, dentro do qual há um config.json que pode ser editado para configurar os caminhos relacionados ao sdk e ndk do Android.
Um amigo criou uma interface GUI que torna o uso mais conveniente; quem precisar pode experimentar, https://github.com/TimScriptov/nmmp
O apk gerado precisa ser alinhado com zipalign (as versões mais recentes já usam zipflinger para processar o apk, então não é necessário usar o zipalign separadamente) e assinado com apksigner para poder ser instalado e usado
apksigner sign --ks ~/.myapp.jks build/input-protect-align.apk
java -jar vm-protect-xxx.jar aab test.aab convertRules.txt
Depois é necessário assinar com jarsigner, ou também é possível integrar o signflinger para realizar a assinatura
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
Após o sucesso, um fatjar executável será gerado em build/libs.
Se não houver arquivo de regras de conversão, todos os métodos de todas as classes no dex serão convertidos (exceto métodos construtores e métodos de inicialização estática). As regras suportam apenas alguns 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 é a implementação concreta da máquina virtual dex, com apenas uma função 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 fornece as instruções necessárias para a execução, a tabela de exceções e o espaço de registradores; vmResolver contém um conjunto de ponteiros de função que fornecem os símbolos em tempo de execução, como field, method, etc. Ao personalizar esses dois parâmetros, é possível implementar diferentes formas de proteção; por exemplo, o test.cpp do projeto contém um vmResolver simples baseado em libdex, usado principalmente para desenvolvimento e testes. Já o nmm-protect converte os dados relacionados ao .dex em estruturas C e também inclui randomização de opcode, entre outros, sendo basicamente utilizável na prática.
Atualmente, a proteção relacionada a módulos já foi implementada, com uso semelhante à proteção de apk; se houver problemas, você pode abrir uma issue.
nmm-protect é distribuído sob a licença GPL, nmm-protect licence, a parte dex-vm é distribuída sob a licença Apache, nmmvm licence. Apenas a parte da vm é empacotada no apk; o nmm-protect apenas converte o dex, e a licença não afeta o resultado gerado.