Advanced Android: custom class loader loads the class file encryption

Before the interview, when there are many problems related to the interviewer asks the class loader, so this is a very important points. And in terms of research and development for advanced Android, know more class loading related things, the development will be a lot of help, such as hot update, like encryption.
In fact, I kind of encryption interested, a little research on a bit. Class encryption fact, in order to prevent APP decompile, prevent there are many, such as confusion, reinforcement decompilation method. Own class file is encrypted, and the custom class loader is one way:

First, our code will become difficult to read binary byte code after compilation package, and become .class file. But after the compiler can be decompiled simple APP, even the code you write is completely exposed. Your code is copied, the copy is small, it is important that you actually APP business information likely to be leaked!
The following is a simple example scene decompiled:
Advanced Android: custom class loader loads the class file encryption
Therefore, in order to prevent the user easily decompiled source code files, .class files necessary to encrypt, decrypt and then loaded by way of a special class, and the class loading into memory.

First of all that encryption, encryption nothing more than some .class bytecode file conversion, there would involve the knowledge of cryptography! There are many ways of encryption, in order to improve privacy, consider DES, AES, RSA. Once the source code encryption algorithm is disclosed, in fact, crack is a very simple thing, it is recommended that you still use highly secure password system, to the time the timely replacement key. It can increase the difficulty of guessing to some extent.

With encryption algorithm, the next step is to encrypt a byte code files:

      private static File file = null;
    private static String path = null;
    // 读取已经编译好的正常的class字节码文件
    public static void readClass(String filePath) throws Exception {
        file = new File(filePath);
        path = filePath;
    }

    // 加密生成已加密的class字节码文件
    public static void encrypt() throws Exception {
        FileInputStream fis = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(path.substring(0,
                path.lastIndexOf(".class"))
                + "附件.class");
        byte[] b = new byte[1024];
        int ch = 0;
        while ((ch = fis.read(b)) != -1) {
            // 变换b
            b=crypt(b, "encrypt");
            fos.write(b, 0, ch);
        }
    }

At this time, calling readClass method and encrypt methods, will be able to generate .class Annex XX in the original directory XX.class file. At this time, we will use this copy of the byte code file, delete the original, and then decrypted when the next run, this will do.

Advanced Android: custom class loader loads the class file encryption

After the class of encryption, make your way to the class and then load it. The normal time we also need to write the class loader class is loaded into memory. So, it comes to knowledge of the class loader:

Three default class loader, namely: BootStrap, ExtClassLoader, the AppClassLoader. So these class loader What difference does it make?

First class loader has a parent-child relationship. BootStrap grandfather (written in C ++, is mainly responsible for loading jre / lib / rt.jar), ExtClassLoader Dad (mainly for loading JRE / lib / ext / *. Jar), ​​AppClassLoader is the son (responsible for loading the specified directory ClassPath All jar) under.

So we generally write AppClassLoader class files are loaded. That if we wrote a class, we have a copy of this class, put ExtClassLoader directory, then the class loader will be how to load it? It is necessary to mention delegation mechanism of the class loader.

Delegate class loader mechanism: When a thread calls a class, with the first class loader of the current thread to load the class, the class loader does not load the outset, will inform him of the parent class loader to load until the time BootStrap loader, if not let's call the lower loader to load. If it did not report a ClassNotFoundException. You may be directly specified class loader to load.

So we can define your own class loader, let this make this class loader to load our encrypted class. Custom class loader needs ClassLoader class inheritance, and rewrites findClass method.

class MyClassLoader extends ClassLoader {
    private String path = null;

    // 设置自定义类加载器的目录
    public MyClassLoader(String path) {
        this.path = path;
    }

    /*
     * findClass和loadClass的区别?
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {           
            File f = new File(path, name.substring(name.lastIndexOf('.') + 1)
                    + ".class");
            FileInputStream fis = new FileInputStream(f);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            int ch = 0;
            while ((ch = fis.read()) != -1) {
                bos.write(ch);
            }
            byte[] buf = bos.toByteArray();
            //解密.class
            buf = Z1Encrypt.crypt(buf, "decrypt");
            fis.close();
            bos.close();
            //根据字节码返回这个类
            return defineClass(name, buf, 0, buf.length);
        } catch (Exception e) {
            throw new ClassNotFoundException(name + " is not found!");
        }
    }
}

Then we used our custom class loader to load our decrypting the encrypted file bytecode

public static void main(String[] args) throws Exception {
        /*Z1Encrypt.readClass("F:\\WorkSpace\\classLoader\\DemoTemp.class");
        Z1Encrypt.encrypt();
        */
        MyClassLoader mcl = new MyClassLoader("F:\\WorkSpace\\classLoader\\");
        Class clazz  = mcl.findClass("DemoTemp");
        Method me = clazz.getMethod("say",null);                       
        Object obj = clazz.newInstance();
        me.invoke(obj, null);
    }

Later successfully decrypted byte code file and load it into memory, and the success of the call related methods.

The above is a very simple code encryption, and custom class loader methods for study in which ideas and knowledge.

Guess you like

Origin blog.51cto.com/14332859/2416220