【Android学习】壳的前置知识

工具学习

Posted by Corax on May 11, 2024

加壳相关

image-20240526024646951

JVM里面三种类加载器

bootstrap classloader
extensions classloader
application classloader
系统中加载顺序也是如上

也可以自定义类加载器

委托关系

先看图

image-20240526025140255

还是很够吧形象的

image-20240526025404779

这种双亲委派好处有俩

避免重复加载

避免类似于想恶意dll注入这种自己实现某个类导致系统本身类不被加载

双亲委派关键 表示父节点

image-20240526042227670

加载时机
隐式加载
	创建类的实例
	访问类的静态变量或者为静态变量赋值
	调用类的静态方法
	使用反射方式强制创建某个类或接口对应的java.lang.Class对象
	初始化某个类的子类
显示加载
	使用LoadClass
	使用forname加载
	

来粗浅看一下如何加载class的

加载
	查找和导入这个class文件
链接
	检查 检查导入的class文件的正确性
	准备 给类的静态变量分配存储空间
	解析 把符号引用转成直接引用
初始化
	调用 clinit 函数 将静态变量 静态代码块做初始化操作

image-20240526030510020

安卓中 一些classloader的继承图

image-20240526030624996

很不错啊

image-20240526041417420

上面这八个 calssloader为抽象类

basedexclassloader与加脱壳紧密相关 其中的pathclassloader是Android默认的类加载器

dexclassloader也是重点

pathclassloader 四大组件要通过这个加载

dexclassloader

http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java

http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java

http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java#30

http://aospxref.com/android-8.0.0_r36/xref/libcore/dalvik/src/main/java/dalvik/system/InMemoryDexClassLoader.java

http://aospxref.com/android-8.0.0_r36/xref/libcore/ojluni/src/main/java/java/lang/ClassLoader.java#180

注释写的非常好

image-20240526042741354

parenet是什么时候给的 拿inmemorydexclassloader举例

image-20240526043635670

回到baseclassloader

image-20240526043703852

回到classloader 到咯

image-20240526043715647

哈哈哈哈自己写了一个demo看看这个mainactivity以及他的parent是谁

package com.example.kanxue12;

import android.os.Bundle;
import android.util.Log;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
        testClassLoader();
    }
    public void testClassLoader(){
        ClassLoader thisClassLoader = MainActivity.class.getClassLoader();
        Log.i("kanxue","thisClassLoader"+thisClassLoader);
        ClassLoader tmpClassLoader=null;
        ClassLoader parentClassLoader=thisClassLoader.getParent();
        while(parentClassLoader!=null){
            Log.i("kanxue","this:"+thisClassLoader+"-----"+parentClassLoader);
            thisClassLoader = parentClassLoader;
            parentClassLoader = tmpClassLoader;
        }
        Log.i("kanxue","root"+thisClassLoader);
    }
}

日志输出的

kanxue                  com.example.kanxue12                 I  thisClassLoaderdalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/lib/arm64, /system/lib64, /vendor/lib64]]]
1970-02-28 14:36:28.646 20586-20586 kanxue                  com.example.kanxue12                 I  this:dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.kanxue12-SIKDTDOcNa_tqDC7e59_RA==/lib/arm64, /system/lib64, /vendor/lib64]]]-----java.lang.BootClassLoader@eece960
1970-02-28 14:36:28.646 20586-20586 kanxue                  com.example.kanxue12                 I  rootjava.lang.BootClassLoader@eece960

可以看到就很简单哈 pathclassloader-bootclassloader

image-20240526045505594

好下一个 通过dexclassloader加载sdcard里面的dex

编译一个dex放进去,dex里面函数就是这样

image-20240526054015244

给主app权限

image-20240526054039039

方法这么些

package com.example.kanxue122;

import android.content.Context;
import android.os.Bundle;
import java.lang.Object;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


import dalvik.system.DexClassLoader;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
        Context appContext = this.getApplicationContext();
        try {
            testDexClassLoader(appContext,"/sdcard/classes3.dex");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    public void testDexClassLoader(Context context,String dexfilepath) throws ClassNotFoundException {
        File optfile = context.getDir("opt_dex",0);
        File libfile = context.getDir("lib_path",0);
        ClassLoader parentClassLoader = MainActivity.class.getClassLoader();
        DexClassLoader dexClassLoader = new DexClassLoader(dexfilepath,optfile.getAbsolutePath(), libfile.getAbsolutePath(), MainActivity.class.getClassLoader());
        Class<?> clazz=null;
        try {
            clazz=dexClassLoader.loadClass("com.example.kanxue12.test");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if(clazz!=null){
            try {
                Method testFunctionMethod = clazz.getDeclaredMethod("test1");
                Object obj = clazz.newInstance();
                testFunctionMethod.invoke(obj);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }

    }
}

反射调用dex里面的方法 成功

image-20240526053953352

实现动态加载

image-20240526054335868