首页
社区
课程
招聘
[原创]Fart 源码攻略笔记
发表于: 2023-5-3 12:10 31678

[原创]Fart 源码攻略笔记

2023-5-3 12:10
31678

最近在学习心心念的 Fart,研究了几天也翻阅了许多文章,但还是发现在有许多的问题不易理解(大佬们的笔记总是惜墨如金),最后决定把每一行代码的分析记录下来,便于日后温习,我始终坚信好记性不如烂笔头,分析再明白的的东西,时间久了也难免生疏,并且本篇笔记分析的 Fart 的源码也会放一份在最后,方便大家下载对比阅读本篇笔记,最后感谢 Fart 的作者 hanbingle 将这么优秀的框架开源供大家学习。

Fart 的作者封装了一些工具类方法,想要彻底理解 Fart 的源码,对这些工具类方法的分析就是基础,而这些工具类方法的分析其实只是是对 Java 反射机制的一个温习,和 Fart 主体的流程关系并不大,所以本篇笔记将分为工具类分析和主体流程分析两部分。

为了方便理解这个函数,这里写了个 demo

为了方便理解这个函数,这里写了个 demo

找到 fart 执行的起始点

本来是想做个流程图的,但我梳理了一下通篇笔记的流程,感觉 Fart 的流程还是清晰明了并不复杂,跟寻我的分析思路,基本上是一条主线,没什么分支,所以这里就偷个懒了。

说一下本篇笔记的意义,对于笔者来讲,当然是温故而知新,可以为师矣,对于小白来讲,可以温习反射机制,熟悉 Fart 的机制,并且还可以移植魔改 Fart,还记得我在笔记中多次提到了高版本的问题,至于大佬嘛……大佬们当然是可以点赞、收藏并投币啦!!!

FART_aosp8.0.7z

