NDK39

编程入门 行业动态 更新时间:2024-10-09 20:28:37

NDK39

NDK39

一 JAVA层逻辑

加载dex,不同虚拟机进行不同处理

ART(Android Runtime)是Android 4.4发布的,用来替换Dalvik虚拟,Android 4.4默认采用的还是dalvik,系统会提供一个选项来开启ART。在Android 5.0时,默认采用ART,dalvik从此退出历史舞台。

public class DexManager {private Context context;private static final DexManager ourInstance = new DexManager();public static DexManager getInstance() {return ourInstance;}private DexManager() {}public void setContext(Context context) {this.context = context;}public void loadFile(File file) {try {DexFile dexFile = DexFile.loadDex(file.getAbsolutePath(),new File(context.getCacheDir(), "opt").getAbsolutePath(), Context.MODE_PRIVATE);//下一步  得到class   ----取出修复好的MethodEnumeration<String> entry= dexFile.entries();while (entry.hasMoreElements()) {// 拿到全类名String className=entry.nextElement();Class clazz=dexFile.loadClass(className, context.getClassLoader());if (clazz != null) {fixClazz(clazz);}}} catch (IOException e) {e.printStackTrace();}}private void fixClazz(Class realClazz) {//  服务器修复好的  realClazzMethod[] methods=realClazz.getDeclaredMethods();for (Method rightMethod : methods) {Replace replace = rightMethod.getAnnotation(Replace.class);if (replace == null) {continue;}//找到了修复好的Method    找到出bug的MethodString wrongClazz=replace.clazz();String  wrongMethodName=replace.method();try {Class clazz=Class.forName(wrongClazz);Method wrongMethod = clazz.getDeclaredMethod(wrongMethodName, rightMethod.getParameterTypes());if (Build.VERSION.SDK_INT <= 18) {replace(Build.VERSION.SDK_INT ,wrongMethod, rightMethod);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}}public native void replace(int  sdk,Method wrongMethod, Method rightMethod);}

因为在JNI调用修复的方法中要使用到相应的系统API,所以要引用对应虚拟机系统的头文件

二 Dalvik 修复

  • 引入Dalvik 系统的 dalvik.h头文件

  • 实现native修复方法:Java_com_example_ray_fix_DexManager_replace

#include <jni.h>
#include <string>
#include "dalvik.h"
typedef Object *(*FindObject)(void *thread, jobject jobject1);
typedef  void* (*FindThread)();
FindObject  findObject;
FindThread  findThread;extern "C"{JNIEXPORT void JNICALL
Java_com_example_ray_fix_DexManager_replace(JNIEnv *env, jobject instance, jint sdk,jobject wrongMethod,jobject rightMethod) {
//    做  跟什么有关   虚拟机    java虚拟机 Method
//找到虚拟机对应的Method 结构体Method *wrong = (Method *) env->FromReflectedMethod(wrongMethod);Method *right =(Method *) env->FromReflectedMethod(rightMethod);//下一步  把right 对应Object   第一个成员变量ClassObject   status//    ClassObjectvoid *dvm_hand=dlopen("libdvm.so", RTLD_NOW);
//    sdk  10    以前是这样   10会发生变化findObject= (FindObject) dlsym(dvm_hand, sdk > 10 ?"_Z20dvmDecodeIndirectRefP6ThreadP8_jobject" :"dvmDecodeIndirectRef");findThread = (FindThread) dlsym(dvm_hand, sdk > 10 ? "_Z13dvmThreadSelfv" : "dvmThreadSelf");
// method   所声明的Classjclass methodClaz = env->FindClass("java/lang/reflect/Method");jmethodID rightMethodId = env->GetMethodID(methodClaz, "getDeclaringClass","()Ljava/lang/Class;");
//jobject ndkObject = env->CallObjectMethod(rightMethod, rightMethodId);ClassObject *firstFiled = (ClassObject *) findObject(findThread(), ndkObject);firstFiled->status=CLASS_INITIALIZED;wrong->accessFlags |= ACC_PUBLIC;wrong->methodIndex=right->methodIndex;wrong->jniArgInfo=right->jniArgInfo;wrong->registersSize=right->registersSize;wrong->outsSize=right->outsSize;
//    方法参数 原型wrong->prototype=right->prototype;
//wrong->insns=right->insns;wrong->nativeFunc=right->nativeFunc;
}
}

三 ART修复

引入Art虚拟器中的相关源码,如7.0的:art_7_0.h

#include <jni.h>
#include <string>
#include "dalvik.h"
typedef Object *(*FindObject)(void *thread, jobject jobject1);
typedef  void* (*FindThread)();
FindObject  findObject;
FindThread  findThread;extern "C"{JNIEXPORT void JNICALL
Java_com_example_ray_fix_DexManager_replace(JNIEnv *env, jobject instance, jint sdk,jobject wrongMethod,jobject rightMethod) {
//    做  跟什么有关   虚拟机    java虚拟机 Method
//找到虚拟机对应的Method 结构体Method *wrong = (Method *) env->FromReflectedMethod(wrongMethod);Method *right =(Method *) env->FromReflectedMethod(rightMethod);//下一步  把right 对应Object   第一个成员变量ClassObject   status//    ClassObjectvoid *dvm_hand=dlopen("libdvm.so", RTLD_NOW);
//    sdk  10    以前是这样   10会发生变化findObject= (FindObject) dlsym(dvm_hand, sdk > 10 ?"_Z20dvmDecodeIndirectRefP6ThreadP8_jobject" :"dvmDecodeIndirectRef");findThread = (FindThread) dlsym(dvm_hand, sdk > 10 ? "_Z13dvmThreadSelfv" : "dvmThreadSelf");
// method   所声明的Classjclass methodClaz = env->FindClass("java/lang/reflect/Method");jmethodID rightMethodId = env->GetMethodID(methodClaz, "getDeclaringClass","()Ljava/lang/Class;");
//jobject ndkObject = env->CallObjectMethod(rightMethod, rightMethodId);ClassObject *firstFiled = (ClassObject *) findObject(findThread(), ndkObject);firstFiled->status=CLASS_INITIALIZED;wrong->accessFlags |= ACC_PUBLIC;wrong->methodIndex=right->methodIndex;wrong->jniArgInfo=right->jniArgInfo;wrong->registersSize=right->registersSize;wrong->outsSize=right->outsSize;
//    方法参数 原型wrong->prototype=right->prototype;
//wrong->insns=right->insns;wrong->nativeFunc=right->nativeFunc;
}
}

四 解决混淆产生的问题

使用工具:apkpatch 将新旧apk进行对比,会将修改的类,打包生成dex文件
注意:由于工具类中将相关的包名路径写死了,所以修复版Replace要重命名为MethodReplace,并修改包路径为:
com.alipay.euler.andfix.annotation

命令

apkpatch.bat -f new.apk -t old.apk -o output -k andfix.jk -p 123456 -a david -e 123456-f 修复好的apk
-t 出现bug的apk
-o 输出的文件
-k 签名
-p 签名 密码
-a 别名
-e 别名的密码

五 Demo

AndroidFix_Ray

六 注意

不同版本Android系统对应的ArtMethod头文件不一样,修复的细节也不一样,github搜索AndroidFix

更多推荐

NDK39

本文发布于:2024-02-14 03:50:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1761908.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!