public static Field getClassField(ClassLoader classloader, String class_name, String filedName) {
    // 该函数通过传入的 classloader、class_name、filedName 获取到反射的对象
    try {
        // 在 classloader 中通过类名获取到类对象
        Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
        // 在类对象中通过反射名称获取到反射对象
        Field field = obj_class.getDeclaredField(filedName);
        // 将反射对象设置为可访问权限
        field.setAccessible(true);
        // 返回得到的反射对象
        return field;
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}
public static Field getClassField(ClassLoader classloader, String class_name, String filedName) {
    // 该函数通过传入的 classloader、class_name、filedName 获取到反射的对象
    try {
        // 在 classloader 中通过类名获取到类对象
        Class obj_class = classloader.loadClass(class_name);//Class.forName(class_name);
        // 在类对象中通过反射名称获取到反射对象
        Field field = obj_class.getDeclaredField(filedName);
        // 将反射对象设置为可访问权限
        field.setAccessible(true);
        // 返回得到的反射对象
        return field;
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}
public static Object getClassFieldObject(
    ClassLoader classloader, String class_name, Object obj, String filedName) {
    // 其实就是通过反射的方法获取对象的属性
    try {
        // 在 classloader 中通过类名获取到类对象
        Class obj_class = classloader.loadClass(class_name);
        // 在类对象中通过反射名称获取到反射对象
        Field field = obj_class.getDeclaredField(filedName);
        // 将反射对象设置为可访问权限
        field.setAccessible(true);
        // 声明一个局部变量 result 作为返回结果
        Object result = null;
        // 调用反射对象的 get 方法获取 obj 对象的属性值
        result = field.get(obj);
        // 将属性值返回
        return result;
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}
public static Object getClassFieldObject(
    ClassLoader classloader, String class_name, Object obj, String filedName) {
    // 其实就是通过反射的方法获取对象的属性
    try {
        // 在 classloader 中通过类名获取到类对象
        Class obj_class = classloader.loadClass(class_name);
        // 在类对象中通过反射名称获取到反射对象
        Field field = obj_class.getDeclaredField(filedName);
        // 将反射对象设置为可访问权限
        field.setAccessible(true);
        // 声明一个局部变量 result 作为返回结果
        Object result = null;
        // 调用反射对象的 get 方法获取 obj 对象的属性值
        result = field.get(obj);
        // 将属性值返回
        return result;
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}
// Person.java
package com.example.demo3;
public class Person {
    private int age = 22;
    public int get_age()
    {
        return age * 2;
    }
}
 
// MainActivity.java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Person person = new Person();
 
        try {
            ClassLoader classLoader = getClassLoader();
            Class classObj = classLoader.loadClass("com.example.demo3.Person");
            Field field = classObj.getDeclaredField("age");
            field.setAccessible(true);
            Object myage = field.get(person);
            Log.d("lxz", String.valueOf(myage));
            // 2023-05-02 14:19:33.054 29940-29940 lxz  com.example.demo3   D  22
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
// Person.java
package com.example.demo3;
public class Person {
    private int age = 22;
    public int get_age()
    {
        return age * 2;
    }
}
 
// MainActivity.java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Person person = new Person();
 
        try {
            ClassLoader classLoader = getClassLoader();
            Class classObj = classLoader.loadClass("com.example.demo3.Person");
            Field field = classObj.getDeclaredField("age");
            field.setAccessible(true);
            Object myage = field.get(person);
            Log.d("lxz", String.valueOf(myage));
            // 2023-05-02 14:19:33.054 29940-29940 lxz  com.example.demo3   D  22
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public static Object invokeStaticMethod(String class_name, String method_name, Class[] pareTyple, Object[] pareVaules) {
    // 通过 类名、方法名、方法参数类型 找到静态的方法,传入参数执行
    try {
        // 通过类名从 Class 中获取到类对象
        Class obj_class = Class.forName(class_name);
        // 在类对象中通过方法名和函数的参数类型,找到静态方法
        // pareTyple    函数的参数类型 (有点类似方法签名,避免重载时方法名相同问题)
        Method method = obj_class.getMethod(method_name, pareTyple);
        // 执行找到的方法,第一个参数传类对象,如果是静态方法传 null 就可以
        // pareVaules   调用函数时传入的参数
        return method.invoke(null, pareVaules);
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}
public static Object invokeStaticMethod(String class_name, String method_name, Class[] pareTyple, Object[] pareVaules) {
    // 通过 类名、方法名、方法参数类型 找到静态的方法,传入参数执行
    try {
        // 通过类名从 Class 中获取到类对象
        Class obj_class = Class.forName(class_name);
        // 在类对象中通过方法名和函数的参数类型,找到静态方法
        // pareTyple    函数的参数类型 (有点类似方法签名,避免重载时方法名相同问题)
        Method method = obj_class.getMethod(method_name, pareTyple);
        // 执行找到的方法,第一个参数传类对象,如果是静态方法传 null 就可以
        // pareVaules   调用函数时传入的参数
        return method.invoke(null, pareVaules);
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return null;
}
// Person.java
public class Person {
    private static int age = 22;
    public static int get_age(int a , int b)
    {
        return age + a + b;
    }
}
 
// MainActivity.java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Person person = new Person();
 
        try {
            Class obj_class = Class.forName("com.example.demo3.Person");
            Method method = obj_class.getMethod("get_age",new Class[]{int.class, int.class});
            Object myage = method.invoke(null, new Object[]{1,2});
            Log.d("lxz", "myage is " + myage.toString());
            //2023-05-02 15:17:47.493  6942-6942  lxz   com.example.demo3   D  myage is 25
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
// Person.java
public class Person {
    private static int age = 22;
    public static int get_age(int a , int b)
    {
        return age + a + b;
    }
}
 
// MainActivity.java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Person person = new Person();
 
        try {
            Class obj_class = Class.forName("com.example.demo3.Person");
            Method method = obj_class.getMethod("get_age",new Class[]{int.class, int.class});
            Object myage = method.invoke(null, new Object[]{1,2});
            Log.d("lxz", "myage is " + myage.toString());
            //2023-05-02 15:17:47.493  6942-6942  lxz   com.example.demo3   D  myage is 25
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
public static Object getFieldOjbect(String class_name, Object obj, String filedName) {
    try {
        // 通过类名从 Class 中获取到类对象
        // 这里发现和上边的 getClassFieldObject 基本一样
        // 所以这里查了一下 Class.forName 和 classloader.loadClass加载类时区别
        // Class.forName 加载类时将类进了初始化
        // classloader.loadClass 并没有对类进行初始化,只是把类加载到了虚拟机中
        // 据说作者之所以搞出来两个是因为有的壳为了对抗主动调用会在一些垃圾方法中在静态代码块中
        // 调用结束进程的指令,如果使用 Class.forName 那显然就掉进壳设置的陷阱了
        Class obj_class = Class.forName(class_name);
        Field field = obj_class.getDeclaredField(filedName);
        field.setAccessible(true);
        return field.get(obj);
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NullPointerException e) {
        e.printStackTrace();
    }
    return null;
}
public static Object getFieldOjbect(String class_name, Object obj, String filedName) {
    try {
        // 通过类名从 Class 中获取到类对象
        // 这里发现和上边的 getClassFieldObject 基本一样
        // 所以这里查了一下 Class.forName 和 classloader.loadClass加载类时区别
        // Class.forName 加载类时将类进了初始化
        // classloader.loadClass 并没有对类进行初始化,只是把类加载到了虚拟机中
        // 据说作者之所以搞出来两个是因为有的壳为了对抗主动调用会在一些垃圾方法中在静态代码块中
        // 调用结束进程的指令,如果使用 Class.forName 那显然就掉进壳设置的陷阱了
        Class obj_class = Class.forName(class_name);
        Field field = obj_class.getDeclaredField(filedName);
        field.setAccessible(true);
        return field.get(obj);
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NullPointerException e) {
        e.printStackTrace();
    }
    return null;
}
public static ClassLoader getClassloader() {
    ClassLoader resultClassloader = null;
    // 调用静态方法 currentActivityThread 得到 scurrentActivityThread
    // 简单搜索一下就可以知道 sCurrentActivityThread 就是 this 指针
     
    //     public static ActivityThread currentActivityThread() {
    //          return sCurrentActivityThread;
    //     }
     
    // private void attach(boolean system) {
    //      sCurrentActivityThread = this;
    //      mSystemThread = system;
     
    Object currentActivityThread = invokeStaticMethod(
            "android.app.ActivityThread", "currentActivityThread",
            new Class[]{}, new Object[]{});
             
    // 传入 this 指针获取当前类中的 mBoundApplication 的值
    // 简单搜索一下就可以知道有如下关系
    // mBoundApplication = data;
    // AppBindData data = (AppBindData)msg.obj;
    // handleBindApplication(data);
    // 笔者对这边的数据结构不是特别熟悉,到这里还看不出什么,但先继续往下跟
     
    Object mBoundApplication = getFieldOjbect(
            "android.app.ActivityThread", currentActivityThread,
            "mBoundApplication");
             
    // 这里和上边如出一辙,获取了 mInitialApplication 属性,不过据说这个属性没用到,可以忽略删掉
    Application mInitialApplication = (Application) getFieldOjbect("android.app.ActivityThread",
            currentActivityThread, "mInitialApplication");
             
    // 这里获取了内部类 AppBindData 的 info 属性的值
    // 这里选择看一这个内部类,info 的类型是 LoadedApk
    // 看到这里也算是图穷匕见了,众所周知 LoadedApk 里面有 mClassLoader 嘛
    // static final class AppBindData {
    //     LoadedApk info;
    //     String processName;
    //     ApplicationInfo appInfo;
     
    Object loadedApkInfo = getFieldOjbect(
            "android.app.ActivityThread$AppBindData",
            mBoundApplication, "info");
             
    // 看到这就挺奇怪的,作者先获取了 mApplication 然后调用 getClassLoader 方法获取 classloader
    // 这里不是特别能理解为什么不直接获取 mClassLoader,从源码来看 mClassLoader 和 mApplication 的定义代码就是紧挨着
    Application mApplication = (Application) getFieldOjbect("android.app.LoadedApk", loadedApkInfo, "mApplication");
    resultClassloader = mApplication.getClassLoader();
    return resultClassloader;
}
public static ClassLoader getClassloader() {
    ClassLoader resultClassloader = null;
    // 调用静态方法 currentActivityThread 得到 scurrentActivityThread
    // 简单搜索一下就可以知道 sCurrentActivityThread 就是 this 指针
     
    //     public static ActivityThread currentActivityThread() {
    //          return sCurrentActivityThread;
    //     }
     
    // private void attach(boolean system) {
    //      sCurrentActivityThread = this;
    //      mSystemThread = system;
     
    Object currentActivityThread = invokeStaticMethod(
            "android.app.ActivityThread", "currentActivityThread",
            new Class[]{}, new Object[]{});
             
    // 传入 this 指针获取当前类中的 mBoundApplication 的值
    // 简单搜索一下就可以知道有如下关系
    // mBoundApplication = data;
    // AppBindData data = (AppBindData)msg.obj;
    // handleBindApplication(data);
    // 笔者对这边的数据结构不是特别熟悉,到这里还看不出什么,但先继续往下跟
     
    Object mBoundApplication = getFieldOjbect(
            "android.app.ActivityThread", currentActivityThread,
            "mBoundApplication");
             
    // 这里和上边如出一辙,获取了 mInitialApplication 属性,不过据说这个属性没用到,可以忽略删掉
    Application mInitialApplication = (Application) getFieldOjbect("android.app.ActivityThread",
            currentActivityThread, "mInitialApplication");
             
    // 这里获取了内部类 AppBindData 的 info 属性的值
    // 这里选择看一这个内部类,info 的类型是 LoadedApk
    // 看到这里也算是图穷匕见了,众所周知 LoadedApk 里面有 mClassLoader 嘛
    // static final class AppBindData {
    //     LoadedApk info;
    //     String processName;
    //     ApplicationInfo appInfo;
     
    Object loadedApkInfo = getFieldOjbect(
            "android.app.ActivityThread$AppBindData",
            mBoundApplication, "info");
             
    // 看到这就挺奇怪的,作者先获取了 mApplication 然后调用 getClassLoader 方法获取 classloader
    // 这里不是特别能理解为什么不直接获取 mClassLoader,从源码来看 mClassLoader 和 mApplication 的定义代码就是紧挨着
    Application mApplication = (Application) getFieldOjbect("android.app.LoadedApk", loadedApkInfo, "mApplication");
    resultClassloader = mApplication.getClassLoader();
    return resultClassloader;
}
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }
    //add
    fartthread();
    //add
    return activity;
}
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }
    //add
    fartthread();
    //add
    return activity;
}
// 创建了一个延时 60 秒后再开始的线程
public static void fartthread() {new Thread(new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                Log.e("ActivityThread", "start sleep......");
                // 休眠 60 秒
                Thread.sleep(1 * 60 * 1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.e("ActivityThread", "sleep over and start fart");
            // 调用函数 fart
            fart();
            Log.e("ActivityThread", "fart run over");
        }
    }).start();
}
// 创建了一个延时 60 秒后再开始的线程
public static void fartthread() {new Thread(new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            try {
                Log.e("ActivityThread", "start sleep......");
                // 休眠 60 秒
                Thread.sleep(1 * 60 * 1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Log.e("ActivityThread", "sleep over and start fart");
            // 调用函数 fart
            fart();
            Log.e("ActivityThread", "fart run over");
        }
    }).start();
}
public static void fart() {
    // 获取 Classloader
    ClassLoader appClassloader = getClassloader();
    ClassLoader tmpClassloader=appClassloader;
    // 获取父 Classloader
    ClassLoader parentClassloader=appClassloader.getParent();
    // 如果 appClassloader 不是 java.lang.BootClassLoader
    if(appClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
    {
        // 暂时不知道做什么的函数,等下分析
        fartwithClassloader(appClassloader);
    }
    while(parentClassloader!=null){
        // 如果 parentClassloader 不是 java.lang.BootClassLoader
        if(parentClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
        {
            // 暂时不知道做什么的函数,等下分析
            fartwithClassloader(parentClassloader);
        }
        tmpClassloader=parentClassloader;
        // 继续向上找 parentClassloader,直到 parentClassloader 为空
        parentClassloader=parentClassloader.getParent();
    }
    // 小结:不停的向上找 parentClassloader,将找到所有的 Classloader
    // 都作为参数传给函数 fartwithClassloader
}
public static void fart() {
    // 获取 Classloader
    ClassLoader appClassloader = getClassloader();
    ClassLoader tmpClassloader=appClassloader;
    // 获取父 Classloader
    ClassLoader parentClassloader=appClassloader.getParent();
    // 如果 appClassloader 不是 java.lang.BootClassLoader
    if(appClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
    {
        // 暂时不知道做什么的函数,等下分析
        fartwithClassloader(appClassloader);
    }
    while(parentClassloader!=null){
        // 如果 parentClassloader 不是 java.lang.BootClassLoader
        if(parentClassloader.toString().indexOf("java.lang.BootClassLoader")==-1)
        {
            // 暂时不知道做什么的函数,等下分析
            fartwithClassloader(parentClassloader);
        }
        tmpClassloader=parentClassloader;
        // 继续向上找 parentClassloader,直到 parentClassloader 为空
        parentClassloader=parentClassloader.getParent();
    }
    // 小结:不停的向上找 parentClassloader,将找到所有的 Classloader
    // 都作为参数传给函数 fartwithClassloader
}
public static void fartwithClassloader(ClassLoader appClassloader) {
    // 定义了一个列表,从名字来看应该是要用来存放 dex 对象
    List<Object> dexFilesArray = new ArrayList<Object>();
    // 获取 dalvik.system.BaseDexClassLoader 中 pathList 的反射,不过好像没用到
    Field pathList_Field = (Field) getClassField(appClassloader, "dalvik.system.BaseDexClassLoader", "pathList");
    // 通过反射获取 dalvik.system.BaseDexClassLoader 中 pathList 对象
    Object pathList_object = getFieldOjbect("dalvik.system.BaseDexClassLoader", appClassloader, "pathList");
    // 获取 dalvik.system.DexPathList 中 dexElements 对象
    Object[] ElementsArray = (Object[]) getFieldOjbect("dalvik.system.DexPathList", pathList_object, "dexElements");
    Field dexFile_fileField = null;
    try {
        // 获取 dalvik.system.DexPathList$Element 中 dexFile 的反射
        dexFile_fileField = (Field) getClassField(appClassloader, "dalvik.system.DexPathList$Element", "dexFile");
    } catch (Exception e) {
        e.printStackTrace();
    } catch (Error e) {
        e.printStackTrace();
    }
     
    Class DexFileClazz = null;
    try {
        // 加载了 dalvik.system.DexFile 类,注意这是 native 层的类
        DexFileClazz = appClassloader.loadClass("dalvik.system.DexFile");
    } catch (Exception e) {
        e.printStackTrace();
    } catch (Error e) {
        e.printStackTrace();
    }
    Method getClassNameList_method = null;
    Method defineClass_method = null;
    Method dumpDexFile_method = null;
    Method dumpMethodCode_method = null;
     
    // 遍历 dalvik.system.DexFile 中所有的方法
    for (Method field : DexFileClazz.getDeclaredMethods()) {
        // getClassNameList 是系统源码原本就有的方法
        if (field.getName().equals("getClassNameList")) {
            getClassNameList_method = field;
            getClassNameList_method.setAccessible(true);
        }
        // defineClassNative 是系统源码原本就有的方法
        if (field.getName().equals("defineClassNative")) {
            defineClass_method = field;
            defineClass_method.setAccessible(true);
        }
        // 这个方法没找到,应该是冗余的代码忘记删了
        if (field.getName().equals("dumpDexFile")) {
            dumpDexFile_method = field;
            dumpDexFile_method.setAccessible(true);
        }
        // 重点看这个方法,它是在 dalvik.system.DexFile
        // 中定义的,是个 native 层的函数,你可以在 DexFile.java 中
        // 找到它的声明,在 dalvik_system_DexFile.cc 中找到它的实现,
        // 相信我,请务必记住这个方法的名字
        if (field.getName().equals("dumpMethodCode")) {
            dumpMethodCode_method = field;
            dumpMethodCode_method.setAccessible(true);
        }
    }
     
    // 获取 dalvik.system.DexFile 中的 mCookie 反射,不过好像没用到
    Field mCookiefield = getClassField(appClassloader, "dalvik.system.DexFile", "mCookie");
    Log.v("ActivityThread->methods", "dalvik.system.DexPathList.ElementsArray.length:" + ElementsArray.length);
    // 遍历 ElementsArray 这里面存放着 DexPathList 里记录的 dex 列表
    for (int j = 0; j < ElementsArray.length; j++) {
        Object element = ElementsArray[j];
        Object dexfile = null;
        try {
            // 通过反射对象 dexFile_fileField 的 get 方法获取到 dex
            dexfile = (Object) dexFile_fileField.get(element);
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Error e) {
            e.printStackTrace();
        }
        if (dexfile == null) {
            Log.e("ActivityThread", "dexfile is null");
            continue;
        }
        if (dexfile != null) {
            // 将 dexfile 添加到 dexFilesArray 中
            dexFilesArray.add(dexfile);
            // 获取 mcookie 的对象
            Object mcookie = getClassFieldObject(appClassloader, "dalvik.system.DexFile", dexfile, "mCookie");
            if (mcookie == null) {
                // 如果 mcookie 没获取到,就获取 mInternalCookie
                // 查阅源码可以知道这两个值是相等的,所以部分加固厂商会抹去 mcookie
                // 这为了避免加固厂商的骚操作两个都获取了一下
                Object mInternalCookie = getClassFieldObject(appClassloader, "dalvik.system.DexFile", dexfile, "mInternalCookie");
                if(mInternalCookie!=null)
                {
                    mcookie=mInternalCookie;
                }else{
                    Log.v("ActivityThread->err", "get mInternalCookie is null");
                    continue;
                }
            }
            String[] classnames = null;
            try {
                // 获取 dex 的类名列表
                classnames = (String[]) getClassNameList_method.invoke(dexfile, mcookie);
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            } catch (Error e) {
                e.printStackTrace();
                continue;
            }
            if (classnames != null) {
                // 遍历类名列表,执行 loadClassAndInvoke
                for (String eachclassname : classnames) {
                    loadClassAndInvoke(appClassloader, eachclassname, dumpMethodCode_method);
                }
            }
        }
    }
    return;
}
public static void fartwithClassloader(ClassLoader appClassloader) {
    // 定义了一个列表,从名字来看应该是要用来存放 dex 对象
    List<Object> dexFilesArray = new ArrayList<Object>();
    // 获取 dalvik.system.BaseDexClassLoader 中 pathList 的反射,不过好像没用到
    Field pathList_Field = (Field) getClassField(appClassloader, "dalvik.system.BaseDexClassLoader", "pathList");
    // 通过反射获取 dalvik.system.BaseDexClassLoader 中 pathList 对象
    Object pathList_object = getFieldOjbect("dalvik.system.BaseDexClassLoader", appClassloader, "pathList");
    // 获取 dalvik.system.DexPathList 中 dexElements 对象
    Object[] ElementsArray = (Object[]) getFieldOjbect("dalvik.system.DexPathList", pathList_object, "dexElements");
    Field dexFile_fileField = null;
    try {
        // 获取 dalvik.system.DexPathList$Element 中 dexFile 的反射
        dexFile_fileField = (Field) getClassField(appClassloader, "dalvik.system.DexPathList$Element", "dexFile");
    } catch (Exception e) {
        e.printStackTrace();
    } catch (Error e) {
        e.printStackTrace();
    }
     
    Class DexFileClazz = null;
    try {
        // 加载了 dalvik.system.DexFile 类,注意这是 native 层的类
        DexFileClazz = appClassloader.loadClass("dalvik.system.DexFile");
    } catch (Exception e) {
        e.printStackTrace();
    } catch (Error e) {
        e.printStackTrace();
    }
    Method getClassNameList_method = null;
    Method defineClass_method = null;
    Method dumpDexFile_method = null;
    Method dumpMethodCode_method = null;
     
    // 遍历 dalvik.system.DexFile 中所有的方法
    for (Method field : DexFileClazz.getDeclaredMethods()) {
        // getClassNameList 是系统源码原本就有的方法
        if (field.getName().equals("getClassNameList")) {
            getClassNameList_method = field;
            getClassNameList_method.setAccessible(true);
        }
        // defineClassNative 是系统源码原本就有的方法
        if (field.getName().equals("defineClassNative")) {
            defineClass_method = field;
            defineClass_method.setAccessible(true);
        }
        // 这个方法没找到,应该是冗余的代码忘记删了
        if (field.getName().equals("dumpDexFile")) {
            dumpDexFile_method = field;
            dumpDexFile_method.setAccessible(true);
        }
        // 重点看这个方法,它是在 dalvik.system.DexFile
        // 中定义的,是个 native 层的函数,你可以在 DexFile.java 中
        // 找到它的声明,在 dalvik_system_DexFile.cc 中找到它的实现,
        // 相信我,请务必记住这个方法的名字
        if (field.getName().equals("dumpMethodCode")) {
            dumpMethodCode_method = field;
            dumpMethodCode_method.setAccessible(true);
        }
    }
     
    // 获取 dalvik.system.DexFile 中的 mCookie 反射,不过好像没用到
    Field mCookiefield = getClassField(appClassloader, "dalvik.system.DexFile", "mCookie");
    Log.v("ActivityThread->methods", "dalvik.system.DexPathList.ElementsArray.length:" + ElementsArray.length);
    // 遍历 ElementsArray 这里面存放着 DexPathList 里记录的 dex 列表
    for (int j = 0; j < ElementsArray.length; j++) {
        Object element = ElementsArray[j];
        Object dexfile = null;
        try {
            // 通过反射对象 dexFile_fileField 的 get 方法获取到 dex
            dexfile = (Object) dexFile_fileField.get(element);
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Error e) {
            e.printStackTrace();
        }
        if (dexfile == null) {
            Log.e("ActivityThread", "dexfile is null");
            continue;

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2023-9-24 12:32 被简单的简单编辑 ,原因: 文末的链接挂了,补一下
收藏
免费 14
支持
分享
最新回复 (7)
雪    币: 3004
活跃值: (30866)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2023-5-10 09:12
1
雪    币: 102
活跃值: (2045)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
mark
2023-5-10 10:11
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
8.0哪个版本
2023-6-6 16:51
0
雪    币: 6418
活跃值: (4822)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
5
mb_pnlabahd 8.0哪个版本
还有很多版本么,不太清楚,不过我分析的版本放在帖子最下面了
2023-6-7 10:04
0
雪    币: 2114
活跃值: (3791)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
请问fart8的源码在哪下载呢
2023-9-24 02:03
0
雪    币: 6418
活跃值: (4822)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
7
mb_bppcorlj 请问fart8的源码在哪下载呢
放在文末了,可以自取哈
2023-9-24 12:33
0
雪    币: 2114
活跃值: (3791)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
简单的简单 放在文末了,可以自取哈
谢谢你,祝你开心每一天
2023-9-25 23:56
0
游客
登录 | 注册 方可回帖
返回
